以下是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 })
Run Code Online (Sandbox Code Playgroud)
似乎你需要一些导入才能开始:
import Text.Parsec
import Text.Parsec.Expr
import Text.Parsec.Token
Run Code Online (Sandbox Code Playgroud)
现在它几乎没有在每一行都进行过类似的检查.
有谁知道如何修理它?
错误看起来像这样:
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 })’
Run Code Online (Sandbox Code Playgroud)
让我对这种类型感到好奇 reservedOp
? :t reservedOp
reservedOp
:: GenTokenParser s u m
-> String -> Text.Parsec.Prim.ParsecT s u m ()
Run Code Online (Sandbox Code Playgroud)
所以在这里查看文档http://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-Token.html:
reservedOp :: String -> ParsecT s u m ()
Run Code Online (Sandbox Code Playgroud)
奥利?那是什么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
Run Code Online (Sandbox Code Playgroud)
谢谢@Christian Conkle和@bheklilr这里http://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-Token.html#v:makeTokenParser
这是2014年版本的buildExpressionParser示例,应该在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 })
Run Code Online (Sandbox Code Playgroud)
数据构造函数GenTokenParser具有所有这些参数,因为它是具有大量字段的类型的构造函数。
制作 a 的方法TokenParser确实是 with makeTokenParser。它的类型表明它返回一个GenTokenParser; TokenParser只是一个受限类型的同义词。TokenParser st与 完全相同GenTokenParser String st Identity。
正如文档所建议的,您可以向其传递预制语言定义,例如haskellDef. 您也可以手动构造一个LanguageDef,这并不太复杂;询问您是否需要详细说明。中间立场是使用记录修改语法来修改预定义之一:makeTokenParser (haskellDef { commentStart = "<<", commentEnd = ">>" })。