@@ -12,6 +12,12 @@ import Data.List (sort)
1212import Control.Applicative (liftA)
1313import ProjectM36.MiscUtils
1414
15+class RelationalMarkerExpr a where
16+ parseMarkerP :: Parser a
17+
18+instance RelationalMarkerExpr () where
19+ parseMarkerP = pure ()
20+
1521--used in projection
1622attributeListP :: Parser AttributeNames
1723attributeListP = do
@@ -20,23 +26,19 @@ attributeListP = do
2026 attrs <- sepBy identifier comma
2127 pure $ constructor (S.fromList attrs)
2228
23−makeRelationP :: Parser RelationalExpr
29+makeRelationP :: RelationalMarkerExpr a => Parser (RelationalExprBase a)
2430makeRelationP = do
2531 reserved "relation"
2632 attrExprs <- try (liftA Just makeAttributeExprsP) <|> pure Nothing
2733 tupleExprs <- braces (sepBy tupleExprP comma) <|> pure []
28− pure $ MakeRelationFromExprs attrExprs tupleExprs
34+ pure $ MakeRelationFromExprs attrExprs tupleExprs
2935
3036--used in relation creation
31−makeAttributeExprsP :: Parser [AttributeExpr]
37+makeAttributeExprsP :: RelationalMarkerExpr a => Parser [AttributeExprBase a]
3238makeAttributeExprsP = braces (sepBy attributeAndTypeNameP comma)
3339
34−attributeAndTypeNameP :: Parser AttributeExpr
35−attributeAndTypeNameP = do
36− attrName <- identifier
37− --convert type name into type
38− typeCons <- typeConstructorP
39− return $ AttributeAndTypeNameExpr attrName typeCons ()
40+attributeAndTypeNameP :: RelationalMarkerExpr a => Parser (AttributeExprBase a)
41+attributeAndTypeNameP = AttributeAndTypeNameExpr <$> identifier <*> typeConstructorP <*> parseMarkerP
4042
4143--abstract data type parser- in this context, the type constructor must not include any type arguments
4244--Either Text Int
@@ -46,7 +48,7 @@ adTypeConstructorP = do
4648 tConsArgs <- many typeConstructorArgP
4749 pure $ ADTypeConstructor tConsName tConsArgs
4850
49−tupleExprP :: Parser TupleExpr
51+tupleExprP :: RelationalMarkerExpr a => Parser (TupleExprBase a)
5052tupleExprP = do
5153 reservedOp "tuple"
5254 attrAssocs <- braces (sepBy tupleAtomExprP comma)
@@ -57,13 +59,13 @@ tupleExprP = do
5759 else
5860 pure (TupleExpr (M.fromList attrAssocs))
5961
60−tupleAtomExprP :: Parser (AttributeName, AtomExpr)
62+tupleAtomExprP :: RelationalMarkerExpr a => Parser (AttributeName, AtomExprBase a)
6163tupleAtomExprP = do
6264 attributeName <- identifier
6365 atomExpr <- atomExprP
6466 pure $ (attributeName, atomExpr)
6567
66−projectP :: Parser (RelationalExpr -> RelationalExpr)
68+projectP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
6769projectP = do
6870 attrs <- braces attributeListP
6971 pure $ Project attrs
@@ -75,17 +77,14 @@ renameClauseP = do
7577 newAttr <- identifier
7678 pure $ (oldAttr, newAttr)
7779
78−renameP :: Parser (RelationalExpr -> RelationalExpr)
80+renameP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
7981renameP = do
8082 reservedOp "rename"
8183 (oldAttr, newAttr) <- braces renameClauseP
8284 return $ Rename oldAttr newAttr
8385
84−whereClauseP :: Parser (RelationalExpr -> RelationalExpr)
85−whereClauseP = do
86− reservedOp "where"
87− boolExpr <- restrictionPredicateP
88− return $ Restrict boolExpr
86+whereClauseP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
87+whereClauseP = reservedOp "where" *> (Restrict <$> restrictionPredicateP)
8988
9089groupClauseP :: Parser (AttributeNames, T.Text)
9190groupClauseP = do
@@ -94,26 +93,26 @@ groupClauseP = do
9493 newAttrName <- identifier
9594 return $ (attrs, newAttrName)
9695
97−groupP :: Parser (RelationalExpr -> RelationalExpr)
96+groupP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
9897groupP = do
9998 reservedOp "group"
10099 (groupAttrList, groupAttrName) <- parens groupClauseP
101100 pure $ Group groupAttrList groupAttrName
102101
103102--in "Time and Relational Theory" (2014), Date's Tutorial D grammar for ungroup takes one attribute, while in previous books, it take multiple arguments. Let us assume that nested ungroups are the same as multiple attributes.
104−ungroupP :: Parser (RelationalExpr -> RelationalExpr)
103+ungroupP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
105104ungroupP = do
106105 reservedOp "ungroup"
107106 rvaAttrName <- identifier
108107 pure $ Ungroup rvaAttrName
109108
110−extendP :: Parser (RelationalExpr -> RelationalExpr)
109+extendP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
111110extendP = do
112111 reservedOp ":"
113112 tupleExpr <- braces extendTupleExpressionP
114113 return $ Extend tupleExpr
115114
116−relOperators :: [[Operator Parser RelationalExpr]]
115+relOperators :: RelationalMarkerExpr a => [[Operator Parser (RelationalExprBase a)]]
117116relOperators = [
118117 [Postfix projectP],
119118 [Postfix renameP],
@@ -127,18 +126,18 @@ relOperators = [
127126 [Postfix extendP]
128127 ]
129128
130−relExprP :: Parser RelationalExpr
129+relExprP :: RelationalMarkerExpr a => Parser (RelationalExprBase a)
131130relExprP = makeExprParser relTerm relOperators
132131
133−relVarP :: Parser RelationalExpr
134−relVarP = RelationVariable <$> identifier <*> pure ()
132+relVarP :: RelationalMarkerExpr a => Parser (RelationalExprBase a)
133+relVarP = RelationVariable <$> identifier <*> parseMarkerP
135134
136−relTerm :: Parser RelationalExpr
135+relTerm :: RelationalMarkerExpr a => Parser (RelationalExprBase a)
137136relTerm = parens relExprP
138137 <|> makeRelationP
139138 <|> relVarP
140139
141−restrictionPredicateP :: Parser RestrictionPredicateExpr
140+restrictionPredicateP :: RelationalMarkerExpr a => Parser (RestrictionPredicateExprBase a)
142141restrictionPredicateP = makeExprParser predicateTerm predicateOperators
143142 where
144143 predicateOperators = [
@@ -152,40 +151,40 @@ restrictionPredicateP = makeExprParser predicateTerm predicateOperators
152151 <|> try relationalBooleanExprP
153152
154153
155−relationalBooleanExprP :: Parser RestrictionPredicateExpr
154+relationalBooleanExprP :: RelationalMarkerExpr a => Parser (RestrictionPredicateExprBase a)
156155relationalBooleanExprP = do
157156 relexpr <- relExprP
158157 return $ RelationalExprPredicate relexpr
159158
160−restrictionAttributeEqualityP :: Parser RestrictionPredicateExpr
159+restrictionAttributeEqualityP :: RelationalMarkerExpr a => Parser (RestrictionPredicateExprBase a)
161160restrictionAttributeEqualityP = do
162161 attributeName <- identifier
163162 reservedOp "="
164163 atomexpr <- atomExprP
165164 return $ AttributeEqualityPredicate attributeName atomexpr
166165
167−restrictionAtomExprP :: Parser RestrictionPredicateExpr --atoms which are of type "boolean"
166+restrictionAtomExprP :: RelationalMarkerExpr a=> Parser (RestrictionPredicateExprBase a) --atoms which are of type "boolean"
168167restrictionAtomExprP = do
169168 _ <- char '^' -- not ideal, but allows me to continue to use a context-free grammar
170169 AtomExprPredicate <$> atomExprP
171170
172−multiTupleExpressionP :: Parser [ExtendTupleExpr]
171+multiTupleExpressionP :: RelationalMarkerExpr a => Parser [ExtendTupleExprBase a]
173172multiTupleExpressionP = sepBy extendTupleExpressionP comma
174173
175−extendTupleExpressionP :: Parser ExtendTupleExpr
174+extendTupleExpressionP :: RelationalMarkerExpr a => Parser (ExtendTupleExprBase a)
176175extendTupleExpressionP = attributeExtendTupleExpressionP
177176
178−attributeExtendTupleExpressionP :: Parser ExtendTupleExpr
177+attributeExtendTupleExpressionP :: RelationalMarkerExpr a => Parser (ExtendTupleExprBase a)
179178attributeExtendTupleExpressionP = do
180179 newAttr <- identifier
181180 reservedOp ":="
182181 atom <- atomExprP
183182 return $ AttributeExtendTupleExpr newAttr atom
184183
185−atomExprP :: Parser AtomExpr
184+atomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
186185atomExprP = consumeAtomExprP True
187186
188−consumeAtomExprP :: Bool -> Parser AtomExpr
187+consumeAtomExprP :: RelationalMarkerExpr a => Bool -> Parser (AtomExprBase a)
189188consumeAtomExprP consume = try functionAtomExprP <|>
190189 try (parens (constructedAtomExprP True)) <|>
191190 constructedAtomExprP consume <|>
@@ -193,20 +192,21 @@ consumeAtomExprP consume = try functionAtomExprP <|>
193192 nakedAtomExprP <|>
194193 relationalAtomExprP
195194
196−attributeAtomExprP :: Parser AtomExpr
195+attributeAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
197196attributeAtomExprP = do
198197 _ <- string "@"
199198 attrName <- identifier
200199 return $ AttributeAtomExpr attrName
201200
202−nakedAtomExprP :: Parser AtomExpr
201+nakedAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
203202nakedAtomExprP = NakedAtomExpr <$> atomP
204203
205−constructedAtomExprP :: Bool -> Parser AtomExpr
204+constructedAtomExprP :: RelationalMarkerExpr a => Bool -> Parser (AtomExprBase a)
206205constructedAtomExprP consume = do
207206 dConsName <- capitalizedIdentifier
208207 dConsArgs <- if consume then sepBy (consumeAtomExprP False) spaceConsumer else pure []
209− pure $ ConstructedAtomExpr dConsName dConsArgs ()
208+ marker <- parseMarkerP
209+ pure $ ConstructedAtomExpr dConsName dConsArgs marker
210210
211211-- used only for primitive type parsing ?
212212atomP :: Parser Atom
@@ -215,13 +215,14 @@ atomP = stringAtomP <|>
215215 intAtomP <|>
216216 boolAtomP
217217
218−functionAtomExprP :: Parser AtomExpr
218+functionAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
219219functionAtomExprP = do
220220 funcName <- identifier
221221 argList <- parens (sepBy atomExprP comma)
222− return $ FunctionAtomExpr funcName argList ()
222+ marker <- parseMarkerP
223+ return $ FunctionAtomExpr funcName argList marker
223224
224−relationalAtomExprP :: Parser AtomExpr
225+relationalAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
225226relationalAtomExprP = RelationAtomExpr <$> relExprP
226227
227228stringAtomP :: Parser Atom
@@ -240,5 +241,5 @@ boolAtomP = do
240241 val <- char 't' <|> char 'f'
241242 return $ BoolAtom (val == 't')
242243
243−relationAtomExprP :: Parser AtomExpr
244+relationAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
244245relationAtomExprP = RelationAtomExpr <$> makeRelationP