Skip to content

Instantly share code, notes, and snippets.

@katoy
Created July 28, 2012 05:33
Show Gist options
  • Save katoy/3191932 to your computer and use it in GitHub Desktop.
Save katoy/3191932 to your computer and use it in GitHub Desktop.
sample for jison
/* description: Parses end executes mathematical expressions. */
/* lexical grammar */
%lex
%%
\s+ /* skip whitespace */
[0-9]+("."[0-9]+)?\b return 'NUMBER'
"*" return '*'
"/" return '/'
"-" return '-'
"+" return '+'
"^" return '^'
"!" return '!'
"%" return '%'
"(" return '('
")" return ')'
"PI" return 'PI'
"E" return 'E'
<<EOF>> return 'EOF'
. return 'INVALID'
/lex
/* operator associations and precedence */
%left '+' '-'
%left '*' '/'
%left '^'
%right '!'
%right '%'
%left UMINUS
%start expressions
%% /* language grammar */
expressions
: e EOF
{ return $1; }
;
e
: e '+' e
{$$ = new (require("./calc_node")).Add($1, $3);}
| e '-' e
{$$ = new (require("./calc_node")).Sub($1, $3);}
| e '*' e
{$$ = new (require("./calc_node")).Mul($1, $3);}
| e '/' e
{$$ = new (require("./calc_node")).Div($1, $3);}
| e '^' e
{$$ = new (require("./calc_node")).Pow($1, $3);}
| e '!'
{$$ = new (require("./calc_node")).Factorial($1);}
| e '%'
{$$ = new (require("./calc_node")).Percentage($1);}
| '-' e %prec UMINUS
{$$ = new (require("./calc_node")).Minus($2);}
| '(' e ')'
{$$ = $2;}
| NUMBER
{$$ = Number($1);}
| E
{$$ = (require("./calc_node")).E;}
| PI
{$$ = (require("./calc_node")).PI;}
;
#
# See http://d.hatena.ne.jp/itchyny/20110711/1310387128
# Jison入門!!!
#
# $ node -f
# v0.8.4
#
# $ coffee -v
# CoffeeScript version 1.3.3
#
# $ jison calc.json # generate cakc.js
#
# $ cat testcalc
# 1 + 2
#
# $ coffee calc_main.coffee
# ========== 1 + 2
# <Add>
# left: 1
# right: 2
# ========== 1 * 2 + PI
# <Add>
# left: <Mul>
# left: 1
# right: 2
# right: <Object>
# value: 3.141592653589793
#
toString = (obj, indent = "") ->
s = '<' + ((if obj then obj.constructor.name else '')) + '>'
for key of obj
if obj.hasOwnProperty(key)
val = obj[key]
s += "\n#{indent}#{key}: "
if typeof val is 'object'
s += toString(val, indent + ' ')
else if typeof val is 'function'
s += val.name
else
s += val or ''
s += "\n#{indent}#{obj}" if typeof obj is 'number'
s
exec = (input) ->
require('./calc').parse(input)
args = process.argv.slice(1)
input = require('fs').readFileSync(require('path').resolve(args[1]), 'utf8')
x = exec(input)
console.log "========== #{input}"
console.log toString(x)
input = '1 * 2 + PI'
x = exec(input)
console.log "========== #{input}"
console.log toString(x)
function Add(x, y) { this.left = x; this.right = y; }
function Sub(x, y) { this.left = x; this.right = y; }
function Mul(x, y) { this.left = x; this.right = y; }
function Div(x, y) { this.left = x; this.right = y; }
function Pow(x, y) { this.left = x; this.right = y; }
function Factorial(x) { this.value = x; }
function Percentage(x) { this.value = x; }
function Minus(x) { this.value = x; }
E = { value : Math.E };
PI = { value : Math.PI };
module.exports.Add = Add;
module.exports.Sub = Sub;
module.exports.Mul = Mul;
module.exports.Div = Div;
module.exports.Pow = Pow;
module.exports.Factorial = Factorial;
module.exports.Percentage = Percentage;
module.exports.Minus = Minus;
module.exports.E = E;
module.exports.PI = PI;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment