diff options
author | sanine <sanine.not@pm.me> | 2023-05-19 21:57:06 -0500 |
---|---|---|
committer | sanine <sanine.not@pm.me> | 2023-05-19 21:57:06 -0500 |
commit | 51eef06ddfb82bedab4f5d70932132e28ba4249a (patch) | |
tree | b57e2bdbcdd861ad6598bc19ce8672271f58eab2 | |
parent | 65a5a203820c4540e8818927f4476bc1a3756b86 (diff) |
initial pass at grammar
-rw-r--r-- | src/parser/grammar.jison | 111 |
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); } + ; |