首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Jison规则优先

Jison规则优先
EN

Stack Overflow用户
提问于 2015-01-19 08:53:34
回答 2查看 220关注 0票数 2

我试图在Jison中为一种编程语言创建语法,但在调用方面遇到了问题。用我的语言调用函数的语法如下:

代码语言:javascript
复制
functionName arg1 arg2 arg3

为了执行不仅仅是简单表达式的参数,需要将它们封装在括号中,如下所示:

代码语言:javascript
复制
functionName (1 + 2) (3 + 3) (otherFunction 5)

但是,我的语法中有一个错误,导致我的解析器将functionName arg1 arg2 arg3解释为functionName(arg1(arg2(arg3)))而不是functionName(arg1, arg2, arg3)

jison语法文件的相关部分如下所示:

代码语言:javascript
复制
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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-01-19 15:07:22

你可以通过玩优先关系游戏来做到这一点,但我认为最直接的解决方案是明确的。

您要说的是,callArgs不能直接包含callExpr。与您的示例一样,如果您希望传递一个callExpr作为参数,则需要将其括在括号中,在这种情况下,它将与其他产品(想必是parenExpr)相匹配。

所以你可以直接写:

代码语言:javascript
复制
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一样没有必要,因为它是默认操作。

票数 1
EN

Stack Overflow用户

发布于 2015-01-19 12:47:33

复习语法的其他部分来给出一个精确的答案是很重要的。我不知道我认为什么是对的,但是从我在代码中看到的情况来看,您可以根据您想要的顺序为参数显式地创建一个规则,而不必在另一个内部嵌套其中的一个:

代码语言:javascript
复制
args:
    |    "(" simple_expression ")" args { /*Do something with $2*/ }
    |    "\n"
    ;

我希望这对你有一点帮助。欢迎光临。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28020848

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档