ptera-0.1.0.0: src/Language/Parser/Ptera/Pipeline/SRB2Parser.hs
module Language.Parser.Ptera.Pipeline.SRB2Parser where
import Language.Parser.Ptera.Prelude
import qualified Data.EnumMap.Strict as EnumMap
import qualified Language.Parser.Ptera.Data.Alignable.Array as AlignableArray
import qualified Language.Parser.Ptera.Data.HEnum as HEnum
import qualified Language.Parser.Ptera.Data.Symbolic.IntMap as SymbolicIntMap
import qualified Language.Parser.Ptera.Machine.LAPEG as LAPEG
import qualified Language.Parser.Ptera.Machine.PEG as PEG
import qualified Language.Parser.Ptera.Machine.SRB as SRB
import qualified Language.Parser.Ptera.Runner.Parser as Parser
import qualified Language.Parser.Ptera.Syntax as Syntax
import qualified Language.Parser.Ptera.Syntax.Grammar as Grammar
import qualified Unsafe.Coerce as Unsafe
type Action ctx = Grammar.Action (Syntax.SemActM ctx)
srb2Parser :: forall ctx tokens elem altHelp
. Syntax.GrammarToken tokens elem
=> Proxy tokens -> SRB.T Int StringLit (Maybe altHelp) (Action ctx)
-> Parser.T ctx elem altHelp
srb2Parser p srb = Parser.RunnerParser
{ parserInitial = \s -> coerce do EnumMap.lookup s do SRB.initials srb
, parserGetTokenNum = \tok ->
HEnum.unsafeHEnum do Syntax.tokenToTerminal p tok
, parserTrans = \s0 t -> if s0 < 0
then Parser.Trans
{
transState = -1,
transOps = []
}
else
let srbSt = AlignableArray.forceIndex
do SRB.states srb
do SRB.StateNum s0
in buildTrans t srbSt
, parserAltKind = \alt -> LAPEG.altKind
do AlignableArray.forceIndex
do SRB.alts srb
do LAPEG.AltNum alt
, parserAction = \alt -> runAction
do LAPEG.altAction
do AlignableArray.forceIndex
do SRB.alts srb
do LAPEG.AltNum alt
, parserStateHelp = \s ->
let srbSt = AlignableArray.forceIndex
do SRB.states srb
do SRB.StateNum s
in buildStateHelp do SRB.stateAltItems srbSt
, parserAltHelp = \alt ->
let vn = LAPEG.altVar
do AlignableArray.forceIndex
do SRB.alts srb
do LAPEG.AltNum alt
v = AlignableArray.forceIndex
do SRB.vars srb
do vn
in (PEG.varHelp v, Nothing)
}
buildTrans :: Int -> SRB.MState -> Parser.Trans
buildTrans t srbSt = case SymbolicIntMap.lookup t do SRB.stateTrans srbSt of
Nothing ->
Parser.Trans
{
transState = -1,
transOps = []
}
Just (SRB.TransWithOps ops (SRB.StateNum s1)) ->
Parser.Trans
{
transState = s1,
transOps = transOp <$> ops
}
Just (SRB.TransReduce (LAPEG.AltNum alt)) ->
Parser.Trans
{
transState = -1,
transOps = [Parser.TransOpReduce alt]
}
buildStateHelp :: [SRB.AltItem] -> [(Parser.AltNum, Int)]
buildStateHelp altItems =
[
( coerce do SRB.altItemAltNum altItem
, coerce do SRB.altItemCurPos altItem
)
| altItem <- altItems
]
transOp :: SRB.TransOp -> Parser.TransOp
transOp = \case
SRB.TransOpEnter (LAPEG.VarNum v) needBack mEnterSn ->
let enterSn = case mEnterSn of
Nothing ->
-1
Just (SRB.StateNum x) ->
x
in Parser.TransOpEnter v needBack enterSn
SRB.TransOpPushBackpoint (SRB.StateNum backSn) ->
Parser.TransOpPushBackpoint backSn
SRB.TransOpHandleNot (LAPEG.AltNum alt) ->
Parser.TransOpHandleNot alt
SRB.TransOpShift ->
Parser.TransOpShift
runAction :: Action ctx -> Parser.ActionM ctx
runAction (Grammar.Action (Syntax.SemActM f)) = Parser.ActionM \l ->
Parser.ReduceArgument <$> f do goL l
where
goL = \case
[] ->
unsafeCoerceHList Syntax.HNil
Parser.ReduceArgument x:xs ->
unsafeCoerceHList do x Syntax.:* goL xs
unsafeCoerceHList :: Syntax.HList us1 -> Syntax.HList us2
unsafeCoerceHList = Unsafe.unsafeCoerce