module AbsSyn (
Code, Directive(..), Scheme(..),
wrapperName,
Scanner(..),
RECtx(..),
RExp(..),
DFA(..), State(..), SNum, StartCode, Accept(..),
RightContext(..), showRCtx, strtype,
encodeStartCodes, extractActions,
Target(..),
UsesPreds(..), usesPreds,
StrType(..)
) where
import CharSet ( CharSet, Encoding )
import Map ( Map )
import qualified Map hiding ( Map )
import Data.IntMap (IntMap)
import Sort ( nub' )
import Util ( str, nl )
import Data.Maybe ( fromJust )
infixl 4 :|
infixl 5 :%%
type Code = String
data Directive
= WrapperDirective String | EncodingDirective Encoding | ActionType String | TypeClass String
| TokenType String
deriving Show
data StrType = Str | Lazy | Strict
instance Show StrType where
show Str = "String"
show Lazy = "ByteString.ByteString"
show Strict = "ByteString.ByteString"
data Scheme
= Default { defaultTypeInfo :: Maybe (Maybe String, String) }
| GScan { gscanTypeInfo :: Maybe (Maybe String, String) }
| Basic { basicStrType :: StrType,
basicTypeInfo :: Maybe (Maybe String, String) }
| Posn { posnByteString :: Bool,
posnTypeInfo :: Maybe (Maybe String, String) }
| Monad { monadByteString :: Bool, monadUserState :: Bool,
monadTypeInfo :: Maybe (Maybe String, String) }
strtype :: Bool -> String
strtype True = "ByteString.ByteString"
strtype False = "String"
wrapperName :: Scheme -> Maybe String
wrapperName Default {} = Nothing
wrapperName GScan {} = Just "gscan"
wrapperName Basic { basicStrType = Str } = Just "basic"
wrapperName Basic { basicStrType = Lazy } = Just "basic-bytestring"
wrapperName Basic { basicStrType = Strict } = Just "strict-bytestring"
wrapperName Posn { posnByteString = False } = Just "posn"
wrapperName Posn { posnByteString = True } = Just "posn-bytestring"
wrapperName Monad { monadByteString = False,
monadUserState = False } = Just "monad"
wrapperName Monad { monadByteString = True,
monadUserState = False } = Just "monad-bytestring"
wrapperName Monad { monadByteString = False,
monadUserState = True } = Just "monadUserState"
wrapperName Monad { monadByteString = True,
monadUserState = True } = Just "monadUserState-bytestring"
data Scanner = Scanner { scannerName :: String,
scannerTokens :: [RECtx] }
deriving Show
data RECtx = RECtx { reCtxStartCodes :: [(String,StartCode)],
reCtxPreCtx :: Maybe CharSet,
reCtxRE :: RExp,
reCtxPostCtx :: RightContext RExp,
reCtxCode :: Maybe Code
}
data RightContext r
= NoRightContext
| RightContextRExp r
| RightContextCode Code
deriving (Eq,Ord)
instance Show RECtx where
showsPrec _ (RECtx scs _ r rctx code) =
showStarts scs . shows r . showRCtx rctx . showMaybeCode code
showMaybeCode :: Maybe String -> String -> String
showMaybeCode Nothing = id
showMaybeCode (Just code) = showCode code
showCode :: String -> String -> String
showCode code = showString " { " . showString code . showString " }"
showStarts :: [(String, StartCode)] -> String -> String
showStarts [] = id
showStarts scs = shows scs
showRCtx :: Show r => RightContext r -> String -> String
showRCtx NoRightContext = id
showRCtx (RightContextRExp r) = ('\\':) . shows r
showRCtx (RightContextCode code) = showString "\\ " . showCode code
data DFA s a = DFA
{ dfa_start_states :: [s],
dfa_states :: Map s (State s a)
}
data State s a = State { state_acc :: [Accept a],
state_out :: IntMap s }
type SNum = Int
data Accept a
= Acc { accPrio :: Int,
accAction :: Maybe a,
accLeftCtx :: Maybe CharSet, accRightCtx :: RightContext SNum
}
deriving (Eq,Ord)
instance Show (Accept a) where
showsPrec _ (Acc p _act _lctx _rctx) = shows p
type StartCode = Int
data UsesPreds = UsesPreds | DoesntUsePreds
usesPreds :: DFA s a -> UsesPreds
usesPreds dfa
| any acceptHasCtx [ acc | st <- Map.elems (dfa_states dfa)
, acc <- state_acc st ]
= UsesPreds
| otherwise
= DoesntUsePreds
where
acceptHasCtx Acc { accLeftCtx = Nothing
, accRightCtx = NoRightContext } = False
acceptHasCtx _ = True
data RExp
= Eps
| Ch CharSet
| RExp :%% RExp
| RExp :| RExp
| Star RExp
| Plus RExp
| Ques RExp
instance Show RExp where
showsPrec _ Eps = showString "()"
showsPrec _ (Ch _) = showString "[..]"
showsPrec _ (l :%% r) = shows l . shows r
showsPrec _ (l :| r) = shows l . ('|':) . shows r
showsPrec _ (Star r) = shows r . ('*':)
showsPrec _ (Plus r) = shows r . ('+':)
showsPrec _ (Ques r) = shows r . ('?':)
encodeStartCodes:: Scanner -> (Scanner,[StartCode],ShowS)
encodeStartCodes scan = (scan', 0 : map snd name_code_pairs, sc_hdr)
where
scan' = scan{ scannerTokens = map mk_re_ctx (scannerTokens scan) }
mk_re_ctx (RECtx scs lc re rc code)
= RECtx (map mk_sc scs) lc re rc code
mk_sc (nm,_) = (nm, if nm=="0" then 0
else fromJust (Map.lookup nm code_map))
sc_hdr tl =
case name_code_pairs of
[] -> tl
(nm,_):rst -> "\n" ++ nm ++ foldr f t rst
where
f (nm', _) t' = "," ++ nm' ++ t'
t = " :: Int\n" ++ foldr fmt_sc tl name_code_pairs
where
fmt_sc (nm,sc) t = nm ++ " = " ++ show sc ++ "\n" ++ t
code_map = Map.fromList name_code_pairs
name_code_pairs = zip (nub' (<=) nms) [1..]
nms = [nm | RECtx{reCtxStartCodes = scs} <- scannerTokens scan,
(nm,_) <- scs, nm /= "0"]
extractActions :: Scheme -> Scanner -> (Scanner,ShowS)
extractActions scheme scanner = (scanner{scannerTokens = new_tokens}, decl_str)
where
(new_tokens, decls) = unzip (zipWith f (scannerTokens scanner) act_names)
f r@RECtx{ reCtxCode = Just code } name
= (r{reCtxCode = Just name}, Just (mkDecl name code))
f r@RECtx{ reCtxCode = Nothing } _
= (r{reCtxCode = Nothing}, Nothing)
mkDecl fun code = case scheme of
_ -> str "fn " . str fun
. str "(p: &mut Parser, pos: Position, len: isize, inp: InputStream) -> Res<Token> {" . nl
. str code . nl . str "}" . nl . nl
act_names = map (\n -> "alex_action_" ++ show (n::Int)) [0..]
decl_str = foldr (.) id [ decl | Just decl <- decls ]
data Target = GhcTarget | HaskellTarget