diff options
| -rw-r--r-- | data/java-21/syntax.grammar | 963 | ||||
| -rw-r--r-- | data/java-8/syntax.grammar | 845 | ||||
| -rw-r--r-- | meson.build | 47 | ||||
| -rw-r--r-- | src/gen_ast.cc | 545 | ||||
| -rw-r--r-- | src/gen_syntax.cc | 136 |
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; +} |
