我正在尝试编写一个词法分析器,它可以对 c 样式的注释进行词法分析,而不是其他任何东西(现在)。
{
module Lexer where
import Prelude hiding (head, take, tail)
import Data.ByteString.Lazy
}
%wrapper "monad-bytestring"
@not_bc_end = ~\* | \* ~\/
tl :-
<0> $white+ ;
<0> "/*" { tok (\p s -> BCBegin p) `andBegin` bc }
<bc> .+ / not_bc_end { tok (\p s -> BCContent p s) }
<bc> "*/" { tok (\p s -> BCEnd p) `andBegin` 0 }
<0> "//" { tok (\p s -> LCBegin p) `andBegin` lc }
<lc> .*$ { tok (\p s -> LCContent p s) }
{
tok :: (AlexPosn -> ByteString -> Token) -> AlexInput -> Int64 -> Alex Token
tok f (p, _, bs, _) len = pure $ f p (take len bs)
data Token
= LCBegin AlexPosn
| LCContent AlexPosn ByteString
| BCBegin AlexPosn
| BCEnd AlexPosn
| BCContent AlexPosn ByteString
| End AlexPosn
alexEOF = pure End
}
代码生成成功,但编译失败,出现以下错误:
templates/wrappers.hs:288:9: error:
• Couldn't match type ‘Token’ with ‘AlexPosn -> Token’
Expected type: Alex (AlexPosn -> Token)
Actual type: Alex Token
• In a stmt of a 'do' block: action (ignorePendingBytes inp__) len
In the expression:
do alexSetInput inp__'
action (ignorePendingBytes inp__) len
In the expression:
let len = n' - n
in
do alexSetInput inp__'
action (ignorePendingBytes inp__) len
编译器抱怨令牌类型(包含在 中Alex
)必须采用 type 的参数AlexPosn
。我很困惑,因为用户指南中已经有一个AlexPosn
,AlexInput
并且用户指南明确指出,只要它们在所有令牌中保持相同,令牌类型就可以做任何事情。
将定义更改为tok
以下解决了该问题:
tok :: (AlexPosn -> ByteString -> Token) -> AlexInput -> Int64 -> Alex (AlexPron -> Token)
tok f (_, _, bs, _) len = pure $ \p -> f p (take len bs)
但我不知道为什么亚历克斯要让令牌采取AlexPosn