|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
--
|
|
Packit |
2cbdf3 |
-- AbsSyn.hs, part of Alex
|
|
Packit |
2cbdf3 |
--
|
|
Packit |
2cbdf3 |
-- (c) Chris Dornan 1995-2000, Simon Marlow 2003
|
|
Packit |
2cbdf3 |
--
|
|
Packit |
2cbdf3 |
-- This module provides a concrete representation for regular expressions and
|
|
Packit |
2cbdf3 |
-- scanners. Scanners are used for tokenising files in preparation for parsing.
|
|
Packit |
2cbdf3 |
--
|
|
Packit |
2cbdf3 |
-- ----------------------------------------------------------------------------}
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
module AbsSyn (
|
|
Packit |
2cbdf3 |
Code, Directive(..), Scheme(..),
|
|
Packit |
2cbdf3 |
wrapperName,
|
|
Packit |
2cbdf3 |
Scanner(..),
|
|
Packit |
2cbdf3 |
RECtx(..),
|
|
Packit |
2cbdf3 |
RExp(..),
|
|
Packit |
2cbdf3 |
DFA(..), State(..), SNum, StartCode, Accept(..),
|
|
Packit |
2cbdf3 |
RightContext(..), showRCtx, strtype,
|
|
Packit |
2cbdf3 |
encodeStartCodes, extractActions,
|
|
Packit |
2cbdf3 |
Target(..),
|
|
Packit |
2cbdf3 |
UsesPreds(..), usesPreds,
|
|
Packit |
2cbdf3 |
StrType(..)
|
|
Packit |
2cbdf3 |
) where
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
import CharSet ( CharSet, Encoding )
|
|
Packit |
2cbdf3 |
import Map ( Map )
|
|
Packit |
2cbdf3 |
import qualified Map hiding ( Map )
|
|
Packit |
2cbdf3 |
import Data.IntMap (IntMap)
|
|
Packit |
2cbdf3 |
import Sort ( nub' )
|
|
Packit |
2cbdf3 |
import Util ( str, nl )
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
import Data.Maybe ( fromJust )
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
infixl 4 :|
|
|
Packit |
2cbdf3 |
infixl 5 :%%
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- Abstract Syntax for Alex scripts
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
type Code = String
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
data Directive
|
|
Packit |
2cbdf3 |
= WrapperDirective String -- use this wrapper
|
|
Packit |
2cbdf3 |
| EncodingDirective Encoding -- use this encoding
|
|
Packit |
2cbdf3 |
| ActionType String -- Type signature of actions,
|
|
Packit |
2cbdf3 |
-- with optional typeclasses
|
|
Packit |
2cbdf3 |
| TypeClass String
|
|
Packit |
2cbdf3 |
| TokenType String
|
|
Packit |
2cbdf3 |
deriving Show
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
data StrType = Str | Lazy | Strict
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
instance Show StrType where
|
|
Packit |
2cbdf3 |
show Str = "String"
|
|
Packit |
2cbdf3 |
show Lazy = "ByteString.ByteString"
|
|
Packit |
2cbdf3 |
show Strict = "ByteString.ByteString"
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
data Scheme
|
|
Packit |
2cbdf3 |
= Default { defaultTypeInfo :: Maybe (Maybe String, String) }
|
|
Packit |
2cbdf3 |
| GScan { gscanTypeInfo :: Maybe (Maybe String, String) }
|
|
Packit |
2cbdf3 |
| Basic { basicStrType :: StrType,
|
|
Packit |
2cbdf3 |
basicTypeInfo :: Maybe (Maybe String, String) }
|
|
Packit |
2cbdf3 |
| Posn { posnByteString :: Bool,
|
|
Packit |
2cbdf3 |
posnTypeInfo :: Maybe (Maybe String, String) }
|
|
Packit |
2cbdf3 |
| Monad { monadByteString :: Bool, monadUserState :: Bool,
|
|
Packit |
2cbdf3 |
monadTypeInfo :: Maybe (Maybe String, String) }
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
strtype :: Bool -> String
|
|
Packit |
2cbdf3 |
strtype True = "ByteString.ByteString"
|
|
Packit |
2cbdf3 |
strtype False = "String"
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
wrapperName :: Scheme -> Maybe String
|
|
Packit |
2cbdf3 |
wrapperName Default {} = Nothing
|
|
Packit |
2cbdf3 |
wrapperName GScan {} = Just "gscan"
|
|
Packit |
2cbdf3 |
wrapperName Basic { basicStrType = Str } = Just "basic"
|
|
Packit |
2cbdf3 |
wrapperName Basic { basicStrType = Lazy } = Just "basic-bytestring"
|
|
Packit |
2cbdf3 |
wrapperName Basic { basicStrType = Strict } = Just "strict-bytestring"
|
|
Packit |
2cbdf3 |
wrapperName Posn { posnByteString = False } = Just "posn"
|
|
Packit |
2cbdf3 |
wrapperName Posn { posnByteString = True } = Just "posn-bytestring"
|
|
Packit |
2cbdf3 |
wrapperName Monad { monadByteString = False,
|
|
Packit |
2cbdf3 |
monadUserState = False } = Just "monad"
|
|
Packit |
2cbdf3 |
wrapperName Monad { monadByteString = True,
|
|
Packit |
2cbdf3 |
monadUserState = False } = Just "monad-bytestring"
|
|
Packit |
2cbdf3 |
wrapperName Monad { monadByteString = False,
|
|
Packit |
2cbdf3 |
monadUserState = True } = Just "monadUserState"
|
|
Packit |
2cbdf3 |
wrapperName Monad { monadByteString = True,
|
|
Packit |
2cbdf3 |
monadUserState = True } = Just "monadUserState-bytestring"
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- TODO: update this comment
|
|
Packit |
2cbdf3 |
--
|
|
Packit |
2cbdf3 |
-- A `Scanner' consists of an association list associating token names with
|
|
Packit |
2cbdf3 |
-- regular expressions with context. The context may include a list of start
|
|
Packit |
2cbdf3 |
-- codes, some leading context to test the character immediately preceding the
|
|
Packit |
2cbdf3 |
-- token and trailing context to test the residual input after the token.
|
|
Packit |
2cbdf3 |
--
|
|
Packit |
2cbdf3 |
-- The start codes consist of the names and numbers of the start codes;
|
|
Packit |
2cbdf3 |
-- initially the names only will be generated by the parser, the numbers being
|
|
Packit |
2cbdf3 |
-- allocated at a later stage. Start codes become meaningful when scanners are
|
|
Packit |
2cbdf3 |
-- converted to DFAs; see the DFA section of the Scan module for details.
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
data Scanner = Scanner { scannerName :: String,
|
|
Packit |
2cbdf3 |
scannerTokens :: [RECtx] }
|
|
Packit |
2cbdf3 |
deriving Show
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
data RECtx = RECtx { reCtxStartCodes :: [(String,StartCode)],
|
|
Packit |
2cbdf3 |
reCtxPreCtx :: Maybe CharSet,
|
|
Packit |
2cbdf3 |
reCtxRE :: RExp,
|
|
Packit |
2cbdf3 |
reCtxPostCtx :: RightContext RExp,
|
|
Packit |
2cbdf3 |
reCtxCode :: Maybe Code
|
|
Packit |
2cbdf3 |
}
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
data RightContext r
|
|
Packit |
2cbdf3 |
= NoRightContext
|
|
Packit |
2cbdf3 |
| RightContextRExp r
|
|
Packit |
2cbdf3 |
| RightContextCode Code
|
|
Packit |
2cbdf3 |
deriving (Eq,Ord)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
instance Show RECtx where
|
|
Packit |
2cbdf3 |
showsPrec _ (RECtx scs _ r rctx code) =
|
|
Packit |
2cbdf3 |
showStarts scs . shows r . showRCtx rctx . showMaybeCode code
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
showMaybeCode :: Maybe String -> String -> String
|
|
Packit |
2cbdf3 |
showMaybeCode Nothing = id
|
|
Packit |
2cbdf3 |
showMaybeCode (Just code) = showCode code
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
showCode :: String -> String -> String
|
|
Packit |
2cbdf3 |
showCode code = showString " { " . showString code . showString " }"
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
showStarts :: [(String, StartCode)] -> String -> String
|
|
Packit |
2cbdf3 |
showStarts [] = id
|
|
Packit |
2cbdf3 |
showStarts scs = shows scs
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
showRCtx :: Show r => RightContext r -> String -> String
|
|
Packit |
2cbdf3 |
showRCtx NoRightContext = id
|
|
Packit |
2cbdf3 |
showRCtx (RightContextRExp r) = ('\\':) . shows r
|
|
Packit |
2cbdf3 |
showRCtx (RightContextCode code) = showString "\\ " . showCode code
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- DFAs
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
data DFA s a = DFA
|
|
Packit |
2cbdf3 |
{ dfa_start_states :: [s],
|
|
Packit |
2cbdf3 |
dfa_states :: Map s (State s a)
|
|
Packit |
2cbdf3 |
}
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
data State s a = State { state_acc :: [Accept a],
|
|
Packit |
2cbdf3 |
state_out :: IntMap s -- 0..255 only
|
|
Packit |
2cbdf3 |
}
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
type SNum = Int
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
data Accept a
|
|
Packit |
2cbdf3 |
= Acc { accPrio :: Int,
|
|
Packit |
2cbdf3 |
accAction :: Maybe a,
|
|
Packit |
2cbdf3 |
accLeftCtx :: Maybe CharSet, -- cannot be converted to byteset at this point.
|
|
Packit |
2cbdf3 |
accRightCtx :: RightContext SNum
|
|
Packit |
2cbdf3 |
}
|
|
Packit |
2cbdf3 |
deriving (Eq,Ord)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- debug stuff
|
|
Packit |
2cbdf3 |
instance Show (Accept a) where
|
|
Packit |
2cbdf3 |
showsPrec _ (Acc p _act _lctx _rctx) = shows p --TODO
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
type StartCode = Int
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- Predicates / contexts
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- we can generate somewhat faster code in the case that
|
|
Packit |
2cbdf3 |
-- the lexer doesn't use predicates
|
|
Packit |
2cbdf3 |
data UsesPreds = UsesPreds | DoesntUsePreds
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
usesPreds :: DFA s a -> UsesPreds
|
|
Packit |
2cbdf3 |
usesPreds dfa
|
|
Packit |
2cbdf3 |
| any acceptHasCtx [ acc | st <- Map.elems (dfa_states dfa)
|
|
Packit |
2cbdf3 |
, acc <- state_acc st ]
|
|
Packit |
2cbdf3 |
= UsesPreds
|
|
Packit |
2cbdf3 |
| otherwise
|
|
Packit |
2cbdf3 |
= DoesntUsePreds
|
|
Packit |
2cbdf3 |
where
|
|
Packit |
2cbdf3 |
acceptHasCtx Acc { accLeftCtx = Nothing
|
|
Packit |
2cbdf3 |
, accRightCtx = NoRightContext } = False
|
|
Packit |
2cbdf3 |
acceptHasCtx _ = True
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- Regular expressions
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- `RExp' provides an abstract syntax for regular expressions. `Eps' will
|
|
Packit |
2cbdf3 |
-- match empty strings; `Ch p' matches strings containinng a single character
|
|
Packit |
2cbdf3 |
-- `c' if `p c' is true; `re1 :%% re2' matches a string if `re1' matches one of
|
|
Packit |
2cbdf3 |
-- its prefixes and `re2' matches the rest; `re1 :| re2' matches a string if
|
|
Packit |
2cbdf3 |
-- `re1' or `re2' matches it; `Star re', `Plus re' and `Ques re' can be
|
|
Packit |
2cbdf3 |
-- expressed in terms of the other operators. See the definitions of `ARexp'
|
|
Packit |
2cbdf3 |
-- for a formal definition of the semantics of these operators.
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
data RExp
|
|
Packit |
2cbdf3 |
= Eps
|
|
Packit |
2cbdf3 |
| Ch CharSet
|
|
Packit |
2cbdf3 |
| RExp :%% RExp
|
|
Packit |
2cbdf3 |
| RExp :| RExp
|
|
Packit |
2cbdf3 |
| Star RExp
|
|
Packit |
2cbdf3 |
| Plus RExp
|
|
Packit |
2cbdf3 |
| Ques RExp
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
instance Show RExp where
|
|
Packit |
2cbdf3 |
showsPrec _ Eps = showString "()"
|
|
Packit |
2cbdf3 |
showsPrec _ (Ch _) = showString "[..]"
|
|
Packit |
2cbdf3 |
showsPrec _ (l :%% r) = shows l . shows r
|
|
Packit |
2cbdf3 |
showsPrec _ (l :| r) = shows l . ('|':) . shows r
|
|
Packit |
2cbdf3 |
showsPrec _ (Star r) = shows r . ('*':)
|
|
Packit |
2cbdf3 |
showsPrec _ (Plus r) = shows r . ('+':)
|
|
Packit |
2cbdf3 |
showsPrec _ (Ques r) = shows r . ('?':)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
{------------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
Abstract Regular Expression
|
|
Packit |
2cbdf3 |
------------------------------------------------------------------------------}
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- This section contains demonstrations; it is not part of Alex.
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
{-
|
|
Packit |
2cbdf3 |
-- This function illustrates `ARexp'. It returns true if the string in its
|
|
Packit |
2cbdf3 |
-- argument is matched by the regular expression.
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
recognise:: RExp -> String -> Bool
|
|
Packit |
2cbdf3 |
recognise re inp = any (==len) (ap_ar (arexp re) inp)
|
|
Packit |
2cbdf3 |
where
|
|
Packit |
2cbdf3 |
len = length inp
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- `ARexp' provides an regular expressions in abstract format. Here regular
|
|
Packit |
2cbdf3 |
-- expressions are represented by a function that takes the string to be
|
|
Packit |
2cbdf3 |
-- matched and returns the sizes of all the prefixes matched by the regular
|
|
Packit |
2cbdf3 |
-- expression (the list may contain duplicates). Each of the `RExp' operators
|
|
Packit |
2cbdf3 |
-- are represented by similarly named functions over ARexp. The `ap' function
|
|
Packit |
2cbdf3 |
-- takes an `ARExp', a string and returns the sizes of all the prefixes
|
|
Packit |
2cbdf3 |
-- matching that regular expression. `arexp' converts an `RExp' to an `ARexp'.
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
arexp:: RExp -> ARexp
|
|
Packit |
2cbdf3 |
arexp Eps = eps_ar
|
|
Packit |
2cbdf3 |
arexp (Ch p) = ch_ar p
|
|
Packit |
2cbdf3 |
arexp (re :%% re') = arexp re `seq_ar` arexp re'
|
|
Packit |
2cbdf3 |
arexp (re :| re') = arexp re `bar_ar` arexp re'
|
|
Packit |
2cbdf3 |
arexp (Star re) = star_ar (arexp re)
|
|
Packit |
2cbdf3 |
arexp (Plus re) = plus_ar (arexp re)
|
|
Packit |
2cbdf3 |
arexp (Ques re) = ques_ar (arexp re)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
star_ar:: ARexp -> ARexp
|
|
Packit |
2cbdf3 |
star_ar sc = eps_ar `bar_ar` plus_ar sc
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
plus_ar:: ARexp -> ARexp
|
|
Packit |
2cbdf3 |
plus_ar sc = sc `seq_ar` star_ar sc
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
ques_ar:: ARexp -> ARexp
|
|
Packit |
2cbdf3 |
ques_ar sc = eps_ar `bar_ar` sc
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- Hugs abstract type definition -- not for GHC.
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
type ARexp = String -> [Int]
|
|
Packit |
2cbdf3 |
-- in ap_ar, eps_ar, ch_ar, seq_ar, bar_ar
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
ap_ar:: ARexp -> String -> [Int]
|
|
Packit |
2cbdf3 |
ap_ar sc = sc
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
eps_ar:: ARexp
|
|
Packit |
2cbdf3 |
eps_ar inp = [0]
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
ch_ar:: (Char->Bool) -> ARexp
|
|
Packit |
2cbdf3 |
ch_ar p "" = []
|
|
Packit |
2cbdf3 |
ch_ar p (c:rst) = if p c then [1] else []
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
seq_ar:: ARexp -> ARexp -> ARexp
|
|
Packit |
2cbdf3 |
seq_ar sc sc' inp = [n+m| n<-sc inp, m<-sc' (drop n inp)]
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
bar_ar:: ARexp -> ARexp -> ARexp
|
|
Packit |
2cbdf3 |
bar_ar sc sc' inp = sc inp ++ sc' inp
|
|
Packit |
2cbdf3 |
-}
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- Utils
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- Map the available start codes onto [1..]
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
encodeStartCodes:: Scanner -> (Scanner,[StartCode],ShowS)
|
|
Packit |
2cbdf3 |
encodeStartCodes scan = (scan', 0 : map snd name_code_pairs, sc_hdr)
|
|
Packit |
2cbdf3 |
where
|
|
Packit |
2cbdf3 |
scan' = scan{ scannerTokens = map mk_re_ctx (scannerTokens scan) }
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
mk_re_ctx (RECtx scs lc re rc code)
|
|
Packit |
2cbdf3 |
= RECtx (map mk_sc scs) lc re rc code
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
mk_sc (nm,_) = (nm, if nm=="0" then 0
|
|
Packit |
2cbdf3 |
else fromJust (Map.lookup nm code_map))
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
sc_hdr tl =
|
|
Packit |
2cbdf3 |
case name_code_pairs of
|
|
Packit |
2cbdf3 |
[] -> tl
|
|
Packit |
2cbdf3 |
(nm,_):rst -> "\n" ++ nm ++ foldr f t rst
|
|
Packit |
2cbdf3 |
where
|
|
Packit |
2cbdf3 |
f (nm', _) t' = "," ++ nm' ++ t'
|
|
Packit |
2cbdf3 |
t = " :: Int\n" ++ foldr fmt_sc tl name_code_pairs
|
|
Packit |
2cbdf3 |
where
|
|
Packit |
2cbdf3 |
fmt_sc (nm,sc) t = nm ++ " = " ++ show sc ++ "\n" ++ t
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
code_map = Map.fromList name_code_pairs
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
name_code_pairs = zip (nub' (<=) nms) [1..]
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
nms = [nm | RECtx{reCtxStartCodes = scs} <- scannerTokens scan,
|
|
Packit |
2cbdf3 |
(nm,_) <- scs, nm /= "0"]
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- Grab the code fragments for the token actions, and replace them
|
|
Packit |
2cbdf3 |
-- with function names of the form alex_action_$n$. We do this
|
|
Packit |
2cbdf3 |
-- because the actual action fragments might be duplicated in the
|
|
Packit |
2cbdf3 |
-- generated file.
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
extractActions :: Scheme -> Scanner -> (Scanner,ShowS)
|
|
Packit |
2cbdf3 |
extractActions scheme scanner = (scanner{scannerTokens = new_tokens}, decl_str)
|
|
Packit |
2cbdf3 |
where
|
|
Packit |
2cbdf3 |
(new_tokens, decls) = unzip (zipWith f (scannerTokens scanner) act_names)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
f r@RECtx{ reCtxCode = Just code } name
|
|
Packit |
2cbdf3 |
= (r{reCtxCode = Just name}, Just (mkDecl name code))
|
|
Packit |
2cbdf3 |
f r@RECtx{ reCtxCode = Nothing } _
|
|
Packit |
2cbdf3 |
= (r{reCtxCode = Nothing}, Nothing)
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
gscanActionType res =
|
|
Packit |
2cbdf3 |
str "AlexPosn -> Char -> String -> Int -> ((Int, state) -> "
|
|
Packit |
2cbdf3 |
. str res . str ") -> (Int, state) -> " . str res
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
mkDecl fun code = case scheme of
|
|
Packit |
2cbdf3 |
Default { defaultTypeInfo = Just (Nothing, actionty) } ->
|
|
Packit |
2cbdf3 |
str fun . str " :: " . str actionty . str "\n"
|
|
Packit |
2cbdf3 |
. str fun . str " = " . str code . nl
|
|
Packit |
2cbdf3 |
Default { defaultTypeInfo = Just (Just tyclasses, actionty) } ->
|
|
Packit |
2cbdf3 |
str fun . str " :: (" . str tyclasses . str ") => " .
|
|
Packit |
2cbdf3 |
str actionty . str "\n" .
|
|
Packit |
2cbdf3 |
str fun . str " = " . str code . nl
|
|
Packit |
2cbdf3 |
GScan { gscanTypeInfo = Just (Nothing, tokenty) } ->
|
|
Packit |
2cbdf3 |
str fun . str " :: " . gscanActionType tokenty . str "\n"
|
|
Packit |
2cbdf3 |
. str fun . str " = " . str code . nl
|
|
Packit |
2cbdf3 |
GScan { gscanTypeInfo = Just (Just tyclasses, tokenty) } ->
|
|
Packit |
2cbdf3 |
str fun . str " :: (" . str tyclasses . str ") => " .
|
|
Packit |
2cbdf3 |
gscanActionType tokenty . str "\n" .
|
|
Packit |
2cbdf3 |
str fun . str " = " . str code . nl
|
|
Packit |
2cbdf3 |
Basic { basicStrType = strty, basicTypeInfo = Just (Nothing, tokenty) } ->
|
|
Packit |
2cbdf3 |
str fun . str " :: " . str (show strty) . str " -> "
|
|
Packit |
2cbdf3 |
. str tokenty . str "\n"
|
|
Packit |
2cbdf3 |
. str fun . str " = " . str code . nl
|
|
Packit |
2cbdf3 |
Basic { basicStrType = strty,
|
|
Packit |
2cbdf3 |
basicTypeInfo = Just (Just tyclasses, tokenty) } ->
|
|
Packit |
2cbdf3 |
str fun . str " :: (" . str tyclasses . str ") => " .
|
|
Packit |
2cbdf3 |
str (show strty) . str " -> " . str tokenty . str "\n" .
|
|
Packit |
2cbdf3 |
str fun . str " = " . str code . nl
|
|
Packit |
2cbdf3 |
Posn { posnByteString = isByteString,
|
|
Packit |
2cbdf3 |
posnTypeInfo = Just (Nothing, tokenty) } ->
|
|
Packit |
2cbdf3 |
str fun . str " :: AlexPosn -> " . str (strtype isByteString) . str " -> "
|
|
Packit |
2cbdf3 |
. str tokenty . str "\n"
|
|
Packit |
2cbdf3 |
. str fun . str " = " . str code . nl
|
|
Packit |
2cbdf3 |
Posn { posnByteString = isByteString,
|
|
Packit |
2cbdf3 |
posnTypeInfo = Just (Just tyclasses, tokenty) } ->
|
|
Packit |
2cbdf3 |
str fun . str " :: (" . str tyclasses . str ") => AlexPosn -> " .
|
|
Packit |
2cbdf3 |
str (strtype isByteString) . str " -> " . str tokenty . str "\n" .
|
|
Packit |
2cbdf3 |
str fun . str " = " . str code . nl
|
|
Packit |
2cbdf3 |
Monad { monadByteString = isByteString,
|
|
Packit |
2cbdf3 |
monadTypeInfo = Just (Nothing, tokenty) } ->
|
|
Packit |
2cbdf3 |
let
|
|
Packit |
2cbdf3 |
actintty = if isByteString then "Int64" else "Int"
|
|
Packit |
2cbdf3 |
in
|
|
Packit |
2cbdf3 |
str fun . str " :: AlexInput -> " . str actintty . str " -> Alex ("
|
|
Packit |
2cbdf3 |
. str tokenty . str ")\n"
|
|
Packit |
2cbdf3 |
. str fun . str " = " . str code . nl
|
|
Packit |
2cbdf3 |
Monad { monadByteString = isByteString,
|
|
Packit |
2cbdf3 |
monadTypeInfo = Just (Just tyclasses, tokenty) } ->
|
|
Packit |
2cbdf3 |
let
|
|
Packit |
2cbdf3 |
actintty = if isByteString then "Int64" else "Int"
|
|
Packit |
2cbdf3 |
in
|
|
Packit |
2cbdf3 |
str fun . str " :: (" . str tyclasses . str ") => "
|
|
Packit |
2cbdf3 |
. str " AlexInput -> " . str actintty
|
|
Packit |
2cbdf3 |
. str " -> Alex (" . str tokenty . str ")\n"
|
|
Packit |
2cbdf3 |
. str fun . str " = " . str code . nl
|
|
Packit |
2cbdf3 |
_ -> str fun . str " = " . str code . nl
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
act_names = map (\n -> "alex_action_" ++ show (n::Int)) [0..]
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
decl_str = foldr (.) id [ decl | Just decl <- decls ]
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
-- -----------------------------------------------------------------------------
|
|
Packit |
2cbdf3 |
-- Code generation targets
|
|
Packit |
2cbdf3 |
|
|
Packit |
2cbdf3 |
data Target = GhcTarget | HaskellTarget
|