2012-05-09 19 views
6

Sto cercando di capire Alex e lexers in generale, ma ho problemi a eseguire il mio lexer.Haskell Alex - errore nel modello di wrapper

Ho scritto i lexer nei wrapper "basic" e "posn", ma non ho potuto nel wrapper "monad". Penso di dover usare il wrapper monad perché ho bisogno di raccogliere le stringhe e le posizioni dei token in input. Ho anche bisogno di più stati. Per ora sto cercando di eseguire questo semplice exmaple:

{ 
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 
} 

mie azioni sono undefined per ora. Quando provo a compilarlo, sto ottenendo questo errore:

➜ 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)' 

Sto anche ricevendo vari errori quando provo a compilare esempi nella repo github di Alex, potrebbe essere correlato con una versione non corrispondente? Ho installato alex da cabal con ghc 7.0.4. Qualche idea?

risposta

7

Questo sembra un bug in Alex 3.0.1. Funziona bene nella versione 2.3.3 dopo aver affrontato altri problemi non collegati nel codice . Il problema è questa riga nel codice generato:

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

Seguendo i tipi nel codice generato, sembra che questa funzione dovrebbe avere il tipo AlexInput -> AlexInput, ma AlexInput ovviamente non può essere sia un 3-tupla e una 4-tupla.

Questo probabilmente si è verificato perché la definizione di AlexInput è stata modificata tra le due versioni.

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

Da quello che posso dire, il codice corretto dovrebbe essere

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

e manualmente rendendo questo cambiamento nel codice generato rende compilare dopo aver affrontato le altre questioni.

Tuttavia, a meno che non si abbia bisogno di qualcosa dalla 3.0.1, suggerisco di eseguire il downgrade fino a quando ciò non viene risolto, in quanto dover mantenere le patch contro il codice generato è di solito più un problema che non ne vale la pena.

Il codice manca un'istanza Show per Lexeme e si sta anche chiamando return su alexMonadScan, che è già in Alex monade.

+0

Grazie! Devo aprire un problema nel suo repository GitHub? – sinan

+0

@sinan: Sì, sarebbe probabilmente una buona idea. – hammar