|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- Alex wrapper code.
|
|
Packit |
2cbdf3 |
--
|
|
Packit |
2cbdf3 |
-- This code is in the PUBLIC DOMAIN; you may copy it freely and use
|
|
Packit |
2cbdf3 |
-- it for any purpose whatsoever.
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#if defined(ALEX_MONAD) || defined(ALEX_MONAD_BYTESTRING)
|
|
Packit |
2cbdf3 |
import Control.Applicative as App (Applicative (..))
|
|
Packit |
2cbdf3 |
import qualified Control.Monad (ap)
|
|
Packit |
2cbdf3 |
#endif
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
import Data.Word (Word8)
|
|
Packit |
2cbdf3 |
#if defined(ALEX_BASIC_BYTESTRING) || defined(ALEX_POSN_BYTESTRING) || defined(ALEX_MONAD_BYTESTRING)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
import Data.Int (Int64)
|
|
Packit |
2cbdf3 |
import qualified Data.Char
|
|
Packit |
2cbdf3 |
import qualified Data.ByteString.Lazy as ByteString
|
|
Packit |
2cbdf3 |
import qualified Data.ByteString.Internal as ByteString (w2c)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#elif defined(ALEX_STRICT_BYTESTRING)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
import qualified Data.Char
|
|
Packit |
2cbdf3 |
import qualified Data.ByteString as ByteString
|
|
Packit |
2cbdf3 |
import qualified Data.ByteString.Internal as ByteString hiding (ByteString)
|
|
Packit |
2cbdf3 |
import qualified Data.ByteString.Unsafe as ByteString
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#else
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
import Data.Char (ord)
|
|
Packit |
2cbdf3 |
import qualified Data.Bits
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- | Encode a Haskell String to a list of Word8 values, in UTF8 format.
|
|
Packit |
2cbdf3 |
utf8Encode :: Char -> [Word8]
|
|
Packit |
2cbdf3 |
utf8Encode = map fromIntegral . go . ord
|
|
Packit |
2cbdf3 |
where
|
|
Packit |
2cbdf3 |
go oc
|
|
Packit |
2cbdf3 |
| oc <= 0x7f = [oc]
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
| oc <= 0x7ff = [ 0xc0 + (oc `Data.Bits.shiftR` 6)
|
|
Packit |
2cbdf3 |
, 0x80 + oc Data.Bits..&. 0x3f
|
|
Packit |
2cbdf3 |
]
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
| oc <= 0xffff = [ 0xe0 + (oc `Data.Bits.shiftR` 12)
|
|
Packit |
2cbdf3 |
, 0x80 + ((oc `Data.Bits.shiftR` 6) Data.Bits..&. 0x3f)
|
|
Packit |
2cbdf3 |
, 0x80 + oc Data.Bits..&. 0x3f
|
|
Packit |
2cbdf3 |
]
|
|
Packit |
2cbdf3 |
| otherwise = [ 0xf0 + (oc `Data.Bits.shiftR` 18)
|
|
Packit |
2cbdf3 |
, 0x80 + ((oc `Data.Bits.shiftR` 12) Data.Bits..&. 0x3f)
|
|
Packit |
2cbdf3 |
, 0x80 + ((oc `Data.Bits.shiftR` 6) Data.Bits..&. 0x3f)
|
|
Packit |
2cbdf3 |
, 0x80 + oc Data.Bits..&. 0x3f
|
|
Packit |
2cbdf3 |
]
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#endif
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
type Byte = Word8
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- The input type
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#if defined(ALEX_POSN) || defined(ALEX_MONAD) || defined(ALEX_GSCAN)
|
|
Packit |
2cbdf3 |
type AlexInput = (AlexPosn, -- current position,
|
|
Packit |
2cbdf3 |
Char, -- previous char
|
|
Packit |
2cbdf3 |
[Byte], -- pending bytes on current char
|
|
Packit |
2cbdf3 |
String) -- current input string
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
ignorePendingBytes :: AlexInput -> AlexInput
|
|
Packit |
2cbdf3 |
ignorePendingBytes (p,c,_ps,s) = (p,c,[],s)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexInputPrevChar :: AlexInput -> Char
|
|
Packit |
2cbdf3 |
alexInputPrevChar (_p,c,_bs,_s) = c
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexGetByte :: AlexInput -> Maybe (Byte,AlexInput)
|
|
Packit |
2cbdf3 |
alexGetByte (p,c,(b:bs),s) = Just (b,(p,c,bs,s))
|
|
Packit |
2cbdf3 |
alexGetByte (_,_,[],[]) = Nothing
|
|
Packit |
2cbdf3 |
alexGetByte (p,_,[],(c:s)) = let p' = alexMove p c
|
|
Packit |
2cbdf3 |
(b:bs) = utf8Encode c
|
|
Packit |
2cbdf3 |
in p' `seq` Just (b, (p', c, bs, s))
|
|
Packit |
2cbdf3 |
#endif
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#if defined(ALEX_POSN_BYTESTRING) || defined(ALEX_MONAD_BYTESTRING)
|
|
Packit |
2cbdf3 |
type AlexInput = (AlexPosn, -- current position,
|
|
Packit |
2cbdf3 |
Char, -- previous char
|
|
Packit |
2cbdf3 |
ByteString.ByteString, -- current input string
|
|
Packit |
2cbdf3 |
Int64) -- bytes consumed so far
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
ignorePendingBytes :: AlexInput -> AlexInput
|
|
Packit |
2cbdf3 |
ignorePendingBytes i = i -- no pending bytes when lexing bytestrings
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexInputPrevChar :: AlexInput -> Char
|
|
Packit |
2cbdf3 |
alexInputPrevChar (_,c,_,_) = c
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexGetByte :: AlexInput -> Maybe (Byte,AlexInput)
|
|
Packit |
2cbdf3 |
alexGetByte (p,_,cs,n) =
|
|
Packit |
2cbdf3 |
case ByteString.uncons cs of
|
|
Packit |
2cbdf3 |
Nothing -> Nothing
|
|
Packit |
2cbdf3 |
Just (b, cs') ->
|
|
Packit |
2cbdf3 |
let c = ByteString.w2c b
|
|
Packit |
2cbdf3 |
p' = alexMove p c
|
|
Packit |
2cbdf3 |
n' = n+1
|
|
Packit |
2cbdf3 |
in p' `seq` cs' `seq` n' `seq` Just (b, (p', c, cs',n'))
|
|
Packit |
2cbdf3 |
#endif
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#ifdef ALEX_BASIC_BYTESTRING
|
|
Packit |
2cbdf3 |
data AlexInput = AlexInput { alexChar :: {-# UNPACK #-} !Char, -- previous char
|
|
Packit |
2cbdf3 |
alexStr :: !ByteString.ByteString, -- current input string
|
|
Packit |
2cbdf3 |
alexBytePos :: {-# UNPACK #-} !Int64} -- bytes consumed so far
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexInputPrevChar :: AlexInput -> Char
|
|
Packit |
2cbdf3 |
alexInputPrevChar = alexChar
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexGetByte (AlexInput {alexStr=cs,alexBytePos=n}) =
|
|
Packit |
2cbdf3 |
case ByteString.uncons cs of
|
|
Packit |
2cbdf3 |
Nothing -> Nothing
|
|
Packit |
2cbdf3 |
Just (c, rest) ->
|
|
Packit |
2cbdf3 |
Just (c, AlexInput {
|
|
Packit |
2cbdf3 |
alexChar = ByteString.w2c c,
|
|
Packit |
2cbdf3 |
alexStr = rest,
|
|
Packit |
2cbdf3 |
alexBytePos = n+1})
|
|
Packit |
2cbdf3 |
#endif
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#ifdef ALEX_STRICT_BYTESTRING
|
|
Packit |
2cbdf3 |
data AlexInput = AlexInput { alexChar :: {-# UNPACK #-} !Char,
|
|
Packit |
2cbdf3 |
alexStr :: {-# UNPACK #-} !ByteString.ByteString,
|
|
Packit |
2cbdf3 |
alexBytePos :: {-# UNPACK #-} !Int}
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexInputPrevChar :: AlexInput -> Char
|
|
Packit |
2cbdf3 |
alexInputPrevChar = alexChar
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexGetByte (AlexInput {alexStr=cs,alexBytePos=n}) =
|
|
Packit |
2cbdf3 |
case ByteString.uncons cs of
|
|
Packit |
2cbdf3 |
Nothing -> Nothing
|
|
Packit |
2cbdf3 |
Just (c, rest) ->
|
|
Packit |
2cbdf3 |
Just (c, AlexInput {
|
|
Packit |
2cbdf3 |
alexChar = ByteString.w2c c,
|
|
Packit |
2cbdf3 |
alexStr = rest,
|
|
Packit |
2cbdf3 |
alexBytePos = n+1})
|
|
Packit |
2cbdf3 |
#endif
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- Token positions
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- `Posn' records the location of a token in the input text. It has three
|
|
Packit |
2cbdf3 |
-- fields: the address (number of chacaters preceding the token), line number
|
|
Packit |
2cbdf3 |
-- and column of a token within the file. `start_pos' gives the position of the
|
|
Packit |
2cbdf3 |
-- start of the file and `eof_pos' a standard encoding for the end of file.
|
|
Packit |
2cbdf3 |
-- `move_pos' calculates the new position after traversing a given character,
|
|
Packit |
2cbdf3 |
-- assuming the usual eight character tab stops.
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#if defined(ALEX_POSN) || defined(ALEX_MONAD) || defined(ALEX_POSN_BYTESTRING) || defined(ALEX_MONAD_BYTESTRING) || defined(ALEX_GSCAN)
|
|
Packit |
2cbdf3 |
data AlexPosn = AlexPn !Int !Int !Int
|
|
Packit |
2cbdf3 |
deriving (Eq,Show)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexStartPos :: AlexPosn
|
|
Packit |
2cbdf3 |
alexStartPos = AlexPn 0 1 1
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexMove :: AlexPosn -> Char -> AlexPosn
|
|
Packit |
2cbdf3 |
alexMove (AlexPn a l c) '\t' = AlexPn (a+1) l (((c+alex_tab_size-1) `div` alex_tab_size)*alex_tab_size+1)
|
|
Packit |
2cbdf3 |
alexMove (AlexPn a l _) '\n' = AlexPn (a+1) (l+1) 1
|
|
Packit |
2cbdf3 |
alexMove (AlexPn a l c) _ = AlexPn (a+1) l (c+1)
|
|
Packit |
2cbdf3 |
#endif
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- Default monad
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#ifdef ALEX_MONAD
|
|
Packit |
2cbdf3 |
data AlexState = AlexState {
|
|
Packit |
2cbdf3 |
alex_pos :: !AlexPosn, -- position at current input location
|
|
Packit |
2cbdf3 |
alex_inp :: String, -- the current input
|
|
Packit |
2cbdf3 |
alex_chr :: !Char, -- the character before the input
|
|
Packit |
2cbdf3 |
alex_bytes :: [Byte],
|
|
Packit |
2cbdf3 |
alex_scd :: !Int -- the current startcode
|
|
Packit |
2cbdf3 |
#ifdef ALEX_MONAD_USER_STATE
|
|
Packit |
2cbdf3 |
, alex_ust :: AlexUserState -- AlexUserState will be defined in the user program
|
|
Packit |
2cbdf3 |
#endif
|
|
Packit |
2cbdf3 |
}
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- Compile with -funbox-strict-fields for best results!
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
runAlex :: String -> Alex a -> Either String a
|
|
Packit |
2cbdf3 |
runAlex input__ (Alex f)
|
|
Packit |
2cbdf3 |
= case f (AlexState {alex_pos = alexStartPos,
|
|
Packit |
2cbdf3 |
alex_inp = input__,
|
|
Packit |
2cbdf3 |
alex_chr = '\n',
|
|
Packit |
2cbdf3 |
alex_bytes = [],
|
|
Packit |
2cbdf3 |
#ifdef ALEX_MONAD_USER_STATE
|
|
Packit |
2cbdf3 |
alex_ust = alexInitUserState,
|
|
Packit |
2cbdf3 |
#endif
|
|
Packit |
2cbdf3 |
alex_scd = 0}) of Left msg -> Left msg
|
|
Packit |
2cbdf3 |
Right ( _, a ) -> Right a
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
newtype Alex a = Alex { unAlex :: AlexState -> Either String (AlexState, a) }
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
instance Functor Alex where
|
|
Packit |
2cbdf3 |
fmap f a = Alex $ \s -> case unAlex a s of
|
|
Packit |
2cbdf3 |
Left msg -> Left msg
|
|
Packit |
2cbdf3 |
Right (s', a') -> Right (s', f a')
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
instance Applicative Alex where
|
|
Packit |
2cbdf3 |
pure a = Alex $ \s -> Right (s, a)
|
|
Packit |
2cbdf3 |
fa <*> a = Alex $ \s -> case unAlex fa s of
|
|
Packit |
2cbdf3 |
Left msg -> Left msg
|
|
Packit |
2cbdf3 |
Right (s', f) -> case unAlex a s' of
|
|
Packit |
2cbdf3 |
Left msg -> Left msg
|
|
Packit |
2cbdf3 |
Right (s'', b) -> Right (s'', f b)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
instance Monad Alex where
|
|
Packit |
2cbdf3 |
m >>= k = Alex $ \s -> case unAlex m s of
|
|
Packit |
2cbdf3 |
Left msg -> Left msg
|
|
Packit |
2cbdf3 |
Right (s',a) -> unAlex (k a) s'
|
|
Packit |
2cbdf3 |
return = App.pure
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexGetInput :: Alex AlexInput
|
|
Packit |
2cbdf3 |
alexGetInput
|
|
Packit |
2cbdf3 |
= Alex $ \s@AlexState{alex_pos=pos,alex_chr=c,alex_bytes=bs,alex_inp=inp__} ->
|
|
Packit |
2cbdf3 |
Right (s, (pos,c,bs,inp__))
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexSetInput :: AlexInput -> Alex ()
|
|
Packit |
2cbdf3 |
alexSetInput (pos,c,bs,inp__)
|
|
Packit |
2cbdf3 |
= Alex $ \s -> case s{alex_pos=pos,alex_chr=c,alex_bytes=bs,alex_inp=inp__} of
|
|
Packit |
2cbdf3 |
state__@(AlexState{}) -> Right (state__, ())
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexError :: String -> Alex a
|
|
Packit |
2cbdf3 |
alexError message = Alex $ const $ Left message
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexGetStartCode :: Alex Int
|
|
Packit |
2cbdf3 |
alexGetStartCode = Alex $ \s@AlexState{alex_scd=sc} -> Right (s, sc)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexSetStartCode :: Int -> Alex ()
|
|
Packit |
2cbdf3 |
alexSetStartCode sc = Alex $ \s -> Right (s{alex_scd=sc}, ())
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#ifdef ALEX_MONAD_USER_STATE
|
|
Packit |
2cbdf3 |
alexGetUserState :: Alex AlexUserState
|
|
Packit |
2cbdf3 |
alexGetUserState = Alex $ \s@AlexState{alex_ust=ust} -> Right (s,ust)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexSetUserState :: AlexUserState -> Alex ()
|
|
Packit |
2cbdf3 |
alexSetUserState ss = Alex $ \s -> Right (s{alex_ust=ss}, ())
|
|
Packit |
2cbdf3 |
#endif
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexMonadScan = do
|
|
Packit |
2cbdf3 |
inp__ <- alexGetInput
|
|
Packit |
2cbdf3 |
sc <- alexGetStartCode
|
|
Packit |
2cbdf3 |
case alexScan inp__ sc of
|
|
Packit |
2cbdf3 |
AlexEOF -> alexEOF
|
|
Packit |
2cbdf3 |
AlexError ((AlexPn _ line column),_,_,_) -> alexError $ "lexical error at line " ++ (show line) ++ ", column " ++ (show column)
|
|
Packit |
2cbdf3 |
AlexSkip inp__' _len -> do
|
|
Packit |
2cbdf3 |
alexSetInput inp__'
|
|
Packit |
2cbdf3 |
alexMonadScan
|
|
Packit |
2cbdf3 |
AlexToken inp__' len action -> do
|
|
Packit |
2cbdf3 |
alexSetInput inp__'
|
|
Packit |
2cbdf3 |
action (ignorePendingBytes inp__) len
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- Useful token actions
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
type AlexAction result = AlexInput -> Int -> Alex result
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- just ignore this token and scan another one
|
|
Packit |
2cbdf3 |
-- skip :: AlexAction result
|
|
Packit |
2cbdf3 |
skip _input _len = alexMonadScan
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- ignore this token, but set the start code to a new value
|
|
Packit |
2cbdf3 |
-- begin :: Int -> AlexAction result
|
|
Packit |
2cbdf3 |
begin code _input _len = do alexSetStartCode code; alexMonadScan
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- perform an action for this token, and set the start code to a new value
|
|
Packit |
2cbdf3 |
andBegin :: AlexAction result -> Int -> AlexAction result
|
|
Packit |
2cbdf3 |
(action `andBegin` code) input__ len = do
|
|
Packit |
2cbdf3 |
alexSetStartCode code
|
|
Packit |
2cbdf3 |
action input__ len
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
token :: (AlexInput -> Int -> token) -> AlexAction token
|
|
Packit |
2cbdf3 |
token t input__ len = return (t input__ len)
|
|
Packit |
2cbdf3 |
#endif /* ALEX_MONAD */
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- Monad (with ByteString input)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#ifdef ALEX_MONAD_BYTESTRING
|
|
Packit |
2cbdf3 |
data AlexState = AlexState {
|
|
Packit |
2cbdf3 |
alex_pos :: !AlexPosn, -- position at current input location
|
|
Packit |
2cbdf3 |
alex_bpos:: !Int64, -- bytes consumed so far
|
|
Packit |
2cbdf3 |
alex_inp :: ByteString.ByteString, -- the current input
|
|
Packit |
2cbdf3 |
alex_chr :: !Char, -- the character before the input
|
|
Packit |
2cbdf3 |
alex_scd :: !Int -- the current startcode
|
|
Packit |
2cbdf3 |
#ifdef ALEX_MONAD_USER_STATE
|
|
Packit |
2cbdf3 |
, alex_ust :: AlexUserState -- AlexUserState will be defined in the user program
|
|
Packit |
2cbdf3 |
#endif
|
|
Packit |
2cbdf3 |
}
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- Compile with -funbox-strict-fields for best results!
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
runAlex :: ByteString.ByteString -> Alex a -> Either String a
|
|
Packit |
2cbdf3 |
runAlex input__ (Alex f)
|
|
Packit |
2cbdf3 |
= case f (AlexState {alex_pos = alexStartPos,
|
|
Packit |
2cbdf3 |
alex_bpos = 0,
|
|
Packit |
2cbdf3 |
alex_inp = input__,
|
|
Packit |
2cbdf3 |
alex_chr = '\n',
|
|
Packit |
2cbdf3 |
#ifdef ALEX_MONAD_USER_STATE
|
|
Packit |
2cbdf3 |
alex_ust = alexInitUserState,
|
|
Packit |
2cbdf3 |
#endif
|
|
Packit |
2cbdf3 |
alex_scd = 0}) of Left msg -> Left msg
|
|
Packit |
2cbdf3 |
Right ( _, a ) -> Right a
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
newtype Alex a = Alex { unAlex :: AlexState -> Either String (AlexState, a) }
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
instance Functor Alex where
|
|
Packit |
2cbdf3 |
fmap f m = do x <- m; return (f x)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
instance Applicative Alex where
|
|
Packit |
2cbdf3 |
pure a = Alex $ \s -> Right (s,a)
|
|
Packit |
2cbdf3 |
(<*>) = Control.Monad.ap
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
instance Monad Alex where
|
|
Packit |
2cbdf3 |
m >>= k = Alex $ \s -> case unAlex m s of
|
|
Packit |
2cbdf3 |
Left msg -> Left msg
|
|
Packit |
2cbdf3 |
Right (s',a) -> unAlex (k a) s'
|
|
Packit |
2cbdf3 |
return = App.pure
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexGetInput :: Alex AlexInput
|
|
Packit |
2cbdf3 |
alexGetInput
|
|
Packit |
2cbdf3 |
= Alex $ \s@AlexState{alex_pos=pos,alex_bpos=bpos,alex_chr=c,alex_inp=inp__} ->
|
|
Packit |
2cbdf3 |
Right (s, (pos,c,inp__,bpos))
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexSetInput :: AlexInput -> Alex ()
|
|
Packit |
2cbdf3 |
alexSetInput (pos,c,inp__,bpos)
|
|
Packit |
2cbdf3 |
= Alex $ \s -> case s{alex_pos=pos,
|
|
Packit |
2cbdf3 |
alex_bpos=bpos,
|
|
Packit |
2cbdf3 |
alex_chr=c,
|
|
Packit |
2cbdf3 |
alex_inp=inp__} of
|
|
Packit |
2cbdf3 |
state__@(AlexState{}) -> Right (state__, ())
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexError :: String -> Alex a
|
|
Packit |
2cbdf3 |
alexError message = Alex $ const $ Left message
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexGetStartCode :: Alex Int
|
|
Packit |
2cbdf3 |
alexGetStartCode = Alex $ \s@AlexState{alex_scd=sc} -> Right (s, sc)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexSetStartCode :: Int -> Alex ()
|
|
Packit |
2cbdf3 |
alexSetStartCode sc = Alex $ \s -> Right (s{alex_scd=sc}, ())
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexMonadScan = do
|
|
Packit |
2cbdf3 |
inp__@(_,_,_,n) <- alexGetInput
|
|
Packit |
2cbdf3 |
sc <- alexGetStartCode
|
|
Packit |
2cbdf3 |
case alexScan inp__ sc of
|
|
Packit |
2cbdf3 |
AlexEOF -> alexEOF
|
|
Packit |
2cbdf3 |
AlexError ((AlexPn _ line column),_,_,_) -> alexError $ "lexical error at line " ++ (show line) ++ ", column " ++ (show column)
|
|
Packit |
2cbdf3 |
AlexSkip inp__' _len -> do
|
|
Packit |
2cbdf3 |
alexSetInput inp__'
|
|
Packit |
2cbdf3 |
alexMonadScan
|
|
Packit |
2cbdf3 |
AlexToken inp__'@(_,_,_,n') _ action -> do
|
|
Packit |
2cbdf3 |
alexSetInput inp__'
|
|
Packit |
2cbdf3 |
action (ignorePendingBytes inp__) len
|
|
Packit |
2cbdf3 |
where
|
|
Packit |
2cbdf3 |
len = n'-n
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- Useful token actions
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
type AlexAction result = AlexInput -> Int64 -> Alex result
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- just ignore this token and scan another one
|
|
Packit |
2cbdf3 |
-- skip :: AlexAction result
|
|
Packit |
2cbdf3 |
skip _input _len = alexMonadScan
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- ignore this token, but set the start code to a new value
|
|
Packit |
2cbdf3 |
-- begin :: Int -> AlexAction result
|
|
Packit |
2cbdf3 |
begin code _input _len = do alexSetStartCode code; alexMonadScan
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- perform an action for this token, and set the start code to a new value
|
|
Packit |
2cbdf3 |
andBegin :: AlexAction result -> Int -> AlexAction result
|
|
Packit |
2cbdf3 |
(action `andBegin` code) input__ len = do
|
|
Packit |
2cbdf3 |
alexSetStartCode code
|
|
Packit |
2cbdf3 |
action input__ len
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
token :: (AlexInput -> Int64 -> token) -> AlexAction token
|
|
Packit |
2cbdf3 |
token t input__ len = return (t input__ len)
|
|
Packit |
2cbdf3 |
#endif /* ALEX_MONAD_BYTESTRING */
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- Basic wrapper
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#ifdef ALEX_BASIC
|
|
Packit |
2cbdf3 |
type AlexInput = (Char,[Byte],String)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexInputPrevChar :: AlexInput -> Char
|
|
Packit |
2cbdf3 |
alexInputPrevChar (c,_,_) = c
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- alexScanTokens :: String -> [token]
|
|
Packit |
2cbdf3 |
alexScanTokens str = go ('\n',[],str)
|
|
Packit |
2cbdf3 |
where go inp__@(_,_bs,s) =
|
|
Packit |
2cbdf3 |
case alexScan inp__ 0 of
|
|
Packit |
2cbdf3 |
AlexEOF -> []
|
|
Packit |
2cbdf3 |
AlexError _ -> error "lexical error"
|
|
Packit |
2cbdf3 |
AlexSkip inp__' _ln -> go inp__'
|
|
Packit |
2cbdf3 |
AlexToken inp__' len act -> act (take len s) : go inp__'
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alexGetByte :: AlexInput -> Maybe (Byte,AlexInput)
|
|
Packit |
2cbdf3 |
alexGetByte (c,(b:bs),s) = Just (b,(c,bs,s))
|
|
Packit |
2cbdf3 |
alexGetByte (_,[],[]) = Nothing
|
|
Packit |
2cbdf3 |
alexGetByte (_,[],(c:s)) = case utf8Encode c of
|
|
Packit |
2cbdf3 |
(b:bs) -> Just (b, (c, bs, s))
|
|
Packit |
2cbdf3 |
[] -> Nothing
|
|
Packit |
2cbdf3 |
#endif
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- Basic wrapper, ByteString version
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#ifdef ALEX_BASIC_BYTESTRING
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- alexScanTokens :: ByteString.ByteString -> [token]
|
|
Packit |
2cbdf3 |
alexScanTokens str = go (AlexInput '\n' str 0)
|
|
Packit |
2cbdf3 |
where go inp__ =
|
|
Packit |
2cbdf3 |
case alexScan inp__ 0 of
|
|
Packit |
2cbdf3 |
AlexEOF -> []
|
|
Packit |
2cbdf3 |
AlexError _ -> error "lexical error"
|
|
Packit |
2cbdf3 |
AlexSkip inp__' _len -> go inp__'
|
|
Packit |
2cbdf3 |
AlexToken inp__' _ act ->
|
|
Packit |
2cbdf3 |
let len = alexBytePos inp__' - alexBytePos inp__ in
|
|
Packit |
2cbdf3 |
act (ByteString.take len (alexStr inp__)) : go inp__'
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#endif
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#ifdef ALEX_STRICT_BYTESTRING
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- alexScanTokens :: ByteString.ByteString -> [token]
|
|
Packit |
2cbdf3 |
alexScanTokens str = go (AlexInput '\n' str 0)
|
|
Packit |
2cbdf3 |
where go inp__ =
|
|
Packit |
2cbdf3 |
case alexScan inp__ 0 of
|
|
Packit |
2cbdf3 |
AlexEOF -> []
|
|
Packit |
2cbdf3 |
AlexError _ -> error "lexical error"
|
|
Packit |
2cbdf3 |
AlexSkip inp__' _len -> go inp__'
|
|
Packit |
2cbdf3 |
AlexToken inp__' _ act ->
|
|
Packit |
2cbdf3 |
let len = alexBytePos inp__' - alexBytePos inp__ in
|
|
Packit |
2cbdf3 |
act (ByteString.take len (alexStr inp__)) : go inp__'
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#endif
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- Posn wrapper
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- Adds text positions to the basic model.
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#ifdef ALEX_POSN
|
|
Packit |
2cbdf3 |
--alexScanTokens :: String -> [token]
|
|
Packit |
2cbdf3 |
alexScanTokens str0 = go (alexStartPos,'\n',[],str0)
|
|
Packit |
2cbdf3 |
where go inp__@(pos,_,_,str) =
|
|
Packit |
2cbdf3 |
case alexScan inp__ 0 of
|
|
Packit |
2cbdf3 |
AlexEOF -> []
|
|
Packit |
2cbdf3 |
AlexError ((AlexPn _ line column),_,_,_) -> error $ "lexical error at line " ++ (show line) ++ ", column " ++ (show column)
|
|
Packit |
2cbdf3 |
AlexSkip inp__' _ln -> go inp__'
|
|
Packit |
2cbdf3 |
AlexToken inp__' len act -> act pos (take len str) : go inp__'
|
|
Packit |
2cbdf3 |
#endif
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- Posn wrapper, ByteString version
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#ifdef ALEX_POSN_BYTESTRING
|
|
Packit |
2cbdf3 |
--alexScanTokens :: ByteString.ByteString -> [token]
|
|
Packit |
2cbdf3 |
alexScanTokens str0 = go (alexStartPos,'\n',str0,0)
|
|
Packit |
2cbdf3 |
where go inp__@(pos,_,str,n) =
|
|
Packit |
2cbdf3 |
case alexScan inp__ 0 of
|
|
Packit |
2cbdf3 |
AlexEOF -> []
|
|
Packit |
2cbdf3 |
AlexError ((AlexPn _ line column),_,_,_) -> error $ "lexical error at line " ++ (show line) ++ ", column " ++ (show column)
|
|
Packit |
2cbdf3 |
AlexSkip inp__' _len -> go inp__'
|
|
Packit |
2cbdf3 |
AlexToken inp__'@(_,_,_,n') _ act ->
|
|
Packit |
2cbdf3 |
act pos (ByteString.take (n'-n) str) : go inp__'
|
|
Packit |
2cbdf3 |
#endif
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- GScan wrapper
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- For compatibility with previous versions of Alex, and because we can.
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
#ifdef ALEX_GSCAN
|
|
Packit |
2cbdf3 |
alexGScan stop__ state__ inp__ =
|
|
Packit |
2cbdf3 |
alex_gscan stop__ alexStartPos '\n' [] inp__ (0,state__)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
alex_gscan stop__ p c bs inp__ (sc,state__) =
|
|
Packit |
2cbdf3 |
case alexScan (p,c,bs,inp__) sc of
|
|
Packit |
2cbdf3 |
AlexEOF -> stop__ p c inp__ (sc,state__)
|
|
Packit |
2cbdf3 |
AlexError _ -> stop__ p c inp__ (sc,state__)
|
|
Packit |
2cbdf3 |
AlexSkip (p',c',bs',inp__') _len ->
|
|
Packit |
2cbdf3 |
alex_gscan stop__ p' c' bs' inp__' (sc,state__)
|
|
Packit |
2cbdf3 |
AlexToken (p',c',bs',inp__') len k ->
|
|
Packit |
2cbdf3 |
k p c inp__ len (\scs -> alex_gscan stop__ p' c' bs' inp__' scs) (sc,state__)
|
|
Packit |
2cbdf3 |
#endif
|