%{ #include #include #include "parser.h" using namespace std; #define yyerror(msg) errFunc(msg, &yylloc) int yylex(YYSTYPE *, YYLTYPE *); extern FILE * yyin; void errFunc(const char * str, YYLTYPE * yyllocp); int yywrap() { return 1; } static YYSTYPE parse_result; %} %pure-parser %locations %error-verbose /* operators */ %token ASSIGN; %token DASSIGN; %token DEQUALS; %token DIVIDE; %token EQUALS; %token GREATER; %token LESS; %token MATCH; %token MINUS; %token MOD; %token PLUS; %token STAR; /* punctuation */ %token COLON; %token COMMA; %token DCOLON; %token DOLLAR; %token DOT; %token FROM; %token QUESTION; %token SEMICOLON; %token LCURLY; %token RCURLY; %token LBRACKET; %token RBRACKET; %token LPAREN; %token RPAREN; /* literals */ %token INT_LITERAL; %token REAL_LITERAL; %token STRING_LITERAL; /* primitive types */ %token BOOL; %token BYTE; %token UBYTE; %token CHAR; %token WCHAR; %token SHORT; %token USHORT; %token INT; %token UINT; %token LONG; %token ULONG; %token FLOAT; %token DOUBLE; /* keywords */ %token C; %token FALSE; %token IMPORT; %token MODULE; %token RETURN; %token STRUCT; %token TRUE; /* identifiers */ %token IDENTIFIER; %% program: program_items { $$ = new ProgramNode(); $$->addChildren($1); parse_result = $$; } ; program_items: /* empty */ { $$ = new ItemsNode(); } | program_item program_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; program_item: function { $$ = $1; } | c_statement { $$ = $1; } ; import: IMPORT import_name SEMICOLON ; import_name: IDENTIFIER import_name_more ; import_name_more: /* empty */ | DOT import_name_more_more ; import_name_more_more: IDENTIFIER import_name_more | STAR ; function: IDENTIFIER LPAREN parameter_list RPAREN COLON type LCURLY function_items RCURLY { $$ = new FunctionNode(); $$->addChild($1); $$->addChild($3); $$->addChild($6); $$->addChildren($8); } ; function_items: /* empty */ { $$ = new ItemsNode(); } | statement function_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; parameter_list: /* empty */ { $$ = new ItemsNode(); } | variable_spec parameter_list_more { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; parameter_list_more: /* empty */ { $$ = new ItemsNode(); } | COMMA variable_spec parameter_list_more { $$ = new ItemsNode(); $$->addChild($2); $$->addChildren($3); } ; primitive_type: BYTE { $$ = new PrimitiveTypeNode(BYTE); } | UBYTE { $$ = new PrimitiveTypeNode(UBYTE); } | CHAR { $$ = new PrimitiveTypeNode(CHAR); } | WCHAR { $$ = new PrimitiveTypeNode(WCHAR); } | SHORT { $$ = new PrimitiveTypeNode(SHORT); } | USHORT { $$ = new PrimitiveTypeNode(USHORT); } | INT { $$ = new PrimitiveTypeNode(INT); } | UINT { $$ = new PrimitiveTypeNode(UINT); } | LONG { $$ = new PrimitiveTypeNode(LONG); } | ULONG { $$ = new PrimitiveTypeNode(ULONG); } ; struct_type: STRUCT LCURLY struct_items RCURLY { $$ = new StructTypeNode(); $$->addChildren($3); } ; struct_items: /* empty */ { $$ = new ItemsNode(); } | struct_item struct_items { $$ = new ItemsNode(); $$->addChild($1); $$->addChildren($2); } ; struct_item: variable_declaration { $$ = $1; } ; variable_declaration: variable_spec SEMICOLON { $$ = $1; } ; variable_spec: IDENTIFIER COLON type { $$ = new VariableSpecNode(); $$->addChild($1); $$->addChild($3); } ; array_type: type LBRACKET RBRACKET { $$ = new ArrayTypeNode(); $$->addChild($1); } ; type: primitive_type { $$ = $1; } | struct_type { $$ = $1; } | array_type { $$ = $1; } | IDENTIFIER { $$ = $1; } ; statement: expression SEMICOLON { $$ = $1; } | return_statement { $$ = $1; } | c_statement { $$ = $1; } ; return_statement: RETURN expression SEMICOLON { $$ = new ReturnStatementNode(); $$->addChild($2); } ; expression: assign_expr { $$ = new ExpressionNode(); $$->addChild($1); } | literal { $$ = new ExpressionNode(); $$->addChild($1); } ; assign_expr: lvalue ASSIGN expression { $$ = new AssignExprNode(); $$->addChild($1); $$->addChild($3); } ; literal: INT_LITERAL { $$ = $1; } | REAL_LITERAL { $$ = $1; } | STRING_LITERAL { $$ = $1; } ; lvalue: IDENTIFIER { $$ = new LValueNode(); $$->addChild($1); } ; c_statement: C LPAREN STRING_LITERAL RPAREN SEMICOLON { $$ = new CStatementNode($3->getString()); } ; %% YYSTYPE parse(const char * fileName) { yyin = fopen(fileName, "r"); if (yyin == NULL) { cerr << "Failed to open file '" << fileName << "'" << endl; } else if (yyparse()) { cerr << "Aborting." << endl; exit(1); } return parse_result; } void errFunc(const char * str, YYLTYPE * yyllocp) { fprintf(stderr, "error: %s: line %d, column %d\n", str, yyllocp->first_line, yyllocp->first_column); }