summaryrefslogtreecommitdiff
path: root/src/parser/grammar.jison
blob: 4a17d2b15e8b9b66c2b596871d524b5c15c27483 (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
%lex

%%

";"              { 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); }
	;