%{ #include #include "bx.h" %} %union { long i; /* char's, int's and longs all go here */ char *s; /* from hash_str() */ double r; struct node *p; /* bx.h */ } %start top %token AND ASSERT ASSOP BEGIN_SYM BOX BREAK CALLFUNC CALLPROC CAST CHAR_CONST CONST CONTINUE DO ELIF ELSE END EQOP EXPORT EXTERN FOR FUNC GEN GEOP GIVE GOTO IDENTIFIER IF INT_CONST IS LABEL LEOP NEOP NOT OR PROC GENCONTEXT REAL_CONST REF REPEAT RETURN SIZEOF STATIC STRING_CONST THEN TOK_FALSE TOK_TRUE TYPE TYPEVAL UNTIL USES IN DOTDOT WHILE WITH WRAP YIELD ATOMIC MOD POW CASE DEFAULT OF PRIVATE %left OR XOR BOR BXOR %left AND BAND %left EQOP NEOP %left '<' '>' GEOP LEOP %left '+' '-' %left '*' '/' MOD %left POW SHIFTL SHIFTR %right NOT UMINUS BNOT %type CHAR_CONST INT_CONST opt_const %type REAL_CONST %type IDENTIFIER STRING_CONST ident %type

assign_stmt block box_decl break_stmt call_func call_stmt cexpr code_body const const_decl const_decl2 const_decl3 continue_stmt decl_or_null declar declaration declarations else_clause else_stuff export export_list expr expr_list file for_ref for_ref_list for_stmt formal_parms formal_prm formal_prm_list func_as_proc func_decl gen_decl gen_func_type goto_stmt if_stmt inst_call inst_call1 inst_call_list inst_decl inst_arg inst_decl_list inst_const_list inst_const label_stmt named_const parm parms path path2 ident_ref rest rest_list ex proc_call_stmt proc_decl repeat_stmt return_stmt statement statements type_ref var_decl var_decl_list while_stmt yield_stmt inst_type_list inst_type named_type named_type2 named_type_list assert_stmt atomic_decl export_part cexpr_sub case_stmt case_entry case_entries default_case range range_part range_parts range_list expr1 extern ex_head export_clause %% top : file { link_parents($1); root_node = append(root_node, $1); } ; file : decl_or_null { $$ = cm(T_file, current_file, NULL, $1, NULL); } ; type_ref : ident inst_call { $$ = cm(T_typeref, $1, $2, NULL, NULL); } | ident { $$ = cm(T_typeref, $1, NULL, NULL, NULL); } ; ident : IDENTIFIER { $$ = $1; } ; decl_or_null : declarations ';' { $$ = $1; } | /* null */ { $$ = NULL; } ; declarations : declarations ';' declaration { $$ = append($1, $3); } | declaration { $$ = $1; } ; declaration : box_decl { $$ = $1; } | atomic_decl { $$ = $1; } | proc_decl { $$ = $1; } | var_decl { $$ = $1; } | func_decl { $$ = $1; } | gen_decl { $$ = $1; } | const_decl { $$ = $1; } | named_type { $$ = $1; } ; box_decl : BOX ident IS export decl_or_null END BOX { $$ = cm(T_box, $2, NULL, append($4, $5), NULL); } | BOX ident IS EXTERN STRING_CONST export decl_or_null END BOX { $$ = cm_extern($5, cm(T_box, $2, NULL, append($6, $7), NULL)); } | BOX ident inst_decl IS export decl_or_null END BOX { $$ = cm(T_complex, $2, $3, append($5, $6), NULL); } | BOX ident inst_decl IS EXTERN STRING_CONST export decl_or_null END BOX { $$ = cm_extern($6, cm(T_complex, $2, $3, append($7, $8), NULL)); } ; atomic_decl : ATOMIC box_decl { $$ = or_flag($2, F_atomic); } ; export : export_clause { $$ = $1; } | /* null */ { $$ = NULL; } ; export_clause : export_clause export_part { $$ = append($1, $2); } | export_part { $$ = $1; } ; export_part : EXPORT export_list ';' { $$ = cm(T_export, NULL, $2, NULL, NULL); } | PRIVATE export_list ';' { $$ = cm(T_private, NULL, $2, NULL, NULL); } ; export_list : export_list ',' ident { $$ = append($1, cm(T_exp, $3, NULL, NULL, NULL)); } | ident { $$ = cm(T_exp, $1, NULL, NULL, NULL); } | /* null */ { $$ = NULL; } ; proc_decl : opt_const PROC ident formal_parms IS code_body END PROC { $$ = or_flag(cm(T_proc, $3, $4, $6, NULL), $1); } | opt_const PROC ident formal_parms IS extern STRING_CONST { $$ = or_flag(cm_extern($7, cm(T_proc, $3, $4, $6, NULL)), $1); } ; func_decl : opt_const FUNC gen_func_type ident formal_parms IS code_body END FUNC { $$ = or_flag(cm(T_func, $4, $5, $7, $3), $1); } | opt_const FUNC gen_func_type ident formal_parms IS extern STRING_CONST { $$ = or_flag(cm_extern($8, cm(T_func, $4, $5, $7, $3)), $1); } ; gen_decl : opt_const GEN gen_func_type ident formal_parms IS code_body END GEN { $$ = or_flag(cm(T_gen, $4, $5, $7, $3), $1); } | opt_const GEN gen_func_type ident formal_parms IS extern STRING_CONST { $$ = or_flag(cm_extern($8, cm(T_gen, $4, $5, $7, $3)), $1); } ; opt_const : CONST { $$ = F_const; } | /* null */ { $$ = 0; } ; extern : EXTERN { $$ = cm(T_block, NULL, NULL, NULL, NULL); } ; var_decl : type_ref var_decl_list { $$ = apply_sub3($1, $2); } | STATIC type_ref var_decl_list { $$ = apply_flag(apply_sub3($2, $3), F_static); } ; var_decl_list : var_decl_list ',' declar { $$ = append($1, $3); } | declar { $$ = $1; } ; declar : ident { $$ = cm(T_var, $1, NULL, NULL, NULL); } | ident ASSOP expr { $$ = cm(T_var, $1, $3, NULL, NULL); } ; named_type : TYPE named_type_list { $$ = $2; } ; named_type_list : named_type_list ',' named_type2 { $$ = append($1, $3); } | named_type2 { $$ = $1; } ; named_type2 : ident ASSOP type_ref { $$ = cm(T_type, $1, NULL, NULL, $3); } ; const_decl : CONST type_ref const_decl3 { $$ = apply_sub3($2, $3); } ; const_decl3 : const_decl3 ',' const_decl2 { $$ = append($1, $3); } | const_decl2 { $$ = $1; } ; const_decl2 : ident ASSOP cexpr { $$ = cm(T_namconst, $1, $3, NULL, NULL); } ; gen_func_type : REF type_ref { $$ = or_flag($2, F_refarg); } | type_ref { $$ = $1; } ; code_body : declarations ';' statements ';' { $$ = cm(T_block, NULL, $1, $3, NULL); } | statements ';' { $$ = cm(T_block, NULL, NULL, $1, NULL); } | declarations ';' { $$ = cm(T_block, NULL, $1, NULL, NULL); } | /* null */ { $$ = cm(T_block, NULL, NULL, NULL, NULL); } ; statements : statements ';' statement { $$ = append($1, $3); } | statement { $$ = $1; } ; statement : goto_stmt { $$ = $1; } | label_stmt { $$ = $1; } | assign_stmt { $$ = $1; } | proc_call_stmt { $$ = $1; } | if_stmt { $$ = $1; } | while_stmt { $$ = $1; } | for_stmt { $$ = $1; } | block { $$ = $1; } | repeat_stmt { $$ = $1; } | return_stmt { $$ = $1; } | yield_stmt { $$ = $1; } | break_stmt { $$ = $1; } | continue_stmt { $$ = $1; } | call_stmt { $$ = $1; } | func_as_proc { $$ = $1; } | assert_stmt { $$ = $1; } | case_stmt { $$ = $1; } | { $$ = NULL; } ; formal_parms : '(' formal_prm_list ')' { $$ = $2; } | /* null */ { $$ = NULL; } ; formal_prm_list : formal_prm_list ';' formal_prm { $$ = append($1, $3); } | formal_prm { $$ = $1; } ; formal_prm : REF type_ref parms { $$ = apply_flag(apply_sub3($2, $3), F_refarg); } | CONST type_ref parms { $$ = apply_flag(apply_sub3($2, $3), F_const); } | type_ref parms { $$ = apply_sub3($1, $2); } ; parms : parms ',' parm { $$ = append($1, $3); } | parm { $$ = $1; } ; parm : ident { $$ = cm(T_var, $1, NULL, NULL, NULL); } ; inst_decl : '{' inst_decl_list '}' { $$ = $2; } ; inst_decl_list : inst_decl_list ';' inst_arg { $$ = append($1, $3); } | inst_arg { $$ = $1; } ; inst_arg : TYPE inst_type_list { $$ = $2; } | type_ref inst_const_list { $$ = apply_sub3($1, $2); } ; inst_type_list : inst_type_list ',' inst_type { $$ = append($1, $3); } | inst_type { $$ = $1; } ; inst_type : ident { $$ = cm(T_type, $1, NULL, NULL, NULL); } ; inst_const_list : inst_const_list ',' inst_const { $$ = append($1, $3); } | inst_const { $$ = $1; } ; inst_const : ident { $$ = cm(T_namconst, $1, NULL, NULL, NULL); } ; inst_call : '{' inst_call_list '}' { $$ = $2; } ; inst_call_list : inst_call_list ',' inst_call1 { $$ = append($1, $3); } | inst_call1 { $$ = $1; } ; inst_call1 : ident inst_call { $$ = cm(T_typeref, $1, $2, NULL, NULL); } | ident { $$ = cm(T_torc, $1, NULL, NULL, NULL); } | cexpr_sub { $$ = $1; } ; named_const : ident { $$ = cm(T_constref, $1, NULL, NULL, NULL); } ; goto_stmt : GOTO ident { $$ = cm(T_goto, $2, NULL, NULL, NULL); } ; label_stmt : LABEL ident { $$ = cm(T_label, $2, NULL, NULL, NULL); } ; assign_stmt : expr ASSOP expr { $$ = cm(T_assign, NULL, $1, $3, NULL); } ; assert_stmt : ASSERT expr { $$ = cm(T_assert, NULL, $2, NULL, NULL); } ; expr_list : expr_list ',' expr { $$ = append($1, $3); } | expr { $$ = $1; } ; expr : expr1 { $$ = cm(T_head, NULL, $1, NULL, NULL); } ; expr1 : ex_head IN range { $$ = cm(T_in, NULL, $1, $3, NULL); } | ex { $$ = $1; } ; ex_head : ex { $$ = cm(T_head, NULL, $1, NULL, NULL); } ; ex : path { $$ = $1; } | '(' ex ')' rest_list { $$ = append($2, $4); } | '(' ex ')' { $$ = $2; } | call_func { $$ = $1; } | ex '+' ex { $$ = cm_op($1, "+", $3); } | ex '-' ex { $$ = cm_op($1, "-", $3); } | ex MOD ex { $$ = cm_op($1, "mod", $3); } | ex POW ex { $$ = cm_op($1, "**", $3); } | ex '*' ex { $$ = cm_op($1, "*", $3); } | ex '/' ex { $$ = cm_op($1, "/", $3); } | ex '<' ex { $$ = cm_op($1, "<", $3); } | ex '>' ex { $$ = cm_op($1, ">", $3); } | ex XOR ex { $$ = cm_op($1, "xor", $3); } | ex AND ex { $$ = cm_op($1, "and", $3); } | ex OR ex { $$ = cm_op($1, "or", $3); } | ex GEOP ex { $$ = cm_op($1, ">=", $3); } | ex LEOP ex { $$ = cm_op($1, "<=", $3); } | ex EQOP ex { $$ = cm_op($1, "==", $3); } | ex NEOP ex { $$ = cm_op($1, "<>", $3); } | ex BAND ex { $$ = cm_op($1, "&", $3); } | ex BOR ex { $$ = cm_op($1, "|", $3); } | ex BXOR ex { $$ = cm_op($1, "^", $3); } | ex SHIFTL ex { $$ = cm_op($1, "<<", $3); } | ex SHIFTR ex { $$ = cm_op($1, ">>", $3); } | BNOT ex { $$ = cm_op($2, "!", NULL);} | NOT ex %prec NOT { $$ = cm_op($2, "not", NULL); } | '-' ex %prec UMINUS { $$ = cm_op($2, "-", NULL); } | CAST '(' expr ',' type_ref ')' { $$ = cm(T_cast, NULL, $3, NULL, $5); } ; range_list : range_list ',' range { $$ = append($1, $3); } | range { $$ = $1; } ; range : ex_head { $$ = cm(T_range, NULL, cm(T_rpart, NULL, $1, NULL, NULL), NULL, NULL); } | '[' range_parts ']' { $$ = cm(T_range, NULL, $2, NULL, NULL); } ; range_parts : range_parts ',' range_part { $$ = append($1, $3); } | range_part { $$ = $1; } ; range_part : expr { $$ = cm(T_rpart, NULL, $1, NULL, NULL); } | expr DOTDOT expr { $$ = cm(T_rpart, NULL, $1, $3, NULL); } ; path : const { $$ = $1; } | const '.' path2 { $$ = append($1, $3); } | path2 { $$ = $1; } ; path2 : ident_ref { $$ = $1; } | ident_ref rest_list { $$ = append($1, $2); } ; ident_ref : ident { $$ = cm(T_path, $1, NULL, NULL, NULL); } | ident '(' expr_list ')' { $$ = cm(T_path, $1, $3, NULL, NULL); } ; rest_list : rest_list rest { $$ = append($1, $2); } | rest { $$ = $1; } ; rest : '^' { $$ = cm(T_path, hash_str("^"), NULL, NULL, NULL);} | '[' expr_list ']' { $$ = cm(T_path, hash_str("[]"), $2, NULL, NULL);} | '.' ident_ref { $$ = $2; } ; proc_call_stmt : expr { $$ = cm(T_call, NULL, $1, NULL, NULL); } ; if_stmt : IF expr THEN code_body else_stuff END IF { $$ = cm(T_if, NULL, $2, $4, $5); } ; else_stuff : ELIF expr THEN code_body else_stuff { $$ = cm(T_block, NULL, NULL, cm(T_if, NULL, $2, $4, $5), NULL); } | ELSE code_body { $$ = $2; } | /* null */ { $$ = NULL; } ; else_clause : ELSE code_body { $$ = $2; } | /* null */ { $$ = NULL; } ; case_stmt : CASE expr OF case_entries default_case END CASE { $$ = cm(T_case, NULL, $2, $4, $5); } ; case_entries : case_entries case_entry { $$ = append($1, $2); } | case_entry { $$ = $1; } ; case_entry : IN range_list ':' code_body { $$ = cm(T_casein, NULL, $2, $4, NULL); } ; default_case : DEFAULT ':' code_body { $$ = cm(T_casedef, NULL, NULL, $3, NULL); } | /* null */ { $$ = NULL; } ; while_stmt : WHILE expr DO code_body else_clause END WHILE { $$ = cm(T_while, NULL, $2, $4, $5); } ; for_stmt : FOR for_ref_list DO code_body else_clause END FOR { $$ = cm(T_for, NULL, $2, $4, $5); } ; for_ref_list : for_ref_list ',' for_ref { $$ = append($1, $3); } | for_ref { $$ = $1; } ; for_ref : type_ref ident ASSOP expr { $$ = cm(T_forref, $2, $4, NULL, $1); } ; block : BEGIN_SYM code_body END { $$ = $2; } ; repeat_stmt : REPEAT code_body UNTIL expr { $$ = cm(T_repeat, NULL, $4, $2, NULL); } ; break_stmt : BREAK { $$ = cm(T_break, NULL, NULL, NULL, NULL); } ; continue_stmt : CONTINUE { $$ = cm(T_continue, NULL, NULL, NULL, NULL); } ; yield_stmt : YIELD expr { $$ = cm(T_yield, NULL, $2, NULL, NULL); } ; return_stmt : RETURN expr { $$ = cm(T_return, NULL, $2, NULL, NULL); } | RETURN { $$ = cm(T_return, NULL, NULL, NULL, NULL); } ; call_stmt : CALLPROC '(' expr ',' expr_list ')' { $$=NULL; } ; call_func : CALLFUNC '(' gen_func_type ',' expr ',' expr_list ')' {$$=NULL;} ; func_as_proc : '@' expr { $$ = cm(T_funcproc, NULL, NULL, $2, NULL); } ; const : CHAR_CONST { $$ = cm2_i("char", $1); } | INT_CONST { $$ = cm2_i("int", $1); } | REAL_CONST { $$ = cm2_r("real", $1); } | STRING_CONST { $$ = cm2_s("string", $1); } | TOK_TRUE { $$ = cm2_i("bool", 1L); } | TOK_FALSE { $$ = cm2_i("bool", 0L); } | SIZEOF '(' type_ref ')' { $$ = cm(T_sizeof, NULL, cm(T_typeref, hash_str("int"), NULL, NULL, NULL), NULL, $3); } | TYPEVAL '(' type_ref ')' { $$ = cm(T_typeval, NULL, NULL, NULL, $3);} ; cexpr : named_const { $$ = $1; } | cexpr_sub { $$ = $1; } ; cexpr_sub : const { $$ = $1; } | '(' cexpr ')' { $$ = $2; } | cexpr '+' cexpr { $$ = cm_cexpr($1, '+', $3); } | cexpr '-' cexpr { $$ = cm_cexpr($1, '-', $3); } | cexpr '*' cexpr { $$ = cm_cexpr($1, '*', $3); } | cexpr '/' cexpr { $$ = cm_cexpr($1, '/', $3); } | cexpr MOD cexpr { $$ = cm_cexpr($1, '%', $3); } | cexpr POW cexpr { $$ = cm_cexpr($1, 'p', $3); } | cexpr OR cexpr { $$ = cm_cexpr($1, '|', $3); } | cexpr AND cexpr { $$ = cm_cexpr($1, '&', $3); } | cexpr XOR cexpr { $$ = cm_cexpr($1, '^', $3); } | cexpr EQOP cexpr { $$ = cm_cexpr($1, '=', $3); } | cexpr GEOP cexpr { $$ = cm_cexpr($1, '}', $3); } | cexpr LEOP cexpr { $$ = cm_cexpr($1, '{', $3); } | cexpr NEOP cexpr { $$ = cm_cexpr($1, '!', $3); } | cexpr '<' cexpr { $$ = cm_cexpr($1, '<', $3); } | cexpr '>' cexpr { $$ = cm_cexpr($1, '>', $3); } | cexpr BAND cexpr { $$ = cm_cexpr($1, 'a', $3); } | cexpr BOR cexpr { $$ = cm_cexpr($1, 'o', $3); } | cexpr BXOR cexpr { $$ = cm_cexpr($1, 'x', $3); } | cexpr SHIFTL cexpr { $$ = cm_cexpr($1, 'l', $3); } | cexpr SHIFTR cexpr { $$ = cm_cexpr($1, 'r', $3); } | BNOT cexpr { $$ = cm_cexpr($2, 'n', NULL); } | NOT cexpr %prec NOT { $$ = cm_cexpr($2, '#', NULL);} | '-' cexpr %prec UMINUS { $$ = cm_cexpr($2, '#', NULL);} ;