解析器中的运算符优先级和关联性(Haskell)

ben*_*wad 6 parsing haskell

我试图扩展一个递归下降的解析器来处理新的运算符,并使它们正确关联.最初只有四个运算符(+ - /*),它们都具有相同的优先级.我正在看的函数是parseExpRec函数:

parseExpRec               :: Exp -> [Token] -> (Exp, [Token])    
parseExpRec e  []         =  (e, [])
parseExpRec e1 (op : ts)  = 
 let (e2, ts') = parsePrimExp ts in
   case op of
    T_Power     -> parseExpRec (BinOpApp Power  e1 e2) ts'
    T_Plus      -> parseExpRec (BinOpApp Plus   e1 e2) ts'
    T_Minus     -> parseExpRec (BinOpApp Minus  e1 e2) ts'
    T_Times     -> parseExpRec (BinOpApp Times  e1 e2) ts'
    T_Divide    -> parseExpRec (BinOpApp Divide e1 e2) ts'
    T_GreaterThan   -> parseExpRec (BinOpApp GreaterThan    e1 e2) ts'
    T_LessThan      -> parseExpRec (BinOpApp LessThan       e1 e2) ts'
    T_GreaterOrEqual -> parseExpRec (BinOpApp GreaterOrEqual e1 e2) ts'
    T_LessOrEqual   -> parseExpRec (BinOpApp LessOrEqual    e1 e2) ts'
    T_EqualTo       -> parseExpRec (BinOpApp EqualTo        e1 e2) ts'
    _           -> (e1, op : ts)
Run Code Online (Sandbox Code Playgroud)

除了T_Plus,T_Minus,T_Times和T_Divide之外的所有模式匹配行都已由我添加(因此具有与Exp数据类型相关联的标记和扩展).但是,它们似乎都没有正确关联.例如,字符串"3 ^ 4 + 2 ^ 3"的计算结果为:

BinOpApp Power(BinOpApp Plus(BinOpApp Power(LitInt 3)(LitInt 4))(LitInt 2))(LitInt 3)

这与中缀表示法相同(包含括号):

((3 ^ 4)2)^ 3

我该如何解决这个问题?

Nor*_*sey 6

我写了一篇关于使用运算符优先级解析表达式论文.本文的附录有一个用ML编写的运算符优先级解析器,您可以轻松地适应Haskell.代码可从上面的页面下载.

虽然Haskell有很多很好的解析组合器库,但我从来没有见过(a)简单易于理解和(b)支持任意级别优先级的运算符优先级解析.


Don*_*art 5

我想你应该看一下现有的解析器组合库.例如,parsec,以了解它们如何实现优先级.特别是运算符表