summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobby Bingham <koorogi@koorogi.info>2017-01-18 20:12:49 -0600
committerBobby Bingham <koorogi@koorogi.info>2017-01-18 20:21:17 -0600
commit633e6598859fc5104bb28d5cccac845cb5d5198e (patch)
tree575e9343507673d3f515993ee636e602c3d33182
parent6c6b91f9a6bc5ae203e99ac7abb3a70215488a6f (diff)
nqasm: support binary arithmetic operators in immediate operands
-rw-r--r--lexer.l4
-rw-r--r--nqasm.c5
-rw-r--r--nqasm.h7
-rw-r--r--parser.y29
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]
<args>@ { return T_DEREF; }
<args>\+ { return T_OPERATOR_ADD; }
<args>- { return T_OPERATOR_SUB; }
+<args>\* { return T_OPERATOR_MUL; }
+<args>\/ { return T_OPERATOR_DIV; }
<args>! { return T_OPERATOR_NOT; }
<args>~ { return T_OPERATOR_INV; }
+<args>\( { return T_LPAREN; }
+<args>\) { return T_RPAREN; }
<args>{DEC}+ { return intlit(yytext, 10, &yylval.lval); }
<args>0x{HEX}+ { return intlit(yytext+2, 16, &yylval.lval); }
<args>{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> inst
%type <arg> 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