是否有一种简单的方法可以让Jison计算器解析器返回符号结果?

时间:2014-10-01 12:35:35

标签: jison

Jison解析器返回计算结果:

calculator.parse("2^3"); // returns 8
calculator.parse("x^2"); // gives a parse err

我希望它返回符号表达式:

calculator.parse("x^2");
// should return
// "Math.pow(x,2)"

calculator.parse("x^(x+1)");
// should return
// "Math.pow(x,x+1)"

calculator.parse("cos(x)");
// should return
// "Math.cos(x)"

3 个答案:

答案 0 :(得分:1)

如果您需要的内容很简单,那么可能会通过修改计算器来实现。例如:

  1. 在令牌列表中IDENTIFIER之后添加NUMBER令牌:

    [a-z]                 return 'IDENTIFIER'
    

    这允许将单个小写字母用作标识。

  2. 修改e '^' e规则以返回字符串而不是计算值:

    | e '^' e
        {$$ = "Math.pow(" + $1 + "," + $3 + ");"}
    
  3. 将新规则添加到e的规则列表中:

    | IDENTIFIER
    

    (无需采取明确行动。)

  4. 通过解析这些更改,x^2会产生"Math.pow(x,2);"

    为了支持运算符,其他规则必须像e '^' e那样修改,以返回字符串而不是数学结果。

    这是非常原始的,不会优化可以优化的东西。例如,当1^2可以优化为"Math.pow(1, 2)"时,1将输出为{{1}}。

答案 1 :(得分:0)

没有

不是一件容易的事。取决于你所谓的'简单'。您需要定义令牌。然后象征性地操纵那些令牌。还有东西。

我不认为计算器会是一个很好的起点,无论如何它抛弃它并从头开始编写JS符号解析器语法并不是一个问题。

只是为每个人节省一些谷歌时间,这就是我们所说的:http://zaach.github.io/jison/demos/calc/

答案 2 :(得分:0)

(基于@Louis的回答和评论)

以下是使用jison的基本符号计算器的代码:

/* description: Parses and executes mathematical expressions. */

/* lexical grammar */
%lex
%%

\s+                   /* skip whitespace */ 
(acos|asin|atan|atan2|cos|log|sin|sqrt|tan) return 'FUNCTION'
[0-9]+("."[0-9]+)?\b  return 'NUMBER'
[a-z]                 return 'IDENTIFIER'
"|"                   return '|'
"*"                   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
        { typeof console !== 'undefined' ? console.log($1) : print($1);
          return $1; }
    ;

e
    : e '+' e
        {$$ = $1 + " + " + $3;}
    | e '-' e
        {$$ = $1 + "-" + $3;}
    | e '*' e
        {$$ = $1 + "*" + $3;}
    | e '/' e
        {$$ = $1 + "/" + $3;}
    | e '^' e
        {$$ = "Math.pow(" + $1 + ", " + $3 + ");"}
    | e '!'
        {{
          $$ = (function fact (n) { return n==0 ? 1 : fact(n-1) * n })($1);
        }}
    | e '%'
        {$$ = $1/100;}
    | '-' e %prec UMINUS
        {$$ = -$2;}
    | '(' e ')'
        {$$ = $2;}
    | FUNCTION '(' e ')'
        {$$ = "Math." + $1 + "(" + $3 + ")";}
    | '|' e '|'
        {$$ = "Math.abs(" + $2 + ")";}
    | NUMBER
        {$$ = Number(yytext);}
    | E
        {$$ = Math.E;}
    | PI
        {$$ = Math.PI;}
    | IDENTIFIER
    | FUNCTION
    ;