Skip to content

Instantly share code, notes, and snippets.

@darkoverlordofdata
Last active December 20, 2015 05:39
Show Gist options
  • Save darkoverlordofdata/6079782 to your computer and use it in GitHub Desktop.
Save darkoverlordofdata/6079782 to your computer and use it in GitHub Desktop.
Jison with CoffeeScript AST
#
# @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()
//
// 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