Я пытаюсь написать лексер, который лексизирует 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
}
Codegen успешно выполнен, но компиляция завершилась следующей ошибкой:
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
) должен принимать аргумент типа AlexPosn
. Я запутался, потому что в AlexInput
уже есть AlexPosn
, и в руководстве пользователя прямо указано, что тип токена может быть любым, если он остается одинаковым для всех токенов.
Изменение определения из tok
, чтобы решить следующую проблему:
tok :: (AlexPosn -> ByteString -> Token) -> AlexInput -> Int64 -> Alex (AlexPron -> Token)
tok f (_, _, bs, _) len = pure $ \p -> f p (take len bs)
Но я понятия не имею, почему Алекс подбирает токен, чтобы взять AlexPosn