haskell - 如何使用 Text.Parsec.Expr 中的 buildExpressionParser 来解析这种语言?

标签 haskell parsec

我一直在尝试使用buildExpressionParser来解析一种语言,而且我几乎已经做到了。感谢Parsec.Expr repeated Prefix/Postfix operator not supported为了解决我的大问题之一。

这段代码片段说明了(我希望的)我最后的困难:

import Text.Parsec.Expr
import Text.Parsec

data Expr = Lit Char | A1 Expr | A2 Expr | B Expr Expr
  deriving (Show)

expr :: Parsec String () Expr
expr = buildExpressionParser table (fmap Lit digit)

prefix p = Prefix . chainl1 p $ return (.)

table =
  [ [prefix $ char ',' >> return A1]
  , [Infix   (char '*' >> return B) AssocNone]
  , [prefix $ char '.' >> return A2]]

这成功(并且正确)解析了 ,,0 , ..0 , .,0 , .0*0 ,和,0*0 ;但是,它无法解析 ,.0.0*.0 。我可以明白为什么这两个不解析,但我不知道如何更改解析器,以便成功的事件不会发生变化,而两个失败的事件会被解析。

“解决”这个问题的一种方法是更改​​ (fmap Lit digit)(fmap Lit Digit <|> expr) ,但是解析器会循环而不是出错。

欢迎咨询。

编辑:以下解析是关键:

> parseTest expr ".0*0"
A2 (B (Lit '0') (Lit '0'))

> parseTest expr ",0*0"
B (A1 (Lit '0')) (Lit '0')

最佳答案

获取“.”和 ',' 在某种程度上您可以将它们放在一起:

import Text.Parsec.Expr
import Text.Parsec

data Expr = Lit Char | A1 Expr | A2 Expr | B Expr Expr
  deriving (Show)

expr :: Parsec String () Expr
expr = buildExpressionParser table  (fmap Lit digit)
prefix p = Prefix . chainl1 p $ return (.)

table =
  [  [prefix $ (char ',' >> return A1) <|> (char '.' >> return A2)]
  , [Infix   (char '*' >> return B) AssocNone]
  , [prefix $ (char ',' >> return A1)] 
  ]

-- *Main> let f = parseTest expr
-- *Main> f ".,0"
-- A2 (A1 (Lit '0'))
-- *Main> f ".0*.0"
-- B (A2 (Lit '0')) (A2 (Lit '0'))
-- *Main> f ".0*,.0"
-- B (A2 (Lit '0')) (A1 (A2 (Lit '0')))
-- *Main> f ".,.0"
-- A2 (A1 (A2 (Lit '0')))
-- *Main> f ",.0"
-- A1 (A2 (Lit '0'))

编辑,这是之前明显不足的尝试

 table =
   [  [prefix $ (char ',' >> return A1) <|> (char '.' >> return A2)]
   , [Infix   (char '*' >> return B) AssocNone]
   ]

关于haskell - 如何使用 Text.Parsec.Expr 中的 buildExpressionParser 来解析这种语言?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11174775/

相关文章:

function - 为什么模式匹配中不允许使用 [x, y, _]

haskell - 使用 Foldl 和 Reader monad 递归地遍历 AST,无需样板

haskell - 一元类型混淆

parsing - 在解析过程中划分不同类型的术语

haskell io流内存

xml - 如何使用 Haskell 查询 RDF 数据?

haskell - 不在范围内,但以全名命名

haskell - 在haskell中使用oneOf,编译错误

parsing - Haskell/Parsec : How do you use the functions in Text. Parsec.Indent?

haskell - 使用 Haskell 的 Parsec 解析 ByteString