//
// 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: "|">
}