From 633e6598859fc5104bb28d5cccac845cb5d5198e Mon Sep 17 00:00:00 2001 From: Bobby Bingham Date: Wed, 18 Jan 2017 20:12:49 -0600 Subject: nqasm: support binary arithmetic operators in immediate operands --- lexer.l | 4 ++++ nqasm.c | 5 +++++ nqasm.h | 7 ++++++- parser.y | 29 +++++++++++++++++++++-------- 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/lexer.l b/lexer.l index 324c3da..9b1548d 100644 --- a/lexer.l +++ b/lexer.l @@ -78,8 +78,12 @@ HEX [0-9a-f] @ { return T_DEREF; } \+ { return T_OPERATOR_ADD; } - { return T_OPERATOR_SUB; } +\* { return T_OPERATOR_MUL; } +\/ { return T_OPERATOR_DIV; } ! { return T_OPERATOR_NOT; } ~ { return T_OPERATOR_INV; } +\( { return T_LPAREN; } +\) { return T_RPAREN; } {DEC}+ { return intlit(yytext, 10, &yylval.lval); } 0x{HEX}+ { return intlit(yytext+2, 16, &yylval.lval); } {SP}*,{SP}* { return T_COMMA; } diff --git a/nqasm.c b/nqasm.c index 49b4ec6..e915bd7 100644 --- a/nqasm.c +++ b/nqasm.c @@ -78,6 +78,11 @@ static long eval_argument(const struct argument *arg, uint16_t 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_ADD: return eval_argument(arg->children[0], pc) + eval_argument(arg->children[1], pc); + case ARG_SUB: return eval_argument(arg->children[0], pc) - eval_argument(arg->children[1], pc); + case ARG_MUL: return eval_argument(arg->children[0], pc) * eval_argument(arg->children[1], pc); + case ARG_DIV: return eval_argument(arg->children[0], pc) / eval_argument(arg->children[1], pc); + case ARG_LABEL: l = vector_search(&labels->v, &(struct label) { .name = arg->label }, cmp_label); if (l) return l->addr; diff --git a/nqasm.h b/nqasm.h index e5a7452..3e6ec72 100644 --- a/nqasm.h +++ b/nqasm.h @@ -10,6 +10,11 @@ enum { ARG_UNARY_SUB, ARG_UNARY_NOT, ARG_UNARY_INV, + + ARG_ADD, + ARG_SUB, + ARG_MUL, + ARG_DIV, }; struct argument { @@ -17,7 +22,7 @@ struct argument { union { long value; char *label; - const struct argument *children[1]; + const struct argument *children[2]; }; }; diff --git a/parser.y b/parser.y index cb1343f..ed33aa4 100644 --- a/parser.y +++ b/parser.y @@ -16,7 +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 } +#define MKARGEXPR(op,...) (struct argument) { .type = (op), .children = { __VA_ARGS__ } } %} @@ -87,8 +87,16 @@ void yyerror(const char *msg) %token T_OPERATOR_ADD "+" %token T_OPERATOR_SUB "-" +%token T_OPERATOR_MUL "*" +%token T_OPERATOR_DIV "/" %token T_OPERATOR_NOT "!" %token T_OPERATOR_INV "~" +%token T_LPAREN "(" +%token T_RPAREN ")" + +%left "-" "+" +%left "*" "/" +%precedence NEG %type inst %type reg @@ -184,13 +192,18 @@ reg: T_LABEL { } 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 { $$ = MKARGVALUE($1); } + | T_LABEL { $$ = MKARGLABEL($1); } + | "." { $$ = MKARGTYPE(ARG_PC); } + | "+" expr %prec NEG { $$ = MKARGEXPR(ARG_UNARY_ADD, argdup(&$2)); } + | "-" expr %prec NEG { $$ = MKARGEXPR(ARG_UNARY_SUB, argdup(&$2)); } + | "!" expr %prec NEG { $$ = MKARGEXPR(ARG_UNARY_NOT, argdup(&$2)); } + | "~" expr %prec NEG { $$ = MKARGEXPR(ARG_UNARY_INV, argdup(&$2)); } + | expr "+" expr { $$ = MKARGEXPR(ARG_ADD, argdup(&$1), argdup(&$3)); } + | expr "-" expr { $$ = MKARGEXPR(ARG_SUB, argdup(&$1), argdup(&$3)); } + | expr "*" expr { $$ = MKARGEXPR(ARG_MUL, argdup(&$1), argdup(&$3)); } + | expr "/" expr { $$ = MKARGEXPR(ARG_DIV, argdup(&$1), argdup(&$3)); } + | "(" expr ")" { $$ = $2; } ; intlit: T_INT -- cgit v1.2.3