%token_type {const char *} %extra_argument {struct t_parser *parser} %name FlowIrParse %token_prefix FLOWIR_ %include { #include "flowir_parser.hpp" using namespace flow; } // Main Symbol: // ============ prog ::= proc_list. proc_list ::= proc. proc_list ::= proc_list proc. // Procedure declarations: // ======================= %type proc {struct t_parser::t_procedure*} proc(R) ::= VOID proc_name(name) OPENPAREN argument_list(L) CLOSEPAREN body(B). { R = parser->procedure(name, L, B); } %type argument_list {struct t_parser::t_variable_decl*} argument_list(R) ::= . { R = NULL; } argument_list(R) ::= argument_decl(D). { R = D; } argument_list(R) ::= argument_list(L) COMMA argument_decl(D). { R = parser->append_to(L, D); } %type argument_decl {struct t_parser::t_variable_decl*} argument_decl(R) ::= type_name(type) variable_name(name). { R = parser->variable_decl(type, name); } %type body {struct t_parser::t_body*} body(R) ::= OPENBRACE CLOSEBRACE. { R = parser->body(NULL, NULL); } body(R) ::= OPENBRACE variable_decls(D) CLOSEBRACE. { R = parser->body(D, NULL); } body(R) ::= OPENBRACE statement_list(L) CLOSEBRACE. { R = parser->body(NULL, L); } body(R) ::= OPENBRACE variable_decls(D) statement_list(L) CLOSEBRACE. { R = parser->body(D, L); } %type variable_decls {struct t_parser::t_variable_decl*} variable_decls(R) ::= variable_decl(L). { R = L; } variable_decls(R) ::= variable_decls(L) variable_decl(D). { R = parser->append_to(L,D); } %type variable_decl {struct t_parser::t_variable_decl*} variable_decl(R) ::= type_name(type) decl_name_list(L) SEMICOLON. { R = parser->variable_decl(type, L); } %type decl_name_list {struct t_parser::t_variable_name*} decl_name_list(R) ::= variable_name(name). { R = parser->variable_name(NULL, name); } decl_name_list(R) ::= decl_name_list(L) COMMA variable_name(name). { R = parser->variable_name(L, name); } // Statements: // =========== %type statement_list {struct t_parser::t_instruction*} statement_list(R) ::= statement(L). { R = L; } statement_list(R) ::= statement_list(L) statement(S). { R = parser->append_to(L,S); } %type statement {struct t_parser::t_instruction*} statement(R) ::= label_name(name) COLON assignment(A) SEMICOLON. { R = A; A->label = name; } statement(R) ::= assignment(A) SEMICOLON. { R = A; } %type assignment {struct t_parser::t_instruction*} assignment(R) ::= variable_name(var) EQUALS expr(S). { R = S; S->assign_to = var; } assignment(R) ::= expr(S). { R = S; } // Expressions: // ============ %type expr {struct t_parser::t_instruction*} // Allow exprs of the form: [opcode arg1=val1 arg2=val2]; %type opcode_arg_list {struct t_parser::t_instruction_arg*} %type opcode_arg {struct t_parser::t_instruction_arg*} %type branch_target {const char *} %type procedure_target {const char *} expr(R) ::= OPENBRACKET IDENTIFIER(OP) opcode_arg_list(ARGS) branch_target(BR) procedure_target(PR) CLOSEBRACKET. { R = parser->instruction(OP, BR, PR, ARGS); } opcode_arg_list(R) ::= . { R = NULL; } opcode_arg_list(R) ::= opcode_arg_list(L) opcode_arg(A). { R = parser->append_to(L,A); } opcode_arg(R) ::= IDENTIFIER(arg_name) EQUALS operand_expr(value). { R = parser->instruction_arg(arg_name, value); } branch_target(R) ::= . { R = NULL; } branch_target(R) ::= STAR label_name(P). { R = P; } procedure_target(R) ::= . { R = NULL; } procedure_target(R) ::= OPENPAREN proc_name(P) CLOSEPAREN. { R = P; } // Allow exprs of the form: queue proc (arg1, arg2) or // tail proc (arg1,arg2), with or without parameters. %type call_type {const char *} %type call_arg_list {struct t_parser::t_instruction_arg*} expr(R) ::= call_type(C) proc_name(P) OPENPAREN call_arg_list(L) CLOSEPAREN. { R = parser->instruction(C, NULL, P, L); } expr(R) ::= call_type(C) proc_name(P) OPENPAREN CLOSEPAREN. { R = parser->instruction(C, NULL, P, NULL); } call_type(R) ::= QUEUE(L). { R = L; } call_type(R) ::= TAIL(L). { R = L; } call_arg_list(R) ::= operand_expr(V). { R = parser->instruction_arg(NULL, V); } call_arg_list(R) ::= call_arg_list(L) COMMA operand_expr(V). { R = parser->append_to(L, parser->instruction_arg(NULL, V)); } // Allow common mathematical stuff. %type math_oper {const char *} expr(R) ::= operand_expr(left) math_oper(O) operand_expr(right). { R = parser->math_instruction(O, left, right); } math_oper(R) ::= PLUS(L). { R = L; } math_oper(R) ::= SUB(L). { R = L; } math_oper(R) ::= STAR(L). { R = L; } math_oper(R) ::= SLASH(L). { R = L; } // Allow "if X goto Y" expr(R) ::= IF operand_expr(E) GOTO label_name(L). { R = parser->single_operand_instruction("IFTRUE", E, L); } // Allow casts. expr(R) ::= CAST operand_expr(E). { R = parser->single_operand_instruction("CAST", E, NULL); } // Finally, allow simple operand_expr. expr(R) ::= operand_expr(E). { R = parser->single_operand_instruction("COPY", E, NULL); } // Operand expressions are either variable names or constants: %type operand_expr {const char *} operand_expr(R) ::= variable_name(V). { R = V; } operand_expr(R) ::= NUMBER(N). { R = N; } operand_expr(R) ::= HEX_NUMBER(N). { R = N; } // Names of things: // ================ %type label_name {const char*} label_name(R) ::= variable_name(L). { R = L; } %type type_name {const char*} type_name(R) ::= variable_name(L). { R = L; } %type proc_name {const char*} proc_name(R) ::= variable_name(L). { R = L; } %type variable_name {const char*} variable_name(R) ::= IDENTIFIER(var_name). { R = var_name; } variable_name(R) ::= VOID(var_name). { R = var_name; } variable_name(R) ::= GOTO(var_name). { R = var_name; }