6

アレックスとレクサーを一般的に理解しようとしていますが、レクサーを実行するのに問題があります。

レクサーは「基本」ラッパーと「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リポジトリで例をコンパイルしようとすると、さまざまなエラーが発生します。バージョンの不一致に関連している可能性がありますか?ghc7.0.4を使用してcabalからalexをインストールしました。何か案は?

4

1 に答える 1

7

これはAlex3.0.1のバグのようです。コード1で他の無関係な問題を処理した後、バージョン2.3.3で正常に動作します。問題は、生成されたコードの次の行です。

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

生成されたコードの型に従うことにより、この関数は型を持つ必要があるように見えますAlexInput -> AlexInputが、AlexInput明らかに3タプルと4タプルの両方にすることはできません。

AlexInputこれは、2つのバージョン間での定義が変更されたために発生した可能性があります。

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コードにShowインスタンスがなく、すでにモナドにあるをLexeme呼び出しreturnています。alexMonadScanAlex

于 2012-05-09T15:54:05.413 に答える