@@ -3,11 +3,12 @@
33module Parse.Primitives
44 ( Parser
55 , run, runAt
6− , try, failure, deadend, expecting, endOfFile
6+ , try, failure, deadend, hint, endOfFile
77 , oneOf
88 , symbol, keyword, keywords
99 , lowVar, capVar, infixOp
1010 , getPosition, getCol
11+ , getContext, pushContext, popContext
1112 , getIndent, setIndent
1213 , SPos(..), whitespace
1314 , docComment, chompUntilDocs
@@ -38,8 +39,11 @@ import qualified AST.Helpers as Help (isSymbol)
3839import qualified AST.Literal as L
3940import qualified Reporting.Annotation as A
4041import qualified Reporting.Error.Syntax as E
41−import Reporting.Error.Syntax ( ParseError(..), Problem(..), Theory(..) )
4242import qualified Reporting.Region as Region
43+import Reporting.Error.Syntax
44+ ( ParseError(..), Problem(..), Theory(..)
45+ , Context(..), BadOp(..)
46+ )
4347
4448
4549
@@ -51,10 +55,10 @@ newtype Parser a =
5155 { _run
5256 :: forall b.
5357 State
54− -> (a -> State -> b) -- consumed ok
55− -> (ParseError -> b) -- consumed err
56− -> (a -> State -> b) -- empty ok
57− -> (ParseError -> b) -- empty err
58+ -> (a -> State -> ParseError -> b) -- consumed ok
59+ -> ( ParseError -> b) -- consumed err
60+ -> (a -> State -> ParseError -> b) -- empty ok
61+ -> ( ParseError -> b) -- empty err
5862 -> b
5963 }
6064
@@ -67,24 +71,20 @@ data State =
6771 , _indent :: !Int
6872 , _row :: !Int
6973 , _col :: !Int
74+ , _context :: [Context]
7075 }
7176
7277
73−data Result a
74− = Ok a State
75− | Err ParseError
76−
78+{-# NOINLINE noError #-}
79+noError :: ParseError
80+noError =
81+ ParseError 0 0 (Theories [] [])
7782
78−{-# INLINE noTheory #-}
79−noTheory :: Int -> Int -> ParseError
80−noTheory row col =
81− ParseError row col (Theories [])
8283
83−
84−{-# INLINE loneTheory #-}
85−loneTheory :: Int -> Int -> Theory -> ParseError
86−loneTheory row col theory =
87− ParseError row col (Theories [theory])
84+{-# INLINE expect #-}
85+expect :: Int -> Int -> [Context] -> Theory -> ParseError
86+expect row col ctx theory =
87+ ParseError row col (Theories ctx [theory])
8888
8989
9090
@@ -98,8 +98,8 @@ run parser text =
9898
9999runAt :: Int -> Int -> Parser a -> Text -> Either (A.Located E.Error) a
100100runAt sRow sCol parser (Text.Text array offset length) =
101− case _run parser (State array offset length 0 sRow sCol) Ok Err Ok Err of
102− Ok value _ ->
101+ case _run parser (State array offset length 0 sRow sCol []) Ok Err Ok Err of
102+ Ok value _ _ ->
103103 Right value
104104
105105 Err (ParseError row col problem) ->
@@ -110,6 +110,11 @@ runAt sRow sCol parser (Text.Text array offset length) =
110110 Left (A.A region (E.Parse problem))
111111
112112
113+data Result a
114+ = Ok a State ParseError
115+ | Err ParseError
116+
117+
113118
114119-- COMBINATORS
115120
@@ -122,7 +127,7 @@ try parser =
122127
123128failure :: Problem -> Parser a
124129failure problem =
125− Parser $ \(State _ _ _ _ row col) _ cerr _ _ ->
130+ Parser $ \(State _ _ _ _ row col _) _ cerr _ _ ->
126131 cerr (ParseError row col problem)
127132
128133
@@ -132,33 +137,33 @@ shaderFailure row col msg =
132137 cerr (ParseError row col (BadShader msg))
133138
134139
135−deadend :: Theory -> Parser a
136−deadend theory =
137− Parser $ \(State _ _ _ _ row col) _ _ _ eerr ->
138− eerr (loneTheory row col theory)
140+deadend :: [Theory] -> Parser a
141+deadend thrys =
142+ Parser $ \(State _ _ _ _ row col ctx) _ _ _ eerr ->
143+ eerr (ParseError row col (Theories ctx thrys))
139144
140145
141−expecting :: Text -> Parser a -> Parser a
142−expecting description parser =
143− Parser $ \state@(State _ _ _ _ row col) cok cerr eok eerr ->
146+hint :: E.Next -> Parser a -> Parser a
147+hint next parser =
148+ Parser $ \state@(State _ _ _ _ row col ctx) cok cerr eok eerr ->
144149 let
145− eok' x s =
146− eok x s
150+ eok' x s _ =
151+ eok x s (expect row col ctx (Expecting next))
147152
148153 eerr' _ =
149− eerr (loneTheory row col (Expecting description))
154+ eerr (expect row col ctx (Expecting next))
150155 in
151156 _run parser state cok cerr eok' eerr'
152157
153158
154159endOfFile :: Parser ()
155160endOfFile =
156− Parser $ \state@(State _ _ length _ row col) _ _ eok eerr ->
161+ Parser $ \state@(State _ _ length _ row col ctx) _ _ eok eerr ->
157162 if length == 0 then
158− eok () state
163+ eok () state (expect row col ctx EndOfFile)
159164
160165 else
161− eerr (noTheory row col)
166+ eerr (expect row col ctx EndOfFile)
162167
163168
164169
@@ -169,8 +174,8 @@ instance Functor Parser where
169174 fmap f parser =
170175 Parser $ \state cok cerr eok eerr ->
171176 let
172− cok' x s = cok (f x) s
173− eok' x s = eok (f x) s
177+ cok' x s e = cok (f x) s e
178+ eok' x s e = eok (f x) s e
174179 in
175180 _run parser state cok' cerr eok' eerr
176181
@@ -196,18 +201,18 @@ oneOf parsers =
196201
197202allTheOptionsFailed :: Parser a
198203allTheOptionsFailed =
199− Parser $ \(State _ _ _ _ row col) _ _ _ eerr ->
200− eerr (noTheory row col)
204+ Parser $ \_ _ _ _ eerr ->
205+ eerr noError
201206
202207
203208oneOfHelp :: Parser a -> Parser a -> Parser a
204209oneOfHelp parser1 parser2 =
205210 Parser $ \state cok cerr eok eerr ->
206211 let
207− eerr1 err1 =
212+ eerr1 e1 =
208213 let
209− eok2 y state' = eok y state'
210− eerr2 err2 = eerr (mergeErrors err1 err2)
214+ eok2 y s e2 = eok y s (mergeErrors e1 e2)
215+ eerr2 e2 = eerr (mergeErrors e1 e2)
211216 in
212217 _run parser2 state cok cerr eok2 eerr2
213218 in
@@ -215,16 +220,30 @@ oneOfHelp parser1 parser2 =
215220
216221
217222mergeErrors :: ParseError -> ParseError -> ParseError
218−mergeErrors error1@(ParseError row col problem1) error2@(ParseError _ _ problem2) =
219− case (problem1, problem2) of
220− (Theories theories1, Theories theories2) ->
221− ParseError row col (Theories (theories1 ++ theories2))
223+mergeErrors e1@(ParseError r1 c1 p1) e2@(ParseError r2 c2 p2) =
224+ case compare r1 r2 of
225+ LT -> e2
226+ GT -> e1
227+ EQ ->
228+ case compare c1 c2 of
229+ LT -> e2
230+ GT -> e1
231+ EQ ->
232+ case (p1, p2) of
233+ (Theories _ [], Theories _ _) ->
234+ e2
235+
236+ (Theories _ _, Theories _ []) ->
237+ e1
222238
223− (Theories _, _) ->
224− error2
239+ (Theories ctx ts1, Theories _ ts2) ->
240+ ParseError r1 c1 (Theories ctx (ts1 ++ ts2))
225241
226− (_, _) ->
227− error1
242+ (Theories _ _, _) ->
243+ e2
244+
245+ (_, _) ->
246+ e1
228247
229248
230249
@@ -234,18 +253,26 @@ mergeErrors error1@(ParseError row col problem1) error2@(ParseError _ _ problem2
234253instance Monad Parser where
235254 return value =
236255 Parser $ \state _ _ eok _ ->
237− eok value state
256+ eok value state noError
238257
239258 parser >>= callback =
240259 Parser $ \state cok cerr eok eerr ->
241260 let
242− cok' value newState =
243− _run (callback value) newState cok cerr cok cerr
261+ cok1 x s1 e1 =
262+ let
263+ eok2 y s2 e2 = cok y s2 (mergeErrors e1 e2)
264+ eerr2 e2 = cerr (mergeErrors e1 e2)
265+ in
266+ _run (callback x) s1 cok cerr eok2 eerr2
244267
245− eok' value newState =
246− _run (callback value) newState cok cerr eok eerr
268+ eok1 x s1 e1 =
269+ let
270+ eok2 y s2 e2 = eok y s2 (mergeErrors e1 e2)
271+ eerr2 e2 = eerr (mergeErrors e1 e2)
272+ in
273+ _run (callback x) s1 cok cerr eok2 eerr2
247274 in
248− _run parser state cok' cerr eok' eerr
275+ _run parser state cok1 cerr eok1 eerr
249276
250277
251278
@@ -254,16 +281,19 @@ instance Monad Parser where
254281
255282symbol :: Text -> Parser ()
256283symbol sym@(Text.Text tArray tOffset tLen) =
257− Parser $ \(State array offset length indent row col) cok _ _ eerr ->
284+ Parser $ \(State array offset length indent row col ctx) cok _ _ eerr ->
258285 if tLen <= length && Text.equal tArray tOffset array offset tLen then
259286 let
260287 (# newRow, newCol #) =
261288 moveCursor tArray tOffset tLen row col
289+
290+ !newState =
291+ State array (offset + tLen) (length - tLen) indent newRow newCol ctx
262292 in
263− cok () (State array (offset + tLen) (length - tLen) indent newRow newCol)
293+ cok () newState noError
264294
265295 else
266− eerr (loneTheory row col (Symbol sym))
296+ eerr (expect row col ctx (Symbol sym))
267297
268298
269299moveCursor :: Text.Array -> Int -> Int -> Int -> Int -> (# Int, Int #)
@@ -291,21 +321,24 @@ moveCursor array offset length row col =
291321
292322keyword :: Text -> Parser ()
293323keyword kwd@(Text.Text tArray tOffset tLen) =
294− Parser $ \(State array offset length indent row col) cok _ _ eerr ->
324+ Parser $ \(State array offset length indent row col ctx) cok _ _ eerr ->
295325 if tLen <= length && Text.equal tArray tOffset array offset tLen then
296326
297327 if isInnerVarChar (peekChar array (offset + tLen)) then
298− eerr (loneTheory row col (Keyword kwd))
328+ eerr (expect row col ctx (Keyword kwd))
299329
300330 else
301331 let
302332 (# newRow, newCol #) =
303333 moveCursor tArray tOffset tLen row col
334+
335+ !newState =
336+ State array (offset + tLen) (length - tLen) indent newRow newCol ctx
304337 in
305− cok () (State array (offset + tLen) (length - tLen) indent newRow newCol)
338+ cok () newState noError
306339
307340 else
308− eerr (loneTheory row col (Keyword kwd))
341+ eerr (expect row col ctx (Keyword kwd))
309342
310343
311344keywords :: Set.Set Text
@@ -328,20 +361,20 @@ keywords =
328361
329362lowVar :: Parser Text.Text
330363lowVar =
331− varPrim Char.isLower
364+ varPrim LowVar Char.isLower
332365
333366
334367capVar :: Parser Text.Text
335368capVar =
336− varPrim Char.isUpper
369+ varPrim CapVar Char.isUpper
337370
338371
339372{-# INLINE varPrim #-}
340−varPrim :: (Char -> Bool) -> Parser Text.Text
341−varPrim isGoodFirstChar =
342− Parser $ \(State array offset length indent row col) cok _ _ eerr ->
373+varPrim :: Theory -> (Char -> Bool) -> Parser Text.Text
374+varPrim theory isGoodFirstChar =
375+ Parser $ \(State array offset length indent row col ctx) cok _ _ eerr ->
343376 if length == 0 then
344− eerr (loneTheory row col Variable)
377+ eerr (expect row col ctx theory)
345378
346379 else
347380 let
@@ -356,12 +389,12 @@ varPrim isGoodFirstChar =
356389 copyText array offset (newOffset - offset)
357390 in
358391 if Set.member copiedText keywords then
359− eerr (loneTheory row newCol Variable)
392+ eerr (expect row newCol ctx theory)
360393 else
361− cok copiedText (State array newOffset newLength indent row newCol)
394+ cok copiedText (State array newOffset newLength indent row newCol ctx) noError
362395
363396 else
364− eerr (loneTheory row col Variable)
397+ eerr (expect row col ctx theory)
365398
366399
367400{-# INLINE copyText #-}
@@ -428,16 +461,16 @@ isInnerVarChar char =
428461
429462infixOp :: Parser Text
430463infixOp =
431− Parser $ \(State array offset length indent row col) cok cerr _ eerr ->
464+ Parser $ \(State array offset length indent row col ctx) cok cerr _ eerr ->
432465 if length == 0 then
433− eerr (loneTheory row col InfixOp)
466+ eerr (expect row col ctx InfixOp)
434467
435468 else
436469 let
437470 (Text.Iter char size) = peek array offset
438471 in
439472 if not (Help.isSymbol char) then
440− eerr (loneTheory row col InfixOp)
473+ eerr (expect row col ctx InfixOp)
441474 else
442475 case infixOpHelp array (offset + size) (length - size) row (col + 1) of
443476 Left err ->
@@ -445,12 +478,12 @@ infixOp =
445478
446479 Right ( newOffset, newLength, newCol ) ->
447480 case copyText array offset (newOffset - offset) of
448− "=" -> cerr (ParseError row col Dot)
449− "|" -> cerr (ParseError row col Pipe)
450− ":" -> cerr (ParseError row col Arrow)
451− "." -> cerr (ParseError row col Equals)
452− "->" -> cerr (ParseError row col HasType)
453− op -> cok op (State array newOffset newLength indent row newCol)
481+ "." -> cerr (ParseError row col (BadOp Dot ctx))
482+ "|" -> cerr (ParseError row col (BadOp Pipe ctx))
483+ "->" -> cerr (ParseError row col (BadOp Arrow ctx))
484+ "=" -> cerr (ParseError row col (BadOp Equals ctx))
485+ ":" -> cerr (ParseError row col (BadOp HasType ctx))
486+ op -> cok op (State array newOffset newLength indent row newCol ctx) noError
454487
455488
456489infixOpHelp :: Text.Array -> Int -> Int -> Int -> Int -> Either ParseError (Int, Int, Int)
@@ -474,26 +507,44 @@ infixOpHelp array offset length row col =
474507
475508getPosition :: Parser Region.Position
476509getPosition =
477− Parser $ \state@(State _ _ _ _ row col) _ _ eok _ ->
478− eok (Region.Position row col) state
510+ Parser $ \state@(State _ _ _ _ row col _) _ _ eok _ ->
511+ eok (Region.Position row col) state noError
479512
480513
481514getIndent :: Parser Int
482515getIndent =
483− Parser $ \state@(State _ _ _ indent _ _) _ _ eok _ ->
484− eok indent state
516+ Parser $ \state@(State _ _ _ indent _ _ _) _ _ eok _ ->
517+ eok indent state noError
485518
486519
487520getCol :: Parser Int
488521getCol =
489− Parser $ \state@(State _ _ _ _ _ col) _ _ eok _ ->
490− eok col state
522+ Parser $ \state@(State _ _ _ _ _ col _) _ _ eok _ ->
523+ eok col state noError
524+
525+
526+getContext :: Parser [E.Context]
527+getContext =
528+ Parser $ \state@(State _ _ _ _ _ _ ctx) _ _ eok _ ->
529+ eok ctx state noError
530+
531+
532+pushContext :: E.Context -> Parser ()
533+pushContext ctx =
534+ Parser $ \state@(State _ _ _ _ _ _ context) _ _ eok _ ->
535+ eok () (state { _context = ctx : context }) noError
536+
537+
538+popContext :: a -> Parser a
539+popContext value =
540+ Parser $ \state@(State _ _ _ _ _ _ context) _ _ eok _ ->
541+ eok value (state { _context = tail context }) noError
491542
492543
493544setIndent :: Int -> Parser ()
494545setIndent indent =
495546 Parser $ \state _ _ eok _ ->
496− eok () (state { _indent = indent })
547+ eok () (state { _indent = indent }) noError
497548
498549
499550
@@ -506,7 +557,7 @@ newtype SPos =
506557
507558whitespace :: Parser SPos
508559whitespace =
509− Parser $ \(State array offset length indent row col) cok cerr _ _ ->
560+ Parser $ \(State array offset length indent row col ctx) cok cerr _ _ ->
510561 case eatSpaces array offset length row col of
511562 Left err ->
512563 cerr err
@@ -514,7 +565,8 @@ whitespace =
514565 Right (newOffset, newLength, newRow, newCol) ->
515566 cok
516567 (SPos (Region.Position newRow newCol))
517− (State array newOffset newLength indent newRow newCol)
568+ (State array newOffset newLength indent newRow newCol ctx)
569+ noError
518570
519571
520572eatSpaces :: Text.Array -> Int -> Int -> Int -> Int -> Either ParseError ( Int, Int, Int, Int )
@@ -646,7 +698,7 @@ eatMultiCommentHelp array offset length row col openComments =
646698docComment :: Parser Text
647699docComment =
648700 do symbol "{-|"
649− Parser $ \(State array offset length indent row col) cok cerr _ _ ->
701+ Parser $ \(State array offset length indent row col ctx) cok cerr _ _ ->
650702 case eatMultiCommentHelp array offset length row col 1 of
651703 Left err ->
652704 cerr err
@@ -654,17 +706,21 @@ docComment =
654706 Right (newOffset, newLength, newRow, newCol) ->
655707 cok
656708 (copyText array offset (newOffset - offset))
657− (State array newOffset newLength indent newRow newCol)
709+ (State array newOffset newLength indent newRow newCol ctx)
710+ noError
658711
659712
660713chompUntilDocs :: Parser Bool
661714chompUntilDocs =
662− Parser $ \(State array offset length indent row col) cok _ _ _ ->
715+ Parser $ \(State array offset length indent row col ctx) cok _ _ _ ->
663716 let
664717 (# isStart, newOffset, newLength, newRow, newCol #) =
665718 eatDocs array offset length row col
719+
720+ !newState =
721+ State array newOffset newLength indent newRow newCol ctx
666722 in
667− cok isStart (State array newOffset newLength indent newRow newCol)
723+ cok isStart newState noError
668724
669725
670726eatDocs :: Text.Array -> Int -> Int -> Int -> Int -> (# Bool, Int, Int, Int, Int #)
@@ -705,16 +761,16 @@ isDocsStart array offset length =
705761
706762string :: Parser Text.Text
707763string =
708− Parser $ \(State array offset length indent row col) cok cerr _ eerr ->
764+ Parser $ \(State array offset length indent row col ctx) cok cerr _ eerr ->
709765 if length == 0 then
710− eerr (noTheory row col)
766+ eerr noError
711767
712768 else
713769 let
714770 !word = Text.unsafeIndex array offset
715771 in
716772 if word /= 0x0022 {- " -} then
717− eerr (noTheory row col)
773+ eerr noError
718774
719775 else
720776 let
@@ -731,7 +787,8 @@ string =
731787 Right ( newOffset, newLength, newCol, builder ) ->
732788 cok
733789 (LT.toStrict (LB.toLazyText builder))
734− (State array newOffset newLength indent row newCol)
790+ (State array newOffset newLength indent row newCol ctx)
791+ noError
735792
736793
737794{-# INLINE isQuote #-}
@@ -880,13 +937,13 @@ multiString array offset length row col initialOffset builder =
880937
881938character :: Parser Text
882939character =
883− Parser $ \(State array offset length indent row col) cok cerr _ eerr ->
940+ Parser $ \(State array offset length indent row col ctx) cok cerr _ eerr ->
884941 if length == 0 then
885− eerr (noTheory row col)
942+ eerr noError
886943
887944 else
888945 if Text.unsafeIndex array offset /= 0x0027 {- ' -} then
889− eerr (noTheory row col)
946+ eerr noError
890947
891948 else if length < 3 then
892949 cerr (ParseError row col BadChar)
@@ -907,7 +964,8 @@ character =
907964 else
908965 cok
909966 (copyText array (offset + 1) size)
910− (State array (newOffset + 1) (newLength - 1) indent row endCol)
967+ (State array (newOffset + 1) (newLength - 1) indent row endCol ctx)
968+ noError
911969
912970
913971characterHelp :: Text.Array -> Int -> Int -> Int -> Int -> Either ParseError ( Int, Int )
@@ -938,9 +996,9 @@ characterHelp array offset length row col =
938996
939997digit :: Parser Int
940998digit =
941− Parser $ \(State array offset length indent row col) cok _ _ eerr ->
999+ Parser $ \(State array offset length indent row col ctx) cok _ _ eerr ->
9421000 if length == 0 then
943− eerr (loneTheory row col Digit)
1001+ eerr (expect row col ctx Digit)
9441002
9451003 else
9461004 let
@@ -949,9 +1007,10 @@ digit =
9491007 if isDigit word then
9501008 cok
9511009 (fromIntegral (word - 0x0030))
952− (State array (offset + 1) (length - 1) indent row (col + 1))
1010+ (State array (offset + 1) (length - 1) indent row (col + 1) ctx)
1011+ noError
9531012 else
954− eerr (loneTheory row col Digit)
1013+ eerr (expect row col ctx Digit)
9551014
9561015
9571016
@@ -960,16 +1019,16 @@ digit =
9601019
9611020number :: Parser L.Literal
9621021number =
963− Parser $ \(State array offset length indent row col) cok cerr _ eerr ->
1022+ Parser $ \(State array offset length indent row col ctx) cok cerr _ eerr ->
9641023 if length == 0 then
965− eerr (noTheory row col)
1024+ eerr noError
9661025
9671026 else
9681027 let
9691028 !word = Text.unsafeIndex array offset
9701029 in
9711030 if not (isDigit word) then
972− eerr (noTheory row col)
1031+ eerr noError
9731032
9741033 else
9751034 let
@@ -988,7 +1047,10 @@ number =
9881047 cerr (ParseError row (col + (newOffset - offset)) BadNumberEnd)
9891048
9901049 else
991− cok literal (State array newOffset newLength indent row (col + (newOffset - offset)))
1050+ cok
1051+ literal
1052+ (State array newOffset newLength indent row (col + (newOffset - offset)) ctx)
1053+ noError
9921054
9931055
9941056isDirtyEnd :: Text.Array -> Int -> Int -> Bool
@@ -1182,7 +1244,7 @@ readFloat array startOffset endOffset =
11821244shaderSource :: Parser Text
11831245shaderSource =
11841246 do symbol "[glsl|"
1185− Parser $ \(State array offset length indent row col) cok cerr _ _ ->
1247+ Parser $ \(State array offset length indent row col ctx) cok cerr _ _ ->
11861248 case eatShader array offset length row col of
11871249 Nothing ->
11881250 cerr (ParseError row col EndOfFile_Shader)
@@ -1190,10 +1252,10 @@ shaderSource =
11901252 Just ( shaderEndOffset, newRow, newCol ) ->
11911253 let
11921254 !size = shaderEndOffset - offset
1255+ !newState =
1256+ State array (shaderEndOffset + 2) (length - size - 2) indent newRow newCol ctx
11931257 in
1194− cok
1195− (copyText array offset size)
1196− (State array (shaderEndOffset + 2) (length - size - 2) indent newRow newCol)
1258+ cok (copyText array offset size) newState noError
11971259
11981260
11991261eatShader :: Text.Array -> Int -> Int -> Int -> Int -> Maybe (Int, Int, Int)