/* Parser for GPL, by Bryce Schroeder Modified, 1 February, by Bryce Schroeder: added * / and floating point number support. This file contains the input to the bison compiler generator. bison will use this file to generate a C/C++ parser. The default output file for bison is: y.tab.c This grammar describes a simple expression language with: +,-,(,), and integers In other words, the parser generated when bison processes this file will evaluate any legal expression that contains the above symbols. For example, the following are all legal expressions: 5 5 + 5 5 - 5 5 + (6 - 3) (5) (42 - 42) (3) + (2) NOTE: this grammar does not handle binary -, so the following are NOT legal: 5 + -2 5 - -2 -2 */ %{ // bison syntax to indicate the start of the header // the header is copied directly into y.tab.c extern int yylex(); extern int yyerror(char *); extern int line_count; // from expr.l, used for statement blocks #include "error.h" // class for printing errors #include "gpl_assert.h" // function version of standard assert.h #include #include using namespace std; #include "gpl_type.h" #include "symbol_table.h" #include "expression.h" Symbol_table *st = Symbol_table::instance(); char buffer[80]; %} // bison syntax to indicate the end of the header // The union is used to declare the variable yylval which is used to // pass data between the flex generated lexer and the bison generated parser // A union is kind of like a structure or class, but only one field can be // used at a time. Each line describes one item in the union. The left hand // side is the type, the right hand side it out name for the type (the union_ // is used to indicate that this is a member of the union). // the "%union" is bison syntax %union { int union_int; string *union_string; // MUST be a pointer to a string (this sucks!) double union_double; char union_char; int union_type; Expression *union_expression; char union_math; } // each token in the language is defined here // if a token has a type associated with it, put that type (as named in the // union) inside of <> (such as T_INT_CONSTANT). %token T_LPAREN %token T_RPAREN %token T_LBRACE %token T_RBRACE %token T_LBRACKET %token T_RBRACKET %token T_PLUS %token T_ASTERISK %token T_MINUS %token T_MOD %token T_COMMA %token T_PERIOD %token T_SEMIC %token T_DIVIDE %token T_DIVIDE_ASSIGN %token T_PLUS_ASSIGN %token T_MINUS_ASSIGN %token T_MOD_ASSIGN %token T_ASTERISK_ASSIGN %token T_ASSIGN %token T_AND %token T_OR %token T_EQUAL %token T_LESS_EQUAL %token T_GREATER_EQUAL %token T_NOT_EQUAL %token T_GREATER %token T_LESS %token T_IF %token T_ELSE %token T_FOR %token T_FORWARD %token T_INITIALIZATION %token T_ANIMATION %token T_EXIT %token T_ID %token T_PRINT %token T_ON %token T_NOT %token T_TRUE %token T_FALSE %token T_TOUCHES %token T_NEAR %token T_SIN %token T_COS %token T_TAN %token T_ASIN %token T_ACOS %token T_ATAN %token T_SQRT %token T_ABS %token T_FLOOR %token T_RANDOM %token T_TYPE //%token T_INT //%token T_DOUBLE //%token T_STRING %token T_TRIANGLE %token T_PIXMAP %token T_CIRCLE %token T_RECTANGLE %token T_TEXTBOX %token T_LEFTARROW %token T_RIGHTARROW %token T_DOWNARROW %token T_UPARROW %token T_F1 %token T_SPACE %token T_STRING_CONSTANT %token T_DOUBLE_CONSTANT %token T_INT_CONSTANT // this token has a int value associated w/it %token T_ERROR // this token has a string value associated w/it %token T_KEY %type expression %type primary_expression %type math_operator %type variable %type optional_initializer // grammar symbols that have values associated with them need to be // declared here. The above union is used for the "ruturning" the value. // NOTE: values are not really returned as in function calls, but actions // associated with rules sort of look like functions and the values associated // with a bison symbol look like return values //%type expression // The following specifies that the operators T_PLUS and T_MINUS are // left associative, and have the same precedence. // // NOTE: you will have to add a "%left" line for each level of precedence // The lower precedence operators must be first %right T_ASSIGN T_ASTERISK_ASSIGN T_DIVIDE_ASSIGN T_PLUS_ASSIGN T_MINUS_ASSIGN %left T_OR %left T_AND %left T_EQUAL T_NOT_EQUAL T_GREATER T_LESS T_GREATER_EQUAL T_LESS_EQUAL %left T_PLUS T_MINUS %left T_ASTERISK T_DIVIDE T_MOD %left T_PERIOD %nonassoc IF_NO_ELSE %nonassoc T_ELSE %nonassoc UNARY_OPS %% // indicates the start of the rules //--------------------------------------------------------------------- program: declaration_list block_list { // cout << "expression = " << $1 << endl; } ; //--------------------------------------------------------------------- declaration_list: declaration_list declaration | empty ; declaration: variable_declaration T_SEMIC | object_declaration T_SEMIC | forward_declaration T_SEMIC ; variable_declaration: T_TYPE T_ID optional_initializer { string tmp = *$2 + "[0]"; if (st->has_symbol($2) || st->has_symbol(&tmp)) { Error::error(Error::PREVIOUSLY_DECLARED_VARIABLE, *$2); } if ($3 != NULL && $3->type() > $1) { Error::error(Error::INVALID_TYPE_FOR_INITIAL_VALUE, *$2); st->add_symbol($2, $1, NULL); } else { st->add_symbol($2, $1, $3); } } // tmp change: going to replace expression by int | T_TYPE T_ID T_LBRACKET expression T_RBRACKET { string tmp = *$2 + "[0]"; if (st->has_symbol($2) || st->has_symbol(&tmp)) { Error::error(Error::PREVIOUSLY_DECLARED_VARIABLE, *$2); } if ($4->type() != TYPE_INT || $4->as_int() < 1) { Error::error(Error::INVALID_ARRAY_SIZE, *$2, *$4->as_string()); $4 = new IntConstantExpr(1); } else { for (int i = 0; i < $4->as_int(); ++i) { sprintf(buffer, "%s[%d]", $2->c_str(), i); st->add_symbol(new string(buffer), $1, NULL); assert(i < 1000); } } } ; //--------------------------------------------------------------------- /*simple_type: T_INT { $$ = $1; } | T_DOUBLE { $$ = $1; } | T_STRING { $$ = $1; } ; */ //--------------------------------------------------------------------- optional_initializer: T_ASSIGN expression { $$ = $2; } | empty { $$ = NULL; } ; //--------------------------------------------------------------------- object_declaration: object_type T_ID T_LPAREN parameter_list_or_empty T_RPAREN | object_type T_ID T_LBRACKET expression T_RBRACKET ; //--------------------------------------------------------------------- object_type: T_TRIANGLE | T_PIXMAP | T_CIRCLE | T_RECTANGLE | T_TEXTBOX ; //--------------------------------------------------------------------- parameter_list_or_empty : parameter_list | empty ; //--------------------------------------------------------------------- parameter_list : parameter_list T_COMMA parameter | parameter ; //--------------------------------------------------------------------- parameter: T_ID T_ASSIGN expression ; //--------------------------------------------------------------------- forward_declaration: T_FORWARD T_ANIMATION T_ID T_LPAREN animation_parameter T_RPAREN ; //--------------------------------------------------------------------- block_list: block_list block | empty ; //--------------------------------------------------------------------- block: initialization_block | animation_block | on_block ; //--------------------------------------------------------------------- initialization_block: T_INITIALIZATION statement_block ; //--------------------------------------------------------------------- animation_block: T_ANIMATION T_ID T_LPAREN check_animation_parameter T_RPAREN T_LBRACE statement_list T_RBRACE end_of_statement_block ; //--------------------------------------------------------------------- animation_parameter: object_type T_ID ; //--------------------------------------------------------------------- check_animation_parameter: T_TRIANGLE T_ID | T_PIXMAP T_ID | T_CIRCLE T_ID | T_RECTANGLE T_ID | T_TEXTBOX T_ID ; //--------------------------------------------------------------------- on_block: T_ON keystroke statement_block ; //--------------------------------------------------------------------- keystroke: T_SPACE | T_LEFTARROW | T_RIGHTARROW | T_UPARROW | T_DOWNARROW | T_F1 | T_KEY ; //--------------------------------------------------------------------- if_block: statement_block_creator statement end_of_statement_block | statement_block ; //--------------------------------------------------------------------- statement_block: T_LBRACE statement_block_creator statement_list T_RBRACE end_of_statement_block ; //--------------------------------------------------------------------- statement_block_creator: // this goes to nothing so that you can put an action here ; //--------------------------------------------------------------------- end_of_statement_block: // this goes to nothing so that you can put an action here ; //--------------------------------------------------------------------- statement_list: statement_list statement | empty ; //--------------------------------------------------------------------- statement: if_statement | for_statement | assign_statement T_SEMIC | print_statement T_SEMIC | exit_statement T_SEMIC ; //--------------------------------------------------------------------- if_statement: T_IF T_LPAREN expression T_RPAREN if_block %prec IF_NO_ELSE | T_IF T_LPAREN expression T_RPAREN if_block T_ELSE if_block ; //--------------------------------------------------------------------- for_statement: T_FOR T_LPAREN statement_block_creator assign_statement end_of_statement_block T_SEMIC expression T_SEMIC statement_block_creator assign_statement end_of_statement_block T_RPAREN statement_block ; //--------------------------------------------------------------------- print_statement: T_PRINT T_LPAREN expression T_RPAREN ; //--------------------------------------------------------------------- exit_statement: T_EXIT T_LPAREN expression T_RPAREN ; //--------------------------------------------------------------------- assign_statement: variable T_ASSIGN expression | variable T_PLUS_ASSIGN expression | variable T_MINUS_ASSIGN expression | variable T_DIVIDE_ASSIGN expression | variable T_MOD_ASSIGN expression | variable T_ASTERISK_ASSIGN ; //--------------------------------------------------------------------- variable: T_ID { /*TID ATR IDX */ $$ = new VariableExpr($1, NULL, NULL); } | T_ID T_LBRACKET expression T_RBRACKET { $$ = new VariableExpr($1, NULL, $3); } | T_ID T_PERIOD T_ID { $$ = new VariableExpr($1, $3, NULL); } | T_ID T_LBRACKET expression T_RBRACKET T_PERIOD T_ID { $$ = new VariableExpr($1, $6, $3); } ; //--------------------------------------------------------------------- expression: primary_expression | expression T_OR expression { $$ = new BinaryExpr(OP_OR, $1, $3); } | expression T_AND expression { $$ = new BinaryExpr(OP_AND, $1, $3); } | expression T_LESS_EQUAL expression { $$ = new BinaryExpr(OP_LEQ, $1, $3); } | expression T_GREATER_EQUAL expression { $$ = new BinaryExpr(OP_GEQ, $1, $3); } | expression T_LESS expression { $$ = new BinaryExpr(OP_LE, $1, $3); } | expression T_GREATER expression { $$ = new BinaryExpr(OP_GR, $1, $3); } | expression T_EQUAL expression { $$ = new BinaryExpr(OP_EQU, $1, $3); } | expression T_NOT_EQUAL expression { $$ = new BinaryExpr(OP_NEQ, $1, $3); } | expression T_PLUS expression { $$ = new BinaryExpr(OP_ADD, $1, $3); } | expression T_MINUS expression { $$ = new BinaryExpr(OP_SUB, $1, $3); } | expression T_ASTERISK expression { $$ = new BinaryExpr(OP_MUL, $1, $3); } | expression T_DIVIDE expression { $$ = new BinaryExpr(OP_DIV, $1, $3); } | expression T_MOD expression { $$ = new BinaryExpr(OP_MOD, $1, $3); } | T_MINUS expression %prec UNARY_OPS { $$ = new UnaryExpr(OP_NEG, $2); } | T_NOT expression %prec UNARY_OPS { $$ = new UnaryExpr(OP_NOT, $2); } | math_operator T_LPAREN expression T_RPAREN { $$ = new MathExpr($1, $3); } | variable geometric_operator variable ; //--------------------------------------------------------------------- primary_expression: T_LPAREN expression T_RPAREN { $$ = $2; } | variable { $$ = $1; } | T_INT_CONSTANT { $$ = new IntConstantExpr($1); } | T_TRUE { $$ = new IntConstantExpr(1); } | T_FALSE { $$ = new IntConstantExpr(0); } | T_DOUBLE_CONSTANT { $$ = new FloatConstantExpr($1); } | T_STRING_CONSTANT { $$ = new StringConstantExpr($1); } ; //--------------------------------------------------------------------- geometric_operator: T_TOUCHES | T_NEAR ; //--------------------------------------------------------------------- math_operator: T_SIN { $$ = MATH_SIN; } | T_COS { $$ = MATH_COS; } | T_TAN { $$ = MATH_TAN; } | T_ASIN { $$ = MATH_ASIN; } | T_ACOS { $$ = MATH_ACOS; } | T_ATAN { $$ = MATH_ATAN; } | T_SQRT { $$ = MATH_SQRT; } | T_ABS { $$ = MATH_ABS; } | T_FLOOR { $$ = MATH_FLOOR; } | T_RANDOM { $$ = MATH_RANDOM; } ; //--------------------------------------------------------------------- empty: ;