//
// 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.IGraphExpr;
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.GraphDropStatement;
import org.apache.asterix.graphix.lang.statement.GraphElementDecl;
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 GraphElementDecl parseGraphElementBody(GraphElementIdentifier identifier) throws CompilationException {
    return parseImpl(new ParseFunction<GraphElementDecl>() {
        @Override
        public GraphElementDecl 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 GraphElementDecl(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;
    }
  }
}

@merge
Statement CreateStatement() throws ParseException:
{
  // merge area 1
  before:
  after:
}
{
  (
    // merge area 2
    before:
    after:    | stmt = CreateGraphStatement(startToken, false)
  )
  {
    // merge area 3
  }
}

@merge
Statement CreateOrReplaceStatement(Token startStmtToken) throws ParseException:
{
  // merge area 1
  before:
  after:
}
{
  (
    // merge area 2
    before:
    after:    | stmt = CreateGraphStatement(startStmtToken, true)
  )
  {
    // merge area 3
  }
}

@merge
Statement DropStatement() throws ParseException:
{
  // merge area 1
  before:
  after:
}
{
  (
    // merge area 2
    before:
    after:    | stmt = DropGraphStatement(startToken)
  )
  {
    // merge area 3
  }
}

@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.EdgeType edgeType = EdgeDescriptor.EdgeType.UNDIRECTED;
}
{
  (
    <MINUS> { startToken = token; }
    (
      <LEFTBRACKET>
      (
        edgeVariable = Variable()
      )?
      ( <COLON> edgeDetail = EdgeDetail() )?
      <RIGHTBRACKET> <MINUS>
    )?
    ( <GT> { edgeType = EdgeDescriptor.EdgeType.LEFT_TO_RIGHT; } )?
    |
    <LT> {
      startToken = token;
      edgeType = EdgeDescriptor.EdgeType.RIGHT_TO_LEFT;
    }
    <MINUS>
    (
      <LEFTBRACKET>
      (
        edgeVariable = Variable()
      )?
      ( <COLON> edgeDetail = EdgeDetail() )?
      <RIGHTBRACKET> <MINUS>
    )?
  )
  {
    // Edges (by default) are of class EDGE_PATTERN and are not sub-paths.
    IGraphExpr.GraphExprKind edgeClass = IGraphExpr.GraphExprKind.EDGE_PATTERN;
    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) {
        edgeClass = IGraphExpr.GraphExprKind.PATH_PATTERN;
        hopCountMin = edgeDetail.second.first;
        hopCountMax = edgeDetail.second.second;
      }
    }

    return new EdgeDescriptor(edgeType, edgeClass, 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: "|">
}