【问题标题】:Operator precedence and associativity in a parser (Haskell)解析器中的运算符优先级和关联性 (Haskell)
【发布时间】:2010-02-24 13:35:42
【问题描述】:

我正在尝试扩展递归下降解析器来处理新的运算符并使它们正确关联。最初只有四个运算符(+ - / *),它们都具有相同的优先级。我正在查看的函数是 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)

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

BinOpApp 电源 (BinOpApp Plus (BinOpApp 电源 (LitInt 3) (LitInt 4)) (LitInt 2)) (LitInt 3)

这相当于中缀表示法(包括括号):

((3^4)+2)^3

我该如何解决这个问题?

【问题讨论】:

  • Haskell 中有很多很棒的解析器组合器。是否可以选择使用其中之一而不是在递归函数中实现自己的解析(这通常非常困难)?

标签: parsing haskell


【解决方案1】:

我写了一个paper on unparsing expressions using operator precedence。论文的附录有一个用 ML 编写的运算符优先级解析器,您可以轻松地适应 Haskell。代码可从上面的页面下载。

虽然 Haskell 有许多优秀的解析组合子库,但我从未见过一个既 (a) 足够简单让我容易理解又 (b) 支持任意优先级的运算符优先级解析的库。

【讨论】:

    【解决方案2】:

    我认为您应该查看现有的解析器组合器库。例如,parsec,查看它们如何实现优先级。特别是operator table

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-05
      • 2012-08-13
      • 2018-04-12
      • 2015-07-09
      • 1970-01-01
      • 1970-01-01
      • 2014-10-22
      • 2019-11-06
      相关资源
      最近更新 更多