summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lexer.l14
-rw-r--r--parser.y33
2 files changed, 41 insertions, 6 deletions
diff --git a/lexer.l b/lexer.l
index f3a540c..85021c5 100644
--- a/lexer.l
+++ b/lexer.l
@@ -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; }
diff --git a/parser.y b/parser.y
index 2177ae8..c953aa4 100644
--- a/parser.y
+++ b/parser.y
@@ -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