1

我正在尝试 Haskell 的快乐解析器生成器。在happy.hs中生成模块后(生成时没问题!),我运行命令ghc happy.hs,我得到错误:Line 297: parse error on input 'data'. 有没有人有解决方案?或者告诉我在哪里可以得到解决方案?

我尝试在 GHCi 中加载模块,而不是使用 ghc 编译它。但它似乎也不起作用 - 我得到了同样的错误。

happy.y 中的代码(快乐源代码):

-- 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
}

在happy.hs 和±10 行中出错的行(第287~307 行,包括):

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

我希望程序能够顺利运行而不会出现任何错误,但事实并非如此。

4

1 回答 1

2

Happy 在文件的第 1 列生成其生成的代码。因此,要将您的代码视为与生成的代码(您无法控制)相同的块的一部分modulewhere它还必须位于文件的第 1 列。

删除快乐文件中普通 Haskell 代码行开头的四个空格,您将进入下一个错误。删除空格时,请确保您的deriving子句和where子句从其周围缩进一级。

于 2019-07-29T14:37:28.643 回答