我尝试使用一些简单的功能扩展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
似乎无法定义。为什么在将它发送到函数之前解析整个表达式列表呢?
答案 0 :(得分:2)
以下代码执行您要求的操作。突出点:
expression_list
的规则现在构建了一个与要调用的函数一起使用的实际值列表。
由expression_list
构建的列表传递给apply
,以便它们成为被调用函数的参数(undefined
作为第一个设置值的参数this
至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);}
;
答案 1 :(得分:1)
您需要在expression_list
的第一个作品中执行操作。默认操作只是将$1
复制到$$
,这意味着将丢弃附加的值。