Haskell Parsec accounting for multiple expression occrrences in grammar

笑着哭i 提交于 2019-12-25 01:54:10

问题


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


回答1:


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:

  1. You don't need to type ugly ; and braces
  2. It forces you to write (mostly) readable code, unlike the distorted crap I gave as example above.

And the rules are really easy:

  1. Don't use tabs, use spaces. Always. (Your editor can do that, if not, throw it away, it's crapware.)
  2. 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.



来源:https://stackoverflow.com/questions/15133648/haskell-parsec-accounting-for-multiple-expression-occrrences-in-grammar

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!