【问题标题】:Jison rule precedence吉森规则优先
【发布时间】:2015-01-19 23:13:18
【问题描述】:

我正在尝试为 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

【问题讨论】:

    标签: grammar bison jison


    【解决方案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”,应该写成@987654330 @。因此,您可能还想从callArgExpr 中删除binaryExpr,可能还有其他一些。我希望上面的模型能说明如何做到这一点。

    顺便说一句,我删除了所有空的产生式,假设它们是无意的(除非jison 对该语法有一些例外;我不是真正的jison 专家)。我删除了{ $$ = $1; },我认为jison 和经典的yacc/bison/etc 一样没有必要,因为它是默认操作。

    【讨论】:

    • 谢谢。你是对的。事实证明这是这样做的方法:)
    【解决方案2】:

    复习语法的其他部分以给出准确的答案很重要。我不知道我的想法是否正确,但是根据我在您的代码中看到的内容,您可以按照您想要的顺序为参数显式创建一个规则,而无需将一个嵌套在另一个中:

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

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

    【讨论】:

    • 我认为您误解了这个问题。我不想将参数括在括号中。只有复合参数。 a b c d 在我的语法中应该意味着 a(b, c, d) 在传统的 C 语言中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-15
    相关资源
    最近更新 更多