我正在尝试扩展吉森计算器示例 http://zaach.github.io/jison/try/具有一些简单的功能。我对解析和 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
甚至没有定义。为什么在将整个表达式列表发送到函数之前不解析它?
以下代码可以满足您的要求。要点:
规则为expression_list
现在构建一个与正在调用的函数一起使用的实际值列表。
该列表由expression_list
被传递给apply
以便它们成为被调用函数的参数(undefined
是否作为第一个参数来设置值this
to undefined
).
我添加了一个console.log
行动指示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);}
;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)