blob: 5338219285abaf40116830ed7a425e0dad7396e7 [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;
390 Expression vertexDefinitionExpr;
ggalvizo08eab6f2022-04-15 15:22:00 -0700391 ElementLabel vertexLabel;
ggalvizoab83c3b2021-12-22 14:15:50 -0800392}
393{
394 <VERTEX>
ggalvizo08eab6f2022-04-15 15:22:00 -0700395 vertexLabel = GraphVertexDefinitionPattern()
ggalvizoab83c3b2021-12-22 14:15:50 -0800396 <PRIMARY> <KEY> <LEFTPAREN> primaryKeyFields = KeyFields() <RIGHTPAREN>
397 <AS>
398 {
399 beginPos = token;
400 createNewScope();
401 }
402 (
ggalvizo08eab6f2022-04-15 15:22:00 -0700403 vertexDefinitionExpr = ViewBody() { endPos = token; }
404 | <LEFTPAREN> { beginPos = token; } vertexDefinitionExpr = ViewBody() { endPos = token; } <RIGHTPAREN>
ggalvizoab83c3b2021-12-22 14:15:50 -0800405 )
406 {
ggalvizoab83c3b2021-12-22 14:15:50 -0800407 String vDef = extractFragment(beginPos.beginLine, beginPos.beginColumn + 1, endPos.endLine, endPos.endColumn + 1);
408 removeCurrentScope();
ggalvizo08eab6f2022-04-15 15:22:00 -0700409 GraphConstructor.VertexConstructor vertexConstructor = new GraphConstructor.VertexConstructor(vertexLabel,
ggalvizoab83c3b2021-12-22 14:15:50 -0800410 primaryKeyFields.second, primaryKeyFields.first, vertexDefinitionExpr, vDef);
ggalvizo08eab6f2022-04-15 15:22:00 -0700411 return addSourceLocation(vertexConstructor, startStmtToken);
ggalvizoab83c3b2021-12-22 14:15:50 -0800412 }
413}
414
415@new
ggalvizo08eab6f2022-04-15 15:22:00 -0700416ElementLabel GraphVertexDefinitionPattern() throws ParseException:
ggalvizoab83c3b2021-12-22 14:15:50 -0800417{
418 String vertexName;
419}
420{
421 <LEFTPAREN> <COLON> vertexName = Identifier() <RIGHTPAREN>
422 {
ggalvizo08eab6f2022-04-15 15:22:00 -0700423 return new ElementLabel(vertexName);
ggalvizoab83c3b2021-12-22 14:15:50 -0800424 }
425}
426
427@new
ggalvizo08eab6f2022-04-15 15:22:00 -0700428GraphConstructor.EdgeConstructor GraphEdgeSpecification(Token startStmtToken) throws ParseException:
ggalvizoab83c3b2021-12-22 14:15:50 -0800429{
ggalvizo08eab6f2022-04-15 15:22:00 -0700430 Pair<Triple<ElementLabel, ElementLabel, ElementLabel>, Boolean> edgeDefinitionPattern;
ggalvizoab83c3b2021-12-22 14:15:50 -0800431 Pair<List<Integer>, List<List<String>>> keyFields;
432 Token beginPos = null, endPos = null;
433 Expression edgeDefinitionExpr = null;
434
435 List<Integer> destinationKeySourceIndicators = null;
436 List<Integer> sourceKeySourceIndicators = null;
ggalvizoab83c3b2021-12-22 14:15:50 -0800437 List<List<String>> destinationKeyFields = null;
438 List<List<String>> sourceKeyFields = null;
ggalvizoab83c3b2021-12-22 14:15:50 -0800439}
440{
441 <EDGE>
442 edgeDefinitionPattern = GraphEdgeDefinitionPattern()
443 (
ggalvizo08eab6f2022-04-15 15:22:00 -0700444 <SOURCE> <KEY> <LEFTPAREN> keyFields = KeyFields() <RIGHTPAREN>
445 {
446 sourceKeyFields = keyFields.second;
447 sourceKeySourceIndicators = keyFields.first;
448 }
449 <DESTINATION> <KEY> <LEFTPAREN> keyFields = KeyFields() <RIGHTPAREN>
450 {
451 destinationKeyFields = keyFields.second;
452 destinationKeySourceIndicators = keyFields.first;
453 }
454 <AS>
455 {
456 beginPos = token;
457 createNewScope();
458 }
ggalvizoab83c3b2021-12-22 14:15:50 -0800459 (
ggalvizo08eab6f2022-04-15 15:22:00 -0700460 edgeDefinitionExpr = SelectExpression(true) { endPos = token; }
461 | <LEFTPAREN> { beginPos = token; } edgeDefinitionExpr = SelectExpression(true) { endPos = token; } <RIGHTPAREN>
ggalvizoab83c3b2021-12-22 14:15:50 -0800462 )
463 )
464 {
ggalvizo08eab6f2022-04-15 15:22:00 -0700465 ElementLabel destinationLabel, edgeLabel, sourceLabel;
ggalvizoab83c3b2021-12-22 14:15:50 -0800466 if (edgeDefinitionPattern.second) { // isDirectedLeft
467 sourceLabel = edgeDefinitionPattern.first.third;
468 edgeLabel = edgeDefinitionPattern.first.second;
469 destinationLabel = edgeDefinitionPattern.first.first;
ggalvizo08eab6f2022-04-15 15:22:00 -0700470
ggalvizoab83c3b2021-12-22 14:15:50 -0800471 } else {
472 sourceLabel = edgeDefinitionPattern.first.first;
473 edgeLabel = edgeDefinitionPattern.first.second;
474 destinationLabel = edgeDefinitionPattern.first.third;
475 }
476
477 String eDef = null;
478 if (edgeDefinitionExpr != null) {
ggalvizoab83c3b2021-12-22 14:15:50 -0800479 eDef = extractFragment(beginPos.beginLine, beginPos.beginColumn + 1, endPos.endLine, endPos.endColumn + 1);
480 removeCurrentScope();
481 }
482
ggalvizo08eab6f2022-04-15 15:22:00 -0700483 GraphConstructor.EdgeConstructor edgeConstructor = new GraphConstructor.EdgeConstructor(edgeLabel, destinationLabel,
484 sourceLabel, destinationKeyFields, destinationKeySourceIndicators, sourceKeyFields, sourceKeySourceIndicators,
485 edgeDefinitionExpr, eDef);
486 return addSourceLocation(edgeConstructor, startStmtToken);
ggalvizoab83c3b2021-12-22 14:15:50 -0800487 }
488}
489
490@new
ggalvizo08eab6f2022-04-15 15:22:00 -0700491Pair<Triple<ElementLabel, ElementLabel, ElementLabel>, Boolean> GraphEdgeDefinitionPattern() throws ParseException:
ggalvizoab83c3b2021-12-22 14:15:50 -0800492{
ggalvizo08eab6f2022-04-15 15:22:00 -0700493 ElementLabel leftVertexLabel, rightVertexLabel;
ggalvizoab83c3b2021-12-22 14:15:50 -0800494 boolean isDirectedLeft;
ggalvizo08eab6f2022-04-15 15:22:00 -0700495 String edgeName;
ggalvizoab83c3b2021-12-22 14:15:50 -0800496}
497{
ggalvizo08eab6f2022-04-15 15:22:00 -0700498 leftVertexLabel = GraphVertexDefinitionPattern()
ggalvizoab83c3b2021-12-22 14:15:50 -0800499 ( <MINUS> <LEFTBRACKET> <COLON> edgeName = Identifier() <RIGHTBRACKET> <MINUS> <GT> { isDirectedLeft = false; }
500 | <LT> <MINUS> <LEFTBRACKET> <COLON> edgeName = Identifier() <RIGHTBRACKET> <MINUS> { isDirectedLeft = true; } )
ggalvizo08eab6f2022-04-15 15:22:00 -0700501 rightVertexLabel = GraphVertexDefinitionPattern()
ggalvizoab83c3b2021-12-22 14:15:50 -0800502 {
ggalvizo08eab6f2022-04-15 15:22:00 -0700503 Triple<ElementLabel, ElementLabel, ElementLabel> t = new Triple<ElementLabel, ElementLabel, ElementLabel>(
504 leftVertexLabel, new ElementLabel(edgeName), rightVertexLabel);
505 return new Pair<Triple<ElementLabel, ElementLabel, ElementLabel>, Boolean>(t, isDirectedLeft);
506 }
507}
508
509@new
510FromGraphClause FromGraphClause() throws ParseException:
511{
512 Token startToken = null;
513 GraphConstructor graphConstructor = null;
514 Pair<DataverseName, Identifier> nameComponents = null;
515 AbstractBinaryCorrelateClause correlateClause = null;
516
517 List<MatchClause> matchClauses = new ArrayList<MatchClause>();
518 List<PathPatternExpr> pathPatternExpressions = null;
519 List<AbstractBinaryCorrelateClause> correlateClauses = new ArrayList<AbstractBinaryCorrelateClause>();
520}
521{
522 <FROM> <GRAPH> { startToken = token; }
523 (
524 graphConstructor = GraphConstructor(token)
525 | nameComponents = QualifiedName()
526 )
527 <MATCH> pathPatternExpressions = PathPatternExpressions()
528 { matchClauses.add(new MatchClause(pathPatternExpressions, MatchType.LEADING)); }
529 ( LOOKAHEAD(3) // We want to avoid getting confused with the correlated clauses below.
530 (
531 <LEFT> ( <OUTER> )? <MATCH> pathPatternExpressions = PathPatternExpressions()
532 { matchClauses.add(new MatchClause(pathPatternExpressions, MatchType.LEFTOUTER)); }
533 |
534 ( <INNER> )? <MATCH> pathPatternExpressions = PathPatternExpressions()
535 { matchClauses.add(new MatchClause(pathPatternExpressions, MatchType.INNER)); }
536 )
537 )*
538 (
539 (
540 correlateClause = JoinOrUnnestClause(JoinType.INNER, UnnestType.INNER)
541 | ( <INNER> correlateClause = JoinOrUnnestClause(JoinType.INNER, UnnestType.INNER) )
542 | ( <LEFT> ( <OUTER> )? correlateClause = JoinOrUnnestClause(JoinType.LEFTOUTER, UnnestType.LEFTOUTER) )
543 | ( <RIGHT> ( <OUTER> )? correlateClause = JoinClause(JoinType.RIGHTOUTER) )
544 | ( <CROSS> correlateClause = CrossJoinClause() )
545 )
546 {
547 correlateClauses.add(correlateClause);
548 }
549 )*
550 {
551 FromGraphClause fromGraphClause;
552 if (graphConstructor == null) {
553 fromGraphClause = new FromGraphClause(nameComponents.first, nameComponents.second,
554 matchClauses, correlateClauses);
555
556 } else {
557 fromGraphClause = new FromGraphClause(graphConstructor, matchClauses, correlateClauses);
558 }
559 return addSourceLocation(fromGraphClause, startToken);
560 }
561}
562
563@new
564List<PathPatternExpr> PathPatternExpressions() throws ParseException:
565{
566 List<PathPatternExpr> pathPatternExpressions = new ArrayList<PathPatternExpr>();
567 PathPatternExpr pathPattern = null;
568 VariableExpr variableExpr = null;
569}
570{
571 pathPattern = PathPatternExpression() { pathPatternExpressions.add(pathPattern); }
572 (
573 ( <AS> )? variableExpr = Variable()
574 {
575 int index = pathPatternExpressions.size() - 1;
576 pathPatternExpressions.get(index).setVariableExpr(variableExpr);
577 }
578 )?
579 ( LOOKAHEAD(2)
580 <COMMA> pathPattern = PathPatternExpression() { pathPatternExpressions.add(pathPattern); }
581 (
582 ( <AS> )? variableExpr = Variable()
583 {
584 int index = pathPatternExpressions.size() - 1;
585 pathPatternExpressions.get(index).setVariableExpr(variableExpr);
586 }
587 )?
588 )*
589 {
590 return pathPatternExpressions;
591 }
592}
593
594@new
595PathPatternExpr PathPatternExpression() throws ParseException:
596{
597 List<VertexPatternExpr> orderedVertexExpressions = new ArrayList<VertexPatternExpr>();
598 List<EdgePatternExpr> orderedEdgeExpressions = new ArrayList<EdgePatternExpr>();
599
600 Token startToken = null, edgeStartToken = null;
601 VertexPatternExpr vertexExpr = null;
602 EdgeDescriptor edgeDescriptor = null;
603}
604{
605 vertexExpr = VertexPatternExpression()
606 {
607 startToken = token;
608 orderedVertexExpressions.add(vertexExpr);
609 }
610 (
611 edgeDescriptor = EdgeDescriptor() { edgeStartToken = token; }
612 vertexExpr = VertexPatternExpression()
613 {
614 VertexPatternExpr leftVertex = orderedVertexExpressions.get(orderedVertexExpressions.size() - 1);
615 EdgePatternExpr edgePattern = new EdgePatternExpr(leftVertex, vertexExpr, edgeDescriptor);
616 orderedEdgeExpressions.add(addSourceLocation(edgePattern, edgeStartToken));
617 orderedVertexExpressions.add(vertexExpr);
618 }
619 )*
620 {
621 PathPatternExpr pathPattern = new PathPatternExpr(orderedVertexExpressions, orderedEdgeExpressions, null);
622 return addSourceLocation(pathPattern, startToken);
623 }
624}
625
626@new
627VertexPatternExpr VertexPatternExpression() throws ParseException:
628{
629 Set<ElementLabel> vertexLabels = new HashSet<ElementLabel>();
630 VariableExpr variableExpr = null;
631 Token startToken = null;
632 String vertexLabelName;
633}
634{
635 <LEFTPAREN> { startToken = token; }
636 (
637 variableExpr = Variable()
638 )?
639 (
640 <COLON> vertexLabelName = Identifier() { vertexLabels.add(new ElementLabel(vertexLabelName)); }
641 ( <BAR> vertexLabelName = Identifier() { vertexLabels.add(new ElementLabel(vertexLabelName)); } )*
642 )?
643 <RIGHTPAREN>
644 {
645 VertexPatternExpr vertexExpression = new VertexPatternExpr(variableExpr, vertexLabels);
646 return addSourceLocation(vertexExpression, startToken);
647 }
648}
649
650@new
651EdgeDescriptor EdgeDescriptor() throws ParseException:
652{
653 Pair<Set<ElementLabel>, Pair<Integer, Integer>> edgeDetail = null;
654 Token startToken = null;
655 VariableExpr edgeVariable = null;
656
657 // We default to undirected edges.
ggalvizo01f41f42022-04-26 18:42:38 -0700658 EdgeDescriptor.EdgeDirection edgeDirection = EdgeDescriptor.EdgeDirection.UNDIRECTED;
ggalvizo08eab6f2022-04-15 15:22:00 -0700659}
660{
661 (
662 <MINUS> { startToken = token; }
663 (
664 <LEFTBRACKET>
665 (
666 edgeVariable = Variable()
667 )?
668 ( <COLON> edgeDetail = EdgeDetail() )?
669 <RIGHTBRACKET> <MINUS>
670 )?
ggalvizo01f41f42022-04-26 18:42:38 -0700671 ( <GT> { edgeDirection = EdgeDescriptor.EdgeDirection.LEFT_TO_RIGHT; } )?
ggalvizo08eab6f2022-04-15 15:22:00 -0700672 |
673 <LT> {
674 startToken = token;
ggalvizo01f41f42022-04-26 18:42:38 -0700675 edgeDirection = EdgeDescriptor.EdgeDirection.RIGHT_TO_LEFT;
ggalvizo08eab6f2022-04-15 15:22:00 -0700676 }
677 <MINUS>
678 (
679 <LEFTBRACKET>
680 (
681 edgeVariable = Variable()
682 )?
683 ( <COLON> edgeDetail = EdgeDetail() )?
684 <RIGHTBRACKET> <MINUS>
685 )?
686 )
687 {
ggalvizo01f41f42022-04-26 18:42:38 -0700688 // Edges (by default) are of pattern type EDGE and are not sub-paths.
689 EdgeDescriptor.PatternType patternType = EdgeDescriptor.PatternType.EDGE;
ggalvizo08eab6f2022-04-15 15:22:00 -0700690 Integer hopCountMin = 1;
691 Integer hopCountMax = 1;
692
693 Set<ElementLabel> labels = new HashSet<ElementLabel>();
694 if (edgeDetail != null) {
695 labels = edgeDetail.first;
696
697 // We have explicitly specified "{" and "}". Use sub-path semantics.
698 if (edgeDetail.second != null) {
ggalvizo01f41f42022-04-26 18:42:38 -0700699 patternType = EdgeDescriptor.PatternType.PATH;
ggalvizo08eab6f2022-04-15 15:22:00 -0700700 hopCountMin = edgeDetail.second.first;
701 hopCountMax = edgeDetail.second.second;
702 }
703 }
704
ggalvizo01f41f42022-04-26 18:42:38 -0700705 return new EdgeDescriptor(edgeDirection, patternType, labels, edgeVariable, hopCountMin, hopCountMax);
ggalvizo08eab6f2022-04-15 15:22:00 -0700706 }
707}
708
709@new
710Pair<Set<ElementLabel>, Pair<Integer, Integer>> EdgeDetail() throws ParseException:
711{
712 Set<ElementLabel> edgeLabels = new HashSet<ElementLabel>();
713 Pair<Integer, Integer> repetitionQuantifier = null;
714 String labelName = null;
715}
716{
717 (
718 // Note: we want to forbid LABEL_1|LABEL_2{...}.
719 LOOKAHEAD(2, <BAR>)
720 (
721 labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); }
722 <BAR> labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); }
723 ( <BAR> labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); } )*
724 )
725 |
726 (
727 labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); }
728 |
729 <LEFTPAREN>
730 labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); }
731 ( <BAR> labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); } )*
732 <RIGHTPAREN>
733 )
734 ( repetitionQuantifier = EdgeRepetitionQuantifier() )?
735 |
736 ( repetitionQuantifier = EdgeRepetitionQuantifier() )
737 )
738 {
739 return new Pair<Set<ElementLabel>, Pair<Integer, Integer>> (edgeLabels, repetitionQuantifier);
740 }
741}
742
743@new
744Pair<Integer, Integer> EdgeRepetitionQuantifier() throws ParseException:
745{
746 Integer hopCountMin = null;
747 Integer hopCountMax = null;
748}
749{
750 <LEFTBRACE>
751 ( // Note: we forbid unbounded edge repetition.
752 ( <INTEGER_LITERAL> { hopCountMin = Integer.valueOf(token.image); } )?
753 <COMMA> <INTEGER_LITERAL> { hopCountMax = Integer.valueOf(token.image); }
754 )
755 <RIGHTBRACE>
756 {
757 return new Pair<Integer, Integer>(hopCountMin, hopCountMax);
ggalvizoab83c3b2021-12-22 14:15:50 -0800758 }
759}
760
761@new
762<DEFAULT,IN_DBL_BRACE>
763TOKEN [IGNORE_CASE]:
764{
765 <DESTINATION: "destination">
766 | <EDGE: "edge">
767 | <GRAPH: "graph">
768 | <SOURCE: "source">
769 | <VERTEX: "vertex">
ggalvizo08eab6f2022-04-15 15:22:00 -0700770 | <MATCH: "match">
ggalvizoab83c3b2021-12-22 14:15:50 -0800771}
772
773@new_at_the_end
774<DEFAULT,IN_DBL_BRACE>
775TOKEN :
776{
777 <BAR: "|">
778}