Вопрос по haskell – Haskell Alex - ошибка в шаблоне оболочки

6

Я пытаюсь понять Алекса и лексеров в целом, но у меня возникают проблемы с запуском моего лексера.

Я написал лексеры в "Basic" и "posn" обертки, но я не могу в "монаде" обертка. Я думаю, что я должен использоватьmonad обертка, потому что мне нужно собирать строки и токены позиции на входе. Мне также нужно несколько состояний. Сейчас я пытаюсь запустить этот простой пример:

{
module Main (main) where
}

%wrapper "monad"

$whitespace = [\ \b\t\n\f\v\r]
$digit      = 0-9
$alpha      = [a-zA-Z_]
$upper      = [A-Z]
$lower      = [a-z]

@tidentifier = $upper($alpha|_|$digit)*
@identifier  = $lower($alpha|_|$digit)*


tokens :-

$whitespace+ ;
$upper $alpha+ { typeId }
$lower $alpha+ { id_ }
$digit+ { int }

{

data Lexeme = L AlexPosn LexemeClass String

data LexemeClass
        = TypeId String
        | Id String
        | Int Int
        | EOF
    deriving (Show, Eq)

typeId :: AlexInput -> Int -> Alex Lexeme
typeId = undefined

id_ :: AlexInput -> Int -> Alex Lexeme
id_ = undefined

int :: AlexInput -> Int -> Alex Lexeme
int = undefined

alexEOF = return (L undefined EOF "")

main :: IO ()
main = do
    s <- getContents
    let r = runAlex s $ do
                return alexMonadScan
    print r
}

Мои действияundefined теперь. Когда я пытаюсь его скомпилировать, я получаю эту ошибку:

➜  haskell  ghc --make Tokens.hs
[1 of 1] Compiling Main             ( Tokens.hs, Tokens.o )

templates/wrappers.hs:208:17:
    Couldn't match expected type `(AlexPosn, Char, [Byte], String)'
                with actual type `(t0, t1, t2)'
    Expected type: AlexInput
      Actual type: (t0, t1, t2)
    In the return type of a call of `ignorePendingBytes'
    In the first argument of `action', namely
      `(ignorePendingBytes inp)'

Я также получаю различные ошибки, когда пытаюсь скомпилировать примеры в репозитории Alex GitHub, может ли это быть связано с несовпадением версий? Я установил alex из cabal с ghc 7.0.4. Есть идеи?

Ваш Ответ

1   ответ
7

после решения некоторых других проблем, связанных с вашим кодом1, Проблема в этой строке в сгенерированном коде:

ignorePendingBytes (p,c,ps,s) = (p,c,s)

Следуя типам в сгенерированном коде, кажется, что эта функция должна иметь типAlexInput -> AlexInput, ноAlexInput очевидно, что это не может быть как 3-кортеж, так и 4-кортеж.

Это, вероятно, произошло потому, что определениеAlexInput был изменен между двумя версиями.

type AlexInput = (AlexPosn, Char, String)         -- v2.3.3
type AlexInput = (AlexPosn, Char, [Byte], String) -- v3.0.1

Из того, что я могу сказать, правильный код должен быть

ignorePendingBytes (p,c,ps,s) = (p,c,[],s)

а внесение этого изменения в сгенерированный код вручную приводит к его компиляции после решения других проблем.

Однако, если вам не нужно что-то из 3.0.1, я рекомендую понизить версию до тех пор, пока это не будет исправлено, так как необходимость поддерживать исправления для сгенерированного кода, как правило, доставляет больше хлопот, чем оно того стоит.

1 Your code is missing a Show instance for Lexeme and you're also calling return on alexMonadScan, which is already in the Alex monad.

@ Синан: Да, это, наверное, хорошая идея.
Спасибо! Должен ли я открыть вопрос в репозитории GitHub? sinan

Похожие вопросы