我正在尝试使用一些简单的功能扩展 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/