on master help sign in
Get Parse.Declaration working

Switch AST.Declarations to Text and get docComments parsing.

commitf908dc87185b394f767b18c73211991207fe8612 authorEvan Czaplicki <evancz@users.noreply.github.com> dateWed 30 Nov 2016, 19:29 (10 years ago) parent4eb08a3
4 files changed+215−93
src/AST/Declaration.hs+7−6 src/Parse/Declaration.hs+111−60 src/Parse/Primitives.hs+64−6 src/Parse/Type.hs+33−21
src/AST/Declaration.hs+7−6
@@ -2,6 +2,7 @@
22module AST.Declaration where
33
44import Data.Binary
5+import Data.Text (Text)
56
67import qualified AST.Expression.Canonical as Canonical
78import qualified AST.Expression.Source as Src
@@ -18,7 +19,7 @@ type Source =
1819
1920
2021data CommentOr a
21− = Comment (A.Located String)
22+ = Comment (A.Located Text)
2223 | Whatever a
2324
2425
@@ -27,7 +28,7 @@ data Raw
2728 | Union (Union Type.Raw)
2829 | Alias (Alias Type.Raw)
2930 | Fixity Infix
30− | Port String Type.Raw
31+ | Port Text Type.Raw
3132
3233
3334
@@ -77,14 +78,14 @@ addInfix fixity decls =
7778
7879data Type body =
7980 Type
80− { _name :: String
81− , _args :: [String]
81+ { _name :: Text
82+ , _args :: [Text]
8283 , _body :: body
8384 }
8485
8586
8687type Union tipe =
87− Type [(String, [tipe])]
88+ Type [(Text, [tipe])]
8889
8990
9091type Alias tipe =
@@ -97,7 +98,7 @@ type Alias tipe =
9798
9899data Infix =
99100 Infix
100− { _op :: String
101+ { _op :: Text
101102 , _associativity :: Assoc
102103 , _precedence :: Int
103104 }
src/Parse/Declaration.hs+111−60
@@ -1,100 +1,151 @@
11{-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}
2+{-# LANGUAGE OverloadedStrings #-}
23module Parse.Declaration where
34
4−import Text.Parsec ( (<?>), choice, digit, optionMaybe, string, try )
5+import Data.Text (Text)
56
67import qualified AST.Declaration as Decl
7−import qualified Parse.Binop as Binop
8+import qualified AST.Type as Type
89import qualified Parse.Expression as Expr
910import Parse.Helpers as Help
1011import qualified Parse.Type as Type
12+import qualified Reporting.Annotation as A
13+import qualified Reporting.Region as R
1114
1215
1316
14−declaration :: IParser Decl.Source
17+-- DECLARATION
18+
19+
20+declaration :: SParser Decl.Source
1521declaration =
16− commentOr $ addLocation $
17− choice
18− [ typeDecl
19− , infixDecl
20− , portDecl
21− , definition
22− ]
23−
24−
25−commentOr :: IParser a -> IParser (Decl.CommentOr a)
26−commentOr parser =
27− choice
28− [ Decl.Comment <$> addLocation Help.docComment
29− , Decl.Whatever <$> parser
30− ]
22+ do start <- getPosition
23+ oneOf
24+ [ docDecl start
25+ , typeDecl start
26+ , infixDecl start
27+ , portDecl start
28+ , defDecl start
29+ ]
30+
31+
32+
33+-- DOC COMMENTS
34+
3135
36+docDecl :: R.Position -> SParser Decl.Source
37+docDecl start =
38+ do comment <- docComment
39+ end <- getPosition
40+ space <- whitespace
41+ return ( Decl.Comment (A.at start end comment), end, space )
3242
3343
3444-- TYPE ANNOTATIONS and DEFINITIONS
3545
3646
37−definition :: IParser Decl.Raw
38−definition =
39− do def <- Expr.def <?> "a definition or type annotation"
40− return $ Decl.Def def
47+defDecl :: R.Position -> SParser Decl.Source
48+defDecl start =
49+ do (def, end, space) <- Expr.definition
50+ let decl = A.at start end (Decl.Def def)
51+ return ( Decl.Whatever decl, end, space )
4152
4253
4354
4455-- TYPE ALIAS and UNION TYPES
4556
4657
47−typeDecl :: IParser Decl.Raw
48−typeDecl =
49− do try (reserved "type") <?> "a type declaration"
50− forcedWS
51− isAlias <- optionMaybe (string "alias" >> forcedWS)
52−
53− name <- capVar
54− args <- spacePrefix lowVar
55− padded equals
58+typeDecl :: R.Position -> SParser Decl.Source
59+typeDecl start =
60+ do keyword "type"
61+ spaces
62+ oneOf
63+ [ do keyword "alias"
64+ spaces
65+ (name, args) <- nameArgsEquals
66+ (tipe, end, space) <- Type.expression
67+ let decl = A.at start end (Decl.Alias (Decl.Type name args tipe))
68+ return ( Decl.Whatever decl, end, space )
69+ , do (name, args) <- nameArgsEquals
70+ (firstCtor, firstEnd, firstSpace) <- Type.unionConstructor
71+ (ctors, end, space) <- chompConstructors [firstCtor] firstEnd firstSpace
72+ let decl = A.at start end (Decl.Union (Decl.Type name args ctors))
73+ return ( Decl.Whatever decl, end, space )
74+ ]
75+
76+
77+nameArgsEquals :: Parser (Text, [Text])
78+nameArgsEquals =
79+ do name <- capVar
80+ spaces
81+ nameArgsEqualsHelp name []
82+
83+
84+nameArgsEqualsHelp :: Text -> [Text] -> Parser (Text, [Text])
85+nameArgsEqualsHelp name args =
86+ oneOf
87+ [ do arg <- lowVar
88+ spaces
89+ nameArgsEqualsHelp name (arg:args)
90+ , do equals
91+ spaces
92+ return ( name, reverse args )
93+ ]
5694
57− case isAlias of
58− Just _ ->
59− do tipe <- Type.expr <?> "a type"
60− return $ Decl.Alias (Decl.Type name args tipe)
6195
62− Nothing ->
63− do tcs <- pipeSep1 Type.constructor <?> "a constructor for a union type"
64− return $ Decl.Union (Decl.Type name args tcs)
96+chompConstructors :: [(Text, [Type.Raw])] -> R.Position -> Space -> SParser [(Text, [Type.Raw])]
97+chompConstructors ctors end space =
98+ oneOf
99+ [ do checkSpaces space
100+ pipe
101+ spaces
102+ (ctor, newEnd, newSpace) <- Type.unionConstructor
103+ chompConstructors (ctor:ctors) newEnd newSpace
104+ , return ( reverse ctors, end, space )
105+ ]
65106
66107
67108
68109-- INFIX
69110
70111
71−infixDecl :: IParser Decl.Raw
72−infixDecl =
73− expecting "an infix declaration" $
74− do assoc <-
75− choice
76− [ try (reserved "infixl") >> return Decl.L
77− , try (reserved "infixr") >> return Decl.R
78− , try (reserved "infix") >> return Decl.N
79− ]
80− forcedWS
112+infixDecl :: R.Position -> SParser Decl.Source
113+infixDecl start =
114+ oneOf
115+ [ do keyword "infixl"
116+ infixDeclHelp start Decl.L
117+ , do keyword "infixr"
118+ infixDeclHelp start Decl.R
119+ , do keyword "infix"
120+ infixDeclHelp start Decl.N
121+ ]
122+
123+
124+infixDeclHelp :: R.Position -> Decl.Assoc -> SParser Decl.Source
125+infixDeclHelp start assoc =
126+ do spaces
81127 n <- digit
82− forcedWS
83− op <- Binop.infixOp
84− return $ Decl.Fixity (Decl.Infix op assoc (read [n]))
128+ spaces
129+ op <- infixOp
130+ end <- getPosition
131+ space <- whitespace
132+ let decl = A.at start end (Decl.Fixity (Decl.Infix op assoc n))
133+ return ( Decl.Whatever decl, end, space )
85134
86135
87136
88137-- FOREIGN
89138
90139
91−portDecl :: IParser Decl.Raw
92−portDecl =
93− expecting "a port declaration" $
94− do try (reserved "port")
95− forcedWS
96− name <- Help.lowVar
97− padded hasType
98− tipe <- Type.expr
99− return $ Decl.Port name tipe
140+portDecl :: R.Position -> SParser Decl.Source
141+portDecl start =
142+ do keyword "port"
143+ spaces
144+ name <- lowVar
145+ spaces
146+ hasType
147+ spaces
148+ (tipe, end, space) <- Type.expression
149+ let decl = A.at start end (Decl.Port name tipe)
150+ return ( Decl.Whatever decl, end, space )
100151
src/Parse/Primitives.hs+64−6
@@ -10,7 +10,9 @@ module Parse.Primitives
1010 , getPosition, getCol
1111 , getIndent, setIndent
1212 , Space(..), whitespace
13+ , docComment
1314 , string, character
15+ , digit
1416 )
1517 where
1618
@@ -557,15 +559,20 @@ eatLineCommentHelp array offset length row col =
557559
558560eatMultiComment :: Text.Array -> Int -> Int -> Int -> Int -> Either Error ( Int, Int, Int, Int )
559561eatMultiComment array offset length row col =
560− if length == 1 then
562+ if length <= 2 then
561563 Right ( offset, length, row, col )
562564
563565 else
564− case Text.unsafeIndex array (offset + 1) of
565− 0x002D {- - -} ->
566− eatMultiCommentHelp array (offset + 2) (length - 2) row (col + 2) 1
566+ let
567+ !yesDash = Text.unsafeIndex array (offset + 1) == 0x002D {- - -}
568+ !noBar = Text.unsafeIndex array (offset + 2) /= 0x007C {- | -}
569+ in
570+ if yesDash && noBar then
571+ do (newOffset, newLength, newRow, newCol) <-
572+ eatMultiCommentHelp array (offset + 2) (length - 2) row (col + 2) 1
573+ eatSpaces array newOffset newLength newRow newCol
567574
568− _ ->
575+ else
569576 Right ( offset, length, row, col )
570577
571578
@@ -585,7 +592,7 @@ eatMultiCommentHelp array offset length row col openComments =
585592 else if word == 0x002D {- - -} && length > 1 && Text.unsafeIndex array (offset + 1) == 0x007D {- } -} then
586593
587594 if openComments == 1 then
588− eatSpaces array (offset + 2) (length - 2) row (col + 2)
595+ Right ( offset + 2, length - 2, row, col + 2 )
589596 else
590597 eatMultiCommentHelp array (offset + 2) (length - 2) row (col + 2) (openComments - 1)
591598
@@ -603,6 +610,34 @@ eatMultiCommentHelp array offset length row col openComments =
603610
604611
605612
613+-- DOCUMENTATION COMMENT
614+
615+
616+docComment :: Parser Text
617+docComment =
618+ do text "{-|"
619+ Parser $ \(State array offset length indent row col) cok cerr _ _ ->
620+ case eatMultiCommentHelp array offset length row col 1 of
621+ Left err ->
622+ cerr err
623+
624+ Right (newOffset, newLength, newRow, newCol) ->
625+ let
626+ !newSize =
627+ newOffset - offset
628+
629+ makeArray =
630+ do mutableArray <- Text.new newSize
631+ Text.copyI mutableArray 0 array offset newSize
632+ return mutableArray
633+
634+ comment =
635+ Text.Text (Text.run makeArray) 0 newSize
636+ in
637+ cok comment (State array newOffset newLength indent newRow newCol)
638+
639+
640+
606641-- STRINGS
607642
608643
@@ -788,3 +823,26 @@ characterHelp array offset length row col =
788823
789824 else
790825 Left (Error row col)
826+
827+
828+
829+-- NUMBERS
830+
831+
832+digit :: Parser Int
833+digit =
834+ Parser $ \(State array offset length indent row col) cok _ _ eerr ->
835+ if length == 0 then
836+ eerr (Error row col)
837+
838+ else
839+ let
840+ !word = Text.unsafeIndex array offset
841+ !isDigit = word <= 0x0039 {- 9 -} && word >= 0x0030 {- 0 -}
842+ in
843+ if isDigit then
844+ cok
845+ (fromIntegral (word - 0x0030))
846+ (State array (offset + 1) (length - 1) indent row (col + 1))
847+ else
848+ eerr (Error row col)
src/Parse/Type.hs+33−21
@@ -1,6 +1,6 @@
11{-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}
22{-# LANGUAGE OverloadedStrings #-}
3−module Parse.Type (expression) where
3+module Parse.Type (expression, unionConstructor) where
44
55import Data.Text (Text)
66
@@ -59,15 +59,7 @@ expression =
5959
6060
6161
62−-- TYPE APPLICATION
63−
64−
65−app :: R.Position -> SParser Type.Raw
66−app start =
67− do ctor <- constructor
68− end <- getPosition
69− space <- whitespace
70− appHelp ctor [] start end space
62+-- TYPE CONSTRUCTORS
7163
7264
7365constructor :: Parser Type.Raw
@@ -76,22 +68,42 @@ constructor =
7668 fmap (Type.RType . Var.Raw) qualifiedCapVar
7769
7870
79−appHelp :: Type.Raw -> [Type.Raw] -> R.Position -> R.Position -> Space -> SParser Type.Raw
80−appHelp ctor args start end space =
71+app :: R.Position -> SParser Type.Raw
72+app start =
73+ do ctor <- constructor
74+ ctorEnd <- getPosition
75+ ctorSpace <- whitespace
76+ (args, end, space) <- eatArgs [] ctorEnd ctorSpace
77+ case args of
78+ [] ->
79+ return ( ctor, end, space )
80+
81+ _ ->
82+ let
83+ tipe =
84+ A.at start end (Type.RApp ctor (reverse args))
85+ in
86+ return ( tipe, end, space )
87+
88+
89+unionConstructor :: SParser (Text, [Type.Raw])
90+unionConstructor =
91+ do ctor <- capVar
92+ ctorEnd <- getPosition
93+ ctorSpace <- whitespace
94+ (args, end, space) <- eatArgs [] ctorEnd ctorSpace
95+ return ( (ctor, args), end, space )
96+
97+
98+eatArgs :: [Type.Raw] -> R.Position -> Space -> SParser [Type.Raw]
99+eatArgs args end space =
81100 oneOf
82101 [ do checkSpaces space
83102 arg <- term
84103 newEnd <- getPosition
85104 newSpace <- whitespace
86− appHelp ctor (arg:args) start newEnd newSpace
87− , let
88− tipe =
89− if null args then
90− ctor
91− else
92− A.at start end (Type.RApp ctor (reverse args))
93− in
94− return ( tipe, end, space )
105+ eatArgs (arg:args) newEnd newSpace
106+ , return ( reverse args, end, space )
95107 ]
96108
97109