blob: 6ac55df2c390d37568ee45d74aa305c38348b709 (
plain)
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
|
%lex
%x comment
%%
";" { this.pushState('comment'); return "COMMENT"; }
<comment>"\n" { this.popState(); return "NEWLINE"; }
<comment>. { /* ignore anything else inside a comment */ }
"\n" { return "NEWLINE"; }
\s+ { /* ignore whitespace */ }
"MOV" { return "MOV"; }
"ADD" { return "ADD"; }
"SUB" { return "SUB"; }
"CMP" { return "CMP"; }
"SLT" { return "SLT"; }
"JMP" { return "JMP"; }
"JMZ" { return "JMZ"; }
"JMN" { return "JMN"; }
"DJN" { return "DJN"; }
"SPL" { return "SPL"; }
"DAT" { return "DAT"; }
"EQU" { return "EQU"; }
"END" { return "END"; }
":" { return ":"; }
"#" { return "#"; }
"@" { return "@"; }
"<" { return "<"; }
"$" { return "$"; }
"(" { return "("; }
")" { return ")"; }
"+" { return "+"; }
"-" { return "-"; }
"*" { return "*"; }
"/" { return "/"; }
[0-9]+ { return "NUMBER"; }
[A-Z][A-Z0-9_]+ { return "LABEL"; }
/lex
%%
program
: lines { return $lines; }
;
lines
: lines line { $lines.push($line); $$ = $lines; }
| line { $$ = [ $line ]; }
;
line
: op NEWLINE { $$ = $op; }
| op EOF { $$ = $op; }
;
op
: opcode address address
{ $$ = { opcode: $opcode, a: $address1, b: $address2 }; }
;
opcode
: MOV { $$ = $1; }
| ADD { $$ = $1; }
| SUB { $$ = $1; }
| CMP { $$ = $1; }
| SLT { $$ = $1; }
| JMP { $$ = $1; }
| JMZ { $$ = $1; }
| JMN { $$ = $1; }
| DJN { $$ = $1; }
| SPL { $$ = $1; }
| DAT { $$ = $1; }
;
address:
: address_mode e { $$ = { mode: $1, value: $2 }; }
| e { $$ = { mode: 'direct', value: $1 }; }
;
address_mode
: "#" { $$ = 'immediate'; }
| "@" { $$ = 'indirect'; }
| "<" { $$ = 'predecrement'; }
| "$" { $$ = 'direct'; }
;
e
: NUMBER { $$ = Math.floor(Number(yytext)); }
| LABEL {
$$ = yy.getLabel(yytext);
if ($$ === null) {
YYABORT;
}
}
| e '+' e { $$ = Math.floor($e1 + $e2); }
| e '-' e { $$ = Math.floor($e1 - $e2); }
| e '*' e { $$ = Math.floor($e1 * $e2); }
| e '/' e { $$ = Math.floor($e1 / $e2); }
| '(' e ')' { $$ = Math.floor($e); }
;
|