blob: 12643bf843851cd57e04de20b7092954635b9c2e [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.IGraphExpr;
30import org.apache.asterix.graphix.lang.expression.PathPatternExpr;
31import org.apache.asterix.graphix.lang.expression.VertexPatternExpr;
32import org.apache.asterix.graphix.lang.optype.MatchType;
ggalvizoab83c3b2021-12-22 14:15:50 -080033import org.apache.asterix.graphix.lang.statement.CreateGraphStatement;
34import org.apache.asterix.graphix.lang.statement.GraphDropStatement;
35import org.apache.asterix.graphix.lang.statement.GraphElementDecl;
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
43public GraphElementDecl parseGraphElementBody(GraphElementIdentifier identifier) throws CompilationException {
44 return parseImpl(new ParseFunction<GraphElementDecl>() {
45 @Override
46 public GraphElementDecl parse() throws ParseException {
47 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;
56 return new GraphElementDecl(identifier, elementBodyExpr);
57 }
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
ggalvizoab83c3b2021-12-22 14:15:50 -0800157@merge
158Statement CreateStatement() throws ParseException:
159{
160 // merge area 1
161 before:
162 after:
163}
164{
165 (
166 // merge area 2
167 before:
168 after: | stmt = CreateGraphStatement(startToken, false)
169 )
170 {
171 // merge area 3
172 }
173}
174
175@merge
176Statement CreateOrReplaceStatement(Token startStmtToken) throws ParseException:
177{
178 // merge area 1
179 before:
180 after:
181}
182{
183 (
184 // merge area 2
185 before:
186 after: | stmt = CreateGraphStatement(startStmtToken, true)
187 )
188 {
189 // merge area 3
190 }
191}
192
193@merge
194Statement DropStatement() throws ParseException:
195{
196 // merge area 1
197 before:
198 after:
199}
200{
201 (
202 // merge area 2
203 before:
204 after: | stmt = DropGraphStatement(startToken)
205 )
206 {
207 // merge area 3
208 }
209}
210
211@new
212CreateGraphStatement CreateGraphStatement(Token startStmtToken, boolean orReplace) throws ParseException:
213{
214 CreateGraphStatement stmt = null;
215}
216{
217 <GRAPH> stmt = CreateGraphSpecification(startStmtToken, orReplace)
218 {
219 return stmt;
220 }
221}
222
223@new
224CreateGraphStatement CreateGraphSpecification(Token startStmtToken, boolean orReplace) throws ParseException:
225{
226 Pair<DataverseName, Identifier> nameComponents = null;
227 GraphConstructor graphConstructor = null;
228 boolean ifNotExists = false;
229}
230{
231 nameComponents = QualifiedName()
232 ifNotExists = IfNotExists()
233 {
234 if (orReplace && ifNotExists) {
235 throw new SqlppParseException(getSourceLocation(startStmtToken), "Unexpected IF NOT EXISTS");
236 }
237 }
238 <AS> graphConstructor = GraphConstructor(token)
239 {
240 CreateGraphStatement stmt = new CreateGraphStatement(nameComponents.first, nameComponents.second.getValue(),
241 orReplace, ifNotExists, graphConstructor);
242 return addSourceLocation(stmt, startStmtToken);
243 }
244}
245
246@new
247GraphDropStatement DropGraphStatement(Token startStmtToken) throws ParseException:
248{
249 GraphDropStatement stmt = null;
250}
251{
252 <GRAPH> stmt = DropGraphSpecification(startStmtToken)
253 {
254 return stmt;
255 }
256}
257
258@new
259GraphDropStatement DropGraphSpecification(Token startStmtToken) throws ParseException:
260{
261 Pair<DataverseName, Identifier> pairId = null;
262 boolean ifExists = false;
263}
264{
265 pairId = QualifiedName() ifExists = IfExists()
266 {
267 GraphDropStatement stmt = new GraphDropStatement(pairId.first, pairId.second.getValue(), ifExists);
268 return addSourceLocation(stmt, startStmtToken);
269 }
270}
271
272@new
273Pair<List<Integer>, List<List<String>>> KeyFields() throws ParseException:
274{
275 Pair<List<Integer>, List<List<String>>> keyFields = null;
276}
277{
278 // This is essentially an alias for the production PrimaryKeyFields.
279 keyFields = PrimaryKeyFields()
280 {
281 return keyFields;
282 }
283}
284
285@new
286GraphConstructor GraphConstructor(Token startStmtToken) throws ParseException:
287{
ggalvizo08eab6f2022-04-15 15:22:00 -0700288 List<GraphConstructor.VertexConstructor> vertexConstructors = new ArrayList<GraphConstructor.VertexConstructor>();
289 List<GraphConstructor.EdgeConstructor> edgeConstructors = new ArrayList<GraphConstructor.EdgeConstructor>();
290 GraphConstructor.VertexConstructor vertexConstructor = null;
291 GraphConstructor.EdgeConstructor edgeConstructor = null;
ggalvizoab83c3b2021-12-22 14:15:50 -0800292}
293{
ggalvizo08eab6f2022-04-15 15:22:00 -0700294 vertexConstructor = GraphVertexSpecification(startStmtToken) { vertexConstructors.add(vertexConstructor); }
ggalvizoab83c3b2021-12-22 14:15:50 -0800295 ( <COMMA>
296 (
ggalvizo08eab6f2022-04-15 15:22:00 -0700297 ( vertexConstructor = GraphVertexSpecification(token) { vertexConstructors.add(vertexConstructor); } )
298 | ( edgeConstructor = GraphEdgeSpecification(token) { edgeConstructors.add(edgeConstructor); } )
ggalvizoab83c3b2021-12-22 14:15:50 -0800299 )
300 )*
301 {
ggalvizo08eab6f2022-04-15 15:22:00 -0700302 GraphConstructor graphConstructor = new GraphConstructor(vertexConstructors, edgeConstructors);
ggalvizoab83c3b2021-12-22 14:15:50 -0800303 return addSourceLocation(graphConstructor, startStmtToken);
304 }
305}
306
307@new
ggalvizo08eab6f2022-04-15 15:22:00 -0700308GraphConstructor.VertexConstructor GraphVertexSpecification(Token startStmtToken) throws ParseException:
ggalvizoab83c3b2021-12-22 14:15:50 -0800309{
310 Pair<List<Integer>, List<List<String>>> primaryKeyFields;
311 Token beginPos = null, endPos = null;
312 Expression vertexDefinitionExpr;
ggalvizo08eab6f2022-04-15 15:22:00 -0700313 ElementLabel vertexLabel;
ggalvizoab83c3b2021-12-22 14:15:50 -0800314}
315{
316 <VERTEX>
ggalvizo08eab6f2022-04-15 15:22:00 -0700317 vertexLabel = GraphVertexDefinitionPattern()
ggalvizoab83c3b2021-12-22 14:15:50 -0800318 <PRIMARY> <KEY> <LEFTPAREN> primaryKeyFields = KeyFields() <RIGHTPAREN>
319 <AS>
320 {
321 beginPos = token;
322 createNewScope();
323 }
324 (
ggalvizo08eab6f2022-04-15 15:22:00 -0700325 vertexDefinitionExpr = ViewBody() { endPos = token; }
326 | <LEFTPAREN> { beginPos = token; } vertexDefinitionExpr = ViewBody() { endPos = token; } <RIGHTPAREN>
ggalvizoab83c3b2021-12-22 14:15:50 -0800327 )
328 {
ggalvizoab83c3b2021-12-22 14:15:50 -0800329 String vDef = extractFragment(beginPos.beginLine, beginPos.beginColumn + 1, endPos.endLine, endPos.endColumn + 1);
330 removeCurrentScope();
ggalvizo08eab6f2022-04-15 15:22:00 -0700331 GraphConstructor.VertexConstructor vertexConstructor = new GraphConstructor.VertexConstructor(vertexLabel,
ggalvizoab83c3b2021-12-22 14:15:50 -0800332 primaryKeyFields.second, primaryKeyFields.first, vertexDefinitionExpr, vDef);
ggalvizo08eab6f2022-04-15 15:22:00 -0700333 return addSourceLocation(vertexConstructor, startStmtToken);
ggalvizoab83c3b2021-12-22 14:15:50 -0800334 }
335}
336
337@new
ggalvizo08eab6f2022-04-15 15:22:00 -0700338ElementLabel GraphVertexDefinitionPattern() throws ParseException:
ggalvizoab83c3b2021-12-22 14:15:50 -0800339{
340 String vertexName;
341}
342{
343 <LEFTPAREN> <COLON> vertexName = Identifier() <RIGHTPAREN>
344 {
ggalvizo08eab6f2022-04-15 15:22:00 -0700345 return new ElementLabel(vertexName);
ggalvizoab83c3b2021-12-22 14:15:50 -0800346 }
347}
348
349@new
ggalvizo08eab6f2022-04-15 15:22:00 -0700350GraphConstructor.EdgeConstructor GraphEdgeSpecification(Token startStmtToken) throws ParseException:
ggalvizoab83c3b2021-12-22 14:15:50 -0800351{
ggalvizo08eab6f2022-04-15 15:22:00 -0700352 Pair<Triple<ElementLabel, ElementLabel, ElementLabel>, Boolean> edgeDefinitionPattern;
ggalvizoab83c3b2021-12-22 14:15:50 -0800353 Pair<List<Integer>, List<List<String>>> keyFields;
354 Token beginPos = null, endPos = null;
355 Expression edgeDefinitionExpr = null;
356
357 List<Integer> destinationKeySourceIndicators = null;
358 List<Integer> sourceKeySourceIndicators = null;
ggalvizoab83c3b2021-12-22 14:15:50 -0800359 List<List<String>> destinationKeyFields = null;
360 List<List<String>> sourceKeyFields = null;
ggalvizoab83c3b2021-12-22 14:15:50 -0800361}
362{
363 <EDGE>
364 edgeDefinitionPattern = GraphEdgeDefinitionPattern()
365 (
ggalvizo08eab6f2022-04-15 15:22:00 -0700366 <SOURCE> <KEY> <LEFTPAREN> keyFields = KeyFields() <RIGHTPAREN>
367 {
368 sourceKeyFields = keyFields.second;
369 sourceKeySourceIndicators = keyFields.first;
370 }
371 <DESTINATION> <KEY> <LEFTPAREN> keyFields = KeyFields() <RIGHTPAREN>
372 {
373 destinationKeyFields = keyFields.second;
374 destinationKeySourceIndicators = keyFields.first;
375 }
376 <AS>
377 {
378 beginPos = token;
379 createNewScope();
380 }
ggalvizoab83c3b2021-12-22 14:15:50 -0800381 (
ggalvizo08eab6f2022-04-15 15:22:00 -0700382 edgeDefinitionExpr = SelectExpression(true) { endPos = token; }
383 | <LEFTPAREN> { beginPos = token; } edgeDefinitionExpr = SelectExpression(true) { endPos = token; } <RIGHTPAREN>
ggalvizoab83c3b2021-12-22 14:15:50 -0800384 )
385 )
386 {
ggalvizo08eab6f2022-04-15 15:22:00 -0700387 ElementLabel destinationLabel, edgeLabel, sourceLabel;
ggalvizoab83c3b2021-12-22 14:15:50 -0800388 if (edgeDefinitionPattern.second) { // isDirectedLeft
389 sourceLabel = edgeDefinitionPattern.first.third;
390 edgeLabel = edgeDefinitionPattern.first.second;
391 destinationLabel = edgeDefinitionPattern.first.first;
ggalvizo08eab6f2022-04-15 15:22:00 -0700392
ggalvizoab83c3b2021-12-22 14:15:50 -0800393 } else {
394 sourceLabel = edgeDefinitionPattern.first.first;
395 edgeLabel = edgeDefinitionPattern.first.second;
396 destinationLabel = edgeDefinitionPattern.first.third;
397 }
398
399 String eDef = null;
400 if (edgeDefinitionExpr != null) {
ggalvizoab83c3b2021-12-22 14:15:50 -0800401 eDef = extractFragment(beginPos.beginLine, beginPos.beginColumn + 1, endPos.endLine, endPos.endColumn + 1);
402 removeCurrentScope();
403 }
404
ggalvizo08eab6f2022-04-15 15:22:00 -0700405 GraphConstructor.EdgeConstructor edgeConstructor = new GraphConstructor.EdgeConstructor(edgeLabel, destinationLabel,
406 sourceLabel, destinationKeyFields, destinationKeySourceIndicators, sourceKeyFields, sourceKeySourceIndicators,
407 edgeDefinitionExpr, eDef);
408 return addSourceLocation(edgeConstructor, startStmtToken);
ggalvizoab83c3b2021-12-22 14:15:50 -0800409 }
410}
411
412@new
ggalvizo08eab6f2022-04-15 15:22:00 -0700413Pair<Triple<ElementLabel, ElementLabel, ElementLabel>, Boolean> GraphEdgeDefinitionPattern() throws ParseException:
ggalvizoab83c3b2021-12-22 14:15:50 -0800414{
ggalvizo08eab6f2022-04-15 15:22:00 -0700415 ElementLabel leftVertexLabel, rightVertexLabel;
ggalvizoab83c3b2021-12-22 14:15:50 -0800416 boolean isDirectedLeft;
ggalvizo08eab6f2022-04-15 15:22:00 -0700417 String edgeName;
ggalvizoab83c3b2021-12-22 14:15:50 -0800418}
419{
ggalvizo08eab6f2022-04-15 15:22:00 -0700420 leftVertexLabel = GraphVertexDefinitionPattern()
ggalvizoab83c3b2021-12-22 14:15:50 -0800421 ( <MINUS> <LEFTBRACKET> <COLON> edgeName = Identifier() <RIGHTBRACKET> <MINUS> <GT> { isDirectedLeft = false; }
422 | <LT> <MINUS> <LEFTBRACKET> <COLON> edgeName = Identifier() <RIGHTBRACKET> <MINUS> { isDirectedLeft = true; } )
ggalvizo08eab6f2022-04-15 15:22:00 -0700423 rightVertexLabel = GraphVertexDefinitionPattern()
ggalvizoab83c3b2021-12-22 14:15:50 -0800424 {
ggalvizo08eab6f2022-04-15 15:22:00 -0700425 Triple<ElementLabel, ElementLabel, ElementLabel> t = new Triple<ElementLabel, ElementLabel, ElementLabel>(
426 leftVertexLabel, new ElementLabel(edgeName), rightVertexLabel);
427 return new Pair<Triple<ElementLabel, ElementLabel, ElementLabel>, Boolean>(t, isDirectedLeft);
428 }
429}
430
431@new
432FromGraphClause FromGraphClause() throws ParseException:
433{
434 Token startToken = null;
435 GraphConstructor graphConstructor = null;
436 Pair<DataverseName, Identifier> nameComponents = null;
437 AbstractBinaryCorrelateClause correlateClause = null;
438
439 List<MatchClause> matchClauses = new ArrayList<MatchClause>();
440 List<PathPatternExpr> pathPatternExpressions = null;
441 List<AbstractBinaryCorrelateClause> correlateClauses = new ArrayList<AbstractBinaryCorrelateClause>();
442}
443{
444 <FROM> <GRAPH> { startToken = token; }
445 (
446 graphConstructor = GraphConstructor(token)
447 | nameComponents = QualifiedName()
448 )
449 <MATCH> pathPatternExpressions = PathPatternExpressions()
450 { matchClauses.add(new MatchClause(pathPatternExpressions, MatchType.LEADING)); }
451 ( LOOKAHEAD(3) // We want to avoid getting confused with the correlated clauses below.
452 (
453 <LEFT> ( <OUTER> )? <MATCH> pathPatternExpressions = PathPatternExpressions()
454 { matchClauses.add(new MatchClause(pathPatternExpressions, MatchType.LEFTOUTER)); }
455 |
456 ( <INNER> )? <MATCH> pathPatternExpressions = PathPatternExpressions()
457 { matchClauses.add(new MatchClause(pathPatternExpressions, MatchType.INNER)); }
458 )
459 )*
460 (
461 (
462 correlateClause = JoinOrUnnestClause(JoinType.INNER, UnnestType.INNER)
463 | ( <INNER> correlateClause = JoinOrUnnestClause(JoinType.INNER, UnnestType.INNER) )
464 | ( <LEFT> ( <OUTER> )? correlateClause = JoinOrUnnestClause(JoinType.LEFTOUTER, UnnestType.LEFTOUTER) )
465 | ( <RIGHT> ( <OUTER> )? correlateClause = JoinClause(JoinType.RIGHTOUTER) )
466 | ( <CROSS> correlateClause = CrossJoinClause() )
467 )
468 {
469 correlateClauses.add(correlateClause);
470 }
471 )*
472 {
473 FromGraphClause fromGraphClause;
474 if (graphConstructor == null) {
475 fromGraphClause = new FromGraphClause(nameComponents.first, nameComponents.second,
476 matchClauses, correlateClauses);
477
478 } else {
479 fromGraphClause = new FromGraphClause(graphConstructor, matchClauses, correlateClauses);
480 }
481 return addSourceLocation(fromGraphClause, startToken);
482 }
483}
484
485@new
486List<PathPatternExpr> PathPatternExpressions() throws ParseException:
487{
488 List<PathPatternExpr> pathPatternExpressions = new ArrayList<PathPatternExpr>();
489 PathPatternExpr pathPattern = null;
490 VariableExpr variableExpr = null;
491}
492{
493 pathPattern = PathPatternExpression() { pathPatternExpressions.add(pathPattern); }
494 (
495 ( <AS> )? variableExpr = Variable()
496 {
497 int index = pathPatternExpressions.size() - 1;
498 pathPatternExpressions.get(index).setVariableExpr(variableExpr);
499 }
500 )?
501 ( LOOKAHEAD(2)
502 <COMMA> pathPattern = PathPatternExpression() { pathPatternExpressions.add(pathPattern); }
503 (
504 ( <AS> )? variableExpr = Variable()
505 {
506 int index = pathPatternExpressions.size() - 1;
507 pathPatternExpressions.get(index).setVariableExpr(variableExpr);
508 }
509 )?
510 )*
511 {
512 return pathPatternExpressions;
513 }
514}
515
516@new
517PathPatternExpr PathPatternExpression() throws ParseException:
518{
519 List<VertexPatternExpr> orderedVertexExpressions = new ArrayList<VertexPatternExpr>();
520 List<EdgePatternExpr> orderedEdgeExpressions = new ArrayList<EdgePatternExpr>();
521
522 Token startToken = null, edgeStartToken = null;
523 VertexPatternExpr vertexExpr = null;
524 EdgeDescriptor edgeDescriptor = null;
525}
526{
527 vertexExpr = VertexPatternExpression()
528 {
529 startToken = token;
530 orderedVertexExpressions.add(vertexExpr);
531 }
532 (
533 edgeDescriptor = EdgeDescriptor() { edgeStartToken = token; }
534 vertexExpr = VertexPatternExpression()
535 {
536 VertexPatternExpr leftVertex = orderedVertexExpressions.get(orderedVertexExpressions.size() - 1);
537 EdgePatternExpr edgePattern = new EdgePatternExpr(leftVertex, vertexExpr, edgeDescriptor);
538 orderedEdgeExpressions.add(addSourceLocation(edgePattern, edgeStartToken));
539 orderedVertexExpressions.add(vertexExpr);
540 }
541 )*
542 {
543 PathPatternExpr pathPattern = new PathPatternExpr(orderedVertexExpressions, orderedEdgeExpressions, null);
544 return addSourceLocation(pathPattern, startToken);
545 }
546}
547
548@new
549VertexPatternExpr VertexPatternExpression() throws ParseException:
550{
551 Set<ElementLabel> vertexLabels = new HashSet<ElementLabel>();
552 VariableExpr variableExpr = null;
553 Token startToken = null;
554 String vertexLabelName;
555}
556{
557 <LEFTPAREN> { startToken = token; }
558 (
559 variableExpr = Variable()
560 )?
561 (
562 <COLON> vertexLabelName = Identifier() { vertexLabels.add(new ElementLabel(vertexLabelName)); }
563 ( <BAR> vertexLabelName = Identifier() { vertexLabels.add(new ElementLabel(vertexLabelName)); } )*
564 )?
565 <RIGHTPAREN>
566 {
567 VertexPatternExpr vertexExpression = new VertexPatternExpr(variableExpr, vertexLabels);
568 return addSourceLocation(vertexExpression, startToken);
569 }
570}
571
572@new
573EdgeDescriptor EdgeDescriptor() throws ParseException:
574{
575 Pair<Set<ElementLabel>, Pair<Integer, Integer>> edgeDetail = null;
576 Token startToken = null;
577 VariableExpr edgeVariable = null;
578
579 // We default to undirected edges.
580 EdgeDescriptor.EdgeType edgeType = EdgeDescriptor.EdgeType.UNDIRECTED;
581}
582{
583 (
584 <MINUS> { startToken = token; }
585 (
586 <LEFTBRACKET>
587 (
588 edgeVariable = Variable()
589 )?
590 ( <COLON> edgeDetail = EdgeDetail() )?
591 <RIGHTBRACKET> <MINUS>
592 )?
593 ( <GT> { edgeType = EdgeDescriptor.EdgeType.LEFT_TO_RIGHT; } )?
594 |
595 <LT> {
596 startToken = token;
597 edgeType = EdgeDescriptor.EdgeType.RIGHT_TO_LEFT;
598 }
599 <MINUS>
600 (
601 <LEFTBRACKET>
602 (
603 edgeVariable = Variable()
604 )?
605 ( <COLON> edgeDetail = EdgeDetail() )?
606 <RIGHTBRACKET> <MINUS>
607 )?
608 )
609 {
610 // Edges (by default) are of class EDGE_PATTERN and are not sub-paths.
611 IGraphExpr.GraphExprKind edgeClass = IGraphExpr.GraphExprKind.EDGE_PATTERN;
612 Integer hopCountMin = 1;
613 Integer hopCountMax = 1;
614
615 Set<ElementLabel> labels = new HashSet<ElementLabel>();
616 if (edgeDetail != null) {
617 labels = edgeDetail.first;
618
619 // We have explicitly specified "{" and "}". Use sub-path semantics.
620 if (edgeDetail.second != null) {
621 edgeClass = IGraphExpr.GraphExprKind.PATH_PATTERN;
622 hopCountMin = edgeDetail.second.first;
623 hopCountMax = edgeDetail.second.second;
624 }
625 }
626
627 return new EdgeDescriptor(edgeType, edgeClass, labels, edgeVariable, hopCountMin, hopCountMax);
628 }
629}
630
631@new
632Pair<Set<ElementLabel>, Pair<Integer, Integer>> EdgeDetail() throws ParseException:
633{
634 Set<ElementLabel> edgeLabels = new HashSet<ElementLabel>();
635 Pair<Integer, Integer> repetitionQuantifier = null;
636 String labelName = null;
637}
638{
639 (
640 // Note: we want to forbid LABEL_1|LABEL_2{...}.
641 LOOKAHEAD(2, <BAR>)
642 (
643 labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); }
644 <BAR> labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); }
645 ( <BAR> labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); } )*
646 )
647 |
648 (
649 labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); }
650 |
651 <LEFTPAREN>
652 labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); }
653 ( <BAR> labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); } )*
654 <RIGHTPAREN>
655 )
656 ( repetitionQuantifier = EdgeRepetitionQuantifier() )?
657 |
658 ( repetitionQuantifier = EdgeRepetitionQuantifier() )
659 )
660 {
661 return new Pair<Set<ElementLabel>, Pair<Integer, Integer>> (edgeLabels, repetitionQuantifier);
662 }
663}
664
665@new
666Pair<Integer, Integer> EdgeRepetitionQuantifier() throws ParseException:
667{
668 Integer hopCountMin = null;
669 Integer hopCountMax = null;
670}
671{
672 <LEFTBRACE>
673 ( // Note: we forbid unbounded edge repetition.
674 ( <INTEGER_LITERAL> { hopCountMin = Integer.valueOf(token.image); } )?
675 <COMMA> <INTEGER_LITERAL> { hopCountMax = Integer.valueOf(token.image); }
676 )
677 <RIGHTBRACE>
678 {
679 return new Pair<Integer, Integer>(hopCountMin, hopCountMax);
ggalvizoab83c3b2021-12-22 14:15:50 -0800680 }
681}
682
683@new
684<DEFAULT,IN_DBL_BRACE>
685TOKEN [IGNORE_CASE]:
686{
687 <DESTINATION: "destination">
688 | <EDGE: "edge">
689 | <GRAPH: "graph">
690 | <SOURCE: "source">
691 | <VERTEX: "vertex">
ggalvizo08eab6f2022-04-15 15:22:00 -0700692 | <MATCH: "match">
ggalvizoab83c3b2021-12-22 14:15:50 -0800693}
694
695@new_at_the_end
696<DEFAULT,IN_DBL_BRACE>
697TOKEN :
698{
699 <BAR: "|">
700}