0

今天,我一直在努力从解析器中删除所有 s/r 冲突。我设法删除了所有这些,但只有一个。

我的语言的语法应该是类似 haskell 的。而不是 a main,我有一个顶级表达式,即条目。

解析器如下所示。我还添加了 Happy 生成的文件的摘录Parser.info,其中描述了 shift/reduce 冲突。

据我所知,问题是一旦解析器遇到varname一个函数定义,它可能需要两个分支。它可以假设还有更多varname的 s,因为它当前正在解析一个函数定义(它有一个或多个参数),或者它可以停止将其解析为变量表达式。之后的可能varname只是另一种表达方式。

我玩过%prec规则,但似乎没有任何帮助。

我的第一个理由是,鉴于解析器想要转换函数定义,我可以赋予该规则优先级。我还尝试为=运算符(用于函数定义)添加优先级,以便我可以将其置于函数定义的优先级之下,但这也不起作用。我的猜测是我不完全理解解析器是如何工作的。非常感谢任何指针。

一个小的旁注,默认行为 - 我认为因此是一种转变 - 也是所需的行为。

state 25 contains 1 shift/reduce conflicts.

...

State 25

    Definition -> varname . ':' ':' Type                (rule 7)
    Definition -> varname . FunctionParameters '=' Exp bl    (rule 8)
    Atom -> varname .                                   (rule 20)

    '('            reduce using rule 20
    '<'            reduce using rule 20
    '>'            reduce using rule 20
    '/'            reduce using rule 20
    '*'            reduce using rule 20
    '-'            reduce using rule 20
    '+'            reduce using rule 20
    "eq?"          reduce using rule 20
    number         reduce using rule 20
    ':'            shift, and enter state 27
    varname        shift, and enter state 28
            (reduce using rule 20)

    %eof           reduce using rule 20

    FunctionParametersgoto state 26

解析器

%nonassoc PARS
%nonassoc VAR
%%
Program
 : Definitions Exp { Program $1 $2 }
 | Exp             { Program [] $1 }


Definitions
 : Definitions Definition { ($1 ++ [$2]) }
 | Definition             { [$1]         }


Definition
 : type upsym '=' Type                   { TypeDef $2 $4  }
 | varname ':' ':' Type                  { FTypeDef $1 $4 }
 | varname FunctionParameters '=' Exp bl { FDef $1 $2 $4  }


FunctionParameters
 : FunctionParameters varname %prec PARS { $1 ++ [$2] }
 | varname                    { [$1]    }



Exp
 : let varname '=' Exp "in" Exp { Let $2 $4 $6  }
 | if Exp then Exp else Exp     { If $2 $4 $6   }
 | "Lam" varname "->" Exp       { Abs $2 $4     }
 | Form                         { $1            }


Form
 : Juxt { $1 }


Juxt
 : Juxt Atom { App $1 $2 }
 | Atom      { $1        }


Atom
 : '(' Exp ')'         { $2                }
 | number              { Value $ Number $1 }
 | varname %prec VAR   { Var $1            }
 | Binfs               { Value $ Binf $1   }


Binfs
 : "eq?"    { BinfEqual }
 | '/'      { BinfDiv   }
 | '*'      { BinfTimes }
 | '+'      { BinfPlus  }
 | '-'      { BinfMinus }
 | '>'      { BinfGT    }
 | '<'      { BinfLT    }
4

0 回答 0