Haskell Parsec在语法中考虑了多个表达式的出现 [英] Haskell Parsec accounting for multiple expression occrrences in grammar
问题描述
我一直在尝试使用以下教程中的详细信息创建解析器
大部分代码直接从教程中复制,只改变了一些名字。
导入合格的Text.ParserCombinators.Parsec.Token为P
保留=保留的词法分析器
整数= P.integer的词法分析器
whiteSpace = P.whiteSpace词法分析器
identifier = P.identifier lexer
data Express = Seq [Express]
| ID字符串
|数字整数
| BoolConst Bool
派生(显示)
whileParser :: Parser Express
whileParser = whiteSpace>> expr7
expr7 = seqOfStmt
< |> expr8
$ b $ seqOfStmt =
do list < - (sepBy1 expr8 whiteSpace)
返回$ if length list == 1 then head list else Seq list
expr8 :: Parser Express
expr8 = name
< |>号码
< |> bTerm
名称:: Parser Express
name = fmap ID标识符
编号:: Parser Express
编号= fmap编号整数
bTerm :: Parser Express
bTerm =(保留True>> return(BoolConst True))
< |> (保留False>> return(BoolConst False))
我知道这段代码可能可笑,但我真的想更多地了解我要去哪里错了。
错误:
输入的解析错误`return'
我相信这个错误与不同的返回类型有关,这很奇怪,我试图在开始的时候使用教程作为我尝试的所有基础。
在此先感谢,
Seán
如果您对布局规则不满意,也可以使用不同的语法:
seqOfStmt =
do {list
< - (sepBy1 expr8 whiteSpace);
如果长度为
list == 1
则返回$如果其他列表为其他列表;}
无花括号和分号的布局被认为是优越的,原因有两个:
- 您不需要打字丑陋;和花括号
- 它强制你编写(大部分)可读的代码,不像上面给出的扭曲废话。
规则非常简单:
- 不要使用制表符,请使用空格。总是。 (你的编辑可以做到这一点,如果没有,扔掉它,它是crapware。)
- 属于一起的东西必须在同一列中对齐。
例如,您有2条属于 do 块的语句,因此它们必须对齐同一列。但是你已经将 return
与 do
对齐,因此编译器将此视为:
do {list< - sepBy1 expr8 whiteSpace; };
返回$ ....;
但是您想要的是:
do {
list< - sepBy1 ....;
返回$ .....; (注意,你可以省略大括号和分号,它将会只要您完整地保留缩进即可。
I have been trying to create a parser using details from the following tutorial
much of the code is copied directly from the tutorial with only a few names changed.
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))
I understand that this code might be laughable but I would really like to learn a bit more about where I'm going wrong. I also think that this should provide enough info but if not let me know.
Error:
parse error on input `return'
I believe that the error has something to do with different return types, which is strange because I have tried to use the tutorial at the start of the post as a basis for all that I am attempting.
Thanks in advance,
Seán
解决方案 If you are not comfortable with the layout rules, you may also use different syntax:
seqOfStmt =
do { list
<- (sepBy1 expr8 whiteSpace);
return $ if length
list == 1
then head list else Seq list;}
The layout without braces and semicolons is regarded superior, though, for 2 reasons:
- You don't need to type ugly ; and braces
- It forces you to write (mostly) readable code, unlike the distorted crap I gave as example above.
And the rules are really easy:
- Don't use tabs, use spaces. Always. (Your editor can do that, if not, throw it away, it's crapware.)
- Things that belong together must be aligned in the same column.
For example, you have 2 statements that belong to the do block, hence they must be aligned in the same column. But you have aligned the return
with the do
, hence the compiler sees this as:
do { list <- sepBy1 expr8 whiteSpace; };
return $ ....;
but what you want is this:
do {
list <- sepBy1 ....;
return $ .....;
}
(Note that you can just leave out the braces and the semicolon and it will be ok as long as you leave the indentation intact.
这篇关于Haskell Parsec在语法中考虑了多个表达式的出现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!