我试图在Jison中为一种编程语言创建语法,但在调用方面遇到了问题。用我的语言调用函数的语法如下:
functionName arg1 arg2 arg3为了执行不仅仅是简单表达式的参数,需要将它们封装在括号中,如下所示:
functionName (1 + 2) (3 + 3) (otherFunction 5)但是,我的语法中有一个错误,导致我的解析器将functionName arg1 arg2 arg3解释为functionName(arg1(arg2(arg3)))而不是functionName(arg1, arg2, arg3)。
jison语法文件的相关部分如下所示:
expr:
| constantExpr { $$ = $1; }
| binaryExpr { $$ = $1; }
| callExpr { $$ = $1; }
| tupleExpr { $$ = $1; }
| parenExpr { $$ = $1; }
| identExpr { $$ = $1; }
| blockExpr { $$ = $1; }
;
callArgs:
| callArgs expr { $$ = $1.concat($2); }
| expr { $$ = [$1]; }
;
callExpr:
| path callArgs { $$ = ast.Expr.Call($1, $2); }
;
identExpr:
| path { $$ = ast.Expr.Ident($1); }
;我怎样才能让Jison更喜欢callArgs而不是expr
发布于 2015-01-19 15:07:22
你可以通过玩优先关系游戏来做到这一点,但我认为最直接的解决方案是明确的。
您要说的是,callArgs不能直接包含callExpr。与您的示例一样,如果您希望传递一个callExpr作为参数,则需要将其括在括号中,在这种情况下,它将与其他产品(想必是parenExpr)相匹配。
所以你可以直接写:
callArgExpr
: constantExpr
| binaryExpr
| tupleExpr
| parenExpr
| identExpr
| blockExpr
;
expr
: callArgExpr
| callExpr
;
callArgs
: callArgs callArgExpr { $$ = $1.concat($2); }
| callArgExpr { $$ = [$1]; }
;
callExpr
: path callArgs { $$ = ast.Expr.Call($1, $2); }
;实际上,您很可能希望进一步限制callArgs,因为(如果我理解正确的话) func a + b并不意味着“将a+b应用于func",这应该是编写func (a + b)的。因此,您可能还希望从binaryExpr中删除callArgExpr,并可能删除其他内容。我希望上面的模型说明了如何做到这一点。
顺便说一句,我删除了所有的空产品,假设它们是无意的(除非jison对这个语法有一些例外;我并不是一个真正的jison专家)。我删除了{ $$ = $1; },我认为它在jison中和经典的yacc/bison/etc一样没有必要,因为它是默认操作。
发布于 2015-01-19 12:47:33
复习语法的其他部分来给出一个精确的答案是很重要的。我不知道我认为什么是对的,但是从我在代码中看到的情况来看,您可以根据您想要的顺序为参数显式地创建一个规则,而不必在另一个内部嵌套其中的一个:
args:
| "(" simple_expression ")" args { /*Do something with $2*/ }
| "\n"
;我希望这对你有一点帮助。欢迎光临。
https://stackoverflow.com/questions/28020848
复制相似问题