Search code examples
haskellparser-generatoralex

Haskell source generated by happy has error "parse error on input 'data'"


I'm trying out the happy parser generator of Haskell. After generating the module in happy.hs (no problem while generating!), I run the command ghc happy.hs, and I get the error: Line 297: parse error on input 'data'. Does anyone have solutions? Or tell me where can I get the solution?

I tried loading the module in GHCi, rather than compiling it using ghc. But it seems not to be working too - I get the same error.

Code in happy.y (happy source):

-- TODO: add more of my things!!!

{
    module Main where
}
%name calc
%tokentype { Token }
%error { parseError }
-- tokens
%token
    let { TokenLet }
    in { TokenIn }
    int { TokenInt $$ }
    var { TokenVar $$ }
    '=' { TokenEq }
    '+' { TokenPlus }
    '-' { TokenSub }
    '*' { TokenMul }
    '/' { TokenDvd }
    '(' { TokenOB }
    ')' { TokenCB }
%%
Exp : let var '=' Exp in Exp { Let $2 $4 $6 }
    | Exp1 { Exp1 $1 }
Exp1 : Exp1 '+' Term { Plus $1 $3 }
    | Exp1 '-' Term { Minus $1 $3 }
    | Term { Term $1 }
Term : Term '*' Factor { Times $1 $3 }
    | Term '/' Factor { Div $1 $3 }
    | Factor { Factor $1 }
Factor : int { Int $1 }
    | var { Var $1 }
    | '(' Exp ')' { Brack $2 }

{
    parseError :: [Token] -> a
    parseError _ = error "Parse error! please try again..."

    data Exp = Let String Exp Exp
        | Exp1 Exp1
    deriving Show

    data Exp1 = Plus Exp1 Term
        | Minus Exp1 Term
        | Term Term
    deriving Show

    data Term = Times Term Factor
        | Div Term Factor
        | Factor Factor
    deriving Show

    data Factor = Int Int
        | Var String
        | Brack Exp
    deriving Show

    -- the tokens 
    data Token = TokenLet
        | TokenIn
        | TokenInt Int
        | TokenVar String
        | TokenEq
        | TokenPlus
        | TokenMinus
        | TokenTimes
        | TokenDiv
        | TokenOB
        | TokenCB
        deriving Show

    -- the lexer
    lexer :: String -> [Token]
    lexer [] = []
    lexer (c:cs)
        | isSpace c = lexer cs
        | isAlpha c = lexVar (c:cs)
        | isDigit c = lexNum (c:cs)
    lexer ('=':cs) = TokenEq : lexer cs
    lexer ('+':cs) = TokenPlus : lexer cs
    lexer ('-':cs) = TokenMinus : lexer cs
    lexer ('*':cs) = TokenTimes : lexer cs
    lexer ('/':cs) = TokenDiv : lexer cs
    lexer ('(':cs) = TokenOB : lexer cs
    lexer (')':cs) = TokenCB : lexer cs
    lexNum cs = TokenInt (read num) : lexer rest
    where (num,rest) = span isDigit cs
    lexVar cs =
        case span isAlpha cs of
        ("let",rest) -> TokenLet : lexer rest
        ("in",rest) -> TokenIn : lexer rest
        (var,rest) -> TokenVar var : lexer rest

    -- the main function
    main = getContents >>= print . calc . lexer
}

Line that makes error in happy.hs and ±10 Lines(Lines 287~307, including):

287: calc tks = happyRunIdentity happySomeParser where
288:  happySomeParser = happyThen (happyParse action_0 tks) (\x -> case x of 289: {HappyAbsSyn4 z -> happyReturn z; _other -> notHappyAtAll })
290: 
291: happySeq = happyDontSeq
292:
293:
294: parseError :: [Token] -> a
295:    parseError _ = error "Parse error! please try again..."
296:
297:    data Exp = Let String Exp Exp       -- <= I get error on this line!
298:       | Exp1 Exp1
299:    deriving Show
300:
301:    data Exp1 = Plus Exp1 Term
302:        | Minus Exp1 Term
303:        | Term Term
304:    deriving Show
305:
306:    data Term = Times Term Factor
307:        | Div Term Factor

I expect the program to run smoothly without any errors, but it doesn't.


Solution

  • Happy produces its generated code on column 1 of the file. Therefore, to have your code be considered part of the same module-where block as the generated code (which you cannot control), it must also live on column 1 of the file.

    Delete four spaces from the beginning of the plain-Haskell lines of code in your happy file and you'll be on your way to the next error. Make sure that your deriving clauses and where clauses are indented one level from their surroundings when you are deleting spaces.