1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
|
%{
#include <stdio.h>
#include "lexer.h"
#include "mnemonics.h"
void yyerror(const char *msg)
{
fprintf(stderr, "%s\n", 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) { .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,...) (struct argument) { .type = (op), .children = { __VA_ARGS__ } }
%}
%output "parser.c"
%defines "parser.h"
%code requires {
#include "nqasm.h"
}
%union {
struct instruction inst;
struct arguments args;
struct argument arg;
long lval;
char *str;
}
%token END 0 "end of file"
%token T_UNKNOWN
%token T_EOL
%token T_ADD
%token T_SUB
%token T_MUL
%token T_DIV
%token T_AND
%token T_OR
%token T_XOR
%token T_LSL
%token T_LSR
%token T_ASL
%token T_ASR
%token T_ROL
%token T_ROR
%token T_NOT
%token T_NEG
%token T_BTC
%token T_BTS
%token T_MOV
%token T_ST_B
%token T_ST_W
%token T_LD_BL
%token T_LD_BH
%token T_LD_W
%token T_LDI_BL
%token T_LDI_BH
%token T_BEQ
%token T_BNE
%token T_BGT
%token T_BGE
%token T_BLT
%token T_BLE
%token T_BRA
%token T_JMP
%token T_ADDPC
%token T_NOP
%token <str> T_LABEL
%token <lval> T_INT
%token T_BADINT
%token T_COMMA ","
%token T_COLON ":"
%token T_DOT "."
%token T_DEREF "@"
%token T_SPACE " "
%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
%type <arg> regp
%type <arg> expr
%type <args> a_reg2
%type <args> a_reg3
%type <args> a_regp
%type <args> a_regp_reg
%type <args> a_reg_regp
%type <args> a_reg_expr
%type <args> a_expr
%type <lval> intlit
%%
input: line
| input line
;
line:
bol inst eol { add_instruction(&$2); }
| eol
;
bol:
" "
| T_LABEL ":" { add_label($1); }
;
inst:
T_ADD a_reg3 { $$ = INSTRUCTION_ARGS(ADD, $2); }
| T_SUB a_reg3 { $$ = INSTRUCTION_ARGS(SUB, $2); }
| T_MUL a_reg3 { $$ = INSTRUCTION_ARGS(MUL, $2); }
| T_DIV a_reg3 { $$ = INSTRUCTION_ARGS(DIV, $2); }
| T_AND a_reg3 { $$ = INSTRUCTION_ARGS(AND, $2); }
| T_OR a_reg3 { $$ = INSTRUCTION_ARGS(OR, $2); }
| T_XOR a_reg3 { $$ = INSTRUCTION_ARGS(XOR, $2); }
| T_LSL a_reg3 { $$ = INSTRUCTION_ARGS(LSL, $2); }
| T_LSR a_reg3 { $$ = INSTRUCTION_ARGS(LSR, $2); }
| T_ASL a_reg3 { $$ = INSTRUCTION_ARGS(ASL, $2); }
| T_ASR a_reg3 { $$ = INSTRUCTION_ARGS(ASR, $2); }
| T_ROL a_reg3 { $$ = INSTRUCTION_ARGS(ROL, $2); }
| T_ROR a_reg3 { $$ = INSTRUCTION_ARGS(ROR, $2); }
| T_NOT a_reg2 { $$ = INSTRUCTION_ARGS(NOT, $2); }
| T_NEG a_reg2 { $$ = INSTRUCTION_ARGS(NEG, $2); }
| T_BTC a_reg2 { $$ = INSTRUCTION_ARGS(BTC, $2); }
| T_BTS a_reg2 { $$ = INSTRUCTION_ARGS(BTS, $2); }
| T_MOV a_reg2 { $$ = INSTRUCTION_ARGS(MOV, $2); }
| T_ST_B a_regp_reg { $$ = INSTRUCTION_ARGS(ST_B, $2); }
| T_ST_W a_regp_reg { $$ = INSTRUCTION_ARGS(ST_W, $2); }
| T_LD_BL a_reg_regp { $$ = INSTRUCTION_ARGS(LD_BL, $2); }
| T_LD_BH a_reg_regp { $$ = INSTRUCTION_ARGS(LD_BH, $2); }
| T_LD_W a_reg_regp { $$ = INSTRUCTION_ARGS(LD_W, $2); }
| T_LDI_BL a_reg_expr { $$ = INSTRUCTION_ARGS(LDI_BL, $2); }
| T_LDI_BH a_reg_expr { $$ = INSTRUCTION_ARGS(LDI_BH, $2); }
| T_BEQ a_expr { $$ = INSTRUCTION_ARGS(BEQ, $2); }
| T_BNE a_expr { $$ = INSTRUCTION_ARGS(BNE, $2); }
| T_BGT a_expr { $$ = INSTRUCTION_ARGS(BGT, $2); }
| T_BGE a_expr { $$ = INSTRUCTION_ARGS(BGE, $2); }
| T_BLT a_expr { $$ = INSTRUCTION_ARGS(BLT, $2); }
| T_BLE a_expr { $$ = INSTRUCTION_ARGS(BLE, $2); }
| T_BRA a_expr { $$ = INSTRUCTION_ARGS(BRA, $2); }
| T_JMP a_regp { $$ = INSTRUCTION_ARGS(JMP, $2); }
| T_ADDPC a_reg_expr { $$ = INSTRUCTION_ARGS(ADDPC, $2); }
| T_NOP { $$ = INSTRUCTION(NOP); }
;
a_reg2: " " reg "," reg { $$ = MKARGS($2, $4); }
a_reg3: " " reg "," reg "," reg { $$ = MKARGS($2, $4, $6); }
a_regp: " " regp { $$ = MKARGS($2); }
a_regp_reg: " " regp "," reg { $$ = MKARGS($2, $4); }
a_reg_regp: " " reg "," regp { $$ = MKARGS($2, $4); }
a_reg_expr: " " reg "," expr { $$ = MKARGS($2, $4); }
a_expr: " " expr { $$ = MKARGS($2); }
regp: "@" reg { $$ = $2; }
reg: T_LABEL {
int bad = 0;
if ($1[0] != 'r' && $1[0] != 'R')
bad = 1;
else if (0 > $1[1] - '0' || $1[1] - '0' > 9)
bad = 1;
else if ($1[2])
bad = 1;
if (bad) {
yyerror("invalid register");
YYERROR;
} else {
$$ = MKARGVALUE($1[1] - '0');
}
}
expr:
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
| T_BADINT {
yyerror("integer literal out of range");
YYERROR;
}
eol: T_EOL
| " " T_EOL
;
|