0 | module Text.ILex.Shunting
2 | import Text.ByteBounds
3 | import Derive.Prelude
6 | %language ElabReflection
14 | data Assoc = None | InfixR | InfixL
16 | %runElab derive "Assoc" [Show,Eq,Ord]
19 | Interpolation Assoc where
20 | interpolate None = "infix"
21 | interpolate InfixR = "infixr"
22 | interpolate InfixL = "infixl"
26 | data Precedence : Type where
27 | Prefix : (prec : Nat) -> Precedence
28 | Postfix : (prec : Nat) -> Precedence
29 | Infix : (prec : Nat) -> (assoc : Assoc) -> Precedence
31 | %runElab derive "Precedence" [Show,Eq]
34 | Interpolation Precedence where
35 | interpolate (Prefix p) = "prefix \{show p}"
36 | interpolate (Postfix p) = "postfix \{show p}"
37 | interpolate (Infix p a) = "\{a} \{show p}"
40 | Cast a Precedence => Cast (ByteBounded a) Precedence where
44 | toPrec : Cast o Precedence => o -> Precedence
48 | prec : Cast o Precedence => o -> Nat
56 | data ShuntingErr : Type -> Type where
57 | AssocNone : (op : o) -> (prec : Precedence) -> ShuntingErr o
59 | %runElab derive "ShuntingErr" [Show,Eq]
62 | Interpolation o => Interpolation (ShuntingErr o) where
63 | interpolate (AssocNone op p) = "operator '\{op}' (\{p}) is non-associative"
69 | data Tok : (t,p,i,o : Type) -> Type where
70 | TPre : ByteBounded p -> (prec : Nat) -> Tok t p i o
71 | TInf : t -> ByteBounded i -> (prec : Nat) -> Assoc -> Tok t p i o
72 | TPst : ByteBounded o -> (prec : Nat) -> Tok t p i o
74 | %runElab derive "Tok" [Show,Eq]
77 | Cast (Tok t p i o) Precedence where
78 | cast (TPre _ p) = Prefix p
79 | cast (TInf _ _ p a) = Infix p a
80 | cast (TPst _ p) = Postfix p
83 | 0 Toks : (t,p,i,o : Type) -> Type
84 | Toks t p i o = List (Tok t p i o)
87 | 0 Skot : (t,p,i,o : Type) -> Type
88 | Skot t p i o = SnocList (Tok t p i o)
94 | parameters {0 t,p,i,o,e : Type}
95 | {auto cst : Cast (ShuntingErr i) e}
96 | (pre : ByteBounded p -> t -> t)
97 | (inf : t -> ByteBounded i -> t -> t)
98 | (pst : ByteBounded o -> t -> t)
101 | Res = Either (ByteBounded e) (Skot t p i o)
103 | err : ByteBounded i -> Precedence -> Either (ByteBounded e) a
104 | err op p = Left (B (cast $
AssocNone op.val p) op.bounds)
106 | app : Tok t p i o -> t -> t
107 | app (TPre op _) y = pre op y
108 | app (TInf x op _ _) y = inf x op y
109 | app (TPst op _) y = pst op y
111 | apply : Skot t p i o -> t -> t
112 | apply [<] lst = lst
113 | apply (si:<i) lst = apply si (app i lst)
115 | insInf : Skot t p i o -> t -> ByteBounded i -> Nat -> Assoc -> Res
116 | insInf [<] lst op n a = Right $
[<TInf lst op n a]
117 | insInf (si:<i) lst op n a =
118 | case compare (prec i) n of
119 | LT => Right $
si:<i:<TInf lst op n a
120 | GT => insInf si (app i lst) op n a
122 | let False := InfixL == a | True => insInf si (app i lst) op n a
123 | False := None == a | True => err op $
Infix n a
124 | TInf _ o _ x := i | _ => Right $
si:<i:<TInf lst op n a
125 | False := None == x | True => err o $
Infix n x
126 | in Right $
si:<i:<TInf lst op n a
128 | impl : Skot t p i o -> Toks t p i o -> t -> Either (ByteBounded e) t
129 | impl si [] lst = Right $
apply si lst
130 | impl si (i::is) lst =
132 | TPre op n => impl (si:<TPre op n) is lst
133 | TInf t op n a => case insInf si t op n a of
134 | Left err => Left err
135 | Right si2 => impl si2 is lst
136 | TPst op n => impl (si:<TPst op n) is lst
143 | shuntingYard : Skot t p i o -> t -> Either (ByteBounded e) t
144 | shuntingYard = impl [<] . (<>> [])