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