summaryrefslogtreecommitdiff
path: root/src/parser/grammar.jison
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser/grammar.jison')
-rw-r--r--src/parser/grammar.jison111
1 files changed, 111 insertions, 0 deletions
diff --git a/src/parser/grammar.jison b/src/parser/grammar.jison
new file mode 100644
index 0000000..4a17d2b
--- /dev/null
+++ b/src/parser/grammar.jison
@@ -0,0 +1,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); }
+ ;