summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Klinghed <the_jk@spawned.biz>2026-05-01 18:45:23 +0200
committerJoel Klinghed <the_jk@spawned.biz>2026-05-02 10:54:02 +0200
commit19005581a0d35233f862e57308734d3486569bb9 (patch)
tree36b925df49b2f7ca8e4283c0682a3f3087abbce3
parent957b8404b8f902fee6a8de144e6274f05b55d342 (diff)
-rw-r--r--data/java-21/syntax.grammar963
-rw-r--r--data/java-8/syntax.grammar845
-rw-r--r--meson.build47
-rw-r--r--src/gen_ast.cc545
-rw-r--r--src/gen_syntax.cc136
5 files changed, 2536 insertions, 0 deletions
diff --git a/data/java-21/syntax.grammar b/data/java-21/syntax.grammar
new file mode 100644
index 0000000..fd88d68
--- /dev/null
+++ b/data/java-21/syntax.grammar
@@ -0,0 +1,963 @@
+PrimitiveType:
+ {Annotation} NumericType
+ {Annotation} boolean
+
+NumericType:
+ IntegralType
+ FloatingPointType
+
+IntegralType:
+ byte
+ short
+ int
+ long
+ char
+
+FloatingPointType:
+ float
+ double
+
+ReferenceType:
+ ClassOrInterfaceType
+ ArrayType
+
+ClassOrInterfaceType:
+ ClassType
+ InterfaceType
+
+ClassType:
+ {Annotation} TypeIdentifier [TypeArguments]
+ PackageName . {Annotation} TypeIdentifier [TypeArguments]
+ ClassOrInterfaceType . {Annotation} TypeIdentifier [TypeArguments]
+
+InterfaceType:
+ ClassType
+
+ArrayType:
+ PrimitiveType Dims
+ ClassOrInterfaceType Dims
+
+Dims:
+ {Annotation} [ ] {{Annotation} [ ]}
+
+TypeParameter:
+ {TypeParameterModifier} TypeIdentifier [TypeBound]
+
+TypeParameterModifier:
+ Annotation
+
+TypeBound:
+ extends ClassOrInterfaceType {AdditionalBound}
+
+AdditionalBound:
+ & InterfaceType
+
+TypeArguments:
+ < TypeArgumentList >
+
+TypeArgumentList:
+ TypeArgument {, TypeArgument}
+
+TypeArgument:
+ ReferenceType
+ Wildcard
+
+Wildcard:
+ {Annotation} ? [WildcardBounds]
+
+WildcardBounds:
+ extends ReferenceType
+ super ReferenceType
+
+ModuleName:
+ Identifier
+ ModuleName . Identifier
+
+PackageName:
+ Identifier
+ PackageName . Identifier
+
+TypeName:
+ TypeIdentifier
+ PackageOrTypeName . TypeIdentifier
+
+ExpressionName:
+ Identifier
+ AmbiguousName . Identifier
+
+MethodName:
+ UnqualifiedMethodIdentifier
+
+PackageOrTypeName:
+ Identifier
+ PackageOrTypeName . Identifier
+
+AmbiguousName:
+ Identifier
+ AmbiguousName . Identifier
+
+CompilationUnit:
+ OrdinaryCompilationUnit
+ ModularCompilationUnit
+
+OrdinaryCompilationUnit:
+ [PackageDeclaration] {ImportDeclaration} {TopLevelClassOrInterfaceDeclaration}
+
+ModularCompilationUnit:
+ {ImportDeclaration} ModuleDeclaration
+
+PackageDeclaration:
+ {PackageModifier} package Identifier {. Identifier} ;
+
+PackageModifier:
+ Annotation
+
+ImportDeclaration:
+ SingleTypeImportDeclaration
+ TypeImportOnDemandDeclaration
+ SingleStaticImportDeclaration
+ StaticImportOnDemandDeclaration
+
+SingleTypeImportDeclaration:
+ import TypeName ;
+
+TypeImportOnDemandDeclaration:
+ import PackageOrTypeName . * ;
+
+SingleStaticImportDeclaration:
+ import static TypeName . Identifier ;
+
+StaticImportOnDemandDeclaration:
+ import static TypeName . * ;
+
+TopLevelClassOrInterfaceDeclaration:
+ ClassDeclaration
+ InterfaceDeclaration
+ ;
+
+ModuleDeclaration:
+ {Annotation} [open] module Identifier {. Identifier} { {ModuleDirective} }
+
+ModuleDirective:
+ requires {RequiresModifier} ModuleName ;
+ exports PackageName [to ModuleName {, ModuleName}] ;
+ opens PackageName [to ModuleName {, ModuleName}] ;
+ uses TypeName ;
+ provides TypeName with TypeName {, TypeName} ;
+
+RequiresModifier:
+ transitive
+ static
+
+ClassDeclaration:
+ NormalClassDeclaration
+ EnumDeclaration
+ RecordDeclaration
+
+NormalClassDeclaration:
+ {ClassModifier} class TypeIdentifier [TypeParameters] [ClassExtends] [ClassImplements] [ClassPermits] ClassBody
+
+ClassModifier:
+ Annotation
+ public
+ protected
+ private
+ abstract
+ static
+ final
+ sealed
+ non-sealed
+ strictfp
+
+TypeParameters:
+ < TypeParameterList >
+
+TypeParameterList:
+ TypeParameter {, TypeParameter}
+
+ClassExtends:
+ extends ClassType
+
+ClassImplements:
+ implements InterfaceTypeList
+
+InterfaceTypeList:
+ InterfaceType {, InterfaceType}
+
+ClassPermits:
+ permits TypeName {, TypeName}
+
+ClassBody:
+ { {ClassBodyDeclaration} }
+
+ClassBodyDeclaration:
+ ClassMemberDeclaration
+ InstanceInitializer
+ StaticInitializer
+ ConstructorDeclaration
+
+ClassMemberDeclaration:
+ FieldDeclaration
+ MethodDeclaration
+ ClassDeclaration
+ InterfaceDeclaration
+ ;
+
+FieldDeclaration:
+ {FieldModifier} UnannType VariableDeclaratorList ;
+
+FieldModifier:
+ Annotation
+ public
+ protected
+ private
+ static
+ final
+ transient
+ volatile
+
+VariableDeclaratorList:
+ VariableDeclarator {, VariableDeclarator}
+
+VariableDeclarator:
+ VariableDeclaratorId [= VariableInitializer]
+
+VariableDeclaratorId:
+ Identifier [Dims]
+
+VariableInitializer:
+ Expression
+ ArrayInitializer
+
+UnannType:
+ UnannPrimitiveType
+ UnannReferenceType
+
+UnannPrimitiveType:
+ NumericType
+ boolean
+
+UnannReferenceType:
+ UnannClassOrInterfaceType
+ UnannArrayType
+
+UnannClassOrInterfaceType:
+ UnannClassType
+ UnannInterfaceType
+
+UnannClassType:
+ TypeIdentifier [TypeArguments]
+ PackageName . {Annotation} TypeIdentifier [TypeArguments]
+ UnannClassOrInterfaceType . {Annotation} TypeIdentifier [TypeArguments]
+
+UnannInterfaceType:
+ UnannClassType
+
+UnannArrayType:
+ UnannPrimitiveType Dims
+ UnannClassOrInterfaceType Dims
+
+MethodDeclaration:
+ {MethodModifier} MethodHeader MethodBody
+
+MethodModifier:
+ Annotation
+ public
+ protected
+ private
+ abstract
+ static
+ final
+ synchronized
+ native
+ strictfp
+
+MethodHeader:
+ Result MethodDeclarator [Throws]
+ TypeParameters {Annotation} Result MethodDeclarator [Throws]
+
+Result:
+ UnannType
+ void
+
+MethodDeclarator:
+ Identifier ( [ReceiverParameter ,] [FormalParameterList] ) [Dims]
+
+ReceiverParameter:
+ {Annotation} UnannType [Identifier .] this
+
+FormalParameterList:
+ FormalParameter {, FormalParameter}
+
+FormalParameter:
+ {VariableModifier} UnannType VariableDeclaratorId
+ VariableArityParameter
+
+VariableArityParameter:
+ {VariableModifier} UnannType {Annotation} ... Identifier
+
+VariableModifier:
+ Annotation
+ final
+
+Throws:
+ throws ExceptionTypeList
+
+ExceptionTypeList:
+ ExceptionType {, ExceptionType}
+
+ExceptionType:
+ ClassType
+
+MethodBody:
+ Block
+ ;
+
+InstanceInitializer:
+ Block
+
+StaticInitializer:
+ static Block
+
+ConstructorDeclaration:
+ {ConstructorModifier} ConstructorDeclarator [Throws] ConstructorBody
+
+ConstructorModifier:
+ Annotation
+ public
+ protected
+ private
+
+ConstructorDeclarator:
+ [TypeParameters] SimpleTypeName ( [ReceiverParameter ,] [FormalParameterList] )
+
+SimpleTypeName:
+ TypeIdentifier
+
+ConstructorBody:
+ { [ExplicitConstructorInvocation] [BlockStatements] }
+
+ExplicitConstructorInvocation:
+ [TypeArguments] this ( [ArgumentList] ) ;
+ [TypeArguments] super ( [ArgumentList] ) ;
+ ExpressionName . [TypeArguments] super ( [ArgumentList] ) ;
+ Primary . [TypeArguments] super ( [ArgumentList] ) ;
+
+EnumDeclaration:
+ {ClassModifier} enum TypeIdentifier [ClassImplements] EnumBody
+
+EnumBody:
+ { [EnumConstantList] [,] [EnumBodyDeclarations] }
+
+EnumConstantList:
+ EnumConstant {, EnumConstant}
+
+EnumConstant:
+ {EnumConstantModifier} Identifier [( [ArgumentList] )] [ClassBody]
+
+EnumConstantModifier:
+ Annotation
+
+EnumBodyDeclarations:
+ ; {ClassBodyDeclaration}
+
+RecordDeclaration:
+ {ClassModifier} record TypeIdentifier [TypeParameters] RecordHeader [ClassImplements] RecordBody
+
+RecordHeader:
+ ( [RecordComponentList] )
+
+RecordComponentList:
+ RecordComponent {, RecordComponent}
+
+RecordComponent:
+ {RecordComponentModifier} UnannType Identifier
+ VariableArityRecordComponent
+
+VariableArityRecordComponent:
+ {RecordComponentModifier} UnannType {Annotation} ... Identifier
+
+RecordComponentModifier:
+ Annotation
+
+RecordBody:
+ { {RecordBodyDeclaration} }
+
+RecordBodyDeclaration:
+ ClassBodyDeclaration
+ CompactConstructorDeclaration
+
+CompactConstructorDeclaration:
+ {ConstructorModifier} SimpleTypeName ConstructorBody
+
+InterfaceDeclaration:
+ NormalInterfaceDeclaration
+ AnnotationInterfaceDeclaration
+
+NormalInterfaceDeclaration:
+ {InterfaceModifier} interface TypeIdentifier [TypeParameters] [InterfaceExtends] [InterfacePermits] InterfaceBody
+
+InterfaceModifier:
+ Annotation
+ public
+ protected
+ private
+ abstract
+ static
+ sealed
+ non-sealed
+ strictfp
+
+InterfaceExtends:
+ extends InterfaceTypeList
+
+InterfacePermits:
+ permits TypeName {, TypeName}
+
+InterfaceBody:
+ { {InterfaceMemberDeclaration} }
+
+InterfaceMemberDeclaration:
+ ConstantDeclaration
+ InterfaceMethodDeclaration
+ ClassDeclaration
+ InterfaceDeclaration
+ ;
+
+ConstantDeclaration:
+ {ConstantModifier} UnannType VariableDeclaratorList ;
+
+ConstantModifier:
+ Annotation
+ public
+ static
+ final
+
+InterfaceMethodDeclaration:
+ {InterfaceMethodModifier} MethodHeader MethodBody
+
+InterfaceMethodModifier:
+ Annotation
+ public
+ private
+ abstract
+ default
+ static
+ strictfp
+
+AnnotationInterfaceDeclaration:
+ {InterfaceModifier} @ interface TypeIdentifier AnnotationInterfaceBody
+
+AnnotationInterfaceBody:
+ { {AnnotationInterfaceMemberDeclaration} }
+
+AnnotationInterfaceMemberDeclaration:
+ AnnotationInterfaceElementDeclaration
+ ConstantDeclaration
+ ClassDeclaration
+ InterfaceDeclaration
+ ;
+
+AnnotationInterfaceElementDeclaration:
+ {AnnotationInterfaceElementModifier} UnannType Identifier ( ) [Dims] [DefaultValue] ;
+
+AnnotationInterfaceElementModifier:
+ Annotation
+ public
+ abstract
+
+DefaultValue:
+ default ElementValue
+
+Annotation:
+ NormalAnnotation
+ MarkerAnnotation
+ SingleElementAnnotation
+
+NormalAnnotation:
+ @ TypeName ( [ElementValuePairList] )
+
+ElementValuePairList:
+ ElementValuePair {, ElementValuePair}
+
+ElementValuePair:
+ Identifier = ElementValue
+
+ElementValue:
+ ConditionalExpression
+ ElementValueArrayInitializer
+ Annotation
+
+ElementValueArrayInitializer:
+ { [ElementValueList] [,] }
+
+ElementValueList:
+ ElementValue {, ElementValue}
+
+MarkerAnnotation:
+ @ TypeName
+
+SingleElementAnnotation:
+ @ TypeName ( ElementValue )
+
+ArrayInitializer:
+ { [VariableInitializerList] [,] }
+
+VariableInitializerList:
+ VariableInitializer {, VariableInitializer}
+
+Block:
+ { [BlockStatements] }
+
+BlockStatements:
+ BlockStatement {BlockStatement}
+
+BlockStatement:
+ LocalClassOrInterfaceDeclaration
+ LocalVariableDeclarationStatement
+ Statement
+
+LocalClassOrInterfaceDeclaration:
+ ClassDeclaration
+ NormalInterfaceDeclaration
+
+LocalVariableDeclarationStatement:
+ LocalVariableDeclaration ;
+
+LocalVariableDeclaration:
+ {VariableModifier} LocalVariableType VariableDeclaratorList
+
+LocalVariableType:
+ UnannType
+ var
+
+Statement:
+ StatementWithoutTrailingSubstatement
+ LabeledStatement
+ IfThenStatement
+ IfThenElseStatement
+ WhileStatement
+ ForStatement
+
+StatementNoShortIf:
+ StatementWithoutTrailingSubstatement
+ LabeledStatementNoShortIf
+ IfThenElseStatementNoShortIf
+ WhileStatementNoShortIf
+ ForStatementNoShortIf
+
+StatementWithoutTrailingSubstatement:
+ Block
+ EmptyStatement
+ ExpressionStatement
+ AssertStatement
+ SwitchStatement
+ DoStatement
+ BreakStatement
+ ContinueStatement
+ ReturnStatement
+ SynchronizedStatement
+ ThrowStatement
+ TryStatement
+ YieldStatement
+
+EmptyStatement:
+ ;
+
+LabeledStatement:
+ Identifier : Statement
+
+LabeledStatementNoShortIf:
+ Identifier : StatementNoShortIf
+
+ExpressionStatement:
+ StatementExpression ;
+
+StatementExpression:
+ Assignment
+ PreIncrementExpression
+ PreDecrementExpression
+ PostIncrementExpression
+ PostDecrementExpression
+ MethodInvocation
+ ClassInstanceCreationExpression
+
+IfThenStatement:
+ if ( Expression ) Statement
+
+IfThenElseStatement:
+ if ( Expression ) StatementNoShortIf else Statement
+
+IfThenElseStatementNoShortIf:
+ if ( Expression ) StatementNoShortIf else StatementNoShortIf
+
+AssertStatement:
+ assert Expression ;
+ assert Expression : Expression ;
+
+SwitchStatement:
+ switch ( Expression ) SwitchBlock
+
+SwitchBlock:
+ { SwitchRule {SwitchRule} }
+ { {SwitchBlockStatementGroup} {SwitchLabel :} }
+
+SwitchRule:
+ SwitchLabel -> Expression ;
+ SwitchLabel -> Block
+ SwitchLabel -> ThrowStatement
+ SwitchBlockStatementGroup:
+ SwitchLabel : {SwitchLabel :} BlockStatements
+
+SwitchLabel:
+ case CaseConstant {, CaseConstant}
+ case null [, default]
+ case CasePattern [Guard]
+ default
+
+CaseConstant:
+ ConditionalExpression
+
+CasePattern:
+ Pattern
+
+Guard:
+ when Expression
+
+WhileStatement:
+ while ( Expression ) Statement
+
+WhileStatementNoShortIf:
+ while ( Expression ) StatementNoShortIf
+
+DoStatement:
+ do Statement while ( Expression ) ;
+
+ForStatement:
+ BasicForStatement
+ EnhancedForStatement
+
+ForStatementNoShortIf:
+ BasicForStatementNoShortIf
+ EnhancedForStatementNoShortIf
+
+BasicForStatement:
+ for ( [ForInit] ; [Expression] ; [ForUpdate] ) Statement
+
+BasicForStatementNoShortIf:
+ for ( [ForInit] ; [Expression] ; [ForUpdate] ) StatementNoShortIf
+
+ForInit:
+ StatementExpressionList
+ LocalVariableDeclaration
+
+ForUpdate:
+ StatementExpressionList
+
+StatementExpressionList:
+ StatementExpression {, StatementExpression}
+
+EnhancedForStatement:
+ for ( LocalVariableDeclaration : Expression ) Statement
+
+EnhancedForStatementNoShortIf:
+ for ( LocalVariableDeclaration : Expression ) StatementNoShortIf
+
+BreakStatement:
+ break [Identifier] ;
+
+YieldStatement:
+ yield Expression ;
+
+ContinueStatement:
+ continue [Identifier] ;
+
+ReturnStatement:
+ return [Expression] ;
+
+ThrowStatement:
+ throw Expression ;
+
+SynchronizedStatement:
+ synchronized ( Expression ) Block
+
+TryStatement:
+ try Block Catches
+ try Block [Catches] Finally
+ TryWithResourcesStatement
+
+Catches:
+ CatchClause {CatchClause}
+
+CatchClause:
+ catch ( CatchFormalParameter ) Block
+
+CatchFormalParameter:
+ {VariableModifier} CatchType VariableDeclaratorId
+
+CatchType:
+ UnannClassType {| ClassType}
+
+Finally:
+ finally Block
+
+TryWithResourcesStatement:
+ try ResourceSpecification Block [Catches] [Finally]
+
+ResourceSpecification:
+ ( ResourceList [;] )
+
+ResourceList:
+ Resource {; Resource}
+
+Resource:
+ LocalVariableDeclaration
+ VariableAccess
+
+Pattern:
+ TypePattern
+ RecordPattern
+
+TypePattern:
+ LocalVariableDeclaration
+
+RecordPattern:
+ ReferenceType ( [PatternList] )
+
+PatternList:
+ Pattern {, Pattern }
+
+Primary:
+ PrimaryNoNewArray
+ ArrayCreationExpression
+
+PrimaryNoNewArray:
+ Literal
+ ClassLiteral
+ this
+ TypeName . this
+ ( Expression )
+ ClassInstanceCreationExpression
+ FieldAccess
+ ArrayAccess
+ MethodInvocation
+ MethodReference
+
+ClassLiteral:
+ TypeName {[ ]} . class
+ NumericType {[ ]} . class
+ boolean {[ ]} . class
+ void . class
+
+ClassInstanceCreationExpression:
+ UnqualifiedClassInstanceCreationExpression
+ ExpressionName . UnqualifiedClassInstanceCreationExpression
+ Primary . UnqualifiedClassInstanceCreationExpression
+
+UnqualifiedClassInstanceCreationExpression:
+ new [TypeArguments] ClassOrInterfaceTypeToInstantiate ( [ArgumentList] ) [ClassBody]
+
+ClassOrInterfaceTypeToInstantiate:
+ {Annotation} Identifier {. {Annotation} Identifier} [TypeArgumentsOrDiamond]
+
+TypeArgumentsOrDiamond:
+ TypeArguments
+ <>
+
+ArrayCreationExpression:
+ ArrayCreationExpressionWithoutInitializer
+ ArrayCreationExpressionWithInitializer
+
+ArrayCreationExpressionWithoutInitializer:
+ new PrimitiveType DimExprs [Dims]
+ new ClassOrInterfaceType DimExprs [Dims]
+
+ArrayCreationExpressionWithInitializer:
+ new PrimitiveType Dims ArrayInitializer
+ new ClassOrInterfaceType Dims ArrayInitializer
+
+DimExprs:
+ DimExpr {DimExpr}
+
+DimExpr:
+ {Annotation} [ Expression ]
+
+ArrayAccess:
+ ExpressionName [ Expression ]
+ PrimaryNoNewArray [ Expression ]
+ ArrayCreationExpressionWithInitializer [ Expression ]
+
+FieldAccess:
+ Primary . Identifier
+ super . Identifier
+ TypeName . super . Identifier
+
+MethodInvocation:
+ MethodName ( [ArgumentList] )
+ TypeName . [TypeArguments] Identifier ( [ArgumentList] )
+ ExpressionName . [TypeArguments] Identifier ( [ArgumentList] )
+ Primary . [TypeArguments] Identifier ( [ArgumentList] )
+ super . [TypeArguments] Identifier ( [ArgumentList] )
+ TypeName . super . [TypeArguments] Identifier ( [ArgumentList] )
+
+ArgumentList:
+ Expression {, Expression}
+
+MethodReference:
+ ExpressionName :: [TypeArguments] Identifier
+ Primary :: [TypeArguments] Identifier
+ ReferenceType :: [TypeArguments] Identifier
+ super :: [TypeArguments] Identifier
+ TypeName . super :: [TypeArguments] Identifier
+ ClassType :: [TypeArguments] new
+ ArrayType :: new
+
+Expression:
+ LambdaExpression
+ AssignmentExpression
+
+LambdaExpression:
+ LambdaParameters -> LambdaBody
+
+LambdaParameters:
+ ( [LambdaParameterList] )
+ Identifier
+ LambdaParameterList:
+ LambdaParameter {, LambdaParameter}
+ Identifier {, Identifier}
+
+LambdaParameter:
+ {VariableModifier} LambdaParameterType VariableDeclaratorId
+ VariableArityParameter
+ LambdaParameterType:
+ UnannType
+ var
+
+LambdaBody:
+ Expression
+ Block
+
+AssignmentExpression:
+ ConditionalExpression
+ Assignment
+
+Assignment:
+ LeftHandSide AssignmentOperator Expression
+
+LeftHandSide:
+ ExpressionName
+ FieldAccess
+ ArrayAccess
+
+AssignmentOperator:
+ =
+ *=
+ /=
+ %=
+ +=
+ -=
+ <<=
+ >>=
+ >>>=
+ &=
+ ^=
+ |=
+
+ConditionalExpression:
+ ConditionalOrExpression
+ ConditionalOrExpression ? Expression : ConditionalExpression
+ ConditionalOrExpression ? Expression : LambdaExpression
+
+ConditionalOrExpression:
+ ConditionalAndExpression
+ ConditionalOrExpression || ConditionalAndExpression
+
+ConditionalAndExpression:
+ InclusiveOrExpression
+ ConditionalAndExpression && InclusiveOrExpression
+
+InclusiveOrExpression:
+ ExclusiveOrExpression
+ InclusiveOrExpression | ExclusiveOrExpression
+
+ExclusiveOrExpression:
+ AndExpression
+ ExclusiveOrExpression ^ AndExpression
+
+AndExpression:
+ EqualityExpression
+ AndExpression & EqualityExpression
+
+EqualityExpression:
+ RelationalExpression
+ EqualityExpression == RelationalExpression
+ EqualityExpression != RelationalExpression
+
+RelationalExpression:
+ ShiftExpression
+ RelationalExpression < ShiftExpression
+ RelationalExpression > ShiftExpression
+ RelationalExpression <= ShiftExpression
+ RelationalExpression >= ShiftExpression
+ InstanceofExpression
+
+InstanceofExpression:
+ RelationalExpression instanceof ReferenceType
+ RelationalExpression instanceof Pattern
+
+ShiftExpression:
+ AdditiveExpression
+ ShiftExpression << AdditiveExpression
+ ShiftExpression >> AdditiveExpression
+ ShiftExpression >>> AdditiveExpression
+
+AdditiveExpression:
+ MultiplicativeExpression
+ AdditiveExpression + MultiplicativeExpression
+ AdditiveExpression - MultiplicativeExpression
+
+MultiplicativeExpression:
+ UnaryExpression
+ MultiplicativeExpression * UnaryExpression
+ MultiplicativeExpression / UnaryExpression
+ MultiplicativeExpression % UnaryExpression
+
+UnaryExpression:
+ PreIncrementExpression
+ PreDecrementExpression
+ + UnaryExpression
+ - UnaryExpression
+ UnaryExpressionNotPlusMinus
+
+PreIncrementExpression:
+ ++ UnaryExpression
+
+PreDecrementExpression:
+ -- UnaryExpression
+
+UnaryExpressionNotPlusMinus:
+ PostfixExpression
+ ~ UnaryExpression
+ ! UnaryExpression
+ CastExpression
+ SwitchExpression
+
+PostfixExpression:
+ Primary
+ ExpressionName
+ PostIncrementExpression
+ PostDecrementExpression
+
+PostIncrementExpression:
+ PostfixExpression ++
+
+PostDecrementExpression:
+ PostfixExpression --
+
+CastExpression:
+ ( PrimitiveType ) UnaryExpression
+ ( ReferenceType {AdditionalBound} ) UnaryExpressionNotPlusMinus
+ ( ReferenceType {AdditionalBound} ) LambdaExpression
+
+SwitchExpression:
+ switch ( Expression ) SwitchBlock
diff --git a/data/java-8/syntax.grammar b/data/java-8/syntax.grammar
new file mode 100644
index 0000000..1f34289
--- /dev/null
+++ b/data/java-8/syntax.grammar
@@ -0,0 +1,845 @@
+PrimitiveType:
+ {Annotation} NumericType
+ {Annotation} boolean
+
+NumericType:
+ IntegralType
+ FloatingPointType
+
+IntegralType:
+ byte
+ short
+ int
+ long
+ char
+
+FloatingPointType:
+ float
+ double
+
+ReferenceType:
+ ClassOrInterfaceType
+ ArrayType
+
+ClassOrInterfaceType:
+ ClassType
+ InterfaceType
+
+ClassType:
+ {Annotation} Identifier [TypeArguments]
+ ClassOrInterfaceType . {Annotation} Identifier [TypeArguments]
+
+InterfaceType:
+ ClassType
+
+ArrayType:
+ PrimitiveType Dims
+ ClassOrInterfaceType Dims
+
+Dims:
+ {Annotation} [ ] {{Annotation} [ ]}
+
+TypeParameter:
+ {TypeParameterModifier} Identifier [TypeBound]
+
+TypeParameterModifier:
+ Annotation
+
+TypeBound:
+ extends ClassOrInterfaceType {AdditionalBound}
+
+AdditionalBound:
+ & InterfaceType
+
+TypeArguments:
+ < TypeArgumentList >
+
+TypeArgumentList:
+ TypeArgument {, TypeArgument}
+
+TypeArgument:
+ ReferenceType
+ Wildcard
+
+Wildcard:
+ {Annotation} ? [WildcardBounds]
+
+WildcardBounds:
+ extends ReferenceType
+ super ReferenceType
+
+PackageName:
+ Identifier
+ PackageName . Identifier
+
+TypeName:
+ Identifier
+ PackageOrTypeName . Identifier
+
+PackageOrTypeName:
+ Identifier
+ PackageOrTypeName . Identifier
+
+ExpressionName:
+ Identifier
+ AmbiguousName . Identifier
+
+MethodName:
+ Identifier
+
+AmbiguousName:
+ Identifier
+ AmbiguousName . Identifier
+
+CompilationUnit:
+ [PackageDeclaration] {ImportDeclaration} {TypeDeclaration}
+
+PackageDeclaration:
+ {PackageModifier} package Identifier {. Identifier} ;
+
+PackageModifier:
+ Annotation
+
+ImportDeclaration:
+ SingleTypeImportDeclaration
+ TypeImportOnDemandDeclaration
+ SingleStaticImportDeclaration
+ StaticImportOnDemandDeclaration
+
+SingleTypeImportDeclaration:
+ import TypeName ;
+
+TypeImportOnDemandDeclaration:
+ import PackageOrTypeName . * ;
+
+SingleStaticImportDeclaration:
+ import static TypeName . Identifier ;
+
+StaticImportOnDemandDeclaration:
+ import static TypeName . * ;
+
+TypeDeclaration:
+ ClassDeclaration
+ InterfaceDeclaration
+ ;
+
+ClassDeclaration:
+ NormalClassDeclaration
+ EnumDeclaration
+
+NormalClassDeclaration:
+ {ClassModifier} class Identifier [TypeParameters] [Superclass] [Superinterfaces] ClassBody
+
+ClassModifier:
+ Annotation
+ public
+ protected
+ private
+ abstract
+ static
+ final
+ strictfp
+
+TypeParameters:
+ < TypeParameterList >
+
+TypeParameterList:
+ TypeParameter {, TypeParameter}
+
+Superclass:
+ extends ClassType
+
+Superinterfaces:
+ implements InterfaceTypeList
+
+InterfaceTypeList:
+ InterfaceType {, InterfaceType}
+
+ClassBody:
+ { {ClassBodyDeclaration} }
+
+ClassBodyDeclaration:
+ ClassMemberDeclaration
+ InstanceInitializer
+ StaticInitializer
+ ConstructorDeclaration
+
+ClassMemberDeclaration:
+ FieldDeclaration
+ MethodDeclaration
+ ClassDeclaration
+ InterfaceDeclaration
+ ;
+
+FieldDeclaration:
+ {FieldModifier} UnannType VariableDeclaratorList ;
+
+VariableDeclaratorList:
+ VariableDeclarator {, VariableDeclarator}
+
+VariableDeclarator:
+ VariableDeclaratorId [= VariableInitializer]
+
+VariableDeclaratorId:
+ Identifier [Dims]
+
+VariableInitializer:
+ Expression
+ ArrayInitializer
+
+UnannType:
+ UnannPrimitiveType
+ UnannReferenceType
+
+UnannPrimitiveType:
+ NumericType
+ boolean
+
+UnannReferenceType:
+ UnannClassOrInterfaceType
+ UnannArrayType
+
+UnannClassOrInterfaceType:
+ UnannClassType
+ UnannInterfaceType
+
+UnannClassType:
+ Identifier [TypeArguments]
+ UnannClassOrInterfaceType . {Annotation} Identifier [TypeArguments]
+
+UnannInterfaceType:
+ UnannClassType
+
+UnannArrayType:
+ UnannPrimitiveType Dims
+ UnannClassOrInterfaceType Dims
+
+FieldModifier:
+ Annotation
+ public
+ protected
+ private
+ static
+ final
+ transient
+ volatile
+
+MethodDeclaration:
+ {MethodModifier} MethodHeader MethodBody
+
+MethodHeader:
+ Result MethodDeclarator [Throws]
+ TypeParameters {Annotation} Result MethodDeclarator [Throws]
+
+MethodDeclarator:
+ Identifier ( [FormalParameterList] ) [Dims]
+
+FormalParameterList:
+ ReceiverParameter
+ FormalParameters , LastFormalParameter
+ LastFormalParameter
+
+FormalParameters:
+ FormalParameter {, FormalParameter}
+ ReceiverParameter {, FormalParameter}
+
+FormalParameter:
+ {VariableModifier} UnannType VariableDeclaratorId
+
+VariableModifier:
+ Annotation
+ final
+
+ReceiverParameter:
+ {Annotation} UnannType [Identifier .] this
+
+LastFormalParameter:
+ {VariableModifier} UnannType {Annotation} ... VariableDeclaratorId
+ FormalParameter
+
+MethodModifier:
+ Annotation
+ public
+ protected
+ private
+ abstract
+ static
+ final
+ synchronized
+ native
+ strictfp
+
+Result:
+ UnannType
+ void
+
+Throws:
+ throws ExceptionTypeList
+
+ExceptionTypeList:
+ ExceptionType {, ExceptionType}
+
+ExceptionType:
+ ClassType
+
+MethodBody:
+ Block
+ ;
+
+InstanceInitializer:
+ Block
+
+StaticInitializer:
+ static Block
+
+ConstructorDeclaration:
+ {ConstructorModifier} ConstructorDeclarator [Throws] ConstructorBody
+
+ConstructorDeclarator:
+ [TypeParameters] SimpleTypeName ( [FormalParameterList] )
+
+SimpleTypeName:
+ Identifier
+
+ConstructorModifier:
+ Annotation
+ public
+ protected
+ private
+
+ConstructorBody:
+ { [ExplicitConstructorInvocation] [BlockStatements] }
+
+ExplicitConstructorInvocation:
+ [TypeArguments] this ( [ArgumentList] ) ;
+ [TypeArguments] super ( [ArgumentList] ) ;
+ ExpressionName . [TypeArguments] super ( [ArgumentList] ) ;
+ Primary . [TypeArguments] super ( [ArgumentList] ) ;
+
+EnumDeclaration:
+ {ClassModifier} enum Identifier [Superinterfaces] EnumBody
+
+EnumBody:
+ { [EnumConstantList] [,] [EnumBodyDeclarations] }
+
+EnumConstantList:
+ EnumConstant {, EnumConstant}
+
+EnumConstant:
+ {EnumConstantModifier} Identifier [( [ArgumentList] )] [ClassBody]
+
+EnumConstantModifier:
+ Annotation
+
+EnumBodyDeclarations:
+ ; {ClassBodyDeclaration}
+
+InterfaceDeclaration:
+ NormalInterfaceDeclaration
+ AnnotationTypeDeclaration
+
+NormalInterfaceDeclaration:
+ {InterfaceModifier} interface Identifier [TypeParameters] [ExtendsInterfaces] InterfaceBody
+
+InterfaceModifier:
+ Annotation
+ public
+ protected
+ private
+ abstract
+ static
+ strictfp
+
+ExtendsInterfaces:
+ extends InterfaceTypeList
+
+InterfaceBody:
+ { {InterfaceMemberDeclaration} }
+
+InterfaceMemberDeclaration:
+ ConstantDeclaration
+ InterfaceMethodDeclaration
+ ClassDeclaration
+ InterfaceDeclaration
+ ;
+
+ConstantDeclaration:
+ {ConstantModifier} UnannType VariableDeclaratorList ;
+
+ConstantModifier:
+ Annotation
+ public
+ static
+ final
+
+InterfaceMethodDeclaration:
+ {InterfaceMethodModifier} MethodHeader MethodBody
+
+InterfaceMethodModifier:
+ Annotation
+ public
+ abstract
+ default
+ static
+ strictfp
+
+AnnotationTypeDeclaration:
+ {InterfaceModifier} @ interface Identifier AnnotationTypeBody
+
+AnnotationTypeBody:
+ { {AnnotationTypeMemberDeclaration} }
+
+AnnotationTypeMemberDeclaration:
+ AnnotationTypeElementDeclaration
+ ConstantDeclaration
+ ClassDeclaration
+ InterfaceDeclaration
+ ;
+
+AnnotationTypeElementDeclaration:
+ {AnnotationTypeElementModifier} UnannType Identifier ( ) [Dims] [DefaultValue] ;
+
+AnnotationTypeElementModifier:
+ Annotation
+ public
+ abstract
+
+DefaultValue:
+ default ElementValue
+
+Annotation:
+ NormalAnnotation
+ MarkerAnnotation
+ SingleElementAnnotation
+
+NormalAnnotation:
+ @ TypeName ( [ElementValuePairList] )
+
+ElementValuePairList:
+ ElementValuePair {, ElementValuePair}
+
+ElementValuePair:
+ Identifier = ElementValue
+
+ElementValue:
+ ConditionalExpression
+ ElementValueArrayInitializer
+ Annotation
+
+ElementValueArrayInitializer:
+ { [ElementValueList] [,] }
+
+ElementValueList:
+ ElementValue {, ElementValue}
+
+MarkerAnnotation:
+ @ TypeName
+
+SingleElementAnnotation:
+ @ TypeName ( ElementValue )
+
+ArrayInitializer:
+ { [VariableInitializerList] [,] }
+
+VariableInitializerList:
+ VariableInitializer {, VariableInitializer}
+
+Block:
+ { [BlockStatements] }
+
+BlockStatements:
+ BlockStatement {BlockStatement}
+
+BlockStatement:
+ LocalVariableDeclarationStatement
+ ClassDeclaration
+ Statement
+
+LocalVariableDeclarationStatement:
+ LocalVariableDeclaration ;
+
+LocalVariableDeclaration:
+ {VariableModifier} UnannType VariableDeclaratorList
+
+Statement:
+ StatementWithoutTrailingSubstatement
+ LabeledStatement
+ IfThenStatement
+ IfThenElseStatement
+ WhileStatement
+ ForStatement
+
+StatementNoShortIf:
+ StatementWithoutTrailingSubstatement
+ LabeledStatementNoShortIf
+ IfThenElseStatementNoShortIf
+ WhileStatementNoShortIf
+ ForStatementNoShortIf
+ StatementWithoutTrailingSubstatement:
+ Block
+ EmptyStatement
+ ExpressionStatement
+ AssertStatement
+ SwitchStatement
+ DoStatement
+ BreakStatement
+ ContinueStatement
+ ReturnStatement
+ SynchronizedStatement
+ ThrowStatement
+ TryStatement
+
+EmptyStatement:
+ ;
+
+LabeledStatement:
+ Identifier : Statement
+
+LabeledStatementNoShortIf:
+ Identifier : StatementNoShortIf
+
+ExpressionStatement:
+ StatementExpression ;
+
+StatementExpression:
+ Assignment
+ PreIncrementExpression
+ PreDecrementExpression
+ PostIncrementExpression
+ PostDecrementExpression
+ MethodInvocation
+ ClassInstanceCreationExpression
+
+IfThenStatement:
+ if ( Expression ) Statement
+
+IfThenElseStatement:
+ if ( Expression ) StatementNoShortIf else Statement
+
+IfThenElseStatementNoShortIf:
+ if ( Expression ) StatementNoShortIf else StatementNoShortIf
+
+AssertStatement:
+ assert Expression ;
+ assert Expression : Expression ;
+
+SwitchStatement:
+ switch ( Expression ) SwitchBlock
+
+SwitchBlock:
+ { {SwitchBlockStatementGroup} {SwitchLabel} }
+
+SwitchBlockStatementGroup:
+ SwitchLabels BlockStatements
+
+SwitchLabels:
+ SwitchLabel {SwitchLabel}
+
+SwitchLabel:
+ case ConstantExpression :
+ case EnumConstantName :
+ default :
+
+EnumConstantName:
+ Identifier
+
+WhileStatement:
+ while ( Expression ) Statement
+
+WhileStatementNoShortIf:
+ while ( Expression ) StatementNoShortIf
+
+DoStatement:
+ do Statement while ( Expression ) ;
+
+ForStatement:
+ BasicForStatement
+ EnhancedForStatement
+
+ForStatementNoShortIf:
+ BasicForStatementNoShortIf
+ EnhancedForStatementNoShortIf
+
+BasicForStatement:
+ for ( [ForInit] ; [Expression] ; [ForUpdate] ) Statement
+
+BasicForStatementNoShortIf:
+ for ( [ForInit] ; [Expression] ; [ForUpdate] ) StatementNoShortIf
+
+ForInit:
+ StatementExpressionList
+ LocalVariableDeclaration
+
+ForUpdate:
+ StatementExpressionList
+
+StatementExpressionList:
+ StatementExpression {, StatementExpression}
+
+EnhancedForStatement:
+ for ( {VariableModifier} UnannType VariableDeclaratorId : Expression ) Statement
+
+EnhancedForStatementNoShortIf:
+ for ( {VariableModifier} UnannType VariableDeclaratorId : Expression ) StatementNoShortIf
+
+BreakStatement:
+ break [Identifier] ;
+
+ContinueStatement:
+ continue [Identifier] ;
+
+ReturnStatement:
+ return [Expression] ;
+
+ThrowStatement:
+ throw Expression ;
+
+SynchronizedStatement:
+ synchronized ( Expression ) Block
+
+TryStatement:
+ try Block Catches
+ try Block [Catches] Finally
+ TryWithResourcesStatement
+
+Catches:
+ CatchClause {CatchClause}
+
+CatchClause:
+ catch ( CatchFormalParameter ) Block
+
+CatchFormalParameter:
+ {VariableModifier} CatchType VariableDeclaratorId
+
+CatchType:
+ UnannClassType {| ClassType}
+
+Finally:
+ finally Block
+
+TryWithResourcesStatement:
+ try ResourceSpecification Block [Catches] [Finally]
+
+ResourceSpecification:
+ ( ResourceList [;] )
+
+ResourceList:
+ Resource {; Resource}
+
+Resource:
+ {VariableModifier} UnannType VariableDeclaratorId = Expression
+
+Expression:
+ LambdaExpression
+ AssignmentExpression
+
+Primary:
+ PrimaryNoNewArray
+ ArrayCreationExpression
+
+PrimaryNoNewArray:
+ Literal
+ ClassLiteral
+ this
+ TypeName . this
+ ( Expression )
+ ClassInstanceCreationExpression
+ FieldAccess
+ ArrayAccess
+ MethodInvocation
+ MethodReference
+
+ClassLiteral:
+ TypeName {[ ]} . class
+ NumericType {[ ]} . class
+ boolean {[ ]} . class
+ void . class
+
+ClassInstanceCreationExpression:
+ UnqualifiedClassInstanceCreationExpression
+ ExpressionName . UnqualifiedClassInstanceCreationExpression
+ Primary . UnqualifiedClassInstanceCreationExpression
+ UnqualifiedClassInstanceCreationExpression:
+ new [TypeArguments] ClassOrInterfaceTypeToInstantiate ( [ArgumentList] ) [ClassBody]
+ ClassOrInterfaceTypeToInstantiate:
+ {Annotation} Identifier {. {Annotation} Identifier} [TypeArgumentsOrDiamond]
+
+TypeArgumentsOrDiamond:
+ TypeArguments
+ <>
+
+ArrayCreationExpression:
+ new PrimitiveType DimExprs [Dims]
+ new ClassOrInterfaceType DimExprs [Dims]
+ new PrimitiveType Dims ArrayInitializer
+ new ClassOrInterfaceType Dims ArrayInitializer
+
+DimExprs:
+ DimExpr {DimExpr}
+
+DimExpr:
+ {Annotation} [ Expression ]
+
+ArrayAccess:
+ ExpressionName [ Expression ]
+ PrimaryNoNewArray [ Expression ]
+
+FieldAccess:
+ Primary . Identifier
+ super . Identifier
+ TypeName . super . Identifier
+
+MethodInvocation:
+ MethodName ( [ArgumentList] )
+ TypeName . [TypeArguments] Identifier ( [ArgumentList] )
+ ExpressionName . [TypeArguments] Identifier ( [ArgumentList] )
+ Primary . [TypeArguments] Identifier ( [ArgumentList] )
+ super . [TypeArguments] Identifier ( [ArgumentList] )
+ TypeName . super . [TypeArguments] Identifier ( [ArgumentList] )
+
+ArgumentList:
+ Expression {, Expression}
+
+MethodReference:
+ ExpressionName :: [TypeArguments] Identifier
+ ReferenceType :: [TypeArguments] Identifier
+ Primary :: [TypeArguments] Identifier
+ super :: [TypeArguments] Identifier
+ TypeName . super :: [TypeArguments] Identifier
+ ClassType :: [TypeArguments] new
+ ArrayType :: new
+
+PostfixExpression:
+ Primary
+ ExpressionName
+ PostIncrementExpression
+ PostDecrementExpression
+
+PostIncrementExpression:
+ PostfixExpression ++
+
+PostDecrementExpression:
+ PostfixExpression --
+
+UnaryExpression:
+ PreIncrementExpression
+ PreDecrementExpression
+ + UnaryExpression
+ - UnaryExpression
+ UnaryExpressionNotPlusMinus
+
+PreIncrementExpression:
+ ++ UnaryExpression
+
+PreDecrementExpression:
+ -- UnaryExpression
+
+UnaryExpressionNotPlusMinus:
+ PostfixExpression
+ ~ UnaryExpression
+ ! UnaryExpression
+ CastExpression
+
+CastExpression:
+ ( PrimitiveType ) UnaryExpression
+ ( ReferenceType {AdditionalBound} ) UnaryExpressionNotPlusMinus
+ ( ReferenceType {AdditionalBound} ) LambdaExpression
+
+MultiplicativeExpression:
+ UnaryExpression
+ MultiplicativeExpression * UnaryExpression
+ MultiplicativeExpression / UnaryExpression
+ MultiplicativeExpression % UnaryExpression
+
+AdditiveExpression:
+ MultiplicativeExpression
+ AdditiveExpression + MultiplicativeExpression
+ AdditiveExpression - MultiplicativeExpression
+
+ShiftExpression:
+ AdditiveExpression
+ ShiftExpression << AdditiveExpression
+ ShiftExpression >> AdditiveExpression
+ ShiftExpression >>> AdditiveExpression
+
+RelationalExpression:
+ ShiftExpression
+ RelationalExpression < ShiftExpression
+ RelationalExpression > ShiftExpression
+ RelationalExpression <= ShiftExpression
+ RelationalExpression >= ShiftExpression
+ RelationalExpression instanceof ReferenceType
+
+EqualityExpression:
+ RelationalExpression
+ EqualityExpression == RelationalExpression
+ EqualityExpression != RelationalExpression
+
+AndExpression:
+ EqualityExpression
+ AndExpression & EqualityExpression
+
+ExclusiveOrExpression:
+ AndExpression
+ ExclusiveOrExpression ^ AndExpression
+
+InclusiveOrExpression:
+ ExclusiveOrExpression
+ InclusiveOrExpression | ExclusiveOrExpression
+
+ConditionalAndExpression:
+ InclusiveOrExpression
+ ConditionalAndExpression && InclusiveOrExpression
+
+ConditionalOrExpression:
+ ConditionalAndExpression
+ ConditionalOrExpression || ConditionalAndExpression
+
+ConditionalExpression:
+ ConditionalOrExpression
+ ConditionalOrExpression ? Expression : ConditionalExpression
+ ConditionalOrExpression ? Expression : LambdaExpression
+
+AssignmentExpression:
+ ConditionalExpression
+ Assignment
+
+Assignment:
+ LeftHandSide AssignmentOperator Expression
+
+LeftHandSide:
+ ExpressionName
+ FieldAccess
+ ArrayAccess
+
+AssignmentOperator:
+ =
+ *=
+ /=
+ %=
+ +=
+ -=
+ <<=
+ >>=
+ >>>=
+ &=
+ ^=
+ |=
+
+LambdaExpression:
+ LambdaParameters -> LambdaBody
+
+LambdaParameters:
+ Identifier
+ ( [FormalParameterList] )
+ ( InferredFormalParameterList )
+
+InferredFormalParameterList:
+ Identifier {, Identifier}
+
+LambdaBody:
+ Expression
+ Block
+
+ConstantExpression:
+ Expression
diff --git a/meson.build b/meson.build
index a8f4b97..aef17c8 100644
--- a/meson.build
+++ b/meson.build
@@ -261,6 +261,36 @@ gen_tokens = executable(
],
)
+gen_syntax = executable(
+ 'gen_syntax',
+ sources: [
+ 'src/gen_syntax.cc',
+ ],
+ include_directories: inc,
+ install : false,
+ dependencies : [
+ args_dep,
+ grammar_dep,
+ prefix_tree_dep,
+ src_dep,
+ ],
+)
+
+gen_ast = executable(
+ 'gen_ast',
+ sources: [
+ 'src/gen_ast.cc',
+ ],
+ include_directories: inc,
+ install : false,
+ dependencies : [
+ args_dep,
+ grammar_dep,
+ src_dep,
+ ],
+)
+
+# Remember to update gen-ast to latest
java_versions = [
'java-8',
'java-21',
@@ -271,7 +301,14 @@ java_unicode_versions = {
'java-21': '15.0.0',
}
+java_ast_sources = custom_target(
+ 'gen-ast',
+ input: ['data/java-21/syntax.grammar'],
+ output: ['java_ast.hh', 'java_ast.cc'],
+ command : [gen_ast, '@INPUT@', '@OUTPUT@'])
+
java_tokens_sources = []
+java_syntax_sources = []
foreach java_version : java_versions
java_unicode_version = 'u' + java_unicode_versions[java_version].replace('.', '_')
java_tokens_sources += custom_target(
@@ -283,6 +320,14 @@ foreach java_version : java_versions
java_version.replace('.', '_').replace('-', '_'),
'--unicode', java_unicode_version,
'@INPUT@', '@OUTPUT@'])
+ java_syntax_sources += custom_target(
+ 'gen-syntax-' + java_version,
+ input: ['data/' + java_version + '/syntax.grammar'],
+ output: ['java_syntax_' + java_version + '.hh',
+ 'java_syntax_' + java_version + '.cc'],
+ command : [gen_syntax, '--namespace',
+ java_version.replace('.', '_').replace('-', '_'),
+ '@INPUT@', '@OUTPUT@'])
endforeach
java_lib = library(
@@ -292,6 +337,8 @@ java_lib = library(
'src/java_tokens.cc',
'src/java_version.hh',
java_tokens_sources,
+ java_ast_sources,
+ java_syntax_sources,
],
include_directories: inc,
dependencies: [
diff --git a/src/gen_ast.cc b/src/gen_ast.cc
new file mode 100644
index 0000000..e170d55
--- /dev/null
+++ b/src/gen_ast.cc
@@ -0,0 +1,545 @@
+#include "args.hh"
+#include "errors.hh"
+#include "grammar.hh"
+#include "io.hh"
+#include "prefix_tree.hh"
+
+#include <algorithm>
+#include <cassert>
+#include <charconv>
+#include <cstddef>
+#include <cstdint>
+#include <fstream>
+#include <functional>
+#include <iostream>
+#include <map>
+#include <set>
+#include <string>
+#include <string_view>
+#include <utility>
+#include <vector>
+
+#include <iostream>
+
+namespace {
+
+enum class CharacterClass : uint8_t {
+ kIdentifier = 0,
+ kLiteral = 1,
+};
+
+std::vector<std::string> const kCharacterClassNames(
+ {"Identifier", "Literal"});
+
+std::string make_define(std::string_view filename) {
+ std::string ret;
+ ret.reserve(filename.size());
+ for (char c : filename) {
+ if ((c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_') {
+ ret.push_back(c);
+ } else if (c >= 'a' && c <= 'z') {
+ ret.push_back(static_cast<char>(c & ~0x20));
+ } else {
+ ret.push_back('_');
+ }
+ }
+ return ret;
+}
+
+std::string field_name(std::string_view name) {
+ std::string ret;
+ ret.reserve(name.size());
+ for (char c : name) {
+ if (c >= 'A' && c <= 'Z') {
+ if (!ret.empty()) {
+ ret.push_back('_');
+ }
+ ret.push_back(c | 0x20);
+ } else {
+ ret.push_back(c);
+ }
+ }
+ return ret;
+}
+
+grammar::Symbol::Optional merge(grammar::Symbol::Optional parent, grammar::Symbol::Optional child) {
+ switch (parent) {
+ case grammar::Symbol::Optional::kRequired:
+ break;
+ case grammar::Symbol::Optional::kZeroOrOne:
+ if (child == grammar::Symbol::Optional::kRequired) return parent;
+ break;
+ case grammar::Symbol::Optional::kZeroOrMore:
+ case grammar::Symbol::Optional::kExcluded:
+ return parent;
+ }
+ return child;
+}
+
+void visit_named_symbols(
+ grammar::Definition const& definition,
+ grammar::Symbol::Optional optional,
+ std::function<void(grammar::Symbol const& symbol,
+ grammar::Symbol::Optional optional)> visitor) {
+ for (auto const& symbol : definition.symbols) {
+ switch (symbol.type) {
+ case grammar::Symbol::Type::kNonTerminal:
+ if (symbol.element->name.empty()) {
+ for (auto const& element_definition : symbol.element->definitions) {
+ visit_named_symbols(element_definition, merge(optional, symbol.optional), visitor);
+ }
+ } else {
+ visitor(symbol, merge(optional, symbol.optional));
+ }
+ break;
+ case grammar::Symbol::Type::kTerminal:
+ case grammar::Symbol::Type::kCharacterClass:
+ visitor(symbol, merge(optional, symbol.optional));
+ break;
+ }
+ }
+}
+
+void visit_named_symbols(
+ grammar::Definition const& definition,
+ std::function<void(grammar::Symbol const& symbol,
+ grammar::Symbol::Optional optional)> visitor) {
+ visit_named_symbols(definition, grammar::Symbol::Optional::kRequired, std::move(visitor));
+}
+
+enum class NodeChildType : uint8_t {
+ kElement,
+ kIdentifier,
+};
+
+enum class Optional : uint8_t {
+ kRequired = 0,
+ kZeroOrOne,
+ kZeroOrMore,
+};
+
+struct NodeChild {
+ NodeChildType child_type;
+ std::string name;
+ std::string type_name;
+ Optional optional;
+
+ NodeChild(NodeChildType child_type, std::string name, std::string type_name, Optional optional)
+ : child_type(child_type), name(std::move(name)), type_name(std::move(type_name)),
+ optional(optional) {}
+};
+
+struct Node {
+ std::vector<NodeChild> children;
+};
+
+class Generator {
+ public:
+ bool generate(std::string_view header_name, std::string_view source_name,
+ grammar::Grammar& grammar);
+
+ private:
+ void declare_nodes(std::ostream& out);
+ void declare_node_types(std::ostream& out);
+ void implement_nodes(std::ostream& out);
+ void find_nodes(grammar::Element const& element);
+
+ std::map<std::string_view, Node> nodes_;
+};
+
+bool Generator::generate(std::string_view header_name,
+ std::string_view source_name,
+ grammar::Grammar& grammar) {
+ std::fstream header{std::string(header_name),
+ std::fstream::trunc | std::fstream::out};
+ std::fstream source{std::string(source_name),
+ std::fstream::trunc | std::fstream::out};
+
+ find_nodes(grammar.root());
+
+ auto header_guard = make_define(header_name);
+
+ header << "#ifndef " << header_guard << "\n"
+ << "#define " << header_guard << "\n"
+ << "\n"
+ << "#include <cstdint>\n"
+ << "#include <memory>\n"
+ << "#include <optional>\n"
+ << "#include <string_view>\n"
+ << "#include <vector>\n"
+ << "\n"
+ << "namespace java {\n"
+ << "namespace ast {\n"
+ << "\n"
+ << "class Node {\n"
+ << " public:\n"
+ << " virtual ~Node() = default;\n"
+ << " Node(Node const&) = delete;\n"
+ << " Node& operator=(Node const&) = delete;\n"
+ << "\n"
+ << " enum class Type : uint16_t {\n"
+ << " kIdentifier,\n";
+
+ declare_node_types(header);
+
+ header << " };\n"
+ << "\n"
+ << " Type const type;\n"
+ << "\n"
+ << " virtual std::vector<std::unique_ptr<Node>> const& children() const;\n"
+ << "\n"
+ << " protected:\n"
+ << " Node(Type type, std::vector<std::unique_ptr<Node>> children);\n"
+ << " std::vector<std::unique_ptr<Node>> children_;\n"
+ << "};\n"
+ << "\n"
+ << "class Identifier : public Node {\n"
+ << " public:\n"
+ << " explicit Identifier(std::string_view value);\n"
+ << "\n"
+ << " std::string_view value;\n"
+ << "};\n"
+ << "\n";
+
+ declare_nodes(header);
+
+ header << "\n"
+ << "} // namespace ast\n"
+ << "} // namespace java\n"
+ << "\n"
+ << "#endif // " << header_guard << "\n";
+
+ source << "#include \"" << header_name << "\"\n"
+ << "\n"
+ << "#include <utility>\n"
+ << "\n"
+ << "namespace java {\n"
+ << "namespace ast {\n"
+ << "\n"
+ << "Node::Node(Type type, std::vector<std::unique_ptr<Node>> children)\n"
+ << " : type(type), children_(std::move(children)) {}\n"
+ << "std::vector<std::unique_ptr<Node>> const& Node::children() const {\n"
+ << " return children_;\n"
+ << "}\n"
+ << "\n"
+ << "Identifier::Identifier(std::string_view value)\n"
+ << " : Node(Type::kIdentifier, {}), value(value) {}\n"
+ << "\n";
+
+ implement_nodes(source);
+
+ source << "\n"
+ << "} // namespace ast\n"
+ << "} // namespace java\n";
+
+ return true;
+}
+
+void Generator::find_nodes(grammar::Element const& element) {
+ if (element.name.empty()) {
+ for (auto const& definition : element.definitions) {
+ for (auto const& symbol : definition.symbols) {
+ switch (symbol.type) {
+ case grammar::Symbol::Type::kNonTerminal:
+ find_nodes(*symbol.element);
+ break;
+ case grammar::Symbol::Type::kTerminal:
+ case grammar::Symbol::Type::kCharacterClass:
+ break;
+ }
+ }
+ }
+ return;
+ }
+
+ auto insert_pair = nodes_.emplace(element.name, Node());
+ if (!insert_pair.second) {
+ // Already queued
+ return;
+ }
+
+ std::map<std::string, grammar::Element const*, std::less<>> elements;
+ std::map<std::string, uint8_t, std::less<>> lines;
+ std::map<std::string, Optional, std::less<>> optional;
+
+ for (auto const& definition : element.definitions) {
+ size_t identifiers = 0;
+ visit_named_symbols(
+ definition,
+ [&elements, &lines, &optional, &identifiers](auto const& symbol, auto symbol_optional) {
+ std::string name;
+ grammar::Element const* element;
+
+ switch (symbol.type) {
+ case grammar::Symbol::Type::kNonTerminal:
+ element = symbol.element;
+ name = element->name;
+ break;
+ case grammar::Symbol::Type::kTerminal:
+ return;
+ case grammar::Symbol::Type::kCharacterClass:
+ if (symbol.char_class == static_cast<uint8_t>(CharacterClass::kIdentifier)) {
+ name = "identifier";
+ if (identifiers > 0) {
+ char tmp[20];
+ auto ret = std::to_chars(tmp, tmp + sizeof(tmp), identifiers);
+ name.append({tmp, static_cast<std::string::size_type>(ret.ptr - tmp)});
+ }
+ identifiers++;
+ element = nullptr;
+ } else {
+ return;
+ }
+ break;
+ }
+
+ switch (symbol_optional) {
+ case grammar::Symbol::Optional::kRequired:
+ break;
+ case grammar::Symbol::Optional::kZeroOrOne:
+ if (optional[name] == Optional::kRequired) {
+ optional[name] = Optional::kZeroOrOne;
+ }
+ break;
+ case grammar::Symbol::Optional::kZeroOrMore:
+ optional[name] = Optional::kZeroOrMore;
+ break;
+ case grammar::Symbol::Optional::kExcluded:
+ // Don't include in elements
+ return;
+ }
+ elements[name] = element;
+ lines[name]++;
+ });
+ }
+
+ for (auto const& pair : elements) {
+ auto& node = insert_pair.first->second;
+
+ auto child_optional = optional[pair.first];
+ if (child_optional == Optional::kRequired && lines[pair.first] < element.definitions.size()) {
+ child_optional = Optional::kZeroOrOne;
+ }
+
+ if (pair.second) {
+ node.children.emplace_back(
+ NodeChildType::kElement,
+ field_name(pair.first),
+ std::string(pair.first),
+ child_optional);
+
+ find_nodes(*pair.second);
+ } else {
+ node.children.emplace_back(
+ NodeChildType::kIdentifier,
+ pair.first,
+ "std::string_view",
+ child_optional);
+ }
+ }
+}
+
+void Generator::declare_nodes(std::ostream& out) {
+ std::set<std::string_view, std::less<>> declared;
+
+ for (auto const& pair : nodes_) {
+ declared.insert(pair.first);
+
+ out << "class " << pair.first << " : public Node {\n"
+ << " public:\n"
+ << " " << pair.first << "(" << pair.first << "&&);\n";
+
+ for (size_t i = 0; i < pair.second.children.size(); ++i) {
+ auto const& child = pair.second.children[i];
+
+ switch (child.child_type) {
+ case NodeChildType::kElement: {
+ std::string type_name = child.type_name;
+ if (!declared.contains(type_name)) {
+ type_name = "class " + type_name;
+ }
+ switch (child.optional) {
+ case Optional::kRequired:
+ out << " " << type_name << "& " << child.name << "() const;\n";
+ out << " void set_" << child.name << "("
+ << type_name << "&& " << child.name << ");\n";
+ break;
+ case Optional::kZeroOrOne:
+ out << " " << type_name << "* " << child.name << "() const;\n";
+ out << " void set_" << child.name
+ << "(std::unique_ptr<" << type_name << "> " << child.name << ");\n";
+ break;
+ case Optional::kZeroOrMore:
+ out << " std::vector<" << type_name << "&> " << child.name << "() const;\n";
+ break;
+ }
+ break;
+ }
+ case NodeChildType::kIdentifier:
+ switch (child.optional) {
+ case Optional::kRequired:
+ out << " std::string_view " << child.name << "() const {\n"
+ << " return static_cast<Identifier*>("
+ << "children_[" << i << "].get())->value;\n"
+ << " };\n";
+
+ out << " void set_" << child.name << "(std::string_view " << child.name << ");\n";
+ break;
+ case Optional::kZeroOrOne:
+ out << " std::optional<std::string_view> " << child.name << "() const {\n"
+ << " auto* ptr = static_cast<Identifier*>("
+ << "children_[" << i << "].get());\n"
+ << " if (ptr) return ptr->value;\n"
+ << " return std::nullopt;\n"
+ << " };\n";
+
+ out << " void set_" << child.name
+ << "(std::optional<std::string_view> " << child.name << ");\n";
+ break;
+ case Optional::kZeroOrMore:
+ out << " std::vector<std::string_view> " << child.name << "() const;\n";
+ break;
+ }
+ }
+ }
+ out << "};\n"
+ << "\n";
+ }
+
+ for (auto const& pair : nodes_) {
+ for (size_t i = 0; i < pair.second.children.size(); ++i) {
+ auto const& child = pair.second.children[i];
+
+ switch (child.child_type) {
+ case NodeChildType::kElement:
+ switch (child.optional) {
+ case Optional::kRequired:
+ out << "inline " << child.type_name << "& "
+ << pair.first << "::" << child.name << "() const {\n"
+ << " return *static_cast<" << child.type_name << "*>("
+ << "children_[" << i << "].get());\n"
+ << "}\n"
+ << "\n";
+ break;
+ case Optional::kZeroOrOne:
+ out << "inline " << child.type_name << "* "
+ << pair.first << "::" << child.name << "() const {\n"
+ << " return static_cast<" << child.type_name << "*>("
+ << "children_[" << i << "].get());\n"
+ << "}\n"
+ << "\n";
+ break;
+ case Optional::kZeroOrMore:
+ break;
+ }
+ break;
+ case NodeChildType::kIdentifier:
+ break;
+ }
+ }
+ }
+}
+
+void Generator::declare_node_types(std::ostream& out) {
+ for (auto const& pair : nodes_) {
+ out << " k" << pair.first << ",\n";
+ }
+}
+
+void Generator::implement_nodes(std::ostream& out) {
+ for (auto const& pair : nodes_) {
+ for (size_t i = 0; i < pair.second.children.size(); ++i) {
+ auto const& child = pair.second.children[i];
+
+ switch (child.child_type) {
+ case NodeChildType::kElement: {
+ switch (child.optional) {
+ case Optional::kRequired:
+ out << "void " << pair.first << "::set_" << child.name << "("
+ << child.type_name << "&& " << child.name << ") {\n"
+ << " children_[" << i << "] = std::make_unique<"
+ << child.type_name << ">(std::move(" << child.name << "));\n"
+ << "}\n";
+ break;
+ case Optional::kZeroOrOne:
+ out << "void " << pair.first << "::set_" << child.name
+ << "(std::unique_ptr<" << child.type_name << "> " << child.name << ") {\n"
+ << " children_[" << i << "] = std::move(" << child.name << ");\n"
+ << "}\n";
+ break;
+ case Optional::kZeroOrMore:
+ break;
+ }
+ break;
+ }
+ case NodeChildType::kIdentifier:
+ switch (child.optional) {
+ case Optional::kRequired:
+ out << "void " << pair.first << "::set_" << child.name
+ << "(std::string_view " << child.name << ") {\n"
+ << " children_[" << i << "] = std::make_unique<Identifier>("
+ << child.name << ");\n"
+ << "}\n";
+ break;
+ case Optional::kZeroOrOne:
+ out << "void " << pair.first << "::set_" << child.name
+ << "(std::optional<std::string_view> " << child.name << ") {\n"
+ << " if (" << child.name << ".has_value()) {\n"
+ << " children_[" << i << "] = std::make_unique<Identifier>(*"
+ << child.name << ");\n"
+ << " } else {\n"
+ << " children_[" << i << "].reset();\n"
+ << " }\n"
+ << "}\n";
+ break;
+ case Optional::kZeroOrMore:
+ break;
+ }
+ }
+ }
+ out << "\n";
+ }
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ auto args = Args::create();
+ auto opt_help = args->option('h', "help", "display this text and exit");
+ std::vector<std::string_view> arguments;
+ if (!args->run(argc, argv, &arguments)) {
+ args->print_error(std::cerr);
+ std::cerr << "Try `gen_ast --help` for usage\n";
+ return 1;
+ }
+ if (opt_help->is_set()) {
+ std::cout << "Usage: `gen_ast [OPTIONS...] syntax.grammar"
+ << " OUTPUT.hh OUTPUT.cc`\n"
+ << "Generates an AST for grammar.\n"
+ << "\n";
+ args->print_help(std::cout);
+ return 0;
+ }
+ if (arguments.size() != 3) {
+ std::cerr << "Expecting three arguments. No more, no less.\n"
+ << "Try `gen_ast --help` for usage\n";
+ return 1;
+ }
+
+ auto filename = std::string(arguments[0]);
+ auto reader = io::open(filename);
+ if (!reader.has_value()) {
+ std::cerr << "Unable to open " << filename << '\n';
+ return 1;
+ }
+ auto errors = src::file_errors(std::move(filename));
+ auto grammar =
+ grammar::load(std::move(reader.value()), kCharacterClassNames, *errors);
+ if (!grammar || errors->errors() > 0)
+ return 1;
+
+ Generator generator;
+ if (!generator.generate(arguments[1], arguments[2], *grammar))
+ return 1;
+ return 0;
+}
diff --git a/src/gen_syntax.cc b/src/gen_syntax.cc
new file mode 100644
index 0000000..f455eb7
--- /dev/null
+++ b/src/gen_syntax.cc
@@ -0,0 +1,136 @@
+#include "args.hh"
+#include "errors.hh"
+#include "grammar.hh"
+#include "io.hh"
+#include "prefix_tree.hh"
+
+#include <algorithm>
+#include <cassert>
+#include <charconv>
+#include <cstddef>
+#include <cstdint>
+#include <fstream>
+#include <iostream>
+#include <set>
+#include <string>
+#include <string_view>
+#include <utility>
+#include <vector>
+
+#include <iostream>
+
+namespace {
+
+enum class CharacterClass : uint8_t {
+ kIdentifier = 0,
+ kLiteral = 1,
+};
+
+std::vector<std::string> const kCharacterClassNames(
+ {"Identifier", "Literal"});
+
+std::string make_define(std::string_view filename) {
+ std::string ret;
+ ret.reserve(filename.size());
+ for (char c : filename) {
+ if ((c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_') {
+ ret.push_back(c);
+ } else if (c >= 'a' && c <= 'z') {
+ ret.push_back(static_cast<char>(c & ~0x20));
+ } else {
+ ret.push_back('_');
+ }
+ }
+ return ret;
+}
+
+class Generator {
+ public:
+ bool generate(std::string_view header_name, std::string_view source_name,
+ std::string const& ns, grammar::Grammar& grammar);
+};
+
+bool Generator::generate(std::string_view header_name,
+ std::string_view source_name, std::string const& ns,
+ grammar::Grammar& grammar) {
+ std::fstream header{std::string(header_name),
+ std::fstream::trunc | std::fstream::out};
+ std::fstream source{std::string(source_name),
+ std::fstream::trunc | std::fstream::out};
+
+ auto header_guard = make_define(header_name);
+
+ header << "#ifndef " << header_guard << "\n"
+ << "#define " << header_guard << "\n"
+ << "\n"
+ << "namespace " << ns << " {\n"
+ << "\n";
+
+
+ header << "\n"
+ << "} // namespace " << ns << "\n"
+ << "\n"
+ << "#endif // " << header_guard << "\n";
+
+ source << "#include \"" << header_name << "\"\n"
+ << "\n"
+ << "namespace " << ns << " {\n"
+ << "\n";
+
+
+ source << "\n"
+ << "} // namespace " << ns << "\n";
+
+ return true;
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ auto args = Args::create();
+ auto opt_help = args->option('h', "help", "display this text and exit");
+ auto opt_ns = args->option_argument('\0', "namespace", "ARG",
+ "Namespace for syntax reader");
+ std::vector<std::string_view> arguments;
+ if (!args->run(argc, argv, &arguments)) {
+ args->print_error(std::cerr);
+ std::cerr << "Try `gen_syntax --help` for usage\n";
+ return 1;
+ }
+ if (opt_help->is_set()) {
+ std::cout << "Usage: `gen_syntax [OPTIONS...] syntax.grammar"
+ << " OUTPUT.hh OUTPUT.cc`\n"
+ << "Generates a syntax reader for grammar.\n"
+ << "\n";
+ args->print_help(std::cout);
+ return 0;
+ }
+ if (!opt_ns->is_set()) {
+ std::cerr << "No namespace given.\n"
+ << "Try `gen_syntax --help` for usage\n";
+ return 1;
+ }
+ auto ns = opt_ns->argument();
+ if (arguments.size() != 3) {
+ std::cerr << "Expecting three arguments. No more, no less.\n"
+ << "Try `gen_syntax --help` for usage\n";
+ return 1;
+ }
+
+ auto filename = std::string(arguments[0]);
+ auto reader = io::open(filename);
+ if (!reader.has_value()) {
+ std::cerr << "Unable to open " << filename << '\n';
+ return 1;
+ }
+ auto errors = src::file_errors(std::move(filename));
+ auto grammar =
+ grammar::load(std::move(reader.value()), kCharacterClassNames, *errors);
+ if (!grammar || errors->errors() > 0)
+ return 1;
+
+ Generator generator;
+ if (!generator.generate(arguments[1], arguments[2], ns, *grammar))
+ return 1;
+ return 0;
+}