Parsec:在2014年获得buildexpressionParser示例到typecheck

时间:2014-10-23 20:48:26

标签: haskell parsec

以下是http://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-Expr.html的示例:

expr    = buildExpressionParser table term
        <?> "expression"

term    =  parens expr 
        <|> natural
        <?> "simple expression"

table   = [ [prefix "-" negate, prefix "+" id ]
        , [postfix "++" (+1)]
        , [binary "*" (*) AssocLeft, binary "/" (div) AssocLeft ]
        , [binary "+" (+) AssocLeft, binary "-" (-)   AssocLeft ]
        ]

binary  name fun assoc = Infix (do{ reservedOp name; return fun }) assoc
prefix  name fun       = Prefix (do{ reservedOp name; return fun })
postfix name fun       = Postfix (do{ reservedOp name; return fun })

似乎你需要一些导入才能开始:

import Text.Parsec
import Text.Parsec.Expr
import Text.Parsec.Token

现在它几乎没有在每一行都进行过类型检查。

有谁知道如何修复它?

更新

错误看起来像这样:

Couldn't match expected type ‘ParsecT s u m a0’
            with actual type ‘String -> ParsecT s9 u9 m9 ()’
Relevant bindings include
  name :: GenTokenParser s9 u9 m9 (bound at Eval2.hs:28:9)
  postfix :: GenTokenParser s9 u9 m9 -> (a -> a) -> Operator s u m a
    (bound at Eval2.hs:28:1)
Probable cause: ‘reservedOp’ is applied to too few arguments
In a stmt of a 'do' block: reservedOp name
In the first argument of ‘Postfix’, namely
  ‘(do { reservedOp name;
         return fun })’

让我对reservedOp

的类型感到好奇
λ :t reservedOp
reservedOp
  :: GenTokenParser s u m
     -> String -> Text.Parsec.Prim.ParsecT s u m ()

所以在这里查看文档http://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-Token.html

reservedOp :: String -> ParsecT s u m ()

奥利?那么GenTokenParser s u m是什么?我如何获得一个?

只是为了好玩

查看此类型。它可能意味着什么?

λ :t TokenParser
TokenParser
:: Text.Parsec.Prim.ParsecT s u m String
 -> (String -> Text.Parsec.Prim.ParsecT s u m ())
 -> Text.Parsec.Prim.ParsecT s u m String
 -> (String -> Text.Parsec.Prim.ParsecT s u m ())
 -> Text.Parsec.Prim.ParsecT s u m Char
 -> Text.Parsec.Prim.ParsecT s u m String
 -> Text.Parsec.Prim.ParsecT s u m Integer
 -> Text.Parsec.Prim.ParsecT s u m Integer
 -> Text.Parsec.Prim.ParsecT s u m Double
 -> Text.Parsec.Prim.ParsecT s u m (Either Integer Double)
 -> Text.Parsec.Prim.ParsecT s u m Integer
 -> Text.Parsec.Prim.ParsecT s u m Integer
 -> Text.Parsec.Prim.ParsecT s u m Integer
 -> (String -> Text.Parsec.Prim.ParsecT s u m String)
 -> (forall a.
     Text.Parsec.Prim.ParsecT s u m a
     -> Text.Parsec.Prim.ParsecT s u m a)
 -> Text.Parsec.Prim.ParsecT s u m ()
 -> (forall a.
     Text.Parsec.Prim.ParsecT s u m a
     -> Text.Parsec.Prim.ParsecT s u m a)
 -> (forall a.
     Text.Parsec.Prim.ParsecT s u m a
     -> Text.Parsec.Prim.ParsecT s u m a)
 -> (forall a.
     Text.Parsec.Prim.ParsecT s u m a
     -> Text.Parsec.Prim.ParsecT s u m a)
 -> (forall a.
     Text.Parsec.Prim.ParsecT s u m a
     -> Text.Parsec.Prim.ParsecT s u m a)
 -> (forall a.
     Text.Parsec.Prim.ParsecT s u m a
     -> Text.Parsec.Prim.ParsecT s u m a)
 -> Text.Parsec.Prim.ParsecT s u m String
 -> Text.Parsec.Prim.ParsecT s u m String
 -> Text.Parsec.Prim.ParsecT s u m String
 -> Text.Parsec.Prim.ParsecT s u m String
 -> (forall a.
     Text.Parsec.Prim.ParsecT s u m a
     -> Text.Parsec.Prim.ParsecT s u m [a])
 -> (forall a.
     Text.Parsec.Prim.ParsecT s u m a
     -> Text.Parsec.Prim.ParsecT s u m [a])
 -> (forall a.
     Text.Parsec.Prim.ParsecT s u m a
     -> Text.Parsec.Prim.ParsecT s u m [a])
 -> (forall a.
     Text.Parsec.Prim.ParsecT s u m a
     -> Text.Parsec.Prim.ParsecT s u m [a])
 -> GenTokenParser s u m

2 个答案:

答案 0 :(得分:6)

感谢@Christian Conkle和@bheklilr以及http://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-Token.html#v:makeTokenParser

以下是buildExpressionParser示例的2014版本,该版本应该在Parsec文档中,而不是在那里。

import Text.Parsec
import Text.Parsec.Expr
import Text.Parsec.Token
import Text.Parsec.Language (javaStyle)

lexer = makeTokenParser javaStyle

expr    = buildExpressionParser table term
        <?> "expression"

term    =  parens lexer expr 
        <|> natural lexer
        <?> "simple expression"

table   = [ [prefix "-" negate, prefix "+" id ]
        , [postfix "++" (+1)]
        , [binary "*" (*) AssocLeft, binary "/" (div) AssocLeft ]
        , [binary "+" (+) AssocLeft, binary "-" (-)   AssocLeft ]
        ]

binary  name fun assoc = Infix (do{ reservedOp lexer name; return fun }) assoc
prefix  name fun       = Prefix (do{ reservedOp lexer name; return fun })
postfix name fun       = Postfix (do{ reservedOp lexer name; return fun })

答案 1 :(得分:2)

数据构造函数GenTokenParser包含所有这些参数,因为它是具有大量字段的类型的构造函数。

制作TokenParser的方法确实是makeTokenParser。它的类型表示它返回GenTokenParser; TokenParser只是一种限制类型的同义词。 TokenParser stGenTokenParser String st Identity完全相同。

正如文档建议的那样,您可以将预设的语言定义传递给haskellDef。您也可以手动构建LanguageDef,这并不复杂;问你是否想要详细说明。中间立场是使用记录修改语法来修改预先定义的一个定义:makeTokenParser (haskellDef { commentStart = "<<", commentEnd = ">>" })