blob: a1d12e62a814d26dfde8b7ee203f925cbe49f981 [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;
33import org.apache.asterix.graphix.lang.statement.GraphDropStatement;
34import org.apache.asterix.graphix.lang.statement.GraphElementDecl;
ggalvizo08eab6f2022-04-15 15:22:00 -070035import org.apache.asterix.graphix.lang.struct.EdgeDescriptor;
36import org.apache.asterix.graphix.lang.struct.ElementLabel;
ggalvizoab83c3b2021-12-22 14:15:50 -080037import org.apache.asterix.lang.sqlpp.parser.ParseException;
38import org.apache.asterix.lang.sqlpp.parser.SqlppParseException;
39import org.apache.asterix.lang.sqlpp.parser.Token;
40
41@new_at_the_class_def
42public GraphElementDecl parseGraphElementBody(GraphElementIdentifier identifier) throws CompilationException {
43 return parseImpl(new ParseFunction<GraphElementDecl>() {
44 @Override
45 public GraphElementDecl parse() throws ParseException {
46 DataverseName dataverse = defaultDataverse;
47 defaultDataverse = identifier.getGraphIdentifier().getDataverseName();
48
49 // We borrow the ViewBody production, where we have a SelectExpression or a VariableRef.
50 createNewScope();
51 Expression elementBodyExpr = GraphixParser.this.ViewBody();
52 removeCurrentScope();
53
54 defaultDataverse = dataverse;
55 return new GraphElementDecl(identifier, elementBodyExpr);
56 }
57 });
58}
59
ggalvizo08eab6f2022-04-15 15:22:00 -070060@override
61SelectBlock SelectBlock() throws ParseException:
62{
63 SelectClause selectClause = null;
64 FromClause fromClause = null;
65 FromGraphClause fromGraphClause = null;
66 List<LetClause> fromLetClauses = null;
67 WhereClause whereClause = null;
68 GroupbyClause groupbyClause = null;
69 List<LetClause> gbyLetClauses = null;
70 HavingClause havingClause = null;
71 SourceLocation startSrcLoc = null;
72
73 List<AbstractClause> fromLetWhereClauses = new ArrayList<AbstractClause>();
74 List<AbstractClause> gbyLetHavingClauses = new ArrayList<AbstractClause>();
75}
76{
77 (
78 (
79 selectClause = SelectClause() { startSrcLoc = selectClause.getSourceLocation(); }
80 (
81 (
82 ( LOOKAHEAD(2)
83 fromGraphClause = FromGraphClause()
84 | fromClause = FromClause()
85 )
86 ( fromLetClauses = LetClause() )?
87 ( whereClause = WhereClause() )?
88 ( groupbyClause = GroupbyClause()
89 ( gbyLetClauses = LetClause() )?
90 ( havingClause = HavingClause() )? )?
91 )
92 |
93 ( fromLetClauses = LetClause()
94 {
95 // LET without FROM -> create dummy FROM clause: FROM {{missing}} AS #0
96 SourceLocation sourceLoc = getSourceLocation(token);
97 LiteralExpr missingExpr = new LiteralExpr(MissingLiteral.INSTANCE);
98 missingExpr.setSourceLocation(sourceLoc);
99 List<Expression> list = new ArrayList<Expression>(1);
100 list.add(missingExpr);
101 ListConstructor listExpr = new ListConstructor(ListConstructor.Type.ORDERED_LIST_CONSTRUCTOR, list);
102 listExpr.setSourceLocation(sourceLoc);
103 List<FromTerm> fromTerms = new ArrayList<FromTerm>(1);
104 VariableExpr fromVar = new VariableExpr(new VarIdentifier("#0"));
105 fromVar.setSourceLocation(sourceLoc);
106 fromTerms.add(new FromTerm(listExpr, fromVar, null, new ArrayList<AbstractBinaryCorrelateClause>()));
107 fromClause = new FromClause(fromTerms);
108 }
109 ( whereClause = WhereClause() )?
110 )
111 )?
112 )
113 |
114 (
115 ( LOOKAHEAD(2)
116 fromGraphClause = FromGraphClause() { startSrcLoc = fromGraphClause.getSourceLocation(); }
117 | fromClause = FromClause() { startSrcLoc = fromClause.getSourceLocation(); }
118 )
119 ( fromLetClauses = LetClause() )?
120 ( whereClause = WhereClause() )?
121 ( groupbyClause = GroupbyClause()
122 ( gbyLetClauses = LetClause() )?
123 ( havingClause = HavingClause() )? )?
124 selectClause = SelectClause()
125 )
126 )
127 {
128 if (fromLetClauses != null) {
129 fromLetWhereClauses.addAll(fromLetClauses);
130 }
131 if (whereClause != null) {
132 fromLetWhereClauses.add(whereClause);
133 }
134 if (gbyLetClauses != null) {
135 gbyLetHavingClauses.addAll(gbyLetClauses);
136 }
137 if (havingClause != null) {
138 gbyLetHavingClauses.add(havingClause);
139 }
140
141 if (fromClause != null) {
142 SelectBlock selectBlock = new SelectBlock(selectClause, fromClause, fromLetWhereClauses,
143 groupbyClause, gbyLetHavingClauses);
144 selectBlock.setSourceLocation(startSrcLoc);
145 return selectBlock;
146
147 } else {
148 GraphSelectBlock selectBlock = new GraphSelectBlock(selectClause, fromGraphClause,
149 fromLetWhereClauses, groupbyClause, gbyLetHavingClauses);
150 selectBlock.setSourceLocation(startSrcLoc);
151 return selectBlock;
152 }
153 }
154}
155
ggalvizoab83c3b2021-12-22 14:15:50 -0800156@merge
157Statement CreateStatement() throws ParseException:
158{
159 // merge area 1
160 before:
161 after:
162}
163{
164 (
165 // merge area 2
166 before:
167 after: | stmt = CreateGraphStatement(startToken, false)
168 )
169 {
170 // merge area 3
171 }
172}
173
174@merge
175Statement CreateOrReplaceStatement(Token startStmtToken) throws ParseException:
176{
177 // merge area 1
178 before:
179 after:
180}
181{
182 (
183 // merge area 2
184 before:
185 after: | stmt = CreateGraphStatement(startStmtToken, true)
186 )
187 {
188 // merge area 3
189 }
190}
191
192@merge
193Statement DropStatement() throws ParseException:
194{
195 // merge area 1
196 before:
197 after:
198}
199{
200 (
201 // merge area 2
202 before:
203 after: | stmt = DropGraphStatement(startToken)
204 )
205 {
206 // merge area 3
207 }
208}
209
210@new
211CreateGraphStatement CreateGraphStatement(Token startStmtToken, boolean orReplace) throws ParseException:
212{
213 CreateGraphStatement stmt = null;
214}
215{
216 <GRAPH> stmt = CreateGraphSpecification(startStmtToken, orReplace)
217 {
218 return stmt;
219 }
220}
221
222@new
223CreateGraphStatement CreateGraphSpecification(Token startStmtToken, boolean orReplace) throws ParseException:
224{
225 Pair<DataverseName, Identifier> nameComponents = null;
226 GraphConstructor graphConstructor = null;
227 boolean ifNotExists = false;
228}
229{
230 nameComponents = QualifiedName()
231 ifNotExists = IfNotExists()
232 {
233 if (orReplace && ifNotExists) {
234 throw new SqlppParseException(getSourceLocation(startStmtToken), "Unexpected IF NOT EXISTS");
235 }
236 }
237 <AS> graphConstructor = GraphConstructor(token)
238 {
239 CreateGraphStatement stmt = new CreateGraphStatement(nameComponents.first, nameComponents.second.getValue(),
240 orReplace, ifNotExists, graphConstructor);
241 return addSourceLocation(stmt, startStmtToken);
242 }
243}
244
245@new
246GraphDropStatement DropGraphStatement(Token startStmtToken) throws ParseException:
247{
248 GraphDropStatement stmt = null;
249}
250{
251 <GRAPH> stmt = DropGraphSpecification(startStmtToken)
252 {
253 return stmt;
254 }
255}
256
257@new
258GraphDropStatement DropGraphSpecification(Token startStmtToken) throws ParseException:
259{
260 Pair<DataverseName, Identifier> pairId = null;
261 boolean ifExists = false;
262}
263{
264 pairId = QualifiedName() ifExists = IfExists()
265 {
266 GraphDropStatement stmt = new GraphDropStatement(pairId.first, pairId.second.getValue(), ifExists);
267 return addSourceLocation(stmt, startStmtToken);
268 }
269}
270
271@new
272Pair<List<Integer>, List<List<String>>> KeyFields() throws ParseException:
273{
274 Pair<List<Integer>, List<List<String>>> keyFields = null;
275}
276{
277 // This is essentially an alias for the production PrimaryKeyFields.
278 keyFields = PrimaryKeyFields()
279 {
280 return keyFields;
281 }
282}
283
284@new
285GraphConstructor GraphConstructor(Token startStmtToken) throws ParseException:
286{
ggalvizo08eab6f2022-04-15 15:22:00 -0700287 List<GraphConstructor.VertexConstructor> vertexConstructors = new ArrayList<GraphConstructor.VertexConstructor>();
288 List<GraphConstructor.EdgeConstructor> edgeConstructors = new ArrayList<GraphConstructor.EdgeConstructor>();
289 GraphConstructor.VertexConstructor vertexConstructor = null;
290 GraphConstructor.EdgeConstructor edgeConstructor = null;
ggalvizoab83c3b2021-12-22 14:15:50 -0800291}
292{
ggalvizo08eab6f2022-04-15 15:22:00 -0700293 vertexConstructor = GraphVertexSpecification(startStmtToken) { vertexConstructors.add(vertexConstructor); }
ggalvizoab83c3b2021-12-22 14:15:50 -0800294 ( <COMMA>
295 (
ggalvizo08eab6f2022-04-15 15:22:00 -0700296 ( vertexConstructor = GraphVertexSpecification(token) { vertexConstructors.add(vertexConstructor); } )
297 | ( edgeConstructor = GraphEdgeSpecification(token) { edgeConstructors.add(edgeConstructor); } )
ggalvizoab83c3b2021-12-22 14:15:50 -0800298 )
299 )*
300 {
ggalvizo08eab6f2022-04-15 15:22:00 -0700301 GraphConstructor graphConstructor = new GraphConstructor(vertexConstructors, edgeConstructors);
ggalvizoab83c3b2021-12-22 14:15:50 -0800302 return addSourceLocation(graphConstructor, startStmtToken);
303 }
304}
305
306@new
ggalvizo08eab6f2022-04-15 15:22:00 -0700307GraphConstructor.VertexConstructor GraphVertexSpecification(Token startStmtToken) throws ParseException:
ggalvizoab83c3b2021-12-22 14:15:50 -0800308{
309 Pair<List<Integer>, List<List<String>>> primaryKeyFields;
310 Token beginPos = null, endPos = null;
311 Expression vertexDefinitionExpr;
ggalvizo08eab6f2022-04-15 15:22:00 -0700312 ElementLabel vertexLabel;
ggalvizoab83c3b2021-12-22 14:15:50 -0800313}
314{
315 <VERTEX>
ggalvizo08eab6f2022-04-15 15:22:00 -0700316 vertexLabel = GraphVertexDefinitionPattern()
ggalvizoab83c3b2021-12-22 14:15:50 -0800317 <PRIMARY> <KEY> <LEFTPAREN> primaryKeyFields = KeyFields() <RIGHTPAREN>
318 <AS>
319 {
320 beginPos = token;
321 createNewScope();
322 }
323 (
ggalvizo08eab6f2022-04-15 15:22:00 -0700324 vertexDefinitionExpr = ViewBody() { endPos = token; }
325 | <LEFTPAREN> { beginPos = token; } vertexDefinitionExpr = ViewBody() { endPos = token; } <RIGHTPAREN>
ggalvizoab83c3b2021-12-22 14:15:50 -0800326 )
327 {
ggalvizoab83c3b2021-12-22 14:15:50 -0800328 String vDef = extractFragment(beginPos.beginLine, beginPos.beginColumn + 1, endPos.endLine, endPos.endColumn + 1);
329 removeCurrentScope();
ggalvizo08eab6f2022-04-15 15:22:00 -0700330 GraphConstructor.VertexConstructor vertexConstructor = new GraphConstructor.VertexConstructor(vertexLabel,
ggalvizoab83c3b2021-12-22 14:15:50 -0800331 primaryKeyFields.second, primaryKeyFields.first, vertexDefinitionExpr, vDef);
ggalvizo08eab6f2022-04-15 15:22:00 -0700332 return addSourceLocation(vertexConstructor, startStmtToken);
ggalvizoab83c3b2021-12-22 14:15:50 -0800333 }
334}
335
336@new
ggalvizo08eab6f2022-04-15 15:22:00 -0700337ElementLabel GraphVertexDefinitionPattern() throws ParseException:
ggalvizoab83c3b2021-12-22 14:15:50 -0800338{
339 String vertexName;
340}
341{
342 <LEFTPAREN> <COLON> vertexName = Identifier() <RIGHTPAREN>
343 {
ggalvizo08eab6f2022-04-15 15:22:00 -0700344 return new ElementLabel(vertexName);
ggalvizoab83c3b2021-12-22 14:15:50 -0800345 }
346}
347
348@new
ggalvizo08eab6f2022-04-15 15:22:00 -0700349GraphConstructor.EdgeConstructor GraphEdgeSpecification(Token startStmtToken) throws ParseException:
ggalvizoab83c3b2021-12-22 14:15:50 -0800350{
ggalvizo08eab6f2022-04-15 15:22:00 -0700351 Pair<Triple<ElementLabel, ElementLabel, ElementLabel>, Boolean> edgeDefinitionPattern;
ggalvizoab83c3b2021-12-22 14:15:50 -0800352 Pair<List<Integer>, List<List<String>>> keyFields;
353 Token beginPos = null, endPos = null;
354 Expression edgeDefinitionExpr = null;
355
356 List<Integer> destinationKeySourceIndicators = null;
357 List<Integer> sourceKeySourceIndicators = null;
ggalvizoab83c3b2021-12-22 14:15:50 -0800358 List<List<String>> destinationKeyFields = null;
359 List<List<String>> sourceKeyFields = null;
ggalvizoab83c3b2021-12-22 14:15:50 -0800360}
361{
362 <EDGE>
363 edgeDefinitionPattern = GraphEdgeDefinitionPattern()
364 (
ggalvizo08eab6f2022-04-15 15:22:00 -0700365 <SOURCE> <KEY> <LEFTPAREN> keyFields = KeyFields() <RIGHTPAREN>
366 {
367 sourceKeyFields = keyFields.second;
368 sourceKeySourceIndicators = keyFields.first;
369 }
370 <DESTINATION> <KEY> <LEFTPAREN> keyFields = KeyFields() <RIGHTPAREN>
371 {
372 destinationKeyFields = keyFields.second;
373 destinationKeySourceIndicators = keyFields.first;
374 }
375 <AS>
376 {
377 beginPos = token;
378 createNewScope();
379 }
ggalvizoab83c3b2021-12-22 14:15:50 -0800380 (
ggalvizo08eab6f2022-04-15 15:22:00 -0700381 edgeDefinitionExpr = SelectExpression(true) { endPos = token; }
382 | <LEFTPAREN> { beginPos = token; } edgeDefinitionExpr = SelectExpression(true) { endPos = token; } <RIGHTPAREN>
ggalvizoab83c3b2021-12-22 14:15:50 -0800383 )
384 )
385 {
ggalvizo08eab6f2022-04-15 15:22:00 -0700386 ElementLabel destinationLabel, edgeLabel, sourceLabel;
ggalvizoab83c3b2021-12-22 14:15:50 -0800387 if (edgeDefinitionPattern.second) { // isDirectedLeft
388 sourceLabel = edgeDefinitionPattern.first.third;
389 edgeLabel = edgeDefinitionPattern.first.second;
390 destinationLabel = edgeDefinitionPattern.first.first;
ggalvizo08eab6f2022-04-15 15:22:00 -0700391
ggalvizoab83c3b2021-12-22 14:15:50 -0800392 } else {
393 sourceLabel = edgeDefinitionPattern.first.first;
394 edgeLabel = edgeDefinitionPattern.first.second;
395 destinationLabel = edgeDefinitionPattern.first.third;
396 }
397
398 String eDef = null;
399 if (edgeDefinitionExpr != null) {
ggalvizoab83c3b2021-12-22 14:15:50 -0800400 eDef = extractFragment(beginPos.beginLine, beginPos.beginColumn + 1, endPos.endLine, endPos.endColumn + 1);
401 removeCurrentScope();
402 }
403
ggalvizo08eab6f2022-04-15 15:22:00 -0700404 GraphConstructor.EdgeConstructor edgeConstructor = new GraphConstructor.EdgeConstructor(edgeLabel, destinationLabel,
405 sourceLabel, destinationKeyFields, destinationKeySourceIndicators, sourceKeyFields, sourceKeySourceIndicators,
406 edgeDefinitionExpr, eDef);
407 return addSourceLocation(edgeConstructor, startStmtToken);
ggalvizoab83c3b2021-12-22 14:15:50 -0800408 }
409}
410
411@new
ggalvizo08eab6f2022-04-15 15:22:00 -0700412Pair<Triple<ElementLabel, ElementLabel, ElementLabel>, Boolean> GraphEdgeDefinitionPattern() throws ParseException:
ggalvizoab83c3b2021-12-22 14:15:50 -0800413{
ggalvizo08eab6f2022-04-15 15:22:00 -0700414 ElementLabel leftVertexLabel, rightVertexLabel;
ggalvizoab83c3b2021-12-22 14:15:50 -0800415 boolean isDirectedLeft;
ggalvizo08eab6f2022-04-15 15:22:00 -0700416 String edgeName;
ggalvizoab83c3b2021-12-22 14:15:50 -0800417}
418{
ggalvizo08eab6f2022-04-15 15:22:00 -0700419 leftVertexLabel = GraphVertexDefinitionPattern()
ggalvizoab83c3b2021-12-22 14:15:50 -0800420 ( <MINUS> <LEFTBRACKET> <COLON> edgeName = Identifier() <RIGHTBRACKET> <MINUS> <GT> { isDirectedLeft = false; }
421 | <LT> <MINUS> <LEFTBRACKET> <COLON> edgeName = Identifier() <RIGHTBRACKET> <MINUS> { isDirectedLeft = true; } )
ggalvizo08eab6f2022-04-15 15:22:00 -0700422 rightVertexLabel = GraphVertexDefinitionPattern()
ggalvizoab83c3b2021-12-22 14:15:50 -0800423 {
ggalvizo08eab6f2022-04-15 15:22:00 -0700424 Triple<ElementLabel, ElementLabel, ElementLabel> t = new Triple<ElementLabel, ElementLabel, ElementLabel>(
425 leftVertexLabel, new ElementLabel(edgeName), rightVertexLabel);
426 return new Pair<Triple<ElementLabel, ElementLabel, ElementLabel>, Boolean>(t, isDirectedLeft);
427 }
428}
429
430@new
431FromGraphClause FromGraphClause() throws ParseException:
432{
433 Token startToken = null;
434 GraphConstructor graphConstructor = null;
435 Pair<DataverseName, Identifier> nameComponents = null;
436 AbstractBinaryCorrelateClause correlateClause = null;
437
438 List<MatchClause> matchClauses = new ArrayList<MatchClause>();
439 List<PathPatternExpr> pathPatternExpressions = null;
440 List<AbstractBinaryCorrelateClause> correlateClauses = new ArrayList<AbstractBinaryCorrelateClause>();
441}
442{
443 <FROM> <GRAPH> { startToken = token; }
444 (
445 graphConstructor = GraphConstructor(token)
446 | nameComponents = QualifiedName()
447 )
448 <MATCH> pathPatternExpressions = PathPatternExpressions()
449 { matchClauses.add(new MatchClause(pathPatternExpressions, MatchType.LEADING)); }
450 ( LOOKAHEAD(3) // We want to avoid getting confused with the correlated clauses below.
451 (
452 <LEFT> ( <OUTER> )? <MATCH> pathPatternExpressions = PathPatternExpressions()
453 { matchClauses.add(new MatchClause(pathPatternExpressions, MatchType.LEFTOUTER)); }
454 |
455 ( <INNER> )? <MATCH> pathPatternExpressions = PathPatternExpressions()
456 { matchClauses.add(new MatchClause(pathPatternExpressions, MatchType.INNER)); }
457 )
458 )*
459 (
460 (
461 correlateClause = JoinOrUnnestClause(JoinType.INNER, UnnestType.INNER)
462 | ( <INNER> correlateClause = JoinOrUnnestClause(JoinType.INNER, UnnestType.INNER) )
463 | ( <LEFT> ( <OUTER> )? correlateClause = JoinOrUnnestClause(JoinType.LEFTOUTER, UnnestType.LEFTOUTER) )
464 | ( <RIGHT> ( <OUTER> )? correlateClause = JoinClause(JoinType.RIGHTOUTER) )
465 | ( <CROSS> correlateClause = CrossJoinClause() )
466 )
467 {
468 correlateClauses.add(correlateClause);
469 }
470 )*
471 {
472 FromGraphClause fromGraphClause;
473 if (graphConstructor == null) {
474 fromGraphClause = new FromGraphClause(nameComponents.first, nameComponents.second,
475 matchClauses, correlateClauses);
476
477 } else {
478 fromGraphClause = new FromGraphClause(graphConstructor, matchClauses, correlateClauses);
479 }
480 return addSourceLocation(fromGraphClause, startToken);
481 }
482}
483
484@new
485List<PathPatternExpr> PathPatternExpressions() throws ParseException:
486{
487 List<PathPatternExpr> pathPatternExpressions = new ArrayList<PathPatternExpr>();
488 PathPatternExpr pathPattern = null;
489 VariableExpr variableExpr = null;
490}
491{
492 pathPattern = PathPatternExpression() { pathPatternExpressions.add(pathPattern); }
493 (
494 ( <AS> )? variableExpr = Variable()
495 {
496 int index = pathPatternExpressions.size() - 1;
497 pathPatternExpressions.get(index).setVariableExpr(variableExpr);
498 }
499 )?
500 ( LOOKAHEAD(2)
501 <COMMA> pathPattern = PathPatternExpression() { pathPatternExpressions.add(pathPattern); }
502 (
503 ( <AS> )? variableExpr = Variable()
504 {
505 int index = pathPatternExpressions.size() - 1;
506 pathPatternExpressions.get(index).setVariableExpr(variableExpr);
507 }
508 )?
509 )*
510 {
511 return pathPatternExpressions;
512 }
513}
514
515@new
516PathPatternExpr PathPatternExpression() throws ParseException:
517{
518 List<VertexPatternExpr> orderedVertexExpressions = new ArrayList<VertexPatternExpr>();
519 List<EdgePatternExpr> orderedEdgeExpressions = new ArrayList<EdgePatternExpr>();
520
521 Token startToken = null, edgeStartToken = null;
522 VertexPatternExpr vertexExpr = null;
523 EdgeDescriptor edgeDescriptor = null;
524}
525{
526 vertexExpr = VertexPatternExpression()
527 {
528 startToken = token;
529 orderedVertexExpressions.add(vertexExpr);
530 }
531 (
532 edgeDescriptor = EdgeDescriptor() { edgeStartToken = token; }
533 vertexExpr = VertexPatternExpression()
534 {
535 VertexPatternExpr leftVertex = orderedVertexExpressions.get(orderedVertexExpressions.size() - 1);
536 EdgePatternExpr edgePattern = new EdgePatternExpr(leftVertex, vertexExpr, edgeDescriptor);
537 orderedEdgeExpressions.add(addSourceLocation(edgePattern, edgeStartToken));
538 orderedVertexExpressions.add(vertexExpr);
539 }
540 )*
541 {
542 PathPatternExpr pathPattern = new PathPatternExpr(orderedVertexExpressions, orderedEdgeExpressions, null);
543 return addSourceLocation(pathPattern, startToken);
544 }
545}
546
547@new
548VertexPatternExpr VertexPatternExpression() throws ParseException:
549{
550 Set<ElementLabel> vertexLabels = new HashSet<ElementLabel>();
551 VariableExpr variableExpr = null;
552 Token startToken = null;
553 String vertexLabelName;
554}
555{
556 <LEFTPAREN> { startToken = token; }
557 (
558 variableExpr = Variable()
559 )?
560 (
561 <COLON> vertexLabelName = Identifier() { vertexLabels.add(new ElementLabel(vertexLabelName)); }
562 ( <BAR> vertexLabelName = Identifier() { vertexLabels.add(new ElementLabel(vertexLabelName)); } )*
563 )?
564 <RIGHTPAREN>
565 {
566 VertexPatternExpr vertexExpression = new VertexPatternExpr(variableExpr, vertexLabels);
567 return addSourceLocation(vertexExpression, startToken);
568 }
569}
570
571@new
572EdgeDescriptor EdgeDescriptor() throws ParseException:
573{
574 Pair<Set<ElementLabel>, Pair<Integer, Integer>> edgeDetail = null;
575 Token startToken = null;
576 VariableExpr edgeVariable = null;
577
578 // We default to undirected edges.
ggalvizo01f41f42022-04-26 18:42:38 -0700579 EdgeDescriptor.EdgeDirection edgeDirection = EdgeDescriptor.EdgeDirection.UNDIRECTED;
ggalvizo08eab6f2022-04-15 15:22:00 -0700580}
581{
582 (
583 <MINUS> { startToken = token; }
584 (
585 <LEFTBRACKET>
586 (
587 edgeVariable = Variable()
588 )?
589 ( <COLON> edgeDetail = EdgeDetail() )?
590 <RIGHTBRACKET> <MINUS>
591 )?
ggalvizo01f41f42022-04-26 18:42:38 -0700592 ( <GT> { edgeDirection = EdgeDescriptor.EdgeDirection.LEFT_TO_RIGHT; } )?
ggalvizo08eab6f2022-04-15 15:22:00 -0700593 |
594 <LT> {
595 startToken = token;
ggalvizo01f41f42022-04-26 18:42:38 -0700596 edgeDirection = EdgeDescriptor.EdgeDirection.RIGHT_TO_LEFT;
ggalvizo08eab6f2022-04-15 15:22:00 -0700597 }
598 <MINUS>
599 (
600 <LEFTBRACKET>
601 (
602 edgeVariable = Variable()
603 )?
604 ( <COLON> edgeDetail = EdgeDetail() )?
605 <RIGHTBRACKET> <MINUS>
606 )?
607 )
608 {
ggalvizo01f41f42022-04-26 18:42:38 -0700609 // Edges (by default) are of pattern type EDGE and are not sub-paths.
610 EdgeDescriptor.PatternType patternType = EdgeDescriptor.PatternType.EDGE;
ggalvizo08eab6f2022-04-15 15:22:00 -0700611 Integer hopCountMin = 1;
612 Integer hopCountMax = 1;
613
614 Set<ElementLabel> labels = new HashSet<ElementLabel>();
615 if (edgeDetail != null) {
616 labels = edgeDetail.first;
617
618 // We have explicitly specified "{" and "}". Use sub-path semantics.
619 if (edgeDetail.second != null) {
ggalvizo01f41f42022-04-26 18:42:38 -0700620 patternType = EdgeDescriptor.PatternType.PATH;
ggalvizo08eab6f2022-04-15 15:22:00 -0700621 hopCountMin = edgeDetail.second.first;
622 hopCountMax = edgeDetail.second.second;
623 }
624 }
625
ggalvizo01f41f42022-04-26 18:42:38 -0700626 return new EdgeDescriptor(edgeDirection, patternType, labels, edgeVariable, hopCountMin, hopCountMax);
ggalvizo08eab6f2022-04-15 15:22:00 -0700627 }
628}
629
630@new
631Pair<Set<ElementLabel>, Pair<Integer, Integer>> EdgeDetail() throws ParseException:
632{
633 Set<ElementLabel> edgeLabels = new HashSet<ElementLabel>();
634 Pair<Integer, Integer> repetitionQuantifier = null;
635 String labelName = null;
636}
637{
638 (
639 // Note: we want to forbid LABEL_1|LABEL_2{...}.
640 LOOKAHEAD(2, <BAR>)
641 (
642 labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); }
643 <BAR> labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); }
644 ( <BAR> labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); } )*
645 )
646 |
647 (
648 labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); }
649 |
650 <LEFTPAREN>
651 labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); }
652 ( <BAR> labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); } )*
653 <RIGHTPAREN>
654 )
655 ( repetitionQuantifier = EdgeRepetitionQuantifier() )?
656 |
657 ( repetitionQuantifier = EdgeRepetitionQuantifier() )
658 )
659 {
660 return new Pair<Set<ElementLabel>, Pair<Integer, Integer>> (edgeLabels, repetitionQuantifier);
661 }
662}
663
664@new
665Pair<Integer, Integer> EdgeRepetitionQuantifier() throws ParseException:
666{
667 Integer hopCountMin = null;
668 Integer hopCountMax = null;
669}
670{
671 <LEFTBRACE>
672 ( // Note: we forbid unbounded edge repetition.
673 ( <INTEGER_LITERAL> { hopCountMin = Integer.valueOf(token.image); } )?
674 <COMMA> <INTEGER_LITERAL> { hopCountMax = Integer.valueOf(token.image); }
675 )
676 <RIGHTBRACE>
677 {
678 return new Pair<Integer, Integer>(hopCountMin, hopCountMax);
ggalvizoab83c3b2021-12-22 14:15:50 -0800679 }
680}
681
682@new
683<DEFAULT,IN_DBL_BRACE>
684TOKEN [IGNORE_CASE]:
685{
686 <DESTINATION: "destination">
687 | <EDGE: "edge">
688 | <GRAPH: "graph">
689 | <SOURCE: "source">
690 | <VERTEX: "vertex">
ggalvizo08eab6f2022-04-15 15:22:00 -0700691 | <MATCH: "match">
ggalvizoab83c3b2021-12-22 14:15:50 -0800692}
693
694@new_at_the_end
695<DEFAULT,IN_DBL_BRACE>
696TOKEN :
697{
698 <BAR: "|">
699}