%{ #include #include "lexer.h" #include "mnemonics.h" void yyerror(const char *msg) { fprintf(stderr, "%s\n", msg); } #define INSTRUCTION_ARGS(m,a) (struct instruction) { MNEM_ ## m, a } #define INSTRUCTION(m) (struct instruction) { MNEM_ ## m } #define MKARGS(...) (struct arguments) { __VA_ARGS__ } #define MKARGVALUE(v) (struct argument) { (v) } %} %output "parser.c" %defines "parser.h" %code requires { #include "nqasm.h" } %union { struct instruction inst; struct arguments args; struct argument arg; long lval; } %token END 0 "end of file" %token T_SPACE %token T_EOL %token T_ADD %token T_SUB %token T_MUL %token T_DIV %token T_AND %token T_OR %token T_XOR %token T_LSL %token T_LSR %token T_ASL %token T_ASR %token T_ROL %token T_ROR %token T_NOT %token T_NEG %token T_BTC %token T_BTS %token T_MOV %token T_ST_B %token T_ST_W %token T_LD_BL %token T_LD_BH %token T_LD_W %token T_LDI_BL %token T_LDI_BH %token T_BEQ %token T_BNE %token T_BGT %token T_BGE %token T_BLT %token T_BLE %token T_BRA %token T_JMP %token T_ADDPC %token T_NOP %token T_INT %token T_BADINT %token T_REG %token T_REGPTR %token T_COMMA "," %type inst %type imm %type reg2 %type reg3 %type regp %type regp_reg %type reg_regp %type reg_imm %type intlit %% input: line | input line ; line: T_SPACE inst eol { add_instruction(&$2); } | eol ; inst: T_ADD reg3 { $$ = INSTRUCTION_ARGS(ADD, $2); } | T_SUB reg3 { $$ = INSTRUCTION_ARGS(SUB, $2); } | T_MUL reg3 { $$ = INSTRUCTION_ARGS(MUL, $2); } | T_DIV reg3 { $$ = INSTRUCTION_ARGS(DIV, $2); } | T_AND reg3 { $$ = INSTRUCTION_ARGS(AND, $2); } | T_OR reg3 { $$ = INSTRUCTION_ARGS(OR, $2); } | T_XOR reg3 { $$ = INSTRUCTION_ARGS(XOR, $2); } | T_LSL reg3 { $$ = INSTRUCTION_ARGS(LSL, $2); } | T_LSR reg3 { $$ = INSTRUCTION_ARGS(LSR, $2); } | T_ASL reg3 { $$ = INSTRUCTION_ARGS(ASL, $2); } | T_ASR reg3 { $$ = INSTRUCTION_ARGS(ASR, $2); } | T_ROL reg3 { $$ = INSTRUCTION_ARGS(ROL, $2); } | T_ROR reg3 { $$ = INSTRUCTION_ARGS(ROR, $2); } | T_NOT reg2 { $$ = INSTRUCTION_ARGS(NOT, $2); } | T_NEG reg2 { $$ = INSTRUCTION_ARGS(NEG, $2); } | T_BTC reg2 { $$ = INSTRUCTION_ARGS(BTC, $2); } | T_BTS reg2 { $$ = INSTRUCTION_ARGS(BTS, $2); } | T_MOV reg2 { $$ = INSTRUCTION_ARGS(MOV, $2); } | T_ST_B regp_reg { $$ = INSTRUCTION_ARGS(ST_B, $2); } | T_ST_W regp_reg { $$ = INSTRUCTION_ARGS(ST_W, $2); } | T_LD_BL reg_regp { $$ = INSTRUCTION_ARGS(LD_BL, $2); } | T_LD_BH reg_regp { $$ = INSTRUCTION_ARGS(LD_BH, $2); } | T_LD_W reg_regp { $$ = INSTRUCTION_ARGS(LD_W, $2); } | T_LDI_BL reg_imm { $$ = INSTRUCTION_ARGS(LDI_BL, $2); } | T_LDI_BH reg_imm { $$ = INSTRUCTION_ARGS(LDI_BH, $2); } | T_BEQ { $$ = INSTRUCTION(BEQ); } | T_BNE { $$ = INSTRUCTION(BNE); } | T_BGT { $$ = INSTRUCTION(BGT); } | T_BGE { $$ = INSTRUCTION(BGE); } | T_BLT { $$ = INSTRUCTION(BLT); } | T_BLE { $$ = INSTRUCTION(BLE); } | T_BRA { $$ = INSTRUCTION(BRA); } | T_JMP regp { $$ = INSTRUCTION_ARGS(JMP, $2); } | T_ADDPC reg_imm { $$ = INSTRUCTION_ARGS(ADDPC, $2); } | T_NOP { $$ = INSTRUCTION(NOP); } ; reg2: T_SPACE T_REG "," T_REG { $$ = MKARGS($2, $4); } reg3: T_SPACE T_REG "," T_REG "," T_REG { $$ = MKARGS($2, $4, $6); } regp: T_SPACE T_REGPTR { $$ = MKARGS($2); } regp_reg: T_SPACE T_REGPTR "," T_REG { $$ = MKARGS($2, $4); } reg_regp: T_SPACE T_REG "," T_REGPTR { $$ = MKARGS($2, $4); } reg_imm: T_SPACE T_REG "," imm { $$ = MKARGS($2, $4); } imm: intlit { if (-0x80 > $1 || $1 > 0xff) { yyerror("immediate operand out of range"); YYERROR; } else { $$ = MKARGVALUE((uint8_t) $1); } } intlit: T_INT | T_BADINT { yyerror("integer literal out of range"); YYERROR; } eol: T_EOL | T_SPACE T_EOL ;