| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| import org.apache.asterix.graphix.common.metadata.GraphElementIdentifier; |
| import org.apache.asterix.graphix.lang.clause.FromGraphClause; |
| import org.apache.asterix.graphix.lang.clause.GraphSelectBlock; |
| import org.apache.asterix.graphix.lang.clause.MatchClause; |
| import org.apache.asterix.graphix.lang.expression.EdgePatternExpr; |
| import org.apache.asterix.graphix.lang.expression.GraphConstructor; |
| import org.apache.asterix.graphix.lang.expression.PathPatternExpr; |
| import org.apache.asterix.graphix.lang.expression.VertexPatternExpr; |
| import org.apache.asterix.graphix.lang.optype.MatchType; |
| import org.apache.asterix.graphix.lang.statement.CreateGraphStatement; |
| import org.apache.asterix.graphix.lang.statement.DeclareGraphStatement; |
| import org.apache.asterix.graphix.lang.statement.GraphDropStatement; |
| import org.apache.asterix.graphix.lang.statement.GraphElementDeclaration; |
| import org.apache.asterix.graphix.lang.struct.EdgeDescriptor; |
| import org.apache.asterix.graphix.lang.struct.ElementLabel; |
| import org.apache.asterix.lang.sqlpp.parser.ParseException; |
| import org.apache.asterix.lang.sqlpp.parser.SqlppParseException; |
| import org.apache.asterix.lang.sqlpp.parser.Token; |
| |
| @new_at_the_class_def |
| public GraphElementDeclaration parseGraphElementBody(GraphElementIdentifier identifier) throws CompilationException { |
| return parseImpl(new ParseFunction<GraphElementDeclaration>() { |
| @Override |
| public GraphElementDeclaration parse() throws ParseException { |
| DataverseName dataverse = defaultDataverse; |
| defaultDataverse = identifier.getGraphIdentifier().getDataverseName(); |
| |
| // We borrow the ViewBody production, where we have a SelectExpression or a VariableRef. |
| createNewScope(); |
| Expression elementBodyExpr = GraphixParser.this.ViewBody(); |
| removeCurrentScope(); |
| |
| defaultDataverse = dataverse; |
| return new GraphElementDeclaration(identifier, elementBodyExpr); |
| } |
| }); |
| } |
| |
| @override |
| SelectBlock SelectBlock() throws ParseException: |
| { |
| SelectClause selectClause = null; |
| FromClause fromClause = null; |
| FromGraphClause fromGraphClause = null; |
| List<LetClause> fromLetClauses = null; |
| WhereClause whereClause = null; |
| GroupbyClause groupbyClause = null; |
| List<LetClause> gbyLetClauses = null; |
| HavingClause havingClause = null; |
| SourceLocation startSrcLoc = null; |
| |
| List<AbstractClause> fromLetWhereClauses = new ArrayList<AbstractClause>(); |
| List<AbstractClause> gbyLetHavingClauses = new ArrayList<AbstractClause>(); |
| } |
| { |
| ( |
| ( |
| selectClause = SelectClause() { startSrcLoc = selectClause.getSourceLocation(); } |
| ( |
| ( |
| ( LOOKAHEAD(2) |
| fromGraphClause = FromGraphClause() |
| | fromClause = FromClause() |
| ) |
| ( fromLetClauses = LetClause() )? |
| ( whereClause = WhereClause() )? |
| ( groupbyClause = GroupbyClause() |
| ( gbyLetClauses = LetClause() )? |
| ( havingClause = HavingClause() )? )? |
| ) |
| | |
| ( fromLetClauses = LetClause() |
| { |
| // LET without FROM -> create dummy FROM clause: FROM {{missing}} AS #0 |
| SourceLocation sourceLoc = getSourceLocation(token); |
| LiteralExpr missingExpr = new LiteralExpr(MissingLiteral.INSTANCE); |
| missingExpr.setSourceLocation(sourceLoc); |
| List<Expression> list = new ArrayList<Expression>(1); |
| list.add(missingExpr); |
| ListConstructor listExpr = new ListConstructor(ListConstructor.Type.ORDERED_LIST_CONSTRUCTOR, list); |
| listExpr.setSourceLocation(sourceLoc); |
| List<FromTerm> fromTerms = new ArrayList<FromTerm>(1); |
| VariableExpr fromVar = new VariableExpr(new VarIdentifier("#0")); |
| fromVar.setSourceLocation(sourceLoc); |
| fromTerms.add(new FromTerm(listExpr, fromVar, null, new ArrayList<AbstractBinaryCorrelateClause>())); |
| fromClause = new FromClause(fromTerms); |
| } |
| ( whereClause = WhereClause() )? |
| ) |
| )? |
| ) |
| | |
| ( |
| ( LOOKAHEAD(2) |
| fromGraphClause = FromGraphClause() { startSrcLoc = fromGraphClause.getSourceLocation(); } |
| | fromClause = FromClause() { startSrcLoc = fromClause.getSourceLocation(); } |
| ) |
| ( fromLetClauses = LetClause() )? |
| ( whereClause = WhereClause() )? |
| ( groupbyClause = GroupbyClause() |
| ( gbyLetClauses = LetClause() )? |
| ( havingClause = HavingClause() )? )? |
| selectClause = SelectClause() |
| ) |
| ) |
| { |
| if (fromLetClauses != null) { |
| fromLetWhereClauses.addAll(fromLetClauses); |
| } |
| if (whereClause != null) { |
| fromLetWhereClauses.add(whereClause); |
| } |
| if (gbyLetClauses != null) { |
| gbyLetHavingClauses.addAll(gbyLetClauses); |
| } |
| if (havingClause != null) { |
| gbyLetHavingClauses.add(havingClause); |
| } |
| |
| if (fromClause != null) { |
| SelectBlock selectBlock = new SelectBlock(selectClause, fromClause, fromLetWhereClauses, |
| groupbyClause, gbyLetHavingClauses); |
| selectBlock.setSourceLocation(startSrcLoc); |
| return selectBlock; |
| |
| } else { |
| GraphSelectBlock selectBlock = new GraphSelectBlock(selectClause, fromGraphClause, |
| fromLetWhereClauses, groupbyClause, gbyLetHavingClauses); |
| selectBlock.setSourceLocation(startSrcLoc); |
| return selectBlock; |
| } |
| } |
| } |
| |
| @override |
| Statement SingleStatement() throws ParseException: |
| { |
| Statement stmt = null; |
| } |
| { |
| ( |
| stmt = DataverseDeclaration() |
| | stmt = DeclareStatement() |
| | stmt = CreateStatement() |
| | stmt = LoadStatement() |
| | stmt = DropStatement() |
| | stmt = WriteStatement() |
| | stmt = SetStatement() |
| | stmt = InsertStatement() |
| | stmt = DeleteStatement() |
| | stmt = UpdateStatement() |
| | stmt = UpsertStatement() |
| | stmt = ConnectionStatement() |
| | stmt = CompactStatement() |
| | stmt = Query() |
| | stmt = RefreshExternalDatasetStatement() |
| ) |
| { |
| return stmt; |
| } |
| } |
| |
| @new |
| Statement DeclareStatement() throws ParseException: |
| { |
| Token startToken = null; |
| Statement stmt = null; |
| } |
| { |
| <DECLARE> { startToken = token; } |
| ( |
| stmt = FunctionDecl(startToken) |
| | stmt = GraphDecl(startToken) |
| ) |
| { |
| return stmt; |
| } |
| } |
| |
| // Note: this is the same as FunctionDeclaration in the main grammar with the <DECLARE> token removed. |
| @new |
| FunctionDecl FunctionDecl(Token startToken) throws ParseException: |
| { |
| String functionName; |
| Pair<Integer, List<Pair<VarIdentifier,TypeExpression>>> paramsWithArity = null; |
| Expression funcBody; |
| createNewScope(); |
| } |
| { |
| <FUNCTION> |
| functionName = Identifier() |
| paramsWithArity = FunctionParameters() |
| <LEFTBRACE> |
| funcBody = FunctionBody() |
| <RIGHTBRACE> |
| { |
| int arity = paramsWithArity.first; |
| List<Pair<VarIdentifier,TypeExpression>> paramList = paramsWithArity.second; |
| FunctionSignature signature = new FunctionSignature(defaultDataverse, functionName, arity); |
| getCurrentScope().addFunctionDescriptor(signature, false); |
| ensureNoTypeDeclsInFunction(functionName, paramList, null, startToken); |
| List<VarIdentifier> params = new ArrayList<VarIdentifier>(paramList.size()); |
| for (Pair<VarIdentifier,TypeExpression> p: paramList) { |
| params.add(p.getFirst()); |
| } |
| FunctionDecl stmt = new FunctionDecl(signature, params, funcBody, false); |
| removeCurrentScope(); |
| return addSourceLocation(stmt, startToken); |
| } |
| } |
| |
| @merge |
| Statement CreateStatement() throws ParseException: |
| { |
| } |
| { |
| ( |
| before: |
| after: | stmt = CreateGraphStatement(startToken, false) |
| ) |
| { |
| } |
| } |
| |
| @merge |
| Statement CreateOrReplaceStatement(Token startStmtToken) throws ParseException: |
| { |
| } |
| { |
| ( |
| before: |
| after: | stmt = CreateGraphStatement(startStmtToken, true) |
| ) |
| { |
| } |
| } |
| |
| @merge |
| Statement DropStatement() throws ParseException: |
| { |
| } |
| { |
| ( |
| before: |
| after: | stmt = DropGraphStatement(startToken) |
| ) |
| { |
| } |
| } |
| |
| @new |
| DeclareGraphStatement GraphDecl(Token startStmtToken) throws ParseException: |
| { |
| GraphConstructor graphConstructor = null; |
| String graphName = null; |
| } |
| { |
| <GRAPH> |
| graphName = Identifier() |
| <AS> graphConstructor = GraphConstructor(token) |
| { |
| DeclareGraphStatement stmt = new DeclareGraphStatement(graphName, graphConstructor); |
| return addSourceLocation(stmt, startStmtToken); |
| } |
| } |
| |
| @new |
| CreateGraphStatement CreateGraphStatement(Token startStmtToken, boolean orReplace) throws ParseException: |
| { |
| CreateGraphStatement stmt = null; |
| } |
| { |
| <GRAPH> stmt = CreateGraphSpecification(startStmtToken, orReplace) |
| { |
| return stmt; |
| } |
| } |
| |
| @new |
| CreateGraphStatement CreateGraphSpecification(Token startStmtToken, boolean orReplace) throws ParseException: |
| { |
| Pair<DataverseName, Identifier> nameComponents = null; |
| GraphConstructor graphConstructor = null; |
| boolean ifNotExists = false; |
| } |
| { |
| nameComponents = QualifiedName() |
| ifNotExists = IfNotExists() |
| { |
| if (orReplace && ifNotExists) { |
| throw new SqlppParseException(getSourceLocation(startStmtToken), "Unexpected IF NOT EXISTS"); |
| } |
| } |
| <AS> graphConstructor = GraphConstructor(token) |
| { |
| CreateGraphStatement stmt = new CreateGraphStatement(nameComponents.first, nameComponents.second.getValue(), |
| orReplace, ifNotExists, graphConstructor); |
| return addSourceLocation(stmt, startStmtToken); |
| } |
| } |
| |
| @new |
| GraphDropStatement DropGraphStatement(Token startStmtToken) throws ParseException: |
| { |
| GraphDropStatement stmt = null; |
| } |
| { |
| <GRAPH> stmt = DropGraphSpecification(startStmtToken) |
| { |
| return stmt; |
| } |
| } |
| |
| @new |
| GraphDropStatement DropGraphSpecification(Token startStmtToken) throws ParseException: |
| { |
| Pair<DataverseName, Identifier> pairId = null; |
| boolean ifExists = false; |
| } |
| { |
| pairId = QualifiedName() ifExists = IfExists() |
| { |
| GraphDropStatement stmt = new GraphDropStatement(pairId.first, pairId.second.getValue(), ifExists); |
| return addSourceLocation(stmt, startStmtToken); |
| } |
| } |
| |
| @new |
| Pair<List<Integer>, List<List<String>>> KeyFields() throws ParseException: |
| { |
| Pair<List<Integer>, List<List<String>>> keyFields = null; |
| } |
| { |
| // This is essentially an alias for the production PrimaryKeyFields. |
| keyFields = PrimaryKeyFields() |
| { |
| return keyFields; |
| } |
| } |
| |
| @new |
| GraphConstructor GraphConstructor(Token startStmtToken) throws ParseException: |
| { |
| List<GraphConstructor.VertexConstructor> vertexConstructors = new ArrayList<GraphConstructor.VertexConstructor>(); |
| List<GraphConstructor.EdgeConstructor> edgeConstructors = new ArrayList<GraphConstructor.EdgeConstructor>(); |
| GraphConstructor.VertexConstructor vertexConstructor = null; |
| GraphConstructor.EdgeConstructor edgeConstructor = null; |
| } |
| { |
| vertexConstructor = GraphVertexSpecification(startStmtToken) { vertexConstructors.add(vertexConstructor); } |
| ( <COMMA> |
| ( |
| ( vertexConstructor = GraphVertexSpecification(token) { vertexConstructors.add(vertexConstructor); } ) |
| | ( edgeConstructor = GraphEdgeSpecification(token) { edgeConstructors.add(edgeConstructor); } ) |
| ) |
| )* |
| { |
| GraphConstructor graphConstructor = new GraphConstructor(vertexConstructors, edgeConstructors); |
| return addSourceLocation(graphConstructor, startStmtToken); |
| } |
| } |
| |
| @new |
| GraphConstructor.VertexConstructor GraphVertexSpecification(Token startStmtToken) throws ParseException: |
| { |
| Pair<List<Integer>, List<List<String>>> primaryKeyFields; |
| Token beginPos = null, endPos = null; |
| Expression vertexDefinitionExpr; |
| ElementLabel vertexLabel; |
| } |
| { |
| <VERTEX> |
| vertexLabel = GraphVertexDefinitionPattern() |
| <PRIMARY> <KEY> <LEFTPAREN> primaryKeyFields = KeyFields() <RIGHTPAREN> |
| <AS> |
| { |
| beginPos = token; |
| createNewScope(); |
| } |
| ( |
| vertexDefinitionExpr = ViewBody() { endPos = token; } |
| | <LEFTPAREN> { beginPos = token; } vertexDefinitionExpr = ViewBody() { endPos = token; } <RIGHTPAREN> |
| ) |
| { |
| String vDef = extractFragment(beginPos.beginLine, beginPos.beginColumn + 1, endPos.endLine, endPos.endColumn + 1); |
| removeCurrentScope(); |
| GraphConstructor.VertexConstructor vertexConstructor = new GraphConstructor.VertexConstructor(vertexLabel, |
| primaryKeyFields.second, primaryKeyFields.first, vertexDefinitionExpr, vDef); |
| return addSourceLocation(vertexConstructor, startStmtToken); |
| } |
| } |
| |
| @new |
| ElementLabel GraphVertexDefinitionPattern() throws ParseException: |
| { |
| String vertexName; |
| } |
| { |
| <LEFTPAREN> <COLON> vertexName = Identifier() <RIGHTPAREN> |
| { |
| return new ElementLabel(vertexName); |
| } |
| } |
| |
| @new |
| GraphConstructor.EdgeConstructor GraphEdgeSpecification(Token startStmtToken) throws ParseException: |
| { |
| Pair<Triple<ElementLabel, ElementLabel, ElementLabel>, Boolean> edgeDefinitionPattern; |
| Pair<List<Integer>, List<List<String>>> keyFields; |
| Token beginPos = null, endPos = null; |
| Expression edgeDefinitionExpr = null; |
| |
| List<Integer> destinationKeySourceIndicators = null; |
| List<Integer> sourceKeySourceIndicators = null; |
| List<List<String>> destinationKeyFields = null; |
| List<List<String>> sourceKeyFields = null; |
| } |
| { |
| <EDGE> |
| edgeDefinitionPattern = GraphEdgeDefinitionPattern() |
| ( |
| <SOURCE> <KEY> <LEFTPAREN> keyFields = KeyFields() <RIGHTPAREN> |
| { |
| sourceKeyFields = keyFields.second; |
| sourceKeySourceIndicators = keyFields.first; |
| } |
| <DESTINATION> <KEY> <LEFTPAREN> keyFields = KeyFields() <RIGHTPAREN> |
| { |
| destinationKeyFields = keyFields.second; |
| destinationKeySourceIndicators = keyFields.first; |
| } |
| <AS> |
| { |
| beginPos = token; |
| createNewScope(); |
| } |
| ( |
| edgeDefinitionExpr = SelectExpression(true) { endPos = token; } |
| | <LEFTPAREN> { beginPos = token; } edgeDefinitionExpr = SelectExpression(true) { endPos = token; } <RIGHTPAREN> |
| ) |
| ) |
| { |
| ElementLabel destinationLabel, edgeLabel, sourceLabel; |
| if (edgeDefinitionPattern.second) { // isDirectedLeft |
| sourceLabel = edgeDefinitionPattern.first.third; |
| edgeLabel = edgeDefinitionPattern.first.second; |
| destinationLabel = edgeDefinitionPattern.first.first; |
| |
| } else { |
| sourceLabel = edgeDefinitionPattern.first.first; |
| edgeLabel = edgeDefinitionPattern.first.second; |
| destinationLabel = edgeDefinitionPattern.first.third; |
| } |
| |
| String eDef = null; |
| if (edgeDefinitionExpr != null) { |
| eDef = extractFragment(beginPos.beginLine, beginPos.beginColumn + 1, endPos.endLine, endPos.endColumn + 1); |
| removeCurrentScope(); |
| } |
| |
| GraphConstructor.EdgeConstructor edgeConstructor = new GraphConstructor.EdgeConstructor(edgeLabel, destinationLabel, |
| sourceLabel, destinationKeyFields, destinationKeySourceIndicators, sourceKeyFields, sourceKeySourceIndicators, |
| edgeDefinitionExpr, eDef); |
| return addSourceLocation(edgeConstructor, startStmtToken); |
| } |
| } |
| |
| @new |
| Pair<Triple<ElementLabel, ElementLabel, ElementLabel>, Boolean> GraphEdgeDefinitionPattern() throws ParseException: |
| { |
| ElementLabel leftVertexLabel, rightVertexLabel; |
| boolean isDirectedLeft; |
| String edgeName; |
| } |
| { |
| leftVertexLabel = GraphVertexDefinitionPattern() |
| ( <MINUS> <LEFTBRACKET> <COLON> edgeName = Identifier() <RIGHTBRACKET> <MINUS> <GT> { isDirectedLeft = false; } |
| | <LT> <MINUS> <LEFTBRACKET> <COLON> edgeName = Identifier() <RIGHTBRACKET> <MINUS> { isDirectedLeft = true; } ) |
| rightVertexLabel = GraphVertexDefinitionPattern() |
| { |
| Triple<ElementLabel, ElementLabel, ElementLabel> t = new Triple<ElementLabel, ElementLabel, ElementLabel>( |
| leftVertexLabel, new ElementLabel(edgeName), rightVertexLabel); |
| return new Pair<Triple<ElementLabel, ElementLabel, ElementLabel>, Boolean>(t, isDirectedLeft); |
| } |
| } |
| |
| @new |
| FromGraphClause FromGraphClause() throws ParseException: |
| { |
| Token startToken = null; |
| GraphConstructor graphConstructor = null; |
| Pair<DataverseName, Identifier> nameComponents = null; |
| AbstractBinaryCorrelateClause correlateClause = null; |
| |
| List<MatchClause> matchClauses = new ArrayList<MatchClause>(); |
| List<PathPatternExpr> pathPatternExpressions = null; |
| List<AbstractBinaryCorrelateClause> correlateClauses = new ArrayList<AbstractBinaryCorrelateClause>(); |
| } |
| { |
| <FROM> <GRAPH> { startToken = token; } |
| ( |
| graphConstructor = GraphConstructor(token) |
| | nameComponents = QualifiedName() |
| ) |
| <MATCH> pathPatternExpressions = PathPatternExpressions() |
| { matchClauses.add(new MatchClause(pathPatternExpressions, MatchType.LEADING)); } |
| ( LOOKAHEAD(3) // We want to avoid getting confused with the correlated clauses below. |
| ( |
| <LEFT> ( <OUTER> )? <MATCH> pathPatternExpressions = PathPatternExpressions() |
| { matchClauses.add(new MatchClause(pathPatternExpressions, MatchType.LEFTOUTER)); } |
| | |
| ( <INNER> )? <MATCH> pathPatternExpressions = PathPatternExpressions() |
| { matchClauses.add(new MatchClause(pathPatternExpressions, MatchType.INNER)); } |
| ) |
| )* |
| ( |
| ( |
| correlateClause = JoinOrUnnestClause(JoinType.INNER, UnnestType.INNER) |
| | ( <INNER> correlateClause = JoinOrUnnestClause(JoinType.INNER, UnnestType.INNER) ) |
| | ( <LEFT> ( <OUTER> )? correlateClause = JoinOrUnnestClause(JoinType.LEFTOUTER, UnnestType.LEFTOUTER) ) |
| | ( <RIGHT> ( <OUTER> )? correlateClause = JoinClause(JoinType.RIGHTOUTER) ) |
| | ( <CROSS> correlateClause = CrossJoinClause() ) |
| ) |
| { |
| correlateClauses.add(correlateClause); |
| } |
| )* |
| { |
| FromGraphClause fromGraphClause; |
| if (graphConstructor == null) { |
| fromGraphClause = new FromGraphClause(nameComponents.first, nameComponents.second, |
| matchClauses, correlateClauses); |
| |
| } else { |
| fromGraphClause = new FromGraphClause(graphConstructor, matchClauses, correlateClauses); |
| } |
| return addSourceLocation(fromGraphClause, startToken); |
| } |
| } |
| |
| @new |
| List<PathPatternExpr> PathPatternExpressions() throws ParseException: |
| { |
| List<PathPatternExpr> pathPatternExpressions = new ArrayList<PathPatternExpr>(); |
| PathPatternExpr pathPattern = null; |
| VariableExpr variableExpr = null; |
| } |
| { |
| pathPattern = PathPatternExpression() { pathPatternExpressions.add(pathPattern); } |
| ( |
| ( <AS> )? variableExpr = Variable() |
| { |
| int index = pathPatternExpressions.size() - 1; |
| pathPatternExpressions.get(index).setVariableExpr(variableExpr); |
| } |
| )? |
| ( LOOKAHEAD(2) |
| <COMMA> pathPattern = PathPatternExpression() { pathPatternExpressions.add(pathPattern); } |
| ( |
| ( <AS> )? variableExpr = Variable() |
| { |
| int index = pathPatternExpressions.size() - 1; |
| pathPatternExpressions.get(index).setVariableExpr(variableExpr); |
| } |
| )? |
| )* |
| { |
| return pathPatternExpressions; |
| } |
| } |
| |
| @new |
| PathPatternExpr PathPatternExpression() throws ParseException: |
| { |
| List<VertexPatternExpr> orderedVertexExpressions = new ArrayList<VertexPatternExpr>(); |
| List<EdgePatternExpr> orderedEdgeExpressions = new ArrayList<EdgePatternExpr>(); |
| |
| Token startToken = null, edgeStartToken = null; |
| VertexPatternExpr vertexExpr = null; |
| EdgeDescriptor edgeDescriptor = null; |
| } |
| { |
| vertexExpr = VertexPatternExpression() |
| { |
| startToken = token; |
| orderedVertexExpressions.add(vertexExpr); |
| } |
| ( |
| edgeDescriptor = EdgeDescriptor() { edgeStartToken = token; } |
| vertexExpr = VertexPatternExpression() |
| { |
| VertexPatternExpr leftVertex = orderedVertexExpressions.get(orderedVertexExpressions.size() - 1); |
| EdgePatternExpr edgePattern = new EdgePatternExpr(leftVertex, vertexExpr, edgeDescriptor); |
| orderedEdgeExpressions.add(addSourceLocation(edgePattern, edgeStartToken)); |
| orderedVertexExpressions.add(vertexExpr); |
| } |
| )* |
| { |
| PathPatternExpr pathPattern = new PathPatternExpr(orderedVertexExpressions, orderedEdgeExpressions, null); |
| return addSourceLocation(pathPattern, startToken); |
| } |
| } |
| |
| @new |
| VertexPatternExpr VertexPatternExpression() throws ParseException: |
| { |
| Set<ElementLabel> vertexLabels = new HashSet<ElementLabel>(); |
| VariableExpr variableExpr = null; |
| Token startToken = null; |
| String vertexLabelName; |
| } |
| { |
| <LEFTPAREN> { startToken = token; } |
| ( |
| variableExpr = Variable() |
| )? |
| ( |
| <COLON> vertexLabelName = Identifier() { vertexLabels.add(new ElementLabel(vertexLabelName)); } |
| ( <BAR> vertexLabelName = Identifier() { vertexLabels.add(new ElementLabel(vertexLabelName)); } )* |
| )? |
| <RIGHTPAREN> |
| { |
| VertexPatternExpr vertexExpression = new VertexPatternExpr(variableExpr, vertexLabels); |
| return addSourceLocation(vertexExpression, startToken); |
| } |
| } |
| |
| @new |
| EdgeDescriptor EdgeDescriptor() throws ParseException: |
| { |
| Pair<Set<ElementLabel>, Pair<Integer, Integer>> edgeDetail = null; |
| Token startToken = null; |
| VariableExpr edgeVariable = null; |
| |
| // We default to undirected edges. |
| EdgeDescriptor.EdgeDirection edgeDirection = EdgeDescriptor.EdgeDirection.UNDIRECTED; |
| } |
| { |
| ( |
| <MINUS> { startToken = token; } |
| ( |
| <LEFTBRACKET> |
| ( |
| edgeVariable = Variable() |
| )? |
| ( <COLON> edgeDetail = EdgeDetail() )? |
| <RIGHTBRACKET> <MINUS> |
| )? |
| ( <GT> { edgeDirection = EdgeDescriptor.EdgeDirection.LEFT_TO_RIGHT; } )? |
| | |
| <LT> { |
| startToken = token; |
| edgeDirection = EdgeDescriptor.EdgeDirection.RIGHT_TO_LEFT; |
| } |
| <MINUS> |
| ( |
| <LEFTBRACKET> |
| ( |
| edgeVariable = Variable() |
| )? |
| ( <COLON> edgeDetail = EdgeDetail() )? |
| <RIGHTBRACKET> <MINUS> |
| )? |
| ) |
| { |
| // Edges (by default) are of pattern type EDGE and are not sub-paths. |
| EdgeDescriptor.PatternType patternType = EdgeDescriptor.PatternType.EDGE; |
| Integer hopCountMin = 1; |
| Integer hopCountMax = 1; |
| |
| Set<ElementLabel> labels = new HashSet<ElementLabel>(); |
| if (edgeDetail != null) { |
| labels = edgeDetail.first; |
| |
| // We have explicitly specified "{" and "}". Use sub-path semantics. |
| if (edgeDetail.second != null) { |
| patternType = EdgeDescriptor.PatternType.PATH; |
| hopCountMin = edgeDetail.second.first; |
| hopCountMax = edgeDetail.second.second; |
| } |
| } |
| |
| return new EdgeDescriptor(edgeDirection, patternType, labels, edgeVariable, hopCountMin, hopCountMax); |
| } |
| } |
| |
| @new |
| Pair<Set<ElementLabel>, Pair<Integer, Integer>> EdgeDetail() throws ParseException: |
| { |
| Set<ElementLabel> edgeLabels = new HashSet<ElementLabel>(); |
| Pair<Integer, Integer> repetitionQuantifier = null; |
| String labelName = null; |
| } |
| { |
| ( |
| // Note: we want to forbid LABEL_1|LABEL_2{...}. |
| LOOKAHEAD(2, <BAR>) |
| ( |
| labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); } |
| <BAR> labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); } |
| ( <BAR> labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); } )* |
| ) |
| | |
| ( |
| labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); } |
| | |
| <LEFTPAREN> |
| labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); } |
| ( <BAR> labelName = Identifier() { edgeLabels.add(new ElementLabel(labelName)); } )* |
| <RIGHTPAREN> |
| ) |
| ( repetitionQuantifier = EdgeRepetitionQuantifier() )? |
| | |
| ( repetitionQuantifier = EdgeRepetitionQuantifier() ) |
| ) |
| { |
| return new Pair<Set<ElementLabel>, Pair<Integer, Integer>> (edgeLabels, repetitionQuantifier); |
| } |
| } |
| |
| @new |
| Pair<Integer, Integer> EdgeRepetitionQuantifier() throws ParseException: |
| { |
| Integer hopCountMin = null; |
| Integer hopCountMax = null; |
| } |
| { |
| <LEFTBRACE> |
| ( // Note: we forbid unbounded edge repetition. |
| ( <INTEGER_LITERAL> { hopCountMin = Integer.valueOf(token.image); } )? |
| <COMMA> <INTEGER_LITERAL> { hopCountMax = Integer.valueOf(token.image); } |
| ) |
| <RIGHTBRACE> |
| { |
| return new Pair<Integer, Integer>(hopCountMin, hopCountMax); |
| } |
| } |
| |
| @new |
| <DEFAULT,IN_DBL_BRACE> |
| TOKEN [IGNORE_CASE]: |
| { |
| <DESTINATION: "destination"> |
| | <EDGE: "edge"> |
| | <GRAPH: "graph"> |
| | <SOURCE: "source"> |
| | <VERTEX: "vertex"> |
| | <MATCH: "match"> |
| } |
| |
| @new_at_the_end |
| <DEFAULT,IN_DBL_BRACE> |
| TOKEN : |
| { |
| <BAR: "|"> |
| } |