首页>Program>source

我正在尝试解析ocamlyacc(与常规yacc几乎相同)中的语法,该语法支持不带运算符的函数应用程序(例如Ocaml或Haskell),以及二进制和一元运算符的常规分类.我与'-'运算符发生了减少/减少冲突,该运算符可用于减法和负运算.这是我正在使用的语法示例:

%token <int> INT
%token <string> ID
%token MINUS
%start expr
%type <expr> expr
%nonassoc INT ID
%left MINUS
%left APPLY
%%
expr: INT
    { ExprInt $1 }
| ID
    { ExprId $1 }
| expr MINUS expr
    { ExprSub($1, $3) }
| MINUS expr
    { ExprNeg $2 }
| expr expr %prec APPLY
    { ExprApply($1, $2) };

问题在于,当您获得类似" a-b"的表达式时,解析器不知道该将其简化为" a(-b)"(b的否定,后跟应用程序)还是" a- b"(减法).减法减法是正确的.

最新回答
  • 11天前
    1 #

    不幸的是,我只能想出的唯一答案就是增加语法的复杂性。

    分裂 expr   进入维兹维兹   和 simple_expr

    只允许 expr_with_prefix   或 simple_expr   在申请中

    第一步将您的减少/减少冲突转变为转移/减少冲突,但是括号可以解决该问题。

    您将对'a b c'遇到相同的问题:是 (expr_with_prefix)   或 a(b(c)) ? 您还需要断开 (a(b))(c)   和所需的 applied_expression   在语法上。

    我认为这可以做到,但是我不确定:

    (applied_expression)
    

  • 11天前
    2 #

    最简单的答案就是忽略它,让默认的reduce / reduce分辨率处理它-减少语法中最先出现的规则.在这种情况下,这意味着减少 expr := INT | parenthesized_expr | expr MINUS expr parenthesized_expr := ( expr ) | ( applied_expr ) | ( expr_with_prefix ) applied_expr := expr expr expr_with_prefix := MINUS expr   优先于 expr MINUS expr ,这正是您想要的.看了 MINUS expr之后 ,您希望将其解析为二进制减号,而不是一元减号,然后再应用。

    a-b

  • c++:增强Lambda与凤凰
  • java:两个Calendar对象的小时数差异