@@ -12,6 +12,12 @@ import Data.List (sort)
12import Control.Applicative (liftA)
12import Control.Applicative (liftA)
13import ProjectM36.MiscUtils
13import ProjectM36.MiscUtils
15+class RelationalMarkerExpr a where
16+ parseMarkerP :: Parser a
18+instance RelationalMarkerExpr () where
19+ parseMarkerP = pure ()
15--used in projection
21--used in projection
16attributeListP :: Parser AttributeNames
22attributeListP :: Parser AttributeNames
17attributeListP = do
23attributeListP = do
@@ -20,23 +26,19 @@ attributeListP = do
20 attrs <- sepBy identifier comma
26 attrs <- sepBy identifier comma
21 pure $ constructor (S.fromList attrs)
27 pure $ constructor (S.fromList attrs)
23−makeRelationP :: Parser RelationalExpr
29+makeRelationP :: RelationalMarkerExpr a => Parser (RelationalExprBase a)
24makeRelationP = do
30makeRelationP = do
25 reserved "relation"
31 reserved "relation"
26 attrExprs <- try (liftA Just makeAttributeExprsP) <|> pure Nothing
32 attrExprs <- try (liftA Just makeAttributeExprsP) <|> pure Nothing
27 tupleExprs <- braces (sepBy tupleExprP comma) <|> pure []
33 tupleExprs <- braces (sepBy tupleExprP comma) <|> pure []
28− pure $ MakeRelationFromExprs attrExprs tupleExprs
34+ pure $ MakeRelationFromExprs attrExprs tupleExprs
30--used in relation creation
36--used in relation creation
31−makeAttributeExprsP :: Parser [AttributeExpr]
37+makeAttributeExprsP :: RelationalMarkerExpr a => Parser [AttributeExprBase a]
32makeAttributeExprsP = braces (sepBy attributeAndTypeNameP comma)
38makeAttributeExprsP = braces (sepBy attributeAndTypeNameP comma)
34−attributeAndTypeNameP :: Parser AttributeExpr
40+attributeAndTypeNameP :: RelationalMarkerExpr a => Parser (AttributeExprBase a)
35−attributeAndTypeNameP = do
41+attributeAndTypeNameP = AttributeAndTypeNameExpr <$> identifier <*> typeConstructorP <*> parseMarkerP
36− attrName <- identifier
37− --convert type name into type
38− typeCons <- typeConstructorP
39− return $ AttributeAndTypeNameExpr attrName typeCons ()
41--abstract data type parser- in this context, the type constructor must not include any type arguments
43--abstract data type parser- in this context, the type constructor must not include any type arguments
42--Either Text Int
44--Either Text Int
@@ -46,7 +48,7 @@ adTypeConstructorP = do
46 tConsArgs <- many typeConstructorArgP
48 tConsArgs <- many typeConstructorArgP
47 pure $ ADTypeConstructor tConsName tConsArgs
49 pure $ ADTypeConstructor tConsName tConsArgs
49−tupleExprP :: Parser TupleExpr
51+tupleExprP :: RelationalMarkerExpr a => Parser (TupleExprBase a)
50tupleExprP = do
52tupleExprP = do
51 reservedOp "tuple"
53 reservedOp "tuple"
52 attrAssocs <- braces (sepBy tupleAtomExprP comma)
54 attrAssocs <- braces (sepBy tupleAtomExprP comma)
@@ -57,13 +59,13 @@ tupleExprP = do
58 pure (TupleExpr (M.fromList attrAssocs))
60 pure (TupleExpr (M.fromList attrAssocs))
60−tupleAtomExprP :: Parser (AttributeName, AtomExpr)
62+tupleAtomExprP :: RelationalMarkerExpr a => Parser (AttributeName, AtomExprBase a)
61tupleAtomExprP = do
63tupleAtomExprP = do
62 attributeName <- identifier
64 attributeName <- identifier
63 atomExpr <- atomExprP
65 atomExpr <- atomExprP
64 pure $ (attributeName, atomExpr)
66 pure $ (attributeName, atomExpr)
66−projectP :: Parser (RelationalExpr -> RelationalExpr)
68+projectP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
67projectP = do
69projectP = do
68 attrs <- braces attributeListP
70 attrs <- braces attributeListP
69 pure $ Project attrs
71 pure $ Project attrs
@@ -75,17 +77,14 @@ renameClauseP = do
75 newAttr <- identifier
77 newAttr <- identifier
76 pure $ (oldAttr, newAttr)
78 pure $ (oldAttr, newAttr)
78−renameP :: Parser (RelationalExpr -> RelationalExpr)
80+renameP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
79renameP = do
81renameP = do
80 reservedOp "rename"
82 reservedOp "rename"
81 (oldAttr, newAttr) <- braces renameClauseP
83 (oldAttr, newAttr) <- braces renameClauseP
82 return $ Rename oldAttr newAttr
84 return $ Rename oldAttr newAttr
84−whereClauseP :: Parser (RelationalExpr -> RelationalExpr)
86+whereClauseP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
86− reservedOp "where"
87+whereClauseP = reservedOp "where" *> (Restrict <$> restrictionPredicateP)
87− boolExpr <- restrictionPredicateP
88− return $ Restrict boolExpr
90groupClauseP :: Parser (AttributeNames, T.Text)
89groupClauseP :: Parser (AttributeNames, T.Text)
91groupClauseP = do
90groupClauseP = do
@@ -94,26 +93,26 @@ groupClauseP = do
94 newAttrName <- identifier
93 newAttrName <- identifier
95 return $ (attrs, newAttrName)
94 return $ (attrs, newAttrName)
97−groupP :: Parser (RelationalExpr -> RelationalExpr)
96+groupP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
98groupP = do
97groupP = do
99 reservedOp "group"
98 reservedOp "group"
100 (groupAttrList, groupAttrName) <- parens groupClauseP
99 (groupAttrList, groupAttrName) <- parens groupClauseP
101 pure $ Group groupAttrList groupAttrName
100 pure $ Group groupAttrList groupAttrName
103--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.
102--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)
105ungroupP = do
104ungroupP = do
106 reservedOp "ungroup"
105 reservedOp "ungroup"
107 rvaAttrName <- identifier
106 rvaAttrName <- identifier
108 pure $ Ungroup rvaAttrName
107 pure $ Ungroup rvaAttrName
110−extendP :: Parser (RelationalExpr -> RelationalExpr)
109+extendP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
111extendP = do
110extendP = do
112 reservedOp ":"
111 reservedOp ":"
113 tupleExpr <- braces extendTupleExpressionP
112 tupleExpr <- braces extendTupleExpressionP
114 return $ Extend tupleExpr
113 return $ Extend tupleExpr
116−relOperators :: [[Operator Parser RelationalExpr]]
115+relOperators :: RelationalMarkerExpr a => [[Operator Parser (RelationalExprBase a)]]
117relOperators = [
116relOperators = [
118 [Postfix projectP],
117 [Postfix projectP],
119 [Postfix renameP],
118 [Postfix renameP],
@@ -127,18 +126,18 @@ relOperators = [
127 [Postfix extendP]
126 [Postfix extendP]
130−relExprP :: Parser RelationalExpr
129+relExprP :: RelationalMarkerExpr a => Parser (RelationalExprBase a)
131relExprP = makeExprParser relTerm relOperators
130relExprP = makeExprParser relTerm relOperators
133−relVarP :: Parser RelationalExpr
132+relVarP :: RelationalMarkerExpr a => Parser (RelationalExprBase a)
134−relVarP = RelationVariable <$> identifier <*> pure ()
133+relVarP = RelationVariable <$> identifier <*> parseMarkerP
136−relTerm :: Parser RelationalExpr
135+relTerm :: RelationalMarkerExpr a => Parser (RelationalExprBase a)
137relTerm = parens relExprP
136relTerm = parens relExprP
138 <|> makeRelationP
137 <|> makeRelationP
139 <|> relVarP
138 <|> relVarP
141−restrictionPredicateP :: Parser RestrictionPredicateExpr
140+restrictionPredicateP :: RelationalMarkerExpr a => Parser (RestrictionPredicateExprBase a)
142restrictionPredicateP = makeExprParser predicateTerm predicateOperators
141restrictionPredicateP = makeExprParser predicateTerm predicateOperators
144 predicateOperators = [
143 predicateOperators = [
@@ -152,40 +151,40 @@ restrictionPredicateP = makeExprParser predicateTerm predicateOperators
152 <|> try relationalBooleanExprP
151 <|> try relationalBooleanExprP
155−relationalBooleanExprP :: Parser RestrictionPredicateExpr
154+relationalBooleanExprP :: RelationalMarkerExpr a => Parser (RestrictionPredicateExprBase a)
156relationalBooleanExprP = do
155relationalBooleanExprP = do
157 relexpr <- relExprP
156 relexpr <- relExprP
158 return $ RelationalExprPredicate relexpr
157 return $ RelationalExprPredicate relexpr
160−restrictionAttributeEqualityP :: Parser RestrictionPredicateExpr
159+restrictionAttributeEqualityP :: RelationalMarkerExpr a => Parser (RestrictionPredicateExprBase a)
161restrictionAttributeEqualityP = do
160restrictionAttributeEqualityP = do
162 attributeName <- identifier
161 attributeName <- identifier
163 reservedOp "="
162 reservedOp "="
164 atomexpr <- atomExprP
163 atomexpr <- atomExprP
165 return $ AttributeEqualityPredicate attributeName atomexpr
164 return $ AttributeEqualityPredicate attributeName atomexpr
167−restrictionAtomExprP :: Parser RestrictionPredicateExpr --atoms which are of type "boolean"
166+restrictionAtomExprP :: RelationalMarkerExpr a=> Parser (RestrictionPredicateExprBase a) --atoms which are of type "boolean"
168restrictionAtomExprP = do
167restrictionAtomExprP = do
169 _ <- char '^' -- not ideal, but allows me to continue to use a context-free grammar
168 _ <- char '^' -- not ideal, but allows me to continue to use a context-free grammar
170 AtomExprPredicate <$> atomExprP
169 AtomExprPredicate <$> atomExprP
172−multiTupleExpressionP :: Parser [ExtendTupleExpr]
171+multiTupleExpressionP :: RelationalMarkerExpr a => Parser [ExtendTupleExprBase a]
173multiTupleExpressionP = sepBy extendTupleExpressionP comma
172multiTupleExpressionP = sepBy extendTupleExpressionP comma
175−extendTupleExpressionP :: Parser ExtendTupleExpr
174+extendTupleExpressionP :: RelationalMarkerExpr a => Parser (ExtendTupleExprBase a)
176extendTupleExpressionP = attributeExtendTupleExpressionP
175extendTupleExpressionP = attributeExtendTupleExpressionP
178−attributeExtendTupleExpressionP :: Parser ExtendTupleExpr
177+attributeExtendTupleExpressionP :: RelationalMarkerExpr a => Parser (ExtendTupleExprBase a)
179attributeExtendTupleExpressionP = do
178attributeExtendTupleExpressionP = do
180 newAttr <- identifier
179 newAttr <- identifier
181 reservedOp ":="
180 reservedOp ":="
182 atom <- atomExprP
181 atom <- atomExprP
183 return $ AttributeExtendTupleExpr newAttr atom
182 return $ AttributeExtendTupleExpr newAttr atom
185−atomExprP :: Parser AtomExpr
184+atomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
186atomExprP = consumeAtomExprP True
185atomExprP = consumeAtomExprP True
188−consumeAtomExprP :: Bool -> Parser AtomExpr
187+consumeAtomExprP :: RelationalMarkerExpr a => Bool -> Parser (AtomExprBase a)
189consumeAtomExprP consume = try functionAtomExprP <|>
188consumeAtomExprP consume = try functionAtomExprP <|>
190 try (parens (constructedAtomExprP True)) <|>
189 try (parens (constructedAtomExprP True)) <|>
191 constructedAtomExprP consume <|>
190 constructedAtomExprP consume <|>
@@ -193,20 +192,21 @@ consumeAtomExprP consume = try functionAtomExprP <|>
193 nakedAtomExprP <|>
192 nakedAtomExprP <|>
194 relationalAtomExprP
193 relationalAtomExprP
196−attributeAtomExprP :: Parser AtomExpr
195+attributeAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
197attributeAtomExprP = do
196attributeAtomExprP = do
198 _ <- string "@"
197 _ <- string "@"
199 attrName <- identifier
198 attrName <- identifier
200 return $ AttributeAtomExpr attrName
199 return $ AttributeAtomExpr attrName
202−nakedAtomExprP :: Parser AtomExpr
201+nakedAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
203nakedAtomExprP = NakedAtomExpr <$> atomP
202nakedAtomExprP = NakedAtomExpr <$> atomP
205−constructedAtomExprP :: Bool -> Parser AtomExpr
204+constructedAtomExprP :: RelationalMarkerExpr a => Bool -> Parser (AtomExprBase a)
206constructedAtomExprP consume = do
205constructedAtomExprP consume = do
207 dConsName <- capitalizedIdentifier
206 dConsName <- capitalizedIdentifier
208 dConsArgs <- if consume then sepBy (consumeAtomExprP False) spaceConsumer else pure []
207 dConsArgs <- if consume then sepBy (consumeAtomExprP False) spaceConsumer else pure []
208+ marker <- parseMarkerP
209− pure $ ConstructedAtomExpr dConsName dConsArgs ()
209+ pure $ ConstructedAtomExpr dConsName dConsArgs marker
211-- used only for primitive type parsing ?
211-- used only for primitive type parsing ?
212atomP :: Parser Atom
212atomP :: Parser Atom
@@ -215,13 +215,14 @@ atomP = stringAtomP <|>
215 intAtomP <|>
215 intAtomP <|>
216 boolAtomP
216 boolAtomP
218−functionAtomExprP :: Parser AtomExpr
218+functionAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
219functionAtomExprP = do
219functionAtomExprP = do
220 funcName <- identifier
220 funcName <- identifier
221 argList <- parens (sepBy atomExprP comma)
221 argList <- parens (sepBy atomExprP comma)
222+ marker <- parseMarkerP
222− return $ FunctionAtomExpr funcName argList ()
223+ return $ FunctionAtomExpr funcName argList marker
224−relationalAtomExprP :: Parser AtomExpr
225+relationalAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
225relationalAtomExprP = RelationAtomExpr <$> relExprP
226relationalAtomExprP = RelationAtomExpr <$> relExprP
227stringAtomP :: Parser Atom
228stringAtomP :: Parser Atom
@@ -240,5 +241,5 @@ boolAtomP = do
240 val <- char 't' <|> char 'f'
241 val <- char 't' <|> char 'f'
241 return $ BoolAtom (val == 't')
242 return $ BoolAtom (val == 't')
243−relationAtomExprP :: Parser AtomExpr
244+relationAtomExprP :: RelationalMarkerExpr a => Parser (AtomExprBase a)
244relationAtomExprP = RelationAtomExpr <$> makeRelationP
245relationAtomExprP = RelationAtomExpr <$> makeRelationP