diff options
-rw-r--r-- | lexer.l | 14 | ||||
-rw-r--r-- | parser.y | 33 |
2 files changed, 41 insertions, 6 deletions
@@ -1,9 +1,19 @@ %{ +#include <errno.h> +#include <stdlib.h> + #include "parser.h" #define SETVALUE(v) yylval.arg = (struct argument) { .value = (v) } +static int intlit(const char *s, int base, long *out) +{ + errno = 0; + *out = strtol(s, NULL, base); + return errno == ERANGE ? T_BADINT : T_INT; +} + %} %option outfile="lexer.c" header-file="lexer.h" @@ -16,6 +26,8 @@ COMMENT #[^\n]* SP [ \t] EOI [ \t\n#] REGNUM [0-7] +DEC [0-9] +HEX [0-9a-f] %% @@ -59,6 +71,8 @@ REGNUM [0-7] <args>r{REGNUM} { SETVALUE(yytext[1]-'0'); return T_REG; } <args>@r{REGNUM} { SETVALUE(yytext[2]-'0'); return T_REGPTR; } +<args>[-+]?{DEC}+ { return intlit(yytext, 10, &yylval.lval); } +<args>0x{HEX}+ { return intlit(yytext+2, 16, &yylval.lval); } <args>{SP}*,{SP}* { return T_COMMA; } {SP}*{COMMENT}?\n { BEGIN(INITIAL); return T_EOL; } @@ -13,6 +13,7 @@ void yyerror(const char *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) } %} @@ -27,6 +28,7 @@ void yyerror(const char *msg) struct instruction inst; struct arguments args; struct argument arg; + long lval; } %token END 0 "end of file" @@ -70,16 +72,22 @@ void yyerror(const char *msg) %token T_ADDPC %token T_NOP +%token <lval> T_INT +%token T_BADINT + %token <arg> T_REG %token <arg> T_REGPTR %token T_COMMA "," %type <inst> inst +%type <arg> imm %type <args> reg2 %type <args> reg3 %type <args> regp %type <args> regp_reg %type <args> reg_regp +%type <args> reg_imm +%type <lval> intlit %% @@ -115,10 +123,8 @@ inst: T_ADD reg3 { $$ = INSTRUCTION_ARGS(ADD, $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 - { $$ = INSTRUCTION(LDI_BL); } - | T_LDI_BH - { $$ = INSTRUCTION(LDI_BH); } + | 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 @@ -134,8 +140,7 @@ inst: T_ADD reg3 { $$ = INSTRUCTION_ARGS(ADD, $2); } | T_BRA { $$ = INSTRUCTION(BRA); } | T_JMP regp { $$ = INSTRUCTION_ARGS(JMP, $2); } - | T_ADDPC - { $$ = INSTRUCTION(ADDPC); } + | T_ADDPC reg_imm { $$ = INSTRUCTION_ARGS(ADDPC, $2); } | T_NOP { $$ = INSTRUCTION(NOP); } ; @@ -145,6 +150,22 @@ 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 |