@@ -0,0 +1,268 @@
1+{-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}
2+{-# LANGUAGE BangPatterns, UnboxedTuples, OverloadedStrings #-}
18+import Data.Word (Word8, Word16)
19+import Foreign.Ptr (Ptr, plusPtr)
21+import Parse.Primitives (Row, Col)
22+import qualified Parse.Primitives as P
23+import qualified Reporting.Annotation as A
24+import qualified Reporting.Error.Syntax as E
32+ P.Parser x (a, A.Position)
39+chomp :: (E.Space -> Row -> Col -> x) -> P.Parser x ()
41+ P.Parser $ \(P.State pos end indent row col) cok _ cerr _ ->
43+ (# status, newPos, newRow, newCol #) = eatSpaces pos end row col
48+ !newState = P.State newPos end indent newRow newCol
52+ HasTab -> cerr newRow newCol (toError E.HasTab)
53+ EndlessMultiComment -> cerr newRow newCol (toError E.EndlessMultiComment)
54+ UnexpectedDocComment -> cerr newRow newCol (toError E.UnexpectedDocComment)
58+-- CHECKS -- to be called right after a `chomp`
61+checkIndent :: A.Position -> (Row -> Col -> x) -> P.Parser x ()
62+checkIndent (A.Position endRow endCol) toError =
63+ P.Parser $ \state@(P.State _ _ indent _ col) _ eok _ eerr ->
64+ if col > indent && col > 1
66+ else eerr endRow endCol toError
69+checkAligned :: (Word16 -> Row -> Col -> x) -> P.Parser x ()
70+checkAligned toError =
71+ P.Parser $ \state@(P.State _ _ indent row col) _ eok _ eerr ->
74+ else eerr row col (toError indent)
77+checkFreshLine :: (Row -> Col -> x) -> P.Parser x ()
78+checkFreshLine toError =
79+ P.Parser $ \state@(P.State _ _ _ row col) _ eok _ eerr ->
82+ else eerr row col toError
89+chompAndCheckIndent :: (E.Space -> Row -> Col -> x) -> (Row -> Col -> x) -> P.Parser x ()
90+chompAndCheckIndent toWhitespaceError toIndentError =
91+ P.Parser $ \(P.State pos end indent row col) cok _ cerr _ ->
93+ (# status, newPos, newRow, newCol #) = eatSpaces pos end row col
97+ if newCol > indent && newCol > 1
101+ !newState = P.State newPos end indent newRow newCol
106+ cerr row col toIndentError
108+ HasTab -> cerr newRow newCol (toWhitespaceError E.HasTab)
109+ EndlessMultiComment -> cerr newRow newCol (toWhitespaceError E.EndlessMultiComment)
110+ UnexpectedDocComment -> cerr newRow newCol (toWhitespaceError E.UnexpectedDocComment)
120+ | EndlessMultiComment
121+ | UnexpectedDocComment
124+eatSpaces :: Ptr Word8 -> Ptr Word8 -> Row -> Col -> (# Status, Ptr Word8, Row, Col #)
125+eatSpaces pos end row col =
127+ (# Good, pos, row, col #)
130+ case P.unsafeIndex pos of
132+ eatSpaces (plusPtr pos 1) end row (col + 1)
135+ eatSpaces (plusPtr pos 1) end (row + 1) 1
138+ eatMultiComment pos end row col
141+ let !pos1 = plusPtr pos 1 in
142+ if pos1 < end && P.unsafeIndex pos1 == 0x2D {- - -} then
143+ eatLineComment (plusPtr pos 2) end row (col + 2)
145+ (# Good, pos, row, col #)
148+ eatSpaces (plusPtr pos 1) end row col
151+ (# HasTab, pos, row, col #)
154+ (# Good, pos, row, col #)
161+eatLineComment :: Ptr Word8 -> Ptr Word8 -> Word16 -> Word16 -> (# Status, Ptr Word8, Word16, Word16 #)
162+eatLineComment pos end row col =
164+ (# Good, pos, row, col #)
167+ let !word = P.unsafeIndex pos in
168+ if word == 0x0A {- \n -} then
169+ eatSpaces (plusPtr pos 1) end (row + 1) 1
171+ let !newPos = plusPtr pos (P.getCharWidth pos end word) in
172+ eatLineComment newPos end row (col + 1)
179+eatMultiComment :: Ptr Word8 -> Ptr Word8 -> Row -> Col -> (# Status, Ptr Word8, Row, Col #)
180+eatMultiComment pos end row col =
182+ !pos1 = plusPtr pos 1
183+ !pos2 = plusPtr pos 2
186+ (# Good, pos, row, col #)
188+ else if P.unsafeIndex pos1 == 0x2D {- - -} then
190+ if P.unsafeIndex pos2 == 0x7C {- | -} then
191+ (# UnexpectedDocComment, pos, row, col #)
194+ (# status, newPos, newRow, newCol #) =
195+ eatMultiCommentHelp pos2 end row (col + 2) 1
198+ MultiGood -> eatSpaces newPos end newRow newCol
199+ MultiTab -> (# HasTab, newPos, newRow, newCol #)
200+ MultiEndless -> (# EndlessMultiComment, pos, row, col #)
203+ (# Good, pos, row, col #)
212+eatMultiCommentHelp :: Ptr Word8 -> Ptr Word8 -> Row -> Col -> Word16 -> (# MultiStatus, Ptr Word8, Word16, Word16 #)
213+eatMultiCommentHelp pos end row col openComments =
215+ (# MultiEndless, pos, row, col #)
218+ let !word = P.unsafeIndex pos in
219+ if word == 0x0A {- \n -} then
220+ eatMultiCommentHelp (plusPtr pos 1) end (row + 1) 1 openComments
222+ else if word == 0x09 {- \t -} then
223+ (# MultiTab, pos, row, col #)
225+ else if word == 0x2D {- - -} && P.isWord (plusPtr pos 1) end 0x7D {- } -} then
226+ if openComments == 1 then
227+ (# MultiGood, plusPtr pos 2, row, col + 2 #)
229+ eatMultiCommentHelp (plusPtr pos 2) end row (col + 2) (openComments - 1)
231+ else if word == 0x7B {- { -} && P.isWord (plusPtr pos 1) end 0x2D {- - -} then
232+ eatMultiCommentHelp (plusPtr pos 2) end row (col + 2) (openComments + 1)
235+ let !newPos = plusPtr pos (P.getCharWidth pos end word) in
236+ eatMultiCommentHelp newPos end row (col + 1) openComments
240+-- DOCUMENTATION COMMENT
243+docComment :: P.Parser E.Decl ()
245+ P.Parser $ \(P.State pos end indent row col) cok _ cerr eerr ->
247+ !pos3 = plusPtr pos 3
250+ && P.unsafeIndex ( pos ) == 0x7B {- { -}
251+ && P.unsafeIndex (plusPtr pos 1) == 0x2D {- - -}
252+ && P.unsafeIndex (plusPtr pos 2) == 0x7C {- | -}
255+ (# status, newPos, newRow, newCol #) =
256+ eatMultiCommentHelp pos3 end row (col + 3) 1
261+ !newState = P.State newPos end indent newRow newCol
265+ MultiTab -> cerr newRow newCol (E.DeclSpace E.HasTab)
266+ MultiEndless -> cerr row col E.EndlessDocComment
268+ eerr row col E.DeclDeadend