%code requires { #include "../src/ast.h" } %{ #include #include "../src/ast.h" void yyerror(FILE *fp, Node **pRootNode, char *s) { fprintf (stderr, "%s\n", s); } extern char *yytext; extern int yylex (void); extern FILE *yyin; %} %define api.value.type {struct Node*} %token VOID %token INT %token UINT %token FLOAT %token DOUBLE %token STRING %token BOOL %token STRUCT %token INTERFACE %token RETURN %token STATIC %token REFERENCE %token ALLOC %token IF %token ELSE %token IN %token FOR %token NUMBER %token ID %token STRING_LITERAL %token PLUS %token MINUS %token STAR %token SLASH %token PERCENT %token EQUAL %token LESS_THAN %token GREATER_THAN %token QUOTE %token BANG %token BAR %token AMPERSAND %token POINT %token COMMA %token SEMICOLON %token COLON %token QUESTION %token LEFT_PAREN %token RIGHT_PAREN %token LEFT_BRACE %token RIGHT_BRACE %token LEFT_BRACKET %token RIGHT_BRACKET %token COMMENT %token NEWLINE %parse-param { FILE* fp } { Node **pRootNode } %define parse.error verbose %left GREATER_THAN LESS_THAN EQUAL %left PLUS MINUS %left STAR PERCENT %left BANG BAR %left LEFT_PAREN RIGHT_PAREN %% Program : TopLevelDeclarations { *pRootNode = $1; } BaseType : VOID { $$ = MakePrimitiveTypeNode(Void); } | INT { $$ = MakePrimitiveTypeNode(Int); } | UINT { $$ = MakePrimitiveTypeNode(UInt); } | FLOAT { $$ = MakePrimitiveTypeNode(Float); } | DOUBLE { $$ = MakePrimitiveTypeNode(Double); } | STRING { $$ = MakePrimitiveTypeNode(String); } | BOOL { $$ = MakePrimitiveTypeNode(Bool); } | Identifier { $$ = MakeCustomTypeNode(yytext); } | REFERENCE LESS_THAN Type GREATER_THAN { $$ = MakeReferenceTypeNode($3); } ; Type : BaseType { $$ = MakeTypeNode($1); } Identifier : ID { $$ = MakeIdentifierNode(yytext); } HeapAllocation : ALLOC Type { $$ = MakeAllocNode($2); } AccessExpression : Identifier POINT AccessExpression { $$ = MakeAccessExpressionNode($1, $3); } | Identifier { $$ = $1; } Number : NUMBER { $$ = MakeNumberNode(yytext); } PrimaryExpression : Number | STRING_LITERAL { $$ = MakeStringNode(yytext); } | LEFT_PAREN Expression RIGHT_PAREN { $$ = $2; } | FunctionCallExpression | AccessExpression ; UnaryExpression : BANG Expression { $$ = MakeUnaryNode(Negate, $2); } BinaryExpression : Expression PLUS Expression { $$ = MakeBinaryNode(Add, $1, $3); } | Expression MINUS Expression { $$ = MakeBinaryNode(Subtract, $1, $3); } | Expression STAR Expression { $$ = MakeBinaryNode(Multiply, $1, $3); } | Expression PERCENT Expression { $$ = MakeBinaryNode(Mod, $1, $3); } | Expression LESS_THAN Expression { $$ = MakeBinaryNode(LessThan, $1, $3); } | Expression GREATER_THAN Expression { $$ = MakeBinaryNode(GreaterThan, $1, $3); } | Expression EQUAL EQUAL Expression { $$ = MakeBinaryNode(Equal, $1, $4); } | Expression BAR BAR Expression { $$ = MakeBinaryNode(LogicalOr, $1, $4); } Expression : BinaryExpression | UnaryExpression | PrimaryExpression | HeapAllocation ; VariableDeclaration : Identifier COLON Type { $$ = MakeDeclarationNode($3, $1); } AssignmentStatement : VariableDeclaration EQUAL Expression { $$ = MakeAssignmentNode($1, $3); } | AccessExpression EQUAL Expression { $$ = MakeAssignmentNode($1, $3); } | Identifier EQUAL Expression { $$ = MakeAssignmentNode($1, $3); } ReturnStatement : RETURN Expression { $$ = MakeReturnStatementNode($2); } | RETURN { $$ = MakeReturnVoidStatementNode(); } FunctionCallExpression : AccessExpression LEFT_PAREN Arguments RIGHT_PAREN { $$ = MakeFunctionCallExpressionNode($1, $3); } PartialStatement : FunctionCallExpression | AssignmentStatement | VariableDeclaration | ReturnStatement ; IfStatement : IF LEFT_PAREN Expression RIGHT_PAREN LEFT_BRACE Statements RIGHT_BRACE { $$ = MakeIfNode($3, $6); } Conditional : IfStatement | IfStatement ELSE LEFT_BRACE Statements RIGHT_BRACE { $$ = MakeIfElseNode($1, $4); } | IfStatement ELSE Conditional { $$ = MakeIfElseNode($1, $3); } ForStatement : FOR LEFT_PAREN VariableDeclaration IN LEFT_BRACKET Number POINT POINT Number RIGHT_BRACKET RIGHT_PAREN LEFT_BRACE Statements RIGHT_BRACE { $$ = MakeForLoopNode($3, $6, $9, $13); } Statement : PartialStatement SEMICOLON | Conditional | ForStatement ; Statements : Statement { $$ = StartStatementSequenceNode($1); } | Statements Statement { $$ = AddStatement($1, $2); } Arguments : PrimaryExpression { $$ = StartFunctionArgumentSequenceNode($1); } | Arguments COMMA PrimaryExpression { $$ = AddFunctionArgumentNode($1, $3); } | { $$ = MakeEmptyFunctionArgumentSequenceNode(); } SignatureArguments : VariableDeclaration { $$ = StartFunctionSignatureArgumentsNode($1); } | SignatureArguments COMMA VariableDeclaration { $$ = AddFunctionSignatureArgumentNode($1, $3); } | { $$ = MakeEmptyFunctionSignatureArgumentsNode(); } ; Body : LEFT_BRACE Statements RIGHT_BRACE { $$ = $2; } GenericConstraint : Identifier COLON Identifier { $$ = MakeGenericConstraintNode($1, $3); } GenericConstraints : GenericConstraint { $$ = StartGenericConstraintsNode($1); } | GenericConstraints COMMA GenericConstraint { $$ = AddGenericConstraint($1, $3); } ; GenericConstraintClause : LESS_THAN GenericConstraints GREATER_THAN { $$ = $2; } | { $$ = MakeEmptyGenericConstraintsNode(); } ; /* FIXME: modifiers should be recursive */ FunctionSignature : Identifier GenericConstraintClause LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type { $$ = MakeFunctionSignatureNode($1, $7, $4, MakeFunctionModifiersNode(NULL, 0), $2); } | STATIC Identifier LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type { Node *modifier = MakeStaticNode(); $$ = MakeFunctionSignatureNode($2, $7, $4, MakeFunctionModifiersNode(&modifier, 1), MakeEmptyGenericConstraintsNode()); } FunctionDeclaration : FunctionSignature Body { $$ = MakeFunctionDeclarationNode($1, $2); } StructDeclaration : STRUCT Identifier LEFT_BRACE Declarations RIGHT_BRACE { $$ = MakeStructDeclarationNode($2, $4); } InterfaceDeclaration : INTERFACE Identifier LEFT_BRACE InterfaceChildren RIGHT_BRACE { $$ = MakeInterfaceDeclarationNode($2, $4); } InterfaceChild : FunctionSignature SEMICOLON ; InterfaceChildren : InterfaceChild { $$ = StartDeclarationSequenceNode($1); } | InterfaceChildren InterfaceChild { $$ = AddDeclarationNode($1, $2); } ; Declaration : FunctionDeclaration | VariableDeclaration SEMICOLON ; Declarations : Declaration { $$ = StartDeclarationSequenceNode($1); } | Declarations Declaration { $$ = AddDeclarationNode($1, $2); } TopLevelDeclaration : StructDeclaration | InterfaceDeclaration ; TopLevelDeclarations : TopLevelDeclaration { $$ = StartDeclarationSequenceNode($1); } | TopLevelDeclarations TopLevelDeclaration { $$ = AddDeclarationNode($1, $2); } %%