我正在尝试使用一些简单的功能扩展 Jison calculator example。我对解析和野牛/jison 比较陌生,但这是我迄今为止的一些内容:

/* lexical grammar */
%lex

%{
  var funcs = {
    pow: function(a, b) { return Math.pow(a, b); },
    test: function(a) { return a*2; }
  }
%}

%%

\s+                   /* skip whitespace */
[0-9]+("."[0-9]+)?\b  return 'NUMBER'
[a-zA-Z]+             return 'NAME'
","                   return ','
"*"                   return '*'
"("                   return '('
")"                   return ')'
<<EOF>>               return 'EOF'
.                     return 'INVALID'

/lex

%start expressions

%% /* language grammar */
expressions
    : e EOF
      { return $1; }
    ;

expression_list
    : expression_list ',' e
    | e
    ;

e
    : e '*' e
        {$$ = $1*$3;}
    | '(' e ')'
        {$$ = $2;}
    | NUMBER
        {$$ = Number(yytext);}
    | NAME '(' expression_list ')'
        {$$ = funcs[$NAME]($expression_list);}
    ;

问题是函数只得到一个传递给它们的参数。例如:
test(2) -> 4
pow(2,3) -> null

事实上,如果你 console.log pow 的参数,看起来 b 甚至没有定义。为什么在将其发送到函数之前不解析整个表达式列表?

最佳答案

以下代码执行您的要求。要点:

  • expression_list 的规则现在构建一个实际的值列表,用于被调用的函数。
  • expression_list 构建的列表被传递给 apply ,以便它们成为被调用函数的参数( undefined 是将 this 的值设置为 undefined 的第一个参数)。
  • 我在 console.log 的 Action 中添加了一条 expression 指令,这样我就能在命令行中运行结果解析器时看到发生了什么。
  • 我已经将 funcs 的定义移到一开始。 jison 只是没有将它放在最终文件中的正确位置。

  • 这是最终文件:
    %{var funcs = {
        pow: function(a, b) { return Math.pow(a, b); },
        test: function(a) { return a*2; }
      }
    %}
    
    /* lexical grammar */
    %lex
    
    %%
    
    \s+                   /* skip whitespace */
    [0-9]+("."[0-9]+)?\b  return 'NUMBER'
    [a-zA-Z]+             return 'NAME'
    ","                   return ','
    "*"                   return '*'
    "("                   return '('
    ")"                   return ')'
    <<EOF>>               return 'EOF'
    .                     return 'INVALID'
    
    /lex
    
    %start expressions
    
    %% /* language grammar */
    expressions
        : e EOF
          { console.log($1); return $1; }
        ;
    
    expression_list
        : expression_list ',' e
          { $$ = $1.concat([$3]); }
        | e
          { $$ = [$1]; }
        ;
    
    e
        : e '*' e
            {$$ = $1*$3;}
        | '(' e ')'
            {$$ = $2;}
        | NUMBER
            {$$ = Number(yytext);}
        | NAME '(' expression_list ')'
            {$$ = funcs[$NAME].apply(undefined, $expression_list);}
        ;
    

    关于javascript - 向 bison/jison 计算器语言添加函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26661565/

    10-11 22:43
    查看更多