Alex 要求结果标记类型是某个采用 AlexPosn 的函数

Alex requies the result token type to be some function that takes a AlexPosn

我正在尝试编写一个词法分析器,它只对 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 中)必须采用 AlexPosn 类型的参数。我很困惑,因为 AlexInput 中已经有一个 AlexPosn 并且用户指南明确指出令牌类型可以购买任何东西,只要它们在所有令牌中保持相同即可。

tok 的定义更改为以下内容解决了问题:

tok :: (AlexPosn -> ByteString -> Token) -> AlexInput -> Int64 -> Alex (AlexPron -> Token)
tok f (_, _, bs, _) len = pure $ \p -> f p (take len bs)

但我不知道为什么 Alex 会强迫令牌接受 AlexPosn

我不小心在构造函数中添加了一个 AlexPosn 类型的字段 End