javascript - 向 bison/jison 计算器语言添加函数

标签 javascript parsing bison jison

我正在尝试扩展 Jison calculator example带有一些简单的功能。我对解析和 bison/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 甚至都没有定义。为什么在将其发送到函数之前不解析整个表达式列表?

最佳答案

下面的代码完成了您的要求。要点:

  1. expression_list 的规则现在构建一个实际的值列表,用于被调用的函数。

  2. expression_list 构建的列表被传递给 apply 以便它们成为被调用函数的参数(undefined is作为第一个参数,将 this 的值设置为 undefined)。

  3. 我已将 console.log 指令添加到 expression 的操作中,以便在运行生成的解析器时看到发生了什么在命令行。

  4. 我已将 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/

相关文章:

c - Bison 说开始符号不派生任何句子

parsing - 如何使用 Flex 实现两遍扫描仪?

javascript - polymer 核心标签和核心复选框动态

javascript - 使用 AngularJs 模板刷新页面

javascript - 如何将CSS代码放入javascript

javascript - 如何在 iframe 元素内滚动 textarea 元素

具有接受默认值且不抛出异常的 parseInt、parseLong、parseDouble 等的 Java 库?

javascript - 使用 jquery 从文本区域解析 HTML

Java - 解析文本文件 - 扫描仪、阅读器或其他?

c++ - 如何使用中间规则操作在 Bison 中创建短路评估?