我已经在Alex编写了一个词法分析器,我试图将它连接到一个用Happy编写的解析器。我会尽我所能在不粘贴大量代码的情况下总结我的问题。是什么原因导致Happy抛出解析错误?
从我的词法分析器的我的单元测试,字符串"\x7"
被lexed给我知道:
[TokenNonPrint '\x7', TokenEOF]
我的令牌类型(词法分析器吐出),是Token
。我定义lexWrap
和alexEOF
描述here,这给了我下面的头和令牌声明:
%name parseTokens
%tokentype { Token }
%lexer { lexWrap } { alexEOF }
%monad { Alex }
%error { parseError }
%token
NONPRINT {TokenNonPrint $$}
PLAIN { TokenPlain $$ }
我调用与以下解析器+词法组合:
parseExpr :: String -> Either String [Expr]
parseExpr s = runAlex s parseTokens
这里是我的前几个作品:
exprs :: { [Expr] }
exprs
: {- empty -} { trace "exprs 30" [] }
| exprs expr { trace "exprs 31" $ $2 : $1 }
nonprint :: { Cmd }
: NONPRINT { NonPrint $ parseNonPrint $1}
expr :: { Expr }
expr
: nonprint {trace "expr 44" $ Cmd $ $1}
| PLAIN { trace "expr 37" $ Plain $1 }
我将省略Expr
和的数据类型声明,因为它们很长,只有构造函数Cmd
和NonPrint
这里很重要。该功能parseNonPrint
在Parse.y的底部定义为:
parseNonPrint :: Char -> NonPrint
parseNonPrint '\x7' = Bell
而且,我的错误处理函数看起来像:
parseError :: Token -> Alex a
parseError tokens = error ("Error processing token: " ++ show tokens)
这样写的,我希望以下hspec测试通过:
parseExpr "\x7" `shouldBe` Right [Cmd (NonPrint Bell)]
但是,相反,我看到"exprs 30"
打印一次(即使我运行5不同单吨测试)和我所有的测试parseExpr
返回Right []
。我不明白为什么会是这样,但我改变了exprs
产量,以阻止它:
exprs :: { [Expr] }
exprs
: expr { trace "exprs 30" [$1] }
| exprs expr { trace "exprs 31" $ $2 : $1 }
现在我所有的测试失败对他们碰到的第一个令牌--- parseExpr "\x7"
失败:
uncaught exception: ErrorCall (Error processing token: TokenNonPrint '\a')
而且我很困惑,因为我期望解析器能够取得路径exprs -> expr -> nonprint -> NONPRINT
并成功。我不明白为什么这个输入会使解析器处于错误状态。没有任何trace
语句被击中(优化掉?)。
我在做什么错?
你能指点我们的代码 - 即github回购? – ErikR
@ user5402 https://github.com/pscollins/ansi-parser拥有所有代码。目前有点马虎,特别是测试标签。 –