Jison规则优先权

时间:2015-01-19 08:53:34

标签: grammar bison jison

我试图在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

2 个答案:

答案 0 :(得分:1)

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

您想说的是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,我认为{{1}}与经典的yacc / bison / etc中一样不必要,因为它是默认操作。

答案 1 :(得分:0)

重要的是要检查语法的其他部分以给出准确的答案。我不知道我认为是对的,但是从我在你的代码中看到的,你可以按照你想要的顺序为参数显式创建一个规则,而不是将一个嵌套在另一个中:

args:
    |    "(" simple_expression ")" args { /*Do something with $2*/ }
    |    "\n"
    ;

我希望这对你有所帮助。问候。