Last active
December 20, 2015 05:39
-
-
Save darkoverlordofdata/6079782 to your computer and use it in GitHub Desktop.
Jison with CoffeeScript AST
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# @see http://epaperpress.com/lexandyacc/calc1.html | |
# | |
# | |
# Var table | |
# | |
_var = {} | |
# | |
# Private Base Class | |
# | |
class OpBase | |
nops: 0 | |
op: null | |
constructor: ($op...) -> | |
@nops = $op.length | |
@op = $op | |
# | |
# Ast Public Namespace | |
# | |
window.Ast = | |
# | |
# Constant Node | |
# | |
Zer: | |
eval: () -> | |
0 | |
# | |
# Constant Node | |
# | |
Nul: | |
eval: () -> | |
null | |
# | |
# Constant Node | |
# | |
Const: class Const | |
value: null | |
constructor: ($value) -> | |
@value = parseInt($value, 10) | |
eval: () -> | |
@value | |
# | |
# Variable Node | |
# | |
Var: class Var | |
name: '' | |
constructor: ($name) -> | |
@name = $name | |
eval: () -> | |
_var[@name] | |
assign: ($value) -> | |
_var[@name] = $value | |
# | |
# Node Print | |
# | |
Print: class Print extends OpBase | |
eval: () -> | |
console.log @op[0].eval() | |
return 0 | |
# | |
# Node While | |
# | |
While: class While extends OpBase | |
eval: () -> | |
while @op[0].eval() | |
@op[1].eval() | |
return 0 | |
# | |
# Node If | |
# | |
If: class If extends OpBase | |
eval: () -> | |
if @op[0].eval() | |
@op[1].eval() | |
else if (p.nops > 2) | |
@op[2].eval() | |
return 0 | |
# | |
# Node + | |
# | |
Add: class Add extends OpBase | |
eval: () -> | |
@op[0].eval() + @op[1].eval() | |
# | |
# Node - | |
# | |
Sub: class Sub extends OpBase | |
eval: () -> | |
@op[0].eval() - @op[1].eval() | |
# | |
# Node * | |
# | |
Mul: class Mul extends OpBase | |
eval: () -> | |
@op[0].eval() * @op[1].eval() | |
# | |
# Node / | |
# | |
Div: class Div extends OpBase | |
eval: () -> | |
@op[0].eval() / @op[1].eval() | |
# | |
# Node < | |
# | |
LT: class LT extends OpBase | |
eval: () -> | |
@op[0].eval() < @op[1].eval() | |
# | |
# Node > | |
# | |
GT: class GT extends OpBase | |
eval: () -> | |
@op[0].eval() > @op[1].eval() | |
# | |
# Node <= | |
# | |
LE: class LE extends OpBase | |
eval: () -> | |
@op[0].eval() <= @op[1].eval() | |
# | |
# Node >= | |
# | |
GE: class GE extends OpBase | |
eval: () -> | |
@op[0].eval() >= @op[1].eval() | |
# | |
# Node == | |
# | |
EQ: class EQ extends OpBase | |
eval: () -> | |
if @op[0].eval() is @op[1].eval() then true else false | |
# | |
# Node != | |
# | |
NE: class NE extends OpBase | |
eval: () -> | |
if @op[0].eval() isnt @op[1].eval() then true else false | |
# | |
# Node ; | |
# | |
Eol: class Eol extends OpBase | |
eval: () -> | |
@op[0].eval() | |
@op[1].eval() | |
# | |
# Node Let | |
# | |
Let: class Let extends OpBase | |
eval: () -> | |
@op[0].assign @op[1].eval() | |
# | |
# Node Program | |
# | |
Program: class Program | |
constructor: ($node) -> | |
$node.eval() | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// to compile: | |
// | |
// jison parser.jison | |
// | |
// | |
// @see http://epaperpress.com/lexandyacc/calcl.html | |
// | |
%lex | |
%% | |
">=" return 'GE'; | |
"<=" return 'LE'; | |
"==" return 'EQ'; | |
"!=" return 'NE'; | |
"while" return 'WHILE'; | |
"if" return 'IF'; | |
"else" return 'ELSE'; | |
"print" return 'PRINT'; | |
[a-z] return 'VARIABLE'; | |
0 return 'INTEGER'; | |
[1-9][0-9]* return 'INTEGER'; | |
[-()<>=+*/;{}.] return yytext; | |
[ \t\n]+ /* ignore whitespace */; | |
. return 'INVALID' | |
/lex | |
%token WHILE IF PRINT | |
%nonassoc IFX | |
%nonassoc ELSE | |
%token INTEGER | |
%token VARIABLE | |
%left GE LE EQ NE '>' '<' | |
%left '+' '-' | |
%left '*' '/' | |
%nonassoc UMINUS | |
%start program | |
%% /* language grammar */ | |
program | |
: function -> console.log("That's All Folks!") | |
; | |
function | |
: function stmt -> new Ast.Program($2) | |
| /* NULL */ | |
; | |
stmt_list | |
: stmt -> $1 | |
| stmt_list stmt -> new Ast.Eol($1, $2) | |
; | |
stmt | |
: ';' -> new Ast.Eol(Ast.Nul, Ast.Nul) | |
| expr ';' -> $1 | |
| PRINT expr ';' -> new Ast.Print($2) | |
| VARIABLE '=' expr ';' -> new Ast.Let(new Ast.Var($1), $3) | |
| WHILE '(' expr ')' stmt -> new Ast.While($3, $5) | |
| IF '(' expr ')' stmt %prec IFX -> new Ast.If($3, $5) | |
| IF '(' expr ')' stmt ELSE stmt -> new Ast.If($3, $5, $7) | |
| '{' stmt_list '}' -> $2 | |
; | |
expr | |
: INTEGER -> new Ast.Const($1) | |
| VARIABLE -> new Ast.Var($1) | |
| '-' expr %prec UMINUS -> new Ast.Sub(Ast.Zer, $2) | |
| expr '+' expr -> new Ast.Add($1, $3) | |
| expr '-' expr -> new Ast.Sub($1, $3) | |
| expr '*' expr -> new Ast.Mul($1, $3) | |
| expr '/' expr -> new Ast.Div($1, $3) | |
| expr '<' expr -> new Ast.LT($1, $3) | |
| expr '>' expr -> new Ast.GT($1, $3) | |
| expr GE expr -> new Ast.GE($1, $3) | |
| expr LE expr -> new Ast.LE($1, $3) | |
| expr NE expr -> new Ast.NE($1, $3) | |
| expr EQ expr -> new Ast.EQ($1, $3) | |
| '(' expr ')' -> $2 | |
; | |
%% |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment