blob: 99952bf023e78c550b745de1051317f97a78d32e [file] [log] [blame]
ggalvizoab83c3b2021-12-22 14:15:50 -08001//
2// Licensed to the Apache Software Foundation (ASF) under one
3// or more contributor license agreements. See the NOTICE file
4// distributed with this work for additional information
5// regarding copyright ownership. The ASF licenses this file
6// to you under the Apache License, Version 2.0 (the
7// "License"); you may not use this file except in compliance
8// with the License. You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing,
13// software distributed under the License is distributed on an
14// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15// KIND, either express or implied. See the License for the
16// specific language governing permissions and limitations
17// under the License.
18//
19
ggalvizo08eab6f2022-04-15 15:22:00 -070020import java.util.HashSet;
21import java.util.Set;
22
ggalvizoab83c3b2021-12-22 14:15:50 -080023import org.apache.asterix.graphix.common.metadata.GraphElementIdentifier;
ggalvizo08eab6f2022-04-15 15:22:00 -070024import org.apache.asterix.graphix.lang.clause.FromGraphClause;
25import org.apache.asterix.graphix.lang.clause.GraphSelectBlock;
26import org.apache.asterix.graphix.lang.clause.MatchClause;
27import org.apache.asterix.graphix.lang.expression.EdgePatternExpr;
ggalvizoab83c3b2021-12-22 14:15:50 -080028import org.apache.asterix.graphix.lang.expression.GraphConstructor;
ggalvizo08eab6f2022-04-15 15:22:00 -070029import org.apache.asterix.graphix.lang.expression.PathPatternExpr;
30import org.apache.asterix.graphix.lang.expression.VertexPatternExpr;
31import org.apache.asterix.graphix.lang.optype.MatchType;
ggalvizoab83c3b2021-12-22 14:15:50 -080032import org.apache.asterix.graphix.lang.statement.CreateGraphStatement;
ggalvizo02256452022-06-14 19:18:50 -070033import org.apache.asterix.graphix.lang.statement.DeclareGraphStatement;
ggalvizoab83c3b2021-12-22 14:15:50 -080034import org.apache.asterix.graphix.lang.statement.GraphDropStatement;
ggalvizo02256452022-06-14 19:18:50 -070035import org.apache.asterix.graphix.lang.statement.GraphElementDeclaration;
ggalvizo08eab6f2022-04-15 15:22:00 -070036import org.apache.asterix.graphix.lang.struct.EdgeDescriptor;
37import org.apache.asterix.graphix.lang.struct.ElementLabel;
ggalvizoab83c3b2021-12-22 14:15:50 -080038import org.apache.asterix.lang.sqlpp.parser.ParseException;
39import org.apache.asterix.lang.sqlpp.parser.SqlppParseException;
40import org.apache.asterix.lang.sqlpp.parser.Token;
41
42@new_at_the_class_def
ggalvizo02256452022-06-14 19:18:50 -070043public GraphElementDeclaration parseGraphElementBody(GraphElementIdentifier identifier) throws CompilationException {
44 return parseImpl(new ParseFunction<GraphElementDeclaration>() {
ggalvizoab83c3b2021-12-22 14:15:50 -080045 @Override
ggalvizo02256452022-06-14 19:18:50 -070046 public GraphElementDeclaration parse() throws ParseException {
ggalvizoab83c3b2021-12-22 14:15:50 -080047 DataverseName dataverse = defaultDataverse;
48 defaultDataverse = identifier.getGraphIdentifier().getDataverseName();
49
50 // We borrow the ViewBody production, where we have a SelectExpression or a VariableRef.
51 createNewScope();
52 Expression elementBodyExpr = GraphixParser.this.ViewBody();
53 removeCurrentScope();
54
55 defaultDataverse = dataverse;
ggalvizo02256452022-06-14 19:18:50 -070056 return new GraphElementDeclaration(identifier, elementBodyExpr);
ggalvizoab83c3b2021-12-22 14:15:50 -080057 }
58 });
59}
60
ggalvizo08eab6f2022-04-15 15:22:00 -070061@override
62SelectBlock SelectBlock() throws ParseException:
63{
64 SelectClause selectClause = null;
65 FromClause fromClause = null;
66 FromGraphClause fromGraphClause = null;
67 List<LetClause> fromLetClauses = null;
68 WhereClause whereClause = null;
69 GroupbyClause groupbyClause = null;
70 List<LetClause> gbyLetClauses = null;
71 HavingClause havingClause = null;
72 SourceLocation startSrcLoc = null;
73
74 List<AbstractClause> fromLetWhereClauses = new ArrayList<AbstractClause>();
75 List<AbstractClause> gbyLetHavingClauses = new ArrayList<AbstractClause>();
76}
77{
78 (
79 (
80 selectClause = SelectClause() { startSrcLoc = selectClause.getSourceLocation(); }
81 (
82 (
83 ( LOOKAHEAD(2)
84 fromGraphClause = FromGraphClause()
85 | fromClause = FromClause()
86 )
87 ( fromLetClauses = LetClause() )?
88 ( whereClause = WhereClause() )?
89 ( groupbyClause = GroupbyClause()
90 ( gbyLetClauses = LetClause() )?
91 ( havingClause = HavingClause() )? )?
92 )
93 |
94 ( fromLetClauses = LetClause()
95 {
96 // LET without FROM -> create dummy FROM clause: FROM {{missing}} AS #0
97 SourceLocation sourceLoc = getSourceLocation(token);
98 LiteralExpr missingExpr = new LiteralExpr(MissingLiteral.INSTANCE);
99 missingExpr.setSourceLocation(sourceLoc);
100 List<Expression> list = new ArrayList<Expression>(1);
101 list.add(missingExpr);
102 ListConstructor listExpr = new ListConstructor(ListConstructor.Type.ORDERED_LIST_CONSTRUCTOR, list);
103 listExpr.setSourceLocation(sourceLoc);
104 List<FromTerm> fromTerms = new ArrayList<FromTerm>(1);
105 VariableExpr fromVar = new VariableExpr(new VarIdentifier("#0"));
106 fromVar.setSourceLocation(sourceLoc);
107 fromTerms.add(new FromTerm(listExpr, fromVar, null, new ArrayList<AbstractBinaryCorrelateClause>()));
108 fromClause = new FromClause(fromTerms);
109 }
110 ( whereClause = WhereClause() )?
111 )
112 )?
113 )
114 |
115 (
116 ( LOOKAHEAD(2)
117 fromGraphClause = FromGraphClause() { startSrcLoc = fromGraphClause.getSourceLocation(); }
118 | fromClause = FromClause() { startSrcLoc = fromClause.getSourceLocation(); }
119 )
120 ( fromLetClauses = LetClause() )?
121 ( whereClause = WhereClause() )?
122 ( groupbyClause = GroupbyClause()
123 ( gbyLetClauses = LetClause() )?
124 ( havingClause = HavingClause() )? )?
125 selectClause = SelectClause()
126 )
127 )
128 {
129 if (fromLetClauses != null) {
130 fromLetWhereClauses.addAll(fromLetClauses);
131 }
132 if (whereClause != null) {
133 fromLetWhereClauses.add(whereClause);
134 }
135 if (gbyLetClauses != null) {
136 gbyLetHavingClauses.addAll(gbyLetClauses);
137 }
138 if (havingClause != null) {
139 gbyLetHavingClauses.add(havingClause);
140 }
141
142 if (fromClause != null) {
143 SelectBlock selectBlock = new SelectBlock(selectClause, fromClause, fromLetWhereClauses,
144 groupbyClause, gbyLetHavingClauses);
145 selectBlock.setSourceLocation(startSrcLoc);
146 return selectBlock;
147
148 } else {
149 GraphSelectBlock selectBlock = new GraphSelectBlock(selectClause, fromGraphClause,
150 fromLetWhereClauses, groupbyClause, gbyLetHavingClauses);
151 selectBlock.setSourceLocation(startSrcLoc);
152 return selectBlock;
153 }
154 }
155}
156
ggalvizo02256452022-06-14 19:18:50 -0700157@override
158Statement SingleStatement() throws ParseException:
ggalvizoab83c3b2021-12-22 14:15:50 -0800159{
ggalvizo02256452022-06-14 19:18:50 -0700160 Statement stmt = null;
ggalvizoab83c3b2021-12-22 14:15:50 -0800161}
162{
163 (
ggalvizo02256452022-06-14 19:18:50 -0700164 stmt = DataverseDeclaration()
165 | stmt = DeclareStatement()
166 | stmt = CreateStatement()
167 | stmt = LoadStatement()
168 | stmt = DropStatement()
169 | stmt = WriteStatement()
170 | stmt = SetStatement()
171 | stmt = InsertStatement()
172 | stmt = DeleteStatement()
173 | stmt = UpdateStatement()
174 | stmt = UpsertStatement()
175 | stmt = ConnectionStatement()
176 | stmt = CompactStatement()
177 | stmt = Query()
178 | stmt = RefreshExternalDatasetStatement()
179 )
180 {
181 return stmt;
182 }
183}
184
185@new
186Statement DeclareStatement() throws ParseException:
187{
188 Token startToken = null;
189 Statement stmt = null;
190}
191{
192 <DECLARE> { startToken = token; }
193 (
194 stmt = FunctionDecl(startToken)
195 | stmt = GraphDecl(startToken)
196 )
197 {
198 return stmt;
199 }
200}
201
202// Note: this is the same as FunctionDeclaration in the main grammar with the <DECLARE> token removed.
203@new
204FunctionDecl FunctionDecl(Token startToken) throws ParseException:
205{
206 String functionName;
207 Pair<Integer, List<Pair<VarIdentifier,TypeExpression>>> paramsWithArity = null;
208 Expression funcBody;
209 createNewScope();
210}
211{
212 <FUNCTION>
213 functionName = Identifier()
214 paramsWithArity = FunctionParameters()
215 <LEFTBRACE>
216 funcBody = FunctionBody()
217 <RIGHTBRACE>
218 {
219 int arity = paramsWithArity.first;
220 List<Pair<VarIdentifier,TypeExpression>> paramList = paramsWithArity.second;
221 FunctionSignature signature = new FunctionSignature(defaultDataverse, functionName, arity);
222 getCurrentScope().addFunctionDescriptor(signature, false);
223 ensureNoTypeDeclsInFunction(functionName, paramList, null, startToken);
224 List<VarIdentifier> params = new ArrayList<VarIdentifier>(paramList.size());
225 for (Pair<VarIdentifier,TypeExpression> p: paramList) {
226 params.add(p.getFirst());
227 }
228 FunctionDecl stmt = new FunctionDecl(signature, params, funcBody, false);
229 removeCurrentScope();
230 return addSourceLocation(stmt, startToken);
231 }
232}
233
234@merge
235Statement CreateStatement() throws ParseException:
236{
237}
238{
239 (
ggalvizoab83c3b2021-12-22 14:15:50 -0800240 before:
241 after: | stmt = CreateGraphStatement(startToken, false)
242 )
243 {
ggalvizoab83c3b2021-12-22 14:15:50 -0800244 }
245}
246
247@merge
248Statement CreateOrReplaceStatement(Token startStmtToken) throws ParseException:
249{
ggalvizoab83c3b2021-12-22 14:15:50 -0800250}
251{
252 (
ggalvizoab83c3b2021-12-22 14:15:50 -0800253 before:
254 after: | stmt = CreateGraphStatement(startStmtToken, true)
255 )
256 {
ggalvizoab83c3b2021-12-22 14:15:50 -0800257 }
258}
259
260@merge
261Statement DropStatement() throws ParseException:
262{
ggalvizoab83c3b2021-12-22 14:15:50 -0800263}
264{
265 (
ggalvizoab83c3b2021-12-22 14:15:50 -0800266 before:
267 after: | stmt = DropGraphStatement(startToken)
268 )
269 {
ggalvizo02256452022-06-14 19:18:50 -0700270 }
271}
272
273@new
274DeclareGraphStatement GraphDecl(Token startStmtToken) throws ParseException:
275{
276 GraphConstructor graphConstructor = null;
277 String graphName = null;
278}
279{
280 <GRAPH>
281 graphName = Identifier()
282 <AS> graphConstructor = GraphConstructor(token)
283 {
284 DeclareGraphStatement stmt = new DeclareGraphStatement(graphName, graphConstructor);
285 return addSourceLocation(stmt, startStmtToken);
ggalvizoab83c3b2021-12-22 14:15:50 -0800286 }
287}
288
289@new
290CreateGraphStatement CreateGraphStatement(Token startStmtToken, boolean orReplace) throws ParseException:
291{
292 CreateGraphStatement stmt = null;
293}
294{
295 <GRAPH> stmt = CreateGraphSpecification(startStmtToken, orReplace)
296 {
297 return stmt;
298 }
299}
300
301@new
302CreateGraphStatement CreateGraphSpecification(Token startStmtToken, boolean orReplace) throws ParseException:
303{
304 Pair<DataverseName, Identifier> nameComponents = null;
305 GraphConstructor graphConstructor = null;
306 boolean ifNotExists = false;
307}
308{
309 nameComponents = QualifiedName()
310 ifNotExists = IfNotExists()
311 {
312 if (orReplace && ifNotExists) {
313 throw new SqlppParseException(getSourceLocation(startStmtToken), "Unexpected IF NOT EXISTS");
314 }
315 }
316 <AS> graphConstructor = GraphConstructor(token)
317 {
318 CreateGraphStatement stmt = new CreateGraphStatement(nameComponents.first, nameComponents.second.getValue(),
319 orReplace, ifNotExists, graphConstructor);
320 return addSourceLocation(stmt, startStmtToken);
321 }
322}
323
324@new
325GraphDropStatement DropGraphStatement(Token startStmtToken) throws ParseException:
326{
327 GraphDropStatement stmt = null;
328}
329{
330 <GRAPH> stmt = DropGraphSpecification(startStmtToken)
331 {
332 return stmt;
333 }
334}
335
336@new
337GraphDropStatement DropGraphSpecification(Token startStmtToken) throws ParseException:
338{
339 Pair<DataverseName, Identifier> pairId = null;
340 boolean ifExists = false;
341}
342{
343 pairId = QualifiedName() ifExists = IfExists()
344 {
345 GraphDropStatement stmt = new GraphDropStatement(pairId.first, pairId.second.getValue(), ifExists);
346 return addSourceLocation(stmt, startStmtToken);
347 }
348}
349
350@new
351Pair<List<Integer>, List<List<String>>> KeyFields() throws ParseException:
352{
353 Pair<List<Integer>, List<List<String>>> keyFields = null;
354}
355{
356 // This is essentially an alias for the production PrimaryKeyFields.
357 keyFields = PrimaryKeyFields()
358 {
359 return keyFields;
360 }
361}
362
363@new
364GraphConstructor GraphConstructor(Token startStmtToken) throws ParseException:
365{
ggalvizo08eab6f2022-04-15 15:22:00 -0700366 List<GraphConstructor.VertexConstructor> vertexConstructors = new ArrayList<GraphConstructor.VertexConstructor>();
367 List<GraphConstructor.EdgeConstructor> edgeConstructors = new ArrayList<GraphConstructor.EdgeConstructor>();
368 GraphConstructor.VertexConstructor vertexConstructor = null;
369 GraphConstructor.EdgeConstructor edgeConstructor = null;
ggalvizoab83c3b2021-12-22 14:15:50 -0800370}
371{
ggalvizo08eab6f2022-04-15 15:22:00 -0700372 vertexConstructor = GraphVertexSpecification(startStmtToken) { vertexConstructors.add(vertexConstructor); }
ggalvizoab83c3b2021-12-22 14:15:50 -0800373 ( <COMMA>
374 (
ggalvizo08eab6f2022-04-15 15:22:00 -0700375 ( vertexConstructor = GraphVertexSpecification(token) { vertexConstructors.add(vertexConstructor); } )
376 | ( edgeConstructor = GraphEdgeSpecification(token) { edgeConstructors.add(edgeConstructor); } )
ggalvizoab83c3b2021-12-22 14:15:50 -0800377 )
378 )*
379 {
ggalvizo08eab6f2022-04-15 15:22:00 -0700380 GraphConstructor graphConstructor = new GraphConstructor(vertexConstructors, edgeConstructors);
ggalvizoab83c3b2021-12-22 14:15:50 -0800381 return addSourceLocation(graphConstructor, startStmtToken);
382 }
383}
384
385@new
ggalvizo08eab6f2022-04-15 15:22:00 -0700386GraphConstructor.VertexConstructor GraphVertexSpecification(Token startStmtToken) throws ParseException:
ggalvizoab83c3b2021-12-22 14:15:50 -0800387{
388 Pair<List<Integer>, List<List<String>>> primaryKeyFields;
389 Token beginPos = null, endPos = null;
ggalvizo696e5fd2022-06-21 18:12:07 -0700390 int positionOffset = 0;
ggalvizoab83c3b2021-12-22 14:15:50 -0800391 Expression vertexDefinitionExpr;
ggalvizo08eab6f2022-04-15 15:22:00 -0700392 ElementLabel vertexLabel;
ggalvizoab83c3b2021-12-22 14:15:50 -0800393}
394{
395 <VERTEX>
ggalvizo08eab6f2022-04-15 15:22:00 -0700396 vertexLabel = GraphVertexDefinitionPattern()
ggalvizoab83c3b2021-12-22 14:15:50 -0800397 <PRIMARY> <KEY> <LEFTPAREN> primaryKeyFields = KeyFields() <RIGHTPAREN>
398 <AS>
399 {
400 beginPos = token;
401 createNewScope();
402 }
403 (
ggalvizo696e5fd2022-06-21 18:12:07 -0700404 vertexDefinitionExpr = ViewBody() { endPos = token; positionOffset++; }
ggalvizo08eab6f2022-04-15 15:22:00 -0700405 | <LEFTPAREN> { beginPos = token; } vertexDefinitionExpr = ViewBody() { endPos = token; } <RIGHTPAREN>
ggalvizoab83c3b2021-12-22 14:15:50 -0800406 )
407 {
ggalvizo696e5fd2022-06-21 18:12:07 -0700408 String vDef = extractFragment(beginPos.beginLine, beginPos.beginColumn + positionOffset, endPos.endLine,
409 endPos.endColumn + 1);
ggalvizoab83c3b2021-12-22 14:15:50 -0800410 removeCurrentScope();
ggalvizo08eab6f2022-04-15 15:22:00 -0700411 GraphConstructor.VertexConstructor vertexConstructor = new GraphConstructor.VertexConstructor(vertexLabel,
ggalvizoab83c3b2021-12-22 14:15:50 -0800412 primaryKeyFields.second, primaryKeyFields.first, vertexDefinitionExpr, vDef);
ggalvizo08eab6f2022-04-15 15:22:00 -0700413 return addSourceLocation(vertexConstructor, startStmtToken);
ggalvizoab83c3b2021-12-22 14:15:50 -0800414 }
415}
416
417@new
ggalvizo08eab6f2022-04-15 15:22:00 -0700418ElementLabel GraphVertexDefinitionPattern() throws ParseException:
ggalvizoab83c3b2021-12-22 14:15:50 -0800419{
420 String vertexName;
421}
422{
423 <LEFTPAREN> <COLON> vertexName = Identifier() <RIGHTPAREN>
424 {
ggalvizo08eab6f2022-04-15 15:22:00 -0700425 return new ElementLabel(vertexName);
ggalvizoab83c3b2021-12-22 14:15:50 -0800426 }
427}
428
429@new
ggalvizo08eab6f2022-04-15 15:22:00 -0700430GraphConstructor.EdgeConstructor GraphEdgeSpecification(Token startStmtToken) throws ParseException:
ggalvizoab83c3b2021-12-22 14:15:50 -0800431{
ggalvizo08eab6f2022-04-15 15:22:00 -0700432 Pair<Triple<ElementLabel, ElementLabel, ElementLabel>, Boolean> edgeDefinitionPattern;
ggalvizoab83c3b2021-12-22 14:15:50 -0800433 Pair<List<Integer>, List<List<String>>> keyFields;
434 Token beginPos = null, endPos = null;
435 Expression edgeDefinitionExpr = null;
ggalvizo696e5fd2022-06-21 18:12:07 -0700436 int positionOffset = 0;
ggalvizoab83c3b2021-12-22 14:15:50 -0800437
438 List<Integer> destinationKeySourceIndicators = null;
439 List<Integer> sourceKeySourceIndicators = null;
ggalvizoab83c3b2021-12-22 14:15:50 -0800440 List<List<String>> destinationKeyFields = null;
441 List<List<String>> sourceKeyFields = null;
ggalvizoab83c3b2021-12-22 14:15:50 -0800442}
443{
444 <EDGE>
445 edgeDefinitionPattern = GraphEdgeDefinitionPattern()
446 (
ggalvizo08eab6f2022-04-15 15:22:00 -0700447 <SOURCE> <KEY> <LEFTPAREN> keyFields = KeyFields() <RIGHTPAREN>
448 {
449 sourceKeyFields = keyFields.second;
450 sourceKeySourceIndicators = keyFields.first;
451 }
452 <DESTINATION> <KEY> <LEFTPAREN> keyFields = KeyFields() <RIGHTPAREN>
453 {
454 destinationKeyFields = keyFields.second;
455 destinationKeySourceIndicators = keyFields.first;
456 }
457 <AS>
458 {
459 beginPos = token;
460 createNewScope();
461 }
ggalvizoab83c3b2021-12-22 14:15:50 -0800462 (
ggalvizo696e5fd2022-06-21 18:12:07 -0700463 edgeDefinitionExpr = SelectExpression(true) { endPos = token; positionOffset++; }
ggalvizo08eab6f2022-04-15 15:22:00 -0700464 | <LEFTPAREN> { beginPos = token; } edgeDefinitionExpr = SelectExpression(true) { endPos = token; } <RIGHTPAREN>
ggalvizoab83c3b2021-12-22 14:15:50 -0800465 )
466 )
467 {
ggalvizo08eab6f2022-04-15 15:22:00 -0700468 ElementLabel destinationLabel, edgeLabel, sourceLabel;
ggalvizoab83c3b2021-12-22 14:15:50 -0800469 if (edgeDefinitionPattern.second) { // isDirectedLeft
470 sourceLabel = edgeDefinitionPattern.first.third;
471 edgeLabel = edgeDefinitionPattern.first.second;
472 destinationLabel = edgeDefinitionPattern.first.first;
ggalvizo08eab6f2022-04-15 15:22:00 -0700473
ggalvizoab83c3b2021-12-22 14:15:50 -0800474 } else {
475 sourceLabel = edgeDefinitionPattern.first.first;
476 edgeLabel = edgeDefinitionPattern.first.second;
477 destinationLabel = edgeDefinitionPattern.first.third;
478 }
479
480 String eDef = null;
481 if (edgeDefinitionExpr != null) {
ggalvizo696e5fd2022-06-21 18:12:07 -0700482 eDef = extractFragment(beginPos.beginLine, beginPos.beginColumn + positionOffset, endPos.endLine,
483 endPos.endColumn + 1);
ggalvizoab83c3b2021-12-22 14:15:50 -0800484 removeCurrentScope();
485 }
486
ggalvizo08eab6f2022-04-15 15:22:00 -0700487 GraphConstructor.EdgeConstructor edgeConstructor = new GraphConstructor.EdgeConstructor(edgeLabel, destinationLabel,
488 sourceLabel, destinationKeyFields, destinationKeySourceIndicators, sourceKeyFields, sourceKeySourceIndicators,
489 edgeDefinitionExpr, eDef);
490 return addSourceLocation(edgeConstructor, startStmtToken);
ggalvizoab83c3b2021-12-22 14:15:50 -0800491 }
492}
493
494@new
ggalvizo08eab6f2022-04-15 15:22:00 -0700495Pair<Triple<ElementLabel, ElementLabel, ElementLabel>, Boolean> GraphEdgeDefinitionPattern() throws ParseException:
ggalvizoab83c3b2021-12-22 14:15:50 -0800496{
ggalvizo08eab6f2022-04-15 15:22:00 -0700497 ElementLabel leftVertexLabel, rightVertexLabel;
ggalvizoab83c3b2021-12-22 14:15:50 -0800498 boolean isDirectedLeft;
ggalvizo08eab6f2022-04-15 15:22:00 -0700499 String edgeName;
ggalvizoab83c3b2021-12-22 14:15:50 -0800500}
501{
ggalvizo08eab6f2022-04-15 15:22:00 -0700502 leftVertexLabel = GraphVertexDefinitionPattern()
ggalvizoab83c3b2021-12-22 14:15:50 -0800503 ( <MINUS> <LEFTBRACKET> <COLON> edgeName = Identifier() <RIGHTBRACKET> <MINUS> <GT> { isDirectedLeft = false; }
504 | <LT> <MINUS> <LEFTBRACKET> <COLON> edgeName = Identifier() <RIGHTBRACKET> <MINUS> { isDirectedLeft = true; } )
ggalvizo08eab6f2022-04-15 15:22:00 -0700505 rightVertexLabel = GraphVertexDefinitionPattern()
ggalvizoab83c3b2021-12-22 14:15:50 -0800506 {
ggalvizo08eab6f2022-04-15 15:22:00 -0700507 Triple<ElementLabel, ElementLabel, ElementLabel> t = new Triple<ElementLabel, ElementLabel, ElementLabel>(
508 leftVertexLabel, new ElementLabel(edgeName), rightVertexLabel);
509 return new Pair<Triple<ElementLabel, ElementLabel, ElementLabel>, Boolean>(t, isDirectedLeft);
510 }
511}
512
513@new
514FromGraphClause FromGraphClause() throws ParseException:
515{
516 Token startToken = null;
517 GraphConstructor graphConstructor = null;
518 Pair<DataverseName, Identifier> nameComponents = null;
519 AbstractBinaryCorrelateClause correlateClause = null;
520
521 List<MatchClause> matchClauses = new ArrayList<MatchClause>();
522 List<PathPatternExpr> pathPatternExpressions = null;
523 List<AbstractBinaryCorrelateClause> correlateClauses = new ArrayList<AbstractBinaryCorrelateClause>();
524}
525{
526 <FROM> <GRAPH> { startToken = token; }
527 (
528 graphConstructor = GraphConstructor(token)
529 | nameComponents = QualifiedName()
530 )
531 <MATCH> pathPatternExpressions = PathPatternExpressions()
532 { matchClauses.add(new MatchClause(pathPatternExpressions, MatchType.LEADING)); }
533 ( LOOKAHEAD(3) // We want to avoid getting confused with the correlated clauses below.
534 (
535 <LEFT> ( <OUTER> )? <MATCH> pathPatternExpressions = PathPatternExpressions()
536 { matchClauses.add(new MatchClause(pathPatternExpressions, MatchType.LEFTOUTER)); }
537 |
538 ( <INNER> )? <MATCH> pathPatternExpressions = PathPatternExpressions()
539 { matchClauses.add(new MatchClause(pathPatternExpressions, MatchType.INNER)); }
540 )
541 )*
542 (
543 (
544 correlateClause = JoinOrUnnestClause(JoinType.INNER, UnnestType.INNER)
545 | ( <INNER> correlateClause = JoinOrUnnestClause(JoinType.INNER, UnnestType.INNER) )
546 | ( <LEFT> ( <OUTER> )? correlateClause = JoinOrUnnestClause(JoinType.LEFTOUTER, UnnestType.LEFTOUTER) )
547 | ( <RIGHT> ( <OUTER> )? correlateClause = JoinClause(JoinType.RIGHTOUTER) )
548 | ( <CROSS> correlateClause = CrossJoinClause() )
549 )
550 {
551 correlateClauses.add(correlateClause);
552 }
553 )*
554 {
555 FromGraphClause fromGraphClause;
556 if (graphConstructor == null) {
557 fromGraphClause = new FromGraphClause(nameComponents.first, nameComponents.second,
558 matchClauses, correlateClauses);
559
560 } else {
561 fromGraphClause = new FromGraphClause(graphConstructor, matchClauses, correlateClauses);
562 }
563 return addSourceLocation(fromGraphClause, startToken);
564 }
565}
566
567@new
568List<PathPatternExpr> PathPatternExpressions() throws ParseException:
569{
570 List<PathPatternExpr> pathPatternExpressions = new ArrayList<PathPatternExpr>();
571 PathPatternExpr pathPattern = null;
572 VariableExpr variableExpr = null;
573}
574{
575 pathPattern = PathPatternExpression() { pathPatternExpressions.add(pathPattern); }
576 (
577 ( <AS> )? variableExpr = Variable()
578 {
579 int index = pathPatternExpressions.size() - 1;
580 pathPatternExpressions.get(index).setVariableExpr(variableExpr);
581 }
582 )?
583 ( LOOKAHEAD(2)
584 <COMMA> pathPattern = PathPatternExpression() { pathPatternExpressions.add(pathPattern); }
585 (
586 ( <AS> )? variableExpr = Variable()
587 {
588 int index = pathPatternExpressions.size() - 1;
589 pathPatternExpressions.get(index).setVariableExpr(variableExpr);
590 }
591 )?
592 )*
593 {
594 return pathPatternExpressions;
595 }
596}
597
598@new
599PathPatternExpr PathPatternExpression() throws ParseException:
600{
601 List<VertexPatternExpr> orderedVertexExpressions = new ArrayList<VertexPatternExpr>();
602 List<EdgePatternExpr> orderedEdgeExpressions = new ArrayList<EdgePatternExpr>();
603
604 Token startToken = null, edgeStartToken = null;
605 VertexPatternExpr vertexExpr = null;
606 EdgeDescriptor edgeDescriptor = null;
607}
608{
609 vertexExpr = VertexPatternExpression()
610 {
611 startToken = token;
612 orderedVertexExpressions.add(vertexExpr);
613 }
614 (
615 edgeDescriptor = EdgeDescriptor() { edgeStartToken = token; }
616 vertexExpr = VertexPatternExpression()
617 {
618 VertexPatternExpr leftVertex = orderedVertexExpressions.get(orderedVertexExpressions.size() - 1);
619 EdgePatternExpr edgePattern = new EdgePatternExpr(leftVertex, vertexExpr, edgeDescriptor);
620 orderedEdgeExpressions.add(addSourceLocation(edgePattern, edgeStartToken));
621 orderedVertexExpressions.add(vertexExpr);
622 }
623 )*
624 {
625 PathPatternExpr pathPattern = new PathPatternExpr(orderedVertexExpressions, orderedEdgeExpressions, null);
626 return addSourceLocation(pathPattern, startToken);
627 }
628}
629
630@new
631VertexPatternExpr VertexPatternExpression() throws ParseException:
632{
633 Set<ElementLabel> vertexLabels = new HashSet<ElementLabel>();
634 VariableExpr variableExpr = null;
635 Token startToken = null;
636 String vertexLabelName;
637}
638{
639 <LEFTPAREN> { startToken = token; }
640 (
641 variableExpr = Variable()
642 )?
643 (
644 <COLON> vertexLabelName = Identifier() { vertexLabels.add(new ElementLabel(vertexLabelName)); }
645 ( <BAR> vertexLabelName = Identifier() { vertexLabels.add(new ElementLabel(vertexLabelName)); } )*
646 )?
647 <RIGHTPAREN>
648 {
649 VertexPatternExpr vertexExpression = new VertexPatternExpr(variableExpr, vertexLabels);
650 return addSourceLocation(vertexExpression, startToken);
651 }
652}
653
654@new
655EdgeDescriptor EdgeDescriptor() throws ParseException:
656{
657 Pair<Set<ElementLabel>, Pair<Integer, Integer>> edgeDetail = null;
658 Token startToken = null;
659 VariableExpr edgeVariable = null;
660
661 // We default to undirected edges.
ggalvizo01f41f42022-04-26 18:42:38 -0700662 EdgeDescriptor.EdgeDirection edgeDirection = EdgeDescriptor.EdgeDirection.UNDIRECTED;
ggalvizo08eab6f2022-04-15 15:22:00 -0700663}
664{
665 (
666 <MINUS> { startToken = token; }
667 (
668 <LEFTBRACKET>
669 (
670 edgeVariable = Variable()
671 )?
672 ( <COLON> edgeDetail = EdgeDetail() )?
673 <RIGHTBRACKET> <MINUS>
674 )?
ggalvizo01f41f42022-04-26 18:42:38 -0700675 ( <GT> { edgeDirection = EdgeDescriptor.EdgeDirection.LEFT_TO_RIGHT; } )?
ggalvizo08eab6f2022-04-15 15:22:00 -0700676 |
677 <LT> {
678 startToken = token;
ggalvizo01f41f42022-04-26 18:42:38 -0700679 edgeDirection = EdgeDescriptor.EdgeDirection.RIGHT_TO_LEFT;
ggalvizo08eab6f2022-04-15 15:22:00 -0700680 }
681 <MINUS>
682 (
683 <LEFTBRACKET>
684 (
685 edgeVariable = Variable()
686 )?
687 ( <COLON> edgeDetail = EdgeDetail() )?
688 <RIGHTBRACKET> <MINUS>
689 )?
690 )
691 {
ggalvizo01f41f42022-04-26 18:42:38 -0700692 // Edges (by default) are of pattern type EDGE and are not sub-paths.
693 EdgeDescriptor.PatternType patternType = EdgeDescriptor.PatternType.EDGE;
ggalvizo08eab6f2022-04-15 15:22:00 -0700694 Integer hopCountMin = 1;
695 Integer hopCountMax = 1;
696
697 Set<ElementLabel> labels = new HashSet<ElementLabel>();
698 if (edgeDetail != null) {
699 labels = edgeDetail.first;
700
701 // We have explicitly specified "{" and "}". Use sub-path semantics.
702 if (edgeDetail.second != null) {
ggalvizo01f41f42022-04-26 18:42:38 -0700703 patternType = EdgeDescriptor.PatternType.PATH;
ggalvizo08eab6f2022-04-15 15:22:00 -0700704 hopCountMin = edgeDetail.second.first;
705 hopCountMax = edgeDetail.second.second;
706 }
707 }
708
ggalvizo01f41f42022-04-26 18:42:38 -0700709 return new EdgeDescriptor(edgeDirection, patternType, labels, edgeVariable, hopCountMin, hopCountMax);
ggalvizo08eab6f2022-04-15 15:22:00 -0700710 }
711}
712
713@new
714Pair<Set<ElementLabel>, Pair<Integer, Integer>> EdgeDetail() throws ParseException:
715{
716 Set<ElementLabel> edgeLabels = new HashSet<ElementLabel>();
717 Pair<Integer, Integer> repetitionQuantifier = null;
718 String labelName = null;
719}
720{
721 (
722 // Note: we want to forbid LABEL_1|LABEL_2{...}.
723 LOOKAHEAD(2, <BAR>)
724 (
725 labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); }
726 <BAR> labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); }
727 ( <BAR> labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); } )*
728 )
729 |
730 (
731 labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); }
732 |
733 <LEFTPAREN>
734 labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); }
735 ( <BAR> labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); } )*
736 <RIGHTPAREN>
737 )
738 ( repetitionQuantifier = EdgeRepetitionQuantifier() )?
739 |
740 ( repetitionQuantifier = EdgeRepetitionQuantifier() )
741 )
742 {
743 return new Pair<Set<ElementLabel>, Pair<Integer, Integer>> (edgeLabels, repetitionQuantifier);
744 }
745}
746
747@new
748Pair<Integer, Integer> EdgeRepetitionQuantifier() throws ParseException:
749{
750 Integer hopCountMin = null;
751 Integer hopCountMax = null;
752}
753{
754 <LEFTBRACE>
755 ( // Note: we forbid unbounded edge repetition.
756 ( <INTEGER_LITERAL> { hopCountMin = Integer.valueOf(token.image); } )?
757 <COMMA> <INTEGER_LITERAL> { hopCountMax = Integer.valueOf(token.image); }
758 )
759 <RIGHTBRACE>
760 {
761 return new Pair<Integer, Integer>(hopCountMin, hopCountMax);
ggalvizoab83c3b2021-12-22 14:15:50 -0800762 }
763}
764
765@new
766<DEFAULT,IN_DBL_BRACE>
767TOKEN [IGNORE_CASE]:
768{
769 <DESTINATION: "destination">
770 | <EDGE: "edge">
771 | <GRAPH: "graph">
772 | <SOURCE: "source">
773 | <VERTEX: "vertex">
ggalvizo08eab6f2022-04-15 15:22:00 -0700774 | <MATCH: "match">
ggalvizoab83c3b2021-12-22 14:15:50 -0800775}
776
777@new_at_the_end
778<DEFAULT,IN_DBL_BRACE>
779TOKEN :
780{
781 <BAR: "|">
782}