2

我正在尝试编写一个词法分析器,它可以对 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。我很困惑,因为用户指南中已经有一个AlexPosnAlexInput并且用户指南明确指出,只要它们在所有令牌中保持相同,令牌类型就可以做任何事情。

将定义更改为tok以下解决了该问题:

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

但我不知道为什么亚历克斯要让令牌采取AlexPosn

4

1 回答 1

2

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

于 2020-03-24T11:15:45.400 回答