%{ #include #include "nab.h" #include "cgen.h" #include "errormsg.h" extern VALUE_T val; static VALUE_T v_type; int yyerror(); typedef union { int ival; NODE_T *npval; } YYSTYPE; # define YYSTYPE_IS_DECLARED 1 %} %token SYM_ADDRESS %token SYM_ALLOCATE %token SYM_AND %token SYM_ASSERT %token SYM_ASSIGN %token SYM_ATOM %token SYM_ATSIGN %token SYM_ATTRIBUTE %token SYM_BOUNDS %token SYM_BREAK %token SYM_CALL %token SYM_COMMA %token SYM_CONTINUE %token SYM_DEALLOCATE %token SYM_DEBUG %token SYM_DECL %token SYM_DELETE %token SYM_DONT_MATCH %token SYM_DYNAMIC %token SYM_ELSE %token SYM_EQUAL %token SYM_ERROR %token SYM_FILE %token SYM_FLOAT %token SYM_FLOAT_LIT %token SYM_FOR %token SYM_FOREACH %token SYM_GREATER %token SYM_GREATER_EQUAL %token SYM_HASHED %token SYM_IDENT %token SYM_IF %token SYM_IN %token SYM_INDEX %token SYM_INDIRECT %token SYM_INT %token SYM_INT_LIT %token SYM_LBRACE %token SYM_LBRACK %token SYM_LESS %token SYM_LESS_EQUAL %token SYM_LIST %token SYM_LPAREN %token SYM_MATCH %token SYM_MATRIX %token SYM_MINUS %token SYM_MINUS_ASSIGN %token SYM_MINUS_MINUS %token SYM_MODULUS %token SYM_MODULUS_ASSIGN %token SYM_MOLECULE %token SYM_NEGATE %token SYM_NOT %token SYM_NOT_EQUAL %token SYM_OR %token SYM_PARM %token SYM_PERIOD %token SYM_PLUS %token SYM_PLUS_ASSIGN %token SYM_PLUS_PLUS %token SYM_POINT %token SYM_POINTS_TO %token SYM_RBRACE %token SYM_RBRACK %token SYM_RESIDUE %token SYM_RETURN %token SYM_RPAREN %token SYM_SEMICOLON %token SYM_SIZE_T %token SYM_SLASH %token SYM_SLASH_ASSIGN %token SYM_STAR %token SYM_STAR_ASSIGN %token SYM_STMTLIST %token SYM_STRING %token SYM_STRING_LIT %token SYM_STRUCT %token SYM_TEST %token SYM_TYPE %token SYM_UPARROW %token SYM_UPARROW_ASSIGN %token SYM_WHILE %type actuals %type addop %type a_expr %type alloc_stmt %type a_parm %type ap_list %type ar_lval %type asize %type as_list %type aspec %type assert_stmt %type assignop %type at_lval %type break_stmt %type cmpd_stmt %type conj %type continue_stmt %type dbg_list %type dealloc_stmt %type debug_stmt %type def %type defpart %type defs %type delete_stmt %type disj %type e_list %type expr %type expr_stmt %type factor %type field %type field_list %type f_defpart %type for_count %type for_ctrl %type for_expr %type for_hdr %type for_in %type formals %type for_stmt %type for_test_expr %type f_parm %type fp_list %type f_stmtpart %type func_body %type func_decl %type func_def %type func_hdr %type id %type id_list %type if_hdr %type if_stmt %type i_list %type incr %type incrop %type lval %type lv_decls %type mulop %type num %type primary %type program %type relop %type return_stmt %type rval %type simple_type %type stmt %type stmtpart %type stmts %type string %type struct_type %type term %type type %type type_decl %type unop %type var %type var_decl %type var_list %type while_hdr %type while_stmt %% program : defpart stmtpart { CG_genend(); } ; defpart : defs | { $$ = NULL; } ; defs : def | def defs ; stmtpart : stmts | { $$ = NULL; }; stmts : stmt | stmts stmt ; def : type_decl | var_decl | func_decl | func_def ; type_decl : struct_type SYM_SEMICOLON { $$ = node( SYM_DECL, 0, $1, 0 ); CG_genvardecl( $$, 0, 0, 0 ); } ; var_decl : type var_list SYM_SEMICOLON { $$ = node( SYM_DECL, 0, $1, $2 ); CG_genvardecl( $$, 0, 0, 0 ); } ; type : simple_type { $$ = $1; } | struct_type { $$ = $1; } ; simple_type : SYM_INT { v_type.v_type = T_INT; v_type.v_value.v_ival = T_INT; $$ = node( SYM_TYPE, &v_type, 0, 0 ); } | SYM_SIZE_T { v_type.v_type = T_INT; v_type.v_value.v_ival = T_SIZE_T; $$ = node( SYM_TYPE, &v_type, 0, 0 ); } | SYM_FLOAT { v_type.v_type = T_INT; v_type.v_value.v_ival = T_FLOAT; $$ = node( SYM_TYPE, &v_type, 0, 0 ); } | SYM_STRING { v_type.v_type = T_INT; v_type.v_value.v_ival = T_STRING; $$ = node( SYM_TYPE, &v_type, 0, 0 ); } | SYM_FILE { v_type.v_type = T_INT; v_type.v_value.v_ival = T_FILE; $$ = node( SYM_TYPE, &v_type, 0, 0 ); } | SYM_POINT { v_type.v_type = T_INT; v_type.v_value.v_ival = T_POINT; $$ = node( SYM_TYPE, &v_type, 0, 0 ); } | SYM_BOUNDS { v_type.v_type = T_INT; v_type.v_value.v_ival = T_BOUNDS; $$ = node( SYM_TYPE, &v_type, 0, 0 ); } | SYM_MATRIX { v_type.v_type = T_INT; v_type.v_value.v_ival = T_MATRIX; $$ = node( SYM_TYPE, &v_type, 0, 0 ); } | SYM_ATOM { v_type.v_type = T_INT; v_type.v_value.v_ival = T_ATOM; $$ = node( SYM_TYPE, &v_type, 0, 0 ); } | SYM_RESIDUE { v_type.v_type = T_INT; v_type.v_value.v_ival = T_RESIDUE; $$ = node( SYM_TYPE, &v_type, 0, 0 ); } | SYM_MOLECULE { v_type.v_type = T_INT; v_type.v_value.v_ival = T_MOLECULE; $$ = node( SYM_TYPE, &v_type, 0, 0 ); } ; struct_type : SYM_STRUCT id { v_type.v_type = T_INT; v_type.v_value.v_ival = T_USER; $$ = node( SYM_TYPE, &v_type, node( SYM_STRUCT, 0, $2, 0 ), 0 ); } | SYM_STRUCT id SYM_LBRACE field_list SYM_RBRACE { v_type.v_type = T_INT; v_type.v_value.v_ival = T_USER; $$ = node( SYM_TYPE, &v_type, node( SYM_STRUCT, 0, $2, $4 ), 0 ); } ; field_list : field { $$ = node( SYM_LIST, 0, $1, 0 ); } | field field_list { $$ = node( SYM_LIST, 0, $1, $2 ); } ; field : simple_type id_list SYM_SEMICOLON { $$ = node( SYM_DECL, 0, $1, $2 ); } ; id_list : id { $$ = node( SYM_LIST, 0, $1, 0 ); } | id SYM_COMMA id_list { $$ = node( SYM_LIST, 0, $1, $3 ); } ; var_list : var { $$ = node( SYM_LIST, 0, $1, 0 ); } | var SYM_COMMA var_list { $$ = node( SYM_LIST, 0, $1, $3 ); } ; var : id { $$ = $1; } | id SYM_LBRACK aspec SYM_RBRACK { $$ = node( SYM_LBRACK, 0, $1, $3 ); } ; aspec : as_list { $$ = $1; } | SYM_HASHED { $$ = node( SYM_HASHED, 0, 0, 0 ); } ; as_list : asize { $$ = node( SYM_LIST, 0, $1, 0 ); } | asize SYM_COMMA as_list { $$ = node( SYM_LIST, 0, $1, $3 ); } ; asize : expr { $$ = $1; } | SYM_DYNAMIC { $$ = node( SYM_DYNAMIC, 0, 0, 0 ); } ; func_decl : func_hdr SYM_SEMICOLON { CG_genop( NULL, SYM_SEMICOLON); CG_genfend( NULL ); } | func_hdr id SYM_SEMICOLON { CG_genop( NULL, SYM_SEMICOLON ); CG_genfend( $2 ); } ; func_def : func_hdr { CG_genfstart(); } func_body { CG_genfend( NULL ); } ; func_hdr : type id { CG_genfhdr( $1, $2 ); } SYM_LPAREN formals SYM_RPAREN { CG_genplist( $5 ); } ; formals : fp_list { $$ = $1; } | { $$ = NULL; } ; fp_list : f_parm { $$ = node( SYM_LIST, 0, $1, 0 ); } | f_parm SYM_COMMA fp_list { $$ = node( SYM_LIST, 0, $1, $3 ); } ; f_parm : type var { $$ = node( SYM_LIST, 0, $2, NULL ); $$ = node( SYM_DECL, 0, $1, $$ ); } ; func_body : SYM_LBRACE { CG_genpdecls(); CG_genop( NULL, SYM_LBRACE ); } f_defpart { CG_genedefs( TRUE ); } f_stmtpart SYM_RBRACE { CG_genestmts( TRUE ); CG_genop( NULL, SYM_RBRACE ); } SYM_SEMICOLON { $$=NULL; } ; f_defpart : lv_decls | { $$ = NULL; } ; lv_decls : var_decl | lv_decls var_decl ; f_stmtpart : stmts | { $$ = NULL; }; stmt : expr_stmt | alloc_stmt | assert_stmt | break_stmt | continue_stmt | cmpd_stmt | dealloc_stmt | debug_stmt | delete_stmt | for_stmt | if_stmt | return_stmt | while_stmt ; alloc_stmt : SYM_ALLOCATE expr SYM_SEMICOLON { CG_genmain(); $$ = node( SYM_ALLOCATE, 0, 0, $2 ); CG_genexpr( $$ ); CG_genop( NULL, SYM_SEMICOLON ); } ; assert_stmt : SYM_ASSERT expr SYM_SEMICOLON { CG_genmain(); $$ = node( SYM_ASSERT, 0, 0, $2 ); CG_genassert( $$ ); } ; break_stmt : SYM_BREAK SYM_SEMICOLON { CG_genmain(); CG_genrword( SYM_BREAK ); CG_genop( NULL, SYM_SEMICOLON ); } ; cmpd_stmt : SYM_LBRACE { CG_genmain(); CG_genop( NULL, SYM_LBRACE ); } stmts SYM_RBRACE { CG_genop( NULL, SYM_RBRACE ); } ; continue_stmt : SYM_CONTINUE SYM_SEMICOLON { CG_genmain(); CG_genrword( SYM_CONTINUE ); CG_genop( NULL, SYM_SEMICOLON ); } ; dealloc_stmt : SYM_DEALLOCATE expr SYM_SEMICOLON { CG_genmain(); $$ = node( SYM_DEALLOCATE, 0, 0, $2 ); CG_genexpr($$); CG_genop( NULL, SYM_SEMICOLON ); } ; debug_stmt : SYM_DEBUG dbg_list SYM_SEMICOLON { CG_genmain(); $$ = node( SYM_DEBUG, 0, 0, $2 ); CG_gendebug( $$ ); } ; delete_stmt : SYM_DELETE expr SYM_SEMICOLON { CG_genmain(); $$ = node( SYM_DELETE, 0, 0, $2 ); CG_genexpr($$); CG_genop( NULL, SYM_SEMICOLON ); } ; expr_stmt : expr SYM_SEMICOLON { CG_genmain(); CG_genexpr( $1 ); CG_genop( NULL, SYM_SEMICOLON ); } ; if_stmt : if_hdr stmt | if_hdr stmt SYM_ELSE { CG_genrword( SYM_ELSE ); } stmt ; for_stmt : for_hdr stmt ; return_stmt : SYM_RETURN { CG_genmain(); CG_genrword(SYM_RETURN); CG_genop( NULL, SYM_LPAREN ); } expr { CG_genexpr( $3 ); } SYM_SEMICOLON { CG_genop( NULL, SYM_RPAREN ); CG_genop( NULL, SYM_SEMICOLON ); } ; while_stmt : while_hdr stmt ; if_hdr : SYM_IF { CG_genmain(); CG_genrword( SYM_IF ); } SYM_LPAREN { CG_genop( NULL, SYM_LPAREN ); } expr { $$ = node( SYM_TEST, 0, 0, $5 ); CG_genexpr( $$ ); } SYM_RPAREN { CG_genop( NULL, SYM_RPAREN ); } ; for_hdr : SYM_FOR { CG_genmain(); CG_genrword( SYM_FOR ); } SYM_LPAREN { CG_genop( NULL, SYM_LPAREN ); } for_ctrl SYM_RPAREN { CG_genop( NULL, SYM_RPAREN ); } ; for_ctrl : for_in | for_count ; for_in : id SYM_IN id { $$ = node( SYM_FOREACH, 0, $1, $3 ); CG_genexpr( $$ ); } ; for_count : for_expr SYM_SEMICOLON { CG_genop( NULL, SYM_SEMICOLON ); } for_test_expr SYM_SEMICOLON { CG_genop( NULL, SYM_SEMICOLON ); } for_expr ; for_expr : expr { CG_genexpr( $1 ); } | { $$ = NULL; } ; for_test_expr : expr { $$ = node( SYM_TEST, 0, 0, $1 ); CG_genexpr( $$ ); } | { $$ = NULL; } ; while_hdr : SYM_WHILE { CG_genmain(); CG_genrword( SYM_WHILE ); } SYM_LPAREN { CG_genop( NULL, SYM_LPAREN ); } expr { $$ = node( SYM_TEST, 0, 0, $5 ); CG_genexpr( $$ ); } SYM_RPAREN { CG_genop( NULL, SYM_RPAREN ); } ; dbg_list : SYM_LPAREN e_list SYM_RPAREN { $$ = $2; } | e_list { $$ = $1; } ; e_list : expr { $$ = node( SYM_LIST, 0, $1, 0 ); } | expr SYM_COMMA e_list { $$ = node( SYM_LIST, 0, $1, $3 ); } ; expr : rval { $$ = $1; } | lval assignop expr { $$ = node( $2, 0, $1, $3 ); } ; lval : id { $$ = $1; } | ar_lval { $$ = $1; } | at_lval { $$ = $1; } ; ar_lval : lval SYM_LBRACK i_list SYM_RBRACK { $$ = node( SYM_LBRACK, 0, $1, $3 ); } ; at_lval : lval SYM_PERIOD SYM_IDENT { $$ = node( SYM_PERIOD, 0, $1, node( SYM_ATTRIBUTE, &val, 0, 0 ) ); } ; rval : disj { $$ = $1; } | disj SYM_OR rval { $$ = node( SYM_OR, 0, $1, $3 ); } ; disj : conj { $$ = $1; } | conj SYM_AND disj { $$ = node( SYM_AND, 0, $1, $3 ); } ; conj : a_expr { $$ = $1; } | a_expr relop a_expr { $$ = node( $2, 0, $1, $3 ); } ; a_expr : term { $$ = $1; } | term addop a_expr { $$ = node( $2, 0, $1, $3 ); } ; term : factor { $$ = $1; } | factor mulop term { $$ = node( $2, 0, $1, $3 ); } ; factor : primary { $$ = $1; } | primary SYM_UPARROW factor { $$ = node( SYM_UPARROW, 0, $1, $3 ); }; primary : lval { $$ = $1; } | num { $$ = $1; } | string { $$ = $1; } | incr { $$ = $1; } | unop primary { $$ = node( $1, 0, NULL, $2 ); } | id SYM_LPAREN actuals SYM_RPAREN { $$ = node( SYM_CALL, 0, $1, $3 ); } | SYM_LPAREN expr SYM_RPAREN { $$ = node( SYM_LPAREN, 0, NULL, $2 ); } ; incr : incrop lval { $$ = node( $1, 0, 0, $2 ); } | lval incrop { $$ = node( $2, 0, $1, 0 ); } ; actuals : ap_list { $$ = $1; } | { $$ = NULL; } ; ap_list : a_parm { $$ = node( SYM_LIST, 0, $1, 0 ); } | a_parm SYM_COMMA ap_list { $$ = node( SYM_LIST, 0, $1, $3 ); } ; a_parm : expr { $$ = node( SYM_PARM, 0, 0, $1 ); } ; i_list : expr { $$ = node( SYM_INDEX, 0, $1, 0 ); } | expr SYM_COMMA i_list { $$ = node( SYM_INDEX, 0, $1, $3 ); } ; assignop : SYM_ASSIGN { $$ = SYM_ASSIGN; } | SYM_PLUS_ASSIGN { $$ = SYM_PLUS_ASSIGN; } | SYM_MINUS_ASSIGN { $$ = SYM_MINUS_ASSIGN; } | SYM_STAR_ASSIGN { $$ = SYM_STAR_ASSIGN; } | SYM_SLASH_ASSIGN { $$ = SYM_SLASH_ASSIGN; } | SYM_MODULUS_ASSIGN { $$ = SYM_MODULUS_ASSIGN; } | SYM_UPARROW_ASSIGN { $$ = SYM_UPARROW_ASSIGN; } ; relop : SYM_LESS { $$ = SYM_LESS; } | SYM_LESS_EQUAL { $$ = SYM_LESS_EQUAL; } | SYM_EQUAL { $$ = SYM_EQUAL; } | SYM_NOT_EQUAL { $$ = SYM_NOT_EQUAL; } | SYM_GREATER_EQUAL { $$ = SYM_GREATER_EQUAL; } | SYM_GREATER { $$ = SYM_GREATER; } | SYM_MATCH { $$ = SYM_MATCH; } | SYM_DONT_MATCH { $$ = SYM_DONT_MATCH; } | SYM_IN { $$ = SYM_IN; } ; addop : SYM_PLUS { $$ = SYM_PLUS; } | SYM_MINUS { $$ = SYM_MINUS; } ; mulop : SYM_STAR { $$ = SYM_STAR; } | SYM_SLASH { $$ = SYM_SLASH; } | SYM_MODULUS { $$ = SYM_MODULUS; } | SYM_ATSIGN { $$ = SYM_ATSIGN; } ; incrop : SYM_PLUS_PLUS { $$ = SYM_PLUS_PLUS; } | SYM_MINUS_MINUS { $$ = SYM_MINUS_MINUS; } ; unop : SYM_MINUS { $$ = SYM_NEGATE; } | SYM_NOT { $$ = SYM_NOT; } ; id : SYM_IDENT { $$ = node( SYM_IDENT, &val, 0, 0 ); } ; num : SYM_INT_LIT { $$ = node( SYM_INT_LIT, &val, 0, 0 ); } | SYM_FLOAT_LIT { $$ = node( SYM_FLOAT_LIT, &val, 0, 0 ); } ; string : SYM_STRING_LIT { $$ = node( SYM_STRING_LIT, &val, 0, 0 ); } ; %% #include "lex.yy.c"