summaryrefslogtreecommitdiff
path: root/src/Inky/Parser.idr
diff options
context:
space:
mode:
Diffstat (limited to 'src/Inky/Parser.idr')
-rw-r--r--src/Inky/Parser.idr698
1 files changed, 489 insertions, 209 deletions
diff --git a/src/Inky/Parser.idr b/src/Inky/Parser.idr
index 1ad48d8..c44e7bd 100644
--- a/src/Inky/Parser.idr
+++ b/src/Inky/Parser.idr
@@ -1,21 +1,27 @@
module Inky.Parser
+import public Data.List.Quantifiers
+import public Data.Nat
+
import Control.WellFounded
import Data.Bool
+import Data.DPair
import Data.List
-import Data.List.Elem
import Data.List1
-import Data.Nat
import Data.So
+import Data.String.Extra
import Inky.Context
+import Inky.Thinning
import Text.Lexer
+export
+Interpolation Bounds where
+ interpolate bounds = "\{show (1 + bounds.startLine)}:\{show bounds.startCol}--\{show (1 + bounds.endLine)}:\{show bounds.endCol}"
-- Parser Expressions ----------------------------------------------------------
-export
-infixl 3 <**>, **>, <**
-infixr 2 <||>
+export infixl 3 <**>, **>, <**
+export infixr 2 <||>
public export
linUnless : Bool -> Context a -> Context a
@@ -23,124 +29,272 @@ linUnless False ctx = [<]
linUnless True ctx = ctx
public export
-data Parser : (i : Type) -> (nil : Bool) -> (locked, free : Context (Bool, Type)) -> Type -> Type where
- Var : (f : a -> b) -> Var free (nil, a) -> Parser i nil locked free b
- Fail : (msg : String) -> Parser i False locked free a
- Empty : (x : a) -> Parser i True locked free a
- Lit : (text : i) -> (x : String -> a) -> Parser i False locked free a
- (<**>) :
- {nil1, nil2 : Bool} ->
- Parser i nil1 locked free (a -> b) ->
- Parser i nil2 (linUnless nil1 locked) (free ++ linUnless (not nil1) locked) a ->
- Parser i (nil1 && nil2) locked free b
- (<|>) :
- {nil1, nil2 : Bool} ->
- Parser i nil1 locked free a -> Parser i nil2 locked free a ->
- So (not (nil1 && nil2)) =>
- Parser i (nil1 || nil2) locked free a
+linUnlessLin : (0 a : Type) -> (b : Bool) -> linUnless {a} b [<] = [<]
+linUnlessLin a False = Refl
+linUnlessLin a True = Refl
+
+public export
+data Parser : (i : Type) -> (nil : Bool) -> (locked, free : Context (Bool, Type)) -> Type -> Type
+
+public export
+data ParserChain : (i : Type) -> (nil : Bool) -> (locked, free : Context (Bool, Type)) -> List Type -> Type
+
+data Parser where
+ Var : Var free (nil, a) -> Parser i nil locked free a
+ Lit : (text : i) -> Parser i False locked free String
+ Seq :
+ ParserChain i nil locked free as ->
+ Parser i nil locked free (HList as)
+ OneOf :
+ {nils : List Bool} ->
+ All (\nil => Parser i nil locked free a) nils ->
+ {auto 0 prf : length (filter Basics.id nils) `LTE` 1} ->
+ Parser i (any Basics.id nils) locked free a
Fix :
(0 x : String) ->
- (f : a -> b) ->
Parser i nil (locked :< (x :- (nil, a))) free a ->
- Parser i nil locked free b
+ Parser i nil locked free a
+ Map : (a -> b) -> Parser i nil locked free a -> Parser i nil locked free b
+ WithBounds : Parser i nil locked free a -> Parser i nil locked free (WithBounds a)
+
+data ParserChain where
+ Nil : ParserChain i True locked free []
+ (::) :
+ {nil1, nil2 : Bool} ->
+ Parser i nil1 locked free a ->
+ ParserChain i nil2 (linUnless nil1 locked) (free ++ linUnless (not nil1) locked) as ->
+ ParserChain i (nil1 && nil2) locked free (a :: as)
%name Parser p, q
+%name ParserChain ps, qs
+
+-- Weakening -------------------------------------------------------------------
public export
-Functor (Parser i nil locked free) where
- map f (Var g x) = Var (f . g) x
- map f (Fail msg) = Fail msg
- map f (Empty x) = Empty (f x)
- map f (Lit text g) = Lit text (f . g)
- map f ((<**>) {nil1 = True} p q) = map (f .) p <**> q
- map f ((<**>) {nil1 = False} p q) = map (f .) p <**> q
- map f (p <|> q) = map f p <|> map f q
- map f (Fix x g p) = Fix x (f . g) p
+rename :
+ locked1 `Thins` locked2 ->
+ free1 `Thins` free2 ->
+ {auto len : Length locked2} ->
+ Parser i nil locked1 free1 a -> Parser i nil locked2 free2 a
+public export
+renameChain :
+ locked1 `Thins` locked2 ->
+ free1 `Thins` free2 ->
+ {auto len : Length locked2} ->
+ ParserChain i nil locked1 free1 a -> ParserChain i nil locked2 free2 a
+public export
+renameAll :
+ locked1 `Thins` locked2 ->
+ free1 `Thins` free2 ->
+ {auto len : Length locked2} ->
+ All.All (\nil => Parser i nil locked1 free1 a) nils ->
+ All.All (\nil => Parser i nil locked2 free2 a) nils
+
+rename f g (Var i) = Var (index g i)
+rename f g (Lit text) = Lit text
+rename f g (Seq ps) = Seq (renameChain f g ps)
+rename f g (OneOf ps) = OneOf (renameAll f g ps)
+rename f g (Fix x p) = Fix x (rename (Keep f) g p)
+rename f g (Map h p) = Map h (rename f g p)
+rename f g (WithBounds p) = WithBounds (rename f g p)
+
+renameChain f g [] = []
+renameChain f g ((::) {nil1 = False} p ps) = rename f g p :: renameChain Id (append g f) ps
+renameChain f g ((::) {nil1 = True} p ps) = rename f g p :: renameChain f g ps
+
+renameAll f g [] = []
+renameAll f g (p :: ps) = rename f g p :: renameAll f g ps
public export
-Applicative (Parser i True locked free) where
- pure = Empty
- (<*>) = (<**>)
+weaken :
+ (len1 : Length free2) ->
+ {auto len2 : Length locked} ->
+ Parser i nil (free2 ++ locked) free1 a -> Parser i nil locked (free1 ++ free2) a
+public export
+weakenChain :
+ (len1 : Length free2) ->
+ {auto len2 : Length locked} ->
+ ParserChain i nil (free2 ++ locked) free1 a -> ParserChain i nil locked (free1 ++ free2) a
+public export
+weakenAll :
+ (len1 : Length free2) ->
+ {auto len2 : Length locked} ->
+ All.All (\nil => Parser i nil (free2 ++ locked) free1 a) nils ->
+ All.All (\nil => Parser i nil locked (free1 ++ free2) a) nils
+
+weaken len1 (Var x) = Var (wknL x)
+weaken len1 (Lit text) = Lit text
+weaken len1 (Seq ps) = Seq (weakenChain len1 ps)
+weaken len1 (OneOf ps) = OneOf (weakenAll len1 ps)
+weaken len1 (Fix x p) = Fix x (weaken len1 p)
+weaken len1 (Map f p) = Map f (weaken len1 p)
+weaken len1 (WithBounds p) = WithBounds (weaken len1 p)
+
+weakenChain len1 [] = []
+weakenChain len1 ((::) {nil1 = False} p ps) = weaken len1 p :: renameChain Id (assoc len2) ps
+weakenChain len1 ((::) {nil1 = True} p ps) = weaken len1 p :: weakenChain len1 ps
+
+weakenAll len1 [] = []
+weakenAll len1 (p :: ps) = weaken len1 p :: weakenAll len1 ps
-- Typing ----------------------------------------------------------------------
-export
+-- Lists are sufficient, as we assume each symbol appears once.
+-- TODO: switch to some efficient tree?
+
+public export
peek :
(env : All (const (List i)) free) ->
Parser i nil locked free a -> List i
-peek env (Var f x) = indexAll x env
-peek env (Fail msg) = []
-peek env (Empty x) = []
-peek env (Lit text x) = [text]
-peek env ((<**>) {nil1 = False} p q) = peek env p
-peek env ((<**>) {nil1 = True} p q) = peek env p ++ peek env q
-peek env (p <|> q) = peek env p ++ peek env q
-peek env (Fix x f p) = peek env p
+public export
+peekChain :
+ (env : All (const (List i)) free) ->
+ ParserChain i nil locked free a -> List i
+public export
+peekAll :
+ (env : All (const (List i)) free) ->
+ All.All (\nil => Parser i nil locked free a) nils ->
+ All.All (const $ List i) nils
-export
+peek env (Var x) = indexAll x env
+peek env (Lit text) = [text]
+peek env (Seq ps) = peekChain env ps
+peek env (OneOf ps) = concat (forget $ peekAll env ps)
+peek env (Fix x p) = peek env p
+peek env (Map f p) = peek env p
+peek env (WithBounds p) = peek env p
+
+peekChain env [] = []
+peekChain env ((::) {nil1 = False} p ps) = peek env p
+peekChain env ((::) {nil1 = True} p ps) = peek env p ++ peekChain env ps
+
+peekAll env [] = []
+peekAll env (p :: ps) = peek env p :: peekAll env ps
+
+public export
follow :
(penv1 : All (const (List i)) locked) ->
(penv2 : All (const (List i)) free) ->
(fenv1 : All (const (List i)) locked) ->
(fenv2 : All (const (List i)) free) ->
Parser i nil locked free a -> List i
-follow penv1 penv2 fenv1 fenv2 (Var f x) = indexAll x fenv2
-follow penv1 penv2 fenv1 fenv2 (Fail msg) = empty
-follow penv1 penv2 fenv1 fenv2 (Empty x) = empty
-follow penv1 penv2 fenv1 fenv2 (Lit text x) = empty
-follow penv1 penv2 fenv1 fenv2 ((<**>) {nil1 = False} p q) =
- follow [<] (penv2 ++ penv1) [<] (fenv2 ++ fenv1) q
-follow penv1 penv2 fenv1 fenv2 ((<**>) {nil1 = True} p q) =
- peek penv2 q ++
- follow penv1 penv2 fenv1 fenv2 p ++
- follow penv1 penv2 fenv1 fenv2 q
-follow penv1 penv2 fenv1 fenv2 (p <|> q) =
- follow penv1 penv2 fenv1 fenv2 p ++
- follow penv1 penv2 fenv1 fenv2 q
-follow penv1 penv2 fenv1 fenv2 (Fix x f p) =
+public export
+followChain :
+ (penv1 : All (const (List i)) locked) ->
+ (penv2 : All (const (List i)) free) ->
+ (fenv1 : All (const (List i)) locked) ->
+ (fenv2 : All (const (List i)) free) ->
+ ParserChain i nil locked free a -> List i
+public export
+followAll :
+ (penv1 : All (const (List i)) locked) ->
+ (penv2 : All (const (List i)) free) ->
+ (fenv1 : All (const (List i)) locked) ->
+ (fenv2 : All (const (List i)) free) ->
+ All.All (\nil => Parser i nil locked free a) nils -> List i
+
+follow penv1 penv2 fenv1 fenv2 (Var x) = indexAll x fenv2
+follow penv1 penv2 fenv1 fenv2 (Lit text) = []
+follow penv1 penv2 fenv1 fenv2 (Seq ps) = followChain penv1 penv2 fenv1 fenv2 ps
+follow penv1 penv2 fenv1 fenv2 (OneOf ps) = followAll penv1 penv2 fenv1 fenv2 ps
+follow penv1 penv2 fenv1 fenv2 (Fix x p) =
-- Conjecture: The fix point converges after one step
-- Proof:
-- - we always add information
-- - no step depends on existing information
follow (penv1 :< (x :- peek penv2 p)) penv2 (fenv1 :< (x :- empty)) fenv2 p
+follow penv1 penv2 fenv1 fenv2 (Map f p) = follow penv1 penv2 fenv1 fenv2 p
+follow penv1 penv2 fenv1 fenv2 (WithBounds p) = follow penv1 penv2 fenv1 fenv2 p
+
+followChain penv1 penv2 fenv1 fenv2 [] = []
+followChain penv1 penv2 fenv1 fenv2 ((::) {nil1 = False, nil2} p ps) =
+ (if nil2
+ then peekChain (penv2 ++ penv1) ps ++ follow penv1 penv2 fenv1 fenv2 p
+ else []) ++
+ followChain [<] (penv2 ++ penv1) [<] (fenv2 ++ fenv1) ps
+followChain penv1 penv2 fenv1 fenv2 ((::) {nil1 = True, nil2} p ps) =
+ (if nil2
+ then peekChain penv2 ps ++ follow penv1 penv2 fenv1 fenv2 p
+ else []) ++
+ followChain penv1 penv2 fenv1 fenv2 ps
+
+followAll penv1 penv2 fenv1 fenv2 [] = []
+followAll penv1 penv2 fenv1 fenv2 (p :: ps) =
+ follow penv1 penv2 fenv1 fenv2 p ++
+ followAll penv1 penv2 fenv1 fenv2 ps
-export
-WellTyped :
- Eq i =>
- (penv1 : All (const (List i)) locked) ->
- (penv2 : All (const (List i)) free) ->
- (fenv1 : All (const (List i)) locked) ->
- (fenv2 : All (const (List i)) free) ->
- Parser i nil locked free a -> Type
-WellTyped penv1 penv2 fenv1 fenv2 (Var f x) = ()
-WellTyped penv1 penv2 fenv1 fenv2 (Fail msg) = ()
-WellTyped penv1 penv2 fenv1 fenv2 (Empty x) = ()
-WellTyped penv1 penv2 fenv1 fenv2 (Lit text x) = ()
-WellTyped penv1 penv2 fenv1 fenv2 ((<**>) {nil1 = False} p q) =
- let set1 = follow penv1 penv2 fenv1 fenv2 p in
- let set2 = peek (penv2 ++ penv1) q in
- ( WellTyped penv1 penv2 fenv1 fenv2 p
- , WellTyped [<] (penv2 ++ penv1) [<] (fenv2 ++ fenv1) q
- , So (not $ any (`elem` set2) set1)
- )
-WellTyped penv1 penv2 fenv1 fenv2 ((<**>) {nil1 = True} p q) =
- let set1 = follow penv1 penv2 fenv1 fenv2 p in
- let set2 = peek penv2 q in
- ( WellTyped penv1 penv2 fenv1 fenv2 p
- , WellTyped penv1 penv2 fenv1 fenv2 q
- , So (not $ any (`elem` set2) set1)
- )
-WellTyped penv1 penv2 fenv1 fenv2 (p <|> q) =
- let set1 = peek penv2 p in
- let set2 = peek penv2 q in
- ( WellTyped penv1 penv2 fenv1 fenv2 p
- , WellTyped penv1 penv2 fenv1 fenv2 q
- , So (not $ any (`elem` set2) set1)
- )
-WellTyped penv1 penv2 fenv1 fenv2 (Fix x f p) =
- let fst = peek penv2 p in
- let flw = follow (penv1 :< (x :- fst)) penv2 (fenv1 :< (x :- empty)) fenv2 p in
- WellTyped (penv1 :< (x :- fst)) penv2 (fenv1 :< (x :- flw)) fenv2 p
+public export
+all' : (a -> Bool) -> List a -> Bool
+all' f [] = True
+all' f (x :: xs) = f x && all' f xs
+
+allTrue : (xs : List a) -> all' (const True) xs = True
+allTrue [] = Refl
+allTrue (x :: xs) = allTrue xs
+
+public export
+disjoint : Eq a => List (List a) -> Bool
+disjoint [] = True
+disjoint (xs :: xss) = all' (\ys => all' (\x => not (x `elem` ys)) xs) xss && disjoint xss
+
+namespace WellTyped
+ public export
+ wellTyped :
+ (e : Eq i) ->
+ (penv1 : All (const (List i)) locked) ->
+ (penv2 : All (const (List i)) free) ->
+ (fenv1 : All (const (List i)) locked) ->
+ (fenv2 : All (const (List i)) free) ->
+ Parser i nil locked free a ->
+ Bool
+ public export
+ wellTypedChain :
+ (e : Eq i) ->
+ (penv1 : All (const (List i)) locked) ->
+ (penv2 : All (const (List i)) free) ->
+ (fenv1 : All (const (List i)) locked) ->
+ (fenv2 : All (const (List i)) free) ->
+ ParserChain i nil locked free a ->
+ Bool
+ public export
+ allWellTyped :
+ (e : Eq i) ->
+ (penv1 : All (const (List i)) locked) ->
+ (penv2 : All (const (List i)) free) ->
+ (fenv1 : All (const (List i)) locked) ->
+ (fenv2 : All (const (List i)) free) ->
+ All.All (\nil => Parser i nil locked free a) nils ->
+ Bool
+
+ wellTyped e penv1 penv2 fenv1 fenv2 (Var i) = True
+ wellTyped e penv1 penv2 fenv1 fenv2 (Lit txt) = True
+ wellTyped e penv1 penv2 fenv1 fenv2 (Seq ps) = wellTypedChain e penv1 penv2 fenv1 fenv2 ps
+ wellTyped e penv1 penv2 fenv1 fenv2 (OneOf {nils, prf} ps) =
+ disjoint (forget $ peekAll penv2 ps) && allWellTyped e penv1 penv2 fenv1 fenv2 ps
+ wellTyped e penv1 penv2 fenv1 fenv2 (Fix x p) =
+ wellTyped e
+ (penv1 :< (x :- peek penv2 p))
+ penv2
+ (fenv1 :< (x :- follow (penv1 :< (x :- peek penv2 p)) penv2 (fenv1 :< (x :- [])) fenv2 p))
+ fenv2
+ p
+ wellTyped e penv1 penv2 fenv1 fenv2 (Map f p) = wellTyped e penv1 penv2 fenv1 fenv2 p
+ wellTyped e penv1 penv2 fenv1 fenv2 (WithBounds p) = wellTyped e penv1 penv2 fenv1 fenv2 p
+
+ wellTypedChain e penv1 penv2 fenv1 fenv2 [] = True
+ wellTypedChain e penv1 penv2 fenv1 fenv2 ((::) {nil1 = False} p ps) =
+ disjoint [follow penv1 penv2 fenv1 fenv2 p, peekChain (penv2 ++ penv1) ps] &&
+ wellTyped e penv1 penv2 fenv1 fenv2 p &&
+ wellTypedChain e [<] (penv2 ++ penv1) [<] (fenv2 ++ fenv1) ps
+ wellTypedChain e penv1 penv2 fenv1 fenv2 ((::) {nil1 = True} p ps) =
+ disjoint [follow penv1 penv2 fenv1 fenv2 p, peekChain penv2 ps] &&
+ wellTyped e penv1 penv2 fenv1 fenv2 p &&
+ wellTypedChain e penv1 penv2 fenv1 fenv2 ps
+
+ allWellTyped e penv1 penv2 fenv1 fenv2 [] = True
+ allWellTyped e penv1 penv2 fenv1 fenv2 (p :: ps) =
+ wellTyped e penv1 penv2 fenv1 fenv2 p &&
+ allWellTyped e penv1 penv2 fenv1 fenv2 ps
-- Parsing Function ------------------------------------------------------------
@@ -168,8 +322,10 @@ wknSmallerL (Strict prf) _ = ofSmaller prf
wknSmallerL (Lax prf) _ = Lax prf
wknSmallerR : (b1 : Bool) -> SmallerX b2 xs ys -> SmallerX (b1 || b2) xs ys
-wknSmallerR b1 (Strict prf) = rewrite orFalseNeutral b1 in ofSmaller prf
-wknSmallerR b1 (Lax prf) = rewrite orTrueTrue b1 in Lax prf
+wknSmallerR b1 (Strict prf) =
+ if b1 then ofSmaller prf else ofSmaller prf
+wknSmallerR b1 (Lax prf) =
+ if b1 then Lax prf else Lax prf
forget : SmallerX b xs ys -> SmallerX True xs ys
forget = wknSmallerR True
@@ -180,6 +336,16 @@ toSmaller {xs = []} {ys = (y :: ys)} (Strict prf) = LTESucc LTEZero
toSmaller {xs = (x :: xs)} {ys = []} (Strict prf) impossible
toSmaller {xs = (x :: xs)} {ys = (y :: ys)} (Strict (LTESucc prf)) = LTESucc (toSmaller (Strict prf))
+anyCons : (b : Bool) -> (bs : List Bool) -> any Basics.id (b :: bs) = b || any Basics.id bs
+anyCons b [] = sym (orFalseNeutral b)
+anyCons b (b' :: bs) =
+ trans (anyCons (b || b') bs) $
+ trans (sym $ orAssociative b b' (any id bs))
+ (cong (b ||) (sym $ anyCons b' bs))
+
+anyTrue : (bs : List Bool) -> any Basics.id (True :: bs) = True
+anyTrue = anyCons True
+
-- Return Type
namespace M
@@ -203,39 +369,146 @@ namespace M
wknR b1 (Err msg) = Err msg
wknR b1 (Ok res ys prf) = Ok res ys (wknSmallerR b1 prf)
+ export
+ anyL :
+ (b : Bool) -> {0 bs : List Bool} ->
+ M xs (any Basics.id bs) a -> M xs (any Basics.id (b :: bs)) a
+ anyL b m = rewrite anyCons b bs in wknR b m
+
+ export
+ anyR : (bs : List Bool) -> M xs b a -> M xs (any Basics.id (b :: bs)) a
+ anyR bs m = rewrite anyCons b bs in wknL m (any id bs)
+
-- The Big Function
+data FirstNil : List Bool -> Type where
+ Here : FirstNil (True :: bs)
+ There : FirstNil bs -> FirstNil (False :: bs)
+
+findNil : (nils : List Bool) -> Maybe (FirstNil nils)
+findNil [] = Nothing
+findNil (False :: bs) = There <$> findNil bs
+findNil (True :: bs) = Just Here
+
+memberOf : Eq a => (x : a) -> All.All (const $ List a) xs -> Maybe (Any (const ()) xs)
+memberOf x [] = Nothing
+memberOf x (xs :: xss) =
+ if x `elem` xs
+ then Just (Here ())
+ else There <$> (x `memberOf` xss)
+
parser :
- Eq i => Interpolation i =>
+ (e : Eq i) => Interpolation i =>
(p : Parser i nil locked free a) ->
(penv1 : _) ->
(penv2 : _) ->
(fenv1 : _) ->
(fenv2 : _) ->
- {auto 0 wf : WellTyped penv1 penv2 fenv1 fenv2 p} ->
+ {auto 0 wf : So (wellTyped e penv1 penv2 fenv1 fenv2 p)} ->
(xs : List (WithBounds (Token i))) ->
All (\x => (ys : List (WithBounds (Token i))) -> (0 _ : SmallerX False ys xs) -> uncurry (M ys) x) locked ->
All (\x => (ys : List (WithBounds (Token i))) -> (0 _ : SmallerX True ys xs) -> uncurry (M ys) x) free ->
M xs nil a
-parser (Var f x) penv1 penv2 fenv1 fenv2 xs env1 env2 =
- f <$> indexAll x env2 xs (Lax reflexive)
-parser (Fail msg) penv1 penv2 fenv1 fenv2 xs env1 env2 =
- Err msg
-parser (Empty x) penv1 penv2 fenv1 fenv2 xs env1 env2 =
- Ok x xs (Lax reflexive)
-parser (Lit text f) penv1 penv2 fenv1 fenv2 xs env1 env2 =
+parserChain :
+ (e : Eq i) => Interpolation i =>
+ (ps : ParserChain i nil locked free as) ->
+ (penv1 : _) ->
+ (penv2 : _) ->
+ (fenv1 : _) ->
+ (fenv2 : _) ->
+ {auto 0 wf : So (wellTypedChain e penv1 penv2 fenv1 fenv2 ps)} ->
+ (xs : List (WithBounds (Token i))) ->
+ All (\x => (ys : List (WithBounds (Token i))) -> (0 _ : SmallerX False ys xs) -> uncurry (M ys) x) locked ->
+ All (\x => (ys : List (WithBounds (Token i))) -> (0 _ : SmallerX True ys xs) -> uncurry (M ys) x) free ->
+ M xs nil (HList as)
+parserNil :
+ (e : Eq i) => Interpolation i =>
+ (at : FirstNil nils) ->
+ (ps : All (\nil => Parser i nil locked free a) nils) ->
+ (penv1 : _) ->
+ (penv2 : _) ->
+ (fenv1 : _) ->
+ (fenv2 : _) ->
+ {auto 0 wf : So (allWellTyped e penv1 penv2 fenv1 fenv2 ps)} ->
+ (xs : List (WithBounds (Token i))) ->
+ All (\x => (ys : List (WithBounds (Token i))) -> (0 _ : SmallerX False ys xs) -> uncurry (M ys) x) locked ->
+ All (\x => (ys : List (WithBounds (Token i))) -> (0 _ : SmallerX True ys xs) -> uncurry (M ys) x) free ->
+ M xs (any Basics.id nils) a
+parserOneOf :
+ (e : Eq i) => Interpolation i =>
+ {nils : List Bool} ->
+ (at : Any (const ()) nils) ->
+ (ps : All (\nil => Parser i nil locked free a) nils) ->
+ (penv1 : _) ->
+ (penv2 : _) ->
+ (fenv1 : _) ->
+ (fenv2 : _) ->
+ {auto 0 wf : So (allWellTyped e penv1 penv2 fenv1 fenv2 ps)} ->
+ (xs : List1 (WithBounds (Token i))) ->
+ All (\x => (ys : List (WithBounds (Token i))) -> (0 _ : SmallerX False ys (forget xs)) -> uncurry (M ys) x) locked ->
+ All (\x => (ys : List (WithBounds (Token i))) -> (0 _ : SmallerX True ys (forget xs)) -> uncurry (M ys) x) free ->
+ M (forget xs) (any Basics.id nils) a
+
+parser (Var x) penv1 penv2 fenv1 fenv2 xs env1 env2 =
+ indexAll x env2 xs (Lax reflexive)
+parser (Lit text) penv1 penv2 fenv1 fenv2 xs env1 env2 =
case xs of
[] => Err "expected \{text}, got end of file"
y :: ys =>
if y.val.kind == text
- then Ok (f y.val.text) ys (Strict reflexive)
- else Err "\{show y.bounds}: expected \{text}, got \{y.val.kind}"
-parser ((<**>) {nil1 = False, nil2} p q) penv1 penv2 fenv1 fenv2 xs env1 env2 =
+ then Ok y.val.text ys (Strict reflexive)
+ else Err "\{y.bounds}: expected \{text}, got \{y.val.kind}"
+parser (Seq ps) penv1 penv2 fenv1 fenv2 xs env1 env2 =
+ parserChain ps penv1 penv2 fenv1 fenv2 xs env1 env2
+parser (OneOf {nils} ps) penv1 penv2 fenv1 fenv2 [] env1 env2 {wf} =
+ let 0 wfs = soAnd {a = disjoint (forget $ peekAll penv2 ps)} wf in
+ case findNil nils of
+ Nothing => Err "unexpected end of input"
+ Just at => parserNil at ps penv1 penv2 fenv1 fenv2 [] env1 env2
+parser (OneOf {nils} ps) penv1 penv2 fenv1 fenv2 (x :: xs) env1 env2 {wf = wf} =
+ let 0 wfs = soAnd {a = disjoint (forget $ peekAll penv2 ps)} wf in
+ let sets = peekAll penv2 ps in
+ case x.val.kind `memberOf` sets of
+ Just at => parserOneOf at ps penv1 penv2 fenv1 fenv2 (x ::: xs) env1 env2
+ Nothing => case findNil nils of
+ Nothing =>
+ Err
+ "\{x.bounds}: expected one of: \{join ", " $ map (\k => "\{k}") $ concat $ forget sets}; got \{x.val.kind}"
+ Just at => parserNil at ps penv1 penv2 fenv1 fenv2 (x :: xs) env1 env2
+parser (Fix {a, nil} x p) penv1 penv2 fenv1 fenv2 xs env1 env2 =
+ let f = parser p _ _ _ _ {wf} in
+ let
+ res : M xs nil a
+ res =
+ sizeInd {P = \ys => (0 prf : SmallerX True ys xs) -> M ys nil a}
+ (\ys, rec, lte =>
+ f ys
+ ( mapProperty (\f, zs, 0 prf => f zs $ transX prf lte) env1
+ :< (x :- (\zs, prf => rec zs (toSmaller prf) (forget $ transX prf lte)))
+ )
+ (mapProperty (\f, zs, prf => f zs $ transX prf lte) env2))
+ xs
+ (Lax reflexive)
+ in
+ res
+parser (Map f p) penv1 penv2 fenv1 fenv2 xs env1 env2 =
+ f <$> parser p penv1 penv2 fenv1 fenv2 xs env1 env2
+parser (WithBounds p) penv1 penv2 fenv1 fenv2 xs env1 env2 =
+ case xs of
+ [] => irrelevantBounds <$> parser p penv1 penv2 fenv1 fenv2 [] env1 env2
+ (x :: xs) =>
+ (\y => MkBounded y x.isIrrelevant x.bounds) <$>
+ parser p penv1 penv2 fenv1 fenv2 (x :: xs) env1 env2
+
+parserChain [] penv1 penv2 fenv1 fenv2 xs env1 env2 = Ok [] xs (Lax reflexive)
+parserChain ((::) {nil1 = False, nil2} p ps) penv1 penv2 fenv1 fenv2 xs env1 env2 =
+ let 0 wfs = soAnd wf in
+ let 0 wfs' = soAnd (snd wfs) in
case parser p penv1 penv2 fenv1 fenv2 xs env1 env2 of
Err msg => Err msg
- Ok f ys lt =>
+ Ok x ys lt =>
case
- parser q [<] (penv2 ++ penv1) [<] (fenv2 ++ fenv1)
+ parserChain ps [<] (penv2 ++ penv1) [<] (fenv2 ++ fenv1)
ys
[<]
( mapProperty (\f, zs, 0 prf => f zs $ forget $ transX prf lt) env2
@@ -243,122 +516,102 @@ parser ((<**>) {nil1 = False, nil2} p q) penv1 penv2 fenv1 fenv2 xs env1 env2 =
)
of
Err msg => Err msg
- Ok x zs prf => Ok (f x) zs (rewrite sym $ andFalseFalse nil2 in transX prf lt)
-parser ((<**>) {nil1 = True, nil2} p q) penv1 penv2 fenv1 fenv2 xs env1 env2 =
+ Ok y zs prf => Ok (x :: y) zs (rewrite sym $ andFalseFalse nil2 in transX prf lt)
+parserChain ((::) {nil1 = True, nil2} p ps) penv1 penv2 fenv1 fenv2 xs env1 env2 =
+ let 0 wfs = soAnd wf in
+ let 0 wfs' = soAnd (snd wfs) in
case parser p penv1 penv2 fenv1 fenv2 xs env1 env2 of
Err msg => Err msg
- Ok f ys lte =>
+ Ok x ys lte =>
case
- parser q penv1 penv2 fenv1 fenv2
+ parserChain ps penv1 penv2 fenv1 fenv2
ys
(mapProperty (\f, zs, prf => f zs $ transX prf lte) env1)
(mapProperty (\f, zs, prf => f zs $ transX prf lte) env2)
of
Err msg => Err msg
- Ok x zs prf => Ok (f x) zs (rewrite sym $ andTrueNeutral nil2 in transX prf lte)
-parser ((<|>) {nil1, nil2} p q) penv1 penv2 fenv1 fenv2 xs env1 env2 =
- case xs of
- [] =>
- if nil1
- then parser p penv1 penv2 fenv1 fenv2 [] env1 env2
- else if nil2
- then parser q penv1 penv2 fenv1 fenv2 [] env1 env2
- else Err "unexpected end of input"
- x :: xs =>
- if elem x.val.kind (peek penv2 p)
- then wknL (parser p penv1 penv2 fenv1 fenv2 (x :: xs) env1 env2) nil2
- else if elem x.val.kind (peek penv2 q)
- then wknR nil1 (parser q penv1 penv2 fenv1 fenv2 (x :: xs) env1 env2)
- else if nil1
- then parser p penv1 penv2 fenv1 fenv2 (x :: xs) env1 env2
- else if nil2
- then parser q penv1 penv2 fenv1 fenv2 (x :: xs) env1 env2
- else Err "\{show x.bounds}: unexpected \{x.val.kind}"
-parser (Fix {a, b, nil} x f p) penv1 penv2 fenv1 fenv2 xs env1 env2 =
- let g = parser p _ _ _ _ {wf} in
- let
- res : M xs nil a
- res =
- sizeInd {P = \ys => (0 prf : SmallerX True ys xs) -> M ys nil a}
- (\ys, rec, lte =>
- g ys
- ( mapProperty (\f, zs, 0 prf => f zs $ transX prf lte) env1
- :< (x :- (\zs, prf => rec zs (toSmaller prf) (forget $ transX prf lte)))
- )
- (mapProperty (\f, zs, prf => f zs $ transX prf lte) env2))
- xs
- (Lax reflexive)
- in
- f <$> res
+ Ok y zs prf => Ok (x :: y) zs (rewrite sym $ andTrueNeutral nil2 in transX prf lte)
+
+parserNil {nils = True :: nils} Here (p :: ps) penv1 penv2 fenv1 fenv2 xs env1 env2 =
+ let 0 wfs = soAnd wf in
+ rewrite anyTrue nils in
+ parser p penv1 penv2 fenv1 fenv2 xs env1 env2
+parserNil (There at) (p :: ps) penv1 penv2 fenv1 fenv2 xs env1 env2 =
+ let 0 wfs = soAnd {a = wellTyped e penv1 penv2 fenv1 fenv2 p} wf in
+ parserNil at ps penv1 penv2 fenv1 fenv2 xs env1 env2
+
+parserOneOf {nils = nil :: nils} (Here ()) (p :: ps) penv1 penv2 fenv1 fenv2 xs env1 env2 =
+ let 0 wfs = soAnd wf in
+ anyR nils (parser p penv1 penv2 fenv1 fenv2 (forget xs) env1 env2)
+parserOneOf {nils = nil :: nils} (There at) (p :: ps) penv1 penv2 fenv1 fenv2 xs env1 env2 =
+ let 0 wfs = soAnd {a = wellTyped e penv1 penv2 fenv1 fenv2 p} wf in
+ anyL nil (parserOneOf at ps penv1 penv2 fenv1 fenv2 xs env1 env2)
export
parse :
- Eq i => Interpolation i =>
+ (e : Eq i) => Interpolation i =>
(p : Parser i nil [<] [<] a) ->
- {auto 0 wf : WellTyped [<] [<] [<] [<] p} ->
+ {auto 0 wf : So (wellTyped e [<] [<] [<] [<] p)} ->
(xs : List (WithBounds (Token i))) -> M xs nil a
parse p xs = parser p [<] [<] [<] [<] xs [<] [<]
--- Weakening -------------------------------------------------------------------
+-- Functor ---------------------------------------------------------------------
public export
-rename :
- (len1 : Length locked1) ->
- (len2 : Length locked2) ->
- (forall x. Var locked1 x -> Var locked2 x) ->
- (forall x. Var free1 x -> Var free2 x) ->
- Parser i nil locked1 free1 a -> Parser i nil locked2 free2 a
-rename len1 len2 ren1 ren2 (Var f x) = Var f (ren2 x)
-rename len1 len2 ren1 ren2 (Fail msg) = Fail msg
-rename len1 len2 ren1 ren2 (Empty x) = Empty x
-rename len1 len2 ren1 ren2 (Lit text x) = Lit text x
-rename len1 len2 ren1 ren2 ((<**>) {nil1 = False} p q) =
- rename len1 len2 ren1 ren2 p <**>
- rename Z Z id (either (wknL {len = len2} . ren2) (wknR . ren1) . split) q
-rename len1 len2 ren1 ren2 ((<**>) {nil1 = True} p q) =
- rename len1 len2 ren1 ren2 p <**> rename len1 len2 ren1 ren2 q
-rename len1 len2 ren1 ren2 (p <|> q) =
- rename len1 len2 ren1 ren2 p <|> rename len1 len2 ren1 ren2 q
-rename len1 len2 ren1 ren2 (Fix x f p) =
- Fix x f (rename (S len1) (S len2) (lift {len = S Z} ren1) ren2 p)
+(++) :
+ {nil2 : Bool} ->
+ ParserChain i nil1 locked free as ->
+ ParserChain i nil2 (linUnless nil1 locked) (free ++ linUnless (not nil1) locked) bs ->
+ ParserChain i (nil1 && nil2) locked free (as ++ bs)
+[] ++ qs = qs
+((::) {nil1 = False, nil2} p ps) ++ qs =
+ p ::
+ ( ps
+ ++ rewrite linUnlessLin (Bool, Type) nil2 in
+ rewrite linUnlessLin (Bool, Type) (not nil2) in
+ qs)
+((::) {nil1 = True, nil2} p ps) ++ qs = p :: (ps ++ qs)
public export
-weaken :
- (len1 : Length free2) ->
- {auto len2 : Length locked} ->
- Parser i nil (free2 ++ locked) free1 a -> Parser i nil locked (free1 ++ free2) a
-weaken len1 (Var f x) = Var f (wknL x)
-weaken len1 (Fail msg) = Fail msg
-weaken len1 (Empty x) = Empty x
-weaken len1 (Lit text x) = Lit text x
-weaken len1 ((<**>) {nil1 = False} p q) =
- weaken len1 p <**>
- rename Z Z
- id
- ( either (wknL . wknL) (either (wknL . wknR) wknR . split)
- . split {len = lengthAppend len1 len2}
- )
- q
-weaken len1 ((<**>) {nil1 = True} p q) = weaken len1 p <**> weaken len1 q
-weaken len1 (p <|> q) = weaken len1 p <|> weaken len1 q
-weaken len1 (Fix x f p) = Fix x f (weaken len1 p)
-
-public export
-shift :
- {auto len1 : Length locked1} ->
- (len2 : Length locked2) ->
- (len3 : Length free2) ->
- Parser i nil locked1 free1 a -> Parser i nil (locked1 ++ locked2) (free1 ++ free2) a
-shift len2 len3 = rename len1 (lengthAppend len1 len2) wknL wknL
+(<**>) :
+ {nil1, nil2 : Bool} ->
+ Parser i nil1 locked free a ->
+ Parser i nil2 (linUnless nil1 locked) (free ++ linUnless (not nil1) locked) b ->
+ Parser i (nil1 && nil2) locked free (a, b)
+p <**> Seq ps = Map (\(x :: xs) => (x, xs)) $ Seq (p :: ps)
+-- HACK: andTrueNeutral isn't public, so do a full case split.
+(<**>) {nil1 = True, nil2 = True} p q = Map (\[x, y] => (x, y)) $ Seq [p, q]
+(<**>) {nil1 = True, nil2 = False} p q = Map (\[x, y] => (x, y)) $ Seq [p, q]
+(<**>) {nil1 = False, nil2 = True} p q = Map (\[x, y] => (x, y)) $ Seq [p, q]
+(<**>) {nil1 = False, nil2 = False} p q = Map (\[x, y] => (x, y)) $ Seq [p, q]
+
+public export
+Functor (Parser i nil locked free) where
+ map f (Map g p) = Map (f . g) p
+ map f p = Map f p
+
+public export
+Applicative (Parser i True locked free) where
+ pure x = map (const x) (Seq [])
+ p <*> q = map (\(f, x) => f x) (p <**> q)
-- Combinator ------------------------------------------------------------------
public export
+(<|>) :
+ {nil1, nil2 : Bool} ->
+ Parser i nil1 locked free a ->
+ Parser i nil2 locked free a ->
+ {auto 0 prf : length (filter Basics.id [nil1, nil2]) `LTE` 1} ->
+ Parser i (nil1 || nil2) locked free a
+p <|> q = OneOf [p, q]
+
+public export
(<||>) :
{nil1, nil2 : Bool} ->
Parser i nil1 locked free a ->
Parser i nil2 locked free b ->
- So (not (nil1 && nil2)) =>
+ {auto 0 prf : length (filter Basics.id [nil1, nil2]) `LTE` 1} ->
Parser i (nil1 || nil2) locked free (Either a b)
p <||> q = Left <$> p <|> Right <$> q
@@ -368,7 +621,7 @@ public export
Parser i nil1 locked free a ->
Parser i nil2 (linUnless nil1 locked) (free ++ linUnless (not nil1) locked) b ->
Parser i (nil1 && nil2) locked free b
-p **> q = (\_ => id) <$> p <**> q
+p **> q = snd <$> (p <**> q)
public export
(<**) :
@@ -376,11 +629,24 @@ public export
Parser i nil1 locked free a ->
Parser i nil2 (linUnless nil1 locked) (free ++ linUnless (not nil1) locked) b ->
Parser i (nil1 && nil2) locked free a
-p <** q = const <$> p <**> q
+p <** q = fst <$> (p <**> q)
public export
match : TokenKind i => (kind : i) -> Parser i False locked free (TokType kind)
-match kind = Lit kind (tokValue kind)
+match kind = Map (tokValue kind) $ Lit kind
+
+public export
+enclose :
+ {b1, b2, b3 : Bool} ->
+ (left : Parser i b1 locked free ()) ->
+ (right :
+ Parser i b3
+ (linUnless b2 (linUnless b1 locked))
+ ((free ++ linUnless (not b1) locked) ++ linUnless (not b2) (linUnless b1 locked))
+ ()) ->
+ Parser i b2 (linUnless b1 locked) (free ++ linUnless (not b1) locked) a ->
+ Parser i (b1 && b2 && b3 && True) locked free a
+enclose left right p = (\[_, x, _] => x) <$> Seq {as = [(), a, ()]} [left, p, right]
public export
option : Parser i False locked free a -> Parser i True locked free (Maybe a)
@@ -392,15 +658,29 @@ plus :
Parser i False locked free a ->
Parser i False locked free (List1 a)
plus p =
- Fix "plus" id
- ( (:::) <$> shift (S Z) Z p
- <**> maybe [] forget <$> option (Var id (%% "plus")))
+ Fix "plus"
+ ( uncurry (:::)
+ <$> (rename (Drop Id) Id p <**> maybe [] forget <$> option (Var $ %% "plus")))
public export
star :
{auto len : Length locked} ->
Parser i False locked free a ->
Parser i True locked free (List a)
-star p =
- Fix "star" id
- (maybe [] id <$> option ((::) <$> shift (S Z) Z p <**> Var id (%% "star")))
+star p = maybe [] forget <$> option (plus p)
+
+public export
+sepBy1 :
+ {auto len : Length locked} ->
+ (sep : Parser i False locked free ()) ->
+ Parser i False locked free a ->
+ Parser i False locked free (List1 a)
+sepBy1 sep p = uncurry (:::) <$> (p <**> star (weaken len sep **> weaken len p))
+
+public export
+sepBy :
+ {auto len : Length locked} ->
+ (sep : Parser i False locked free ()) ->
+ Parser i False locked free a ->
+ Parser i True locked free (List a)
+sepBy sep p = maybe [] forget <$> option (sepBy1 sep p)