diff options
author | Bobby Bingham <koorogi@koorogi.info> | 2017-01-18 19:40:18 -0600 |
---|---|---|
committer | Bobby Bingham <koorogi@koorogi.info> | 2017-01-18 19:40:18 -0600 |
commit | 6c6b91f9a6bc5ae203e99ac7abb3a70215488a6f (patch) | |
tree | a60ee21b204363128001cf323e5914745a630afd | |
parent | 1e0d0202e614f398f491624c84ae9a8309fa2f96 (diff) |
nqasm: support unary operators in immediate expressions
-rw-r--r-- | lexer.l | 6 | ||||
-rw-r--r-- | nqasm.c | 19 | ||||
-rw-r--r-- | nqasm.h | 16 | ||||
-rw-r--r-- | parser.y | 10 |
4 files changed, 45 insertions, 6 deletions
@@ -76,7 +76,11 @@ HEX [0-9a-f] <args>\. { return T_DOT; } <args>@ { return T_DEREF; } -<args>[-+]?{DEC}+ { return intlit(yytext, 10, &yylval.lval); } +<args>\+ { return T_OPERATOR_ADD; } +<args>- { return T_OPERATOR_SUB; } +<args>! { return T_OPERATOR_NOT; } +<args>~ { return T_OPERATOR_INV; } +<args>{DEC}+ { return intlit(yytext, 10, &yylval.lval); } <args>0x{HEX}+ { return intlit(yytext+2, 16, &yylval.lval); } <args>{SP}*,{SP}* { return T_COMMA; } @@ -56,12 +56,27 @@ void add_instruction(const struct instruction *inst) addr += 2; } +struct argument *argdup(const struct argument *arg) +{ + struct argument *ret = malloc(sizeof *ret); + if (!ret) { + fprintf(stderr, "unable to allocate argument\n"); + exit(1); + } + *ret = *arg; + return ret; +} + static long eval_argument(const struct argument *arg, uint16_t pc) { struct label *l; switch (arg->type) { - case ARG_INTEGER: return arg->value; - case ARG_PC: return pc; + case ARG_INTEGER: return arg->value; + case ARG_PC: return pc; + case ARG_UNARY_ADD: return eval_argument(arg->children[0], pc); + case ARG_UNARY_SUB: return -eval_argument(arg->children[0], pc); + case ARG_UNARY_NOT: return !eval_argument(arg->children[0], pc); + case ARG_UNARY_INV: return ~eval_argument(arg->children[0], pc); case ARG_LABEL: l = vector_search(&labels->v, &(struct label) { .name = arg->label }, cmp_label); @@ -1,15 +1,23 @@ #ifndef NQ_NQASM_H #define NQ_NQASM_H -#define ARG_INTEGER 0 -#define ARG_LABEL 1 -#define ARG_PC 2 +enum { + ARG_INTEGER, + ARG_LABEL, + ARG_PC, + + ARG_UNARY_ADD, + ARG_UNARY_SUB, + ARG_UNARY_NOT, + ARG_UNARY_INV, +}; struct argument { int type; union { long value; char *label; + const struct argument *children[1]; }; }; @@ -25,5 +33,7 @@ struct instruction { void add_instruction(const struct instruction *); void add_label(const char *); +struct argument *argdup(const struct argument *); + #endif @@ -16,6 +16,7 @@ void yyerror(const char *msg) #define MKARGVALUE(v) (struct argument) { .type = ARG_INTEGER, .value = (v) } #define MKARGLABEL(l) (struct argument) { .type = ARG_LABEL, .label = (l) } #define MKARGTYPE(t) (struct argument) { .type = (t) } +#define MKARGEXPR(op,c) (struct argument) { .type = (op), .children = c } %} @@ -84,6 +85,11 @@ void yyerror(const char *msg) %token T_DOT "." %token T_DEREF "@" +%token T_OPERATOR_ADD "+" +%token T_OPERATOR_SUB "-" +%token T_OPERATOR_NOT "!" +%token T_OPERATOR_INV "~" + %type <inst> inst %type <arg> reg %type <arg> regp @@ -181,6 +187,10 @@ expr: intlit { $$ = MKARGVALUE($1); } | T_LABEL { $$ = MKARGLABEL($1); } | "." { $$ = MKARGTYPE(ARG_PC); } + | "+" expr { $$ = MKARGEXPR(ARG_UNARY_ADD, { argdup(&$2) }); } + | "-" expr { $$ = MKARGEXPR(ARG_UNARY_SUB, { argdup(&$2) }); } + | "!" expr { $$ = MKARGEXPR(ARG_UNARY_NOT, { argdup(&$2) }); } + | "~" expr { $$ = MKARGEXPR(ARG_UNARY_INV, { argdup(&$2) }); } ; intlit: T_INT |