我一直在尝试使用以下tutorial
中的详细信息创建解析器大部分代码都直接从教程中复制,只更改了几个名称。
import qualified Text.ParserCombinators.Parsec.Token as P
reserved = P.reserved lexer
integer = P.integer lexer
whiteSpace = P.whiteSpace lexer
identifier = P.identifier lexer
data Express = Seq [Express]
| ID String
| Num Integer
| BoolConst Bool
deriving (Show)
whileParser :: Parser Express
whileParser = whiteSpace >> expr7
expr7 = seqOfStmt
<|> expr8
seqOfStmt =
do list <- (sepBy1 expr8 whiteSpace)
return $ if length list == 1 then head list else Seq list
expr8 :: Parser Express
expr8 = name
<|> number
<|> bTerm
name :: Parser Express
name = fmap ID identifier
number :: Parser Express
number = fmap Num integer
bTerm :: Parser Express
bTerm = (reserved "True" >> return (BoolConst True ))
<|> (reserved "False" >> return (BoolConst False))
我知道这段代码可能很可笑,但我真的想更多地了解一下我出错的地方。我也认为这应该提供足够的信息,但如果不让我知道。
Error:
parse error on input `return'
我认为错误与不同的返回类型有关,这很奇怪,因为我试图在帖子开头使用教程作为我尝试的所有内容的基础。
提前致谢,
肖恩
答案 0 :(得分:3)
如果您对布局规则不满意,也可以使用不同的语法:
seqOfStmt =
do { list
<- (sepBy1 expr8 whiteSpace);
return $ if length
list == 1
then head list else Seq list;}
没有大括号和分号的布局被认为是优越的,但有两个原因:
规则很简单:
例如,您有2个属于 do 块的语句,因此它们必须在同一列中对齐。但是您已将return
与do
对齐,因此编译器将其视为:
do { list <- sepBy1 expr8 whiteSpace; };
return $ ....;
但你想要的是:
do {
list <- sepBy1 ....;
return $ .....;
}
(注意你可以省略大括号和分号,只要你让缩进完好无损就可以了。