richard-to
12/24/2013 - 6:30 AM

Simple calculator language with variable substitution using jison

Simple calculator language with variable substitution using jison

%lex

%{
    var parser = yy.parser;
%}


%%
\n                    return 'NEWLINE'
\s+                   /* skip whitespace */
"$"[A-Z]+[A-Z0-9]*\b  return 'VARIABLE'
[0-9]+("."[0-9]+)?\b  return 'NUMBER'
"="                   return '='
"-"                   return '-'
"+"                   return '+'
"/"                   return '/'
"÷"                   return '/'
"*"                   return '*'
"^"                   return '^'
"("                   return '('
")"                   return ')'
","                   return ','
"√"                   return 'SQRT'
"SQRT"                return 'SQRT'
"COS"                 return 'COS'
"SIN"                 return 'SIN'
"TAN"                 return 'TAN'
"π"                   return 'PI'
"PI"                  return 'PI'
"LN2"                 return 'LN2'
"LN10"                return 'LN10'
"LOG2E"               return 'LOG2E'
"LOG10E"              return 'LOG10E'
'LOG'                 return 'LOG'
"E"                   return 'E'
<<EOF>>               return 'EOF'

/lex

%start pgm

%right '='
%left '+' '-'
%left '*' '/'
%right '^'
%left UMINUS

%%

pgm
    : el EOF
        {
            var results = yy.parser.getResults();
            yy.parser.clearResults();
            return results;
        }
    ;
el
    : e NEWLINE el
        { yy.parser.addResult($1); }
    | e
        { yy.parser.addResult($1); }
    ;

e
    : NUMBER
        {$$ = Number(yytext);}
    |VARIABLE '=' e
        {
            yy.parser.setVar($1, $3);
            $$ = $3;
        }
    | VARIABLE
        {$$ =  yy.parser.getVar($1); }
    | e '+' e
        {$$ = $1+$3; }
    | e '-' e
        {$$ = $1-$3;}
    | e '*' e
        {$$ = $1*$3;}
    | e '/' e
        {$$ = $1/$3;}
    | e '^' 'e'
        {$$ = Math.pow($1, $3);}
    | SQRT '(' e ')'
        {$$ = Math.sqrt($3);}
    | COS '(' e ')'
        {$$ = Math.cos($3);}
    | SIN '(' e ')'
        {$$ = Math.sin($3);}
    | TAN '(' e ')'
        {$$ = Math.tan($3);}
    | '-' e %prec UMINUS
        {$$ = -$2;}
    | '(' e ')'
        {$$ = ($2);}
    | E
        {$$ = Math.E;}
    | PI
        {$$ = Math.PI;}
    | LOG '(' e ',' e ')'
        {$$ = Math.log($3) / Math.log($5);}
    | LOG '(' e ')'
        {$$ = Math.log($3);}
    | LN2
        {$$ = Math.LN2;}
    | LN10
        {$$ = Math.LN10;}
    | LOG2E
        {$$ = Math.LOG2E;}
    | LOG10E
        {$$ = Math.LOG10E;}
    ;

%%

parser.addResult = function(value) {
    if (!this._results) {
        this._results = [];
    }
    this._results.push(value);
}

parser.getResults = function() {
    return this._results;
}

parser.clearResults = function() {
    this._results = [];
}

parser.getVar = function(key) {
    if (!this._varTable) {
        return undefined;
    } else {
        return this._varTable[key];
    }
}

parser.setVar = function(key, val) {
    if (!this._varTable) {
        this._varTable = {};
    }
    this._varTable[key] = val;
}