All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opencypher.v9_0.parser.javacc.cypher.jj Maven / Gradle / Ivy

The newest version!

options {
  LOOKAHEAD = 1;
  CHOICE_AMBIGUITY_CHECK = 2;
  OTHER_AMBIGUITY_CHECK = 1;
  DEBUG_PARSER = false;
  DEBUG_LOOKAHEAD = false;
  DEBUG_TOKEN_MANAGER = false;
  ERROR_REPORTING = true;
  JAVA_UNICODE_ESCAPE = true;
  UNICODE_INPUT = false;
  IGNORE_CASE = false;
  USER_TOKEN_MANAGER = false;
  USER_CHAR_STREAM = true;
  BUILD_PARSER = true;
  BUILD_TOKEN_MANAGER = true;
  SANITY_CHECK = true;
  FORCE_LA_CHECK = false;
  TOKEN_EXTENDS = "WithOffset";
  COMMON_TOKEN_ACTION = true;
}

PARSER_BEGIN(Cypher)
/*
 * Copyright (c) Neo4j Sweden AB (http://neo4j.com)
 *
 * Licensed 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.
 */
package org.opencypher.v9_0.parser.javacc;

import scala.util.Either;
import scala.util.Left;
import scala.util.Right;

import java.util.ArrayList;
import java.util.List;
import org.opencypher.v9_0.ast.factory.ASTExceptionFactory;
import org.opencypher.v9_0.ast.factory.ASTFactory;
import org.opencypher.v9_0.ast.factory.ASTFactory.StringPos;

/** Simple brace matcher. */
public class Cypher {

    ASTExceptionFactory exceptionFactory;
    ASTFactory astFactory;

    public Cypher(ASTFactory astFactory,
                  ASTExceptionFactory exceptionFactory,
                  CharStream stream) {
        this(stream);
        this.astFactory = astFactory;
        this.exceptionFactory = exceptionFactory;
    }

  private POS pos(Token t) {
    return astFactory.inputPosition(t.beginOffset, t.beginLine, t.beginColumn);
  }
}

PARSER_END(Cypher)

TOKEN_MGR_DECLS :
{
	public void CommonTokenAction(Token t)
	{
	    CypherCharStream ccStream = (CypherCharStream)input_stream;
		t.beginOffset = ccStream.getBeginOffset();
		t.endOffset = ccStream.getEndOffset();
	}
}

SKIP :
{
  " "
| "\t"
| "\n"
| "\r"
}

/* COMMENTS */

SPECIAL_TOKEN :
{
  < SINGLE_LINE_COMMENT: "//"(~["\n","\r"])* ("\n"|"\r"|"\r\n")? >
}

MORE :
{
  <"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT
|
  "/*" : IN_MULTI_LINE_COMMENT
}


SPECIAL_TOKEN :
{
   : DEFAULT
}


SPECIAL_TOKEN :
{
   : DEFAULT
}


MORE :
{
  < ~[] >
}

/* LITERALS */

TOKEN :
{
  < DECIMAL_DOUBLE: (["+","-"])? (
                                    (["0"-"9"])+ "." (["0"-"9"])+ ()?
                                  | "." (["0"-"9"])+ ()?
                                  | (["0"-"9"])+ 
                                  ) >
|
  < #DECIMAL_EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
|
  < UNSIGNED_DECIMAL_INTEGER:
    ( ["1"-"9"] (["0"-"9"])* ) | "0" >
|
  < UNSIGNED_HEX_INTEGER: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
|
  < UNSIGNED_OCTAL_INTEGER: "0" ("o")? (["0"-"7"])+ >
}

MORE : { < STRING1_OPEN: "'" > : STRING1 }
 MORE: { "\\\\" { image.delete(image.length()-2, image.length()); image.append("\\"); } }
 MORE: { "\\\'" { image.delete(image.length()-2, image.length()); image.append("'"); } }
 MORE: { "\\\"" { image.delete(image.length()-2, image.length()); image.append("\""); } }
 MORE: { "\\b" { image.delete(image.length()-2, image.length()); image.append("\b"); } }
 MORE: { "\\f" { image.delete(image.length()-2, image.length()); image.append("\f"); } }
 MORE: { "\\n" { image.delete(image.length()-2, image.length()); image.append("\n"); } }
 MORE: { "\\r" { image.delete(image.length()-2, image.length()); image.append("\r"); } }
 MORE: { "\\t" { image.delete(image.length()-2, image.length()); image.append("\t"); } }
 MORE: { "\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]" }
 MORE: { < ~["'"] > }
 TOKEN: {  {matchedToken.image = image.substring(1, image.length()-1); } : DEFAULT }

MORE : { < STRING2_OPEN: "\"" > : STRING2 }
 MORE: { "\\\\" { image.delete(image.length()-2, image.length()); image.append("\\"); } }
 MORE: { "\\\'" { image.delete(image.length()-2, image.length()); image.append("'"); } }
 MORE: { "\\\"" { image.delete(image.length()-2, image.length()); image.append("\""); } }
 MORE: { "\\b" { image.delete(image.length()-2, image.length()); image.append("\b"); } }
 MORE: { "\\f" { image.delete(image.length()-2, image.length()); image.append("\f"); } }
 MORE: { "\\n" { image.delete(image.length()-2, image.length()); image.append("\n"); } }
 MORE: { "\\r" { image.delete(image.length()-2, image.length()); image.append("\r"); } }
 MORE: { "\\t" { image.delete(image.length()-2, image.length()); image.append("\t"); } }
 MORE: { "\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]" }
 MORE: { < ~["\""] > }
 TOKEN: {  {matchedToken.image = image.substring(1, image.length()-1); } : DEFAULT }

MORE : { < ESCAPED_SYMBOLIC_NAME_OPEN: "`" > : ESC_SYMB_NAME }
 MORE: { < ~["`"] > }
 MORE: { "``" { image.delete(image.length()-2, image.length()); image.append("`"); } }
 TOKEN: {  {matchedToken.image = image.substring(1, image.length()-1); } : DEFAULT }

/**
* add new tokens to SymbolicNameString() if they should be accepted as an identifier as well
* add new tokens to IdentifierTokens.tokens for correct filtering of identifier tokens
*/
TOKEN [IGNORE_CASE] :
{
    < ALL_SHORTEST_PATH: "allShortestPaths" >
    | < ALL: "ALL" >
    | < AND: "AND" >
    | < ANY: "ANY" >
    | < AS: "AS" >
    | < ASC: "ASC" ("ENDING")? >
    | < ASSERT: "ASSERT" >
    | < BAR: "|" >
    | < BY: "BY" >
    | < CALL: "CALL" >
    | < CASE: "CASE" >
    | < CATALOG: "CATALOG">
    | < COMMIT: "COMMIT" >
    | < CONSTRAINT: "CONSTRAINT" >
    | < CONTAINS: "CONTAINS" >
    | < COPY: "COPY" >
    | < COUNT: "count" >
    | < CREATE: "CREATE" >
    | < CSV: "CSV" >
    | < DATA: "DATA">
    | < DATABASE: "DATABASE">
    | < DATABASES: "DATABASES">
    | < DBMS: "DBMS">
    | < DEFAULT_TOKEN: "DEFAULT">
    | < DELETE: "DELETE" >
    | < DESC: "DESC" ("ENDING")? >
    | < DESTROY: "DESTROY">
    | < DETACH: "DETACH" >
    | < DISTINCT: "DISTINCT" >
    | < DIVIDE: "/" >
    | < DOT: "." >
    | < DOTDOT: ".." >
    | < DROP: "DROP" >
    | < DUMP: "DUMP">
    | < ELSE: "ELSE" >
    | < END: "END" >
    | < ENDS: "ENDS" >
    | < EQ: "=" >
    | < EQUIV: "~" >
    | < EXISTS: "EXISTS" >
    | < EXTRACT: "EXTRACT" >
    | < FALSE: "false">
    | < FIELDTERMINATOR: "FIELDTERMINATOR" >
    | < FILTER: "FILTER" >
    | < FOREACH: "FOREACH" >
    | < FROM: "FROM" >
    | < GE: ">=" >
    | < GRANT: "GRANT">
    | < GRAPH: "GRAPH" >
    | < GT: ">" >
    | < HEADERS: "HEADERS" >
    | < IF: "IF" >
    | < IN: "IN" >
    | < INDEX: "INDEX" >
    | < IS: "IS" >
    | < JOIN: "JOIN" >
    | < KEY: "KEY" >
    | < LBRACKET: "[" >
    | < LCURLY: "{" >
    | < LE: "<=" >
    | < LIMITROWS: "LIMIT" >
    | < LOAD: "LOAD" >
    | < LPAREN: "(" >
    | < LT: "<" >
    | < MATCH: "MATCH" >
    | < MERGE: "MERGE" >
    | < MINUS: "-" >
    | < MODULO: "%" >
    | < NEQ: "!=" >
    | < NEQ2: "<>" >
    | < NODE: "NODE" >
    | < NONE: "NONE" >
    | < NOT: "NOT" >
    | < NOWAIT: "NOWAIT">
    | < NULL: "null">
    | < OF: "OF" >
    | < ON: "ON" >
    | < OPTIONAL: "OPTIONAL" >
    | < OR: "OR" >
    | < ORDER: "ORDER" >
    | < PERIODIC: "PERIODIC" >
    | < PLUS: "+" >
    | < POPULATED: "POPULATED">
    | < POW: "^" >
    | < RBRACKET: "]" >
    | < RCURLY: "}" >
    | < REDUCE: "REDUCE" >
    | < REGEQ: "=~" >
    | < REMOVE: "REMOVE" >
    | < REPLACE: "REPLACE" >
    | < RETURN: "RETURN" >
    | < REVOKE: "REVOKE">
    | < ROLE: "ROLE">
    | < ROLES: "ROLES">
    | < RPAREN: ")" >
    | < SCAN: "SCAN" >
    | < SEC: "SEC">
    | < SECOND: "SECOND">
    | < SECONDS: "SECONDS">
    | < SEEK: "SEEK" >
    | < SET: "SET" >
    | < SHORTEST_PATH: "shortestPath" >
    | < SHOW: "SHOW">
    | < SINGLE: "SINGLE" >
    | < SKIPROWS: "SKIP" >
    | < START: "START">
    | < STARTS: "STARTS" >
    | < STOP: "STOP">
    | < THEN: "THEN" >
    | < TIMES: "*" >
    | < TO: "TO" >
    | < TRUE: "true">
    | < UNION: "UNION" >
    | < UNIQUE: "UNIQUE" >
    | < UNWIND: "UNWIND" >
    | < USE: "USE" >
    | < USERS: "USERS">
    | < USING: "USING" >
    | < WAIT: "WAIT">
    | < WHEN: "WHEN" >
    | < WHERE: "WHERE" >
    | < WITH: "WITH" >
    | < XOR: "XOR" >
    | < YIELD: "YIELD" >
}

/* IDENTIFIERS */

TOKEN :
{
  < IDENTIFIER:  ()* >
|
  < #LETTER:
      [  // all chars for which Character.isIdentifierStart is true except `$`
         "A"-"Z",
         "_",
         "a"-"z",
         "\u00a2"-"\u00a5",
         "\u00aa",
         "\u00b5",
         "\u00ba",
         "\u00c0"-"\u00d6",
         "\u00d8"-"\u00f6",
         "\u00f8"-"\u021f",
         "\u0222"-"\u0233",
         "\u0250"-"\u02ad",
         "\u02b0"-"\u02b8",
         "\u02bb"-"\u02c1",
         "\u02d0"-"\u02d1",
         "\u02e0"-"\u02e4",
         "\u02ee",
         "\u037a",
         "\u0386",
         "\u0388"-"\u038a",
         "\u038c",
         "\u038e"-"\u03a1",
         "\u03a3"-"\u03ce",
         "\u03d0"-"\u03d7",
         "\u03da"-"\u03f3",
         "\u0400"-"\u0481",
         "\u048c"-"\u04c4",
         "\u04c7"-"\u04c8",
         "\u04cb"-"\u04cc",
         "\u04d0"-"\u04f5",
         "\u04f8"-"\u04f9",
         "\u0531"-"\u0556",
         "\u0559",
         "\u0561"-"\u0587",
         "\u05d0"-"\u05ea",
         "\u05f0"-"\u05f2",
         "\u0621"-"\u063a",
         "\u0640"-"\u064a",
         "\u0671"-"\u06d3",
         "\u06d5",
         "\u06e5"-"\u06e6",
         "\u06fa"-"\u06fc",
         "\u0710",
         "\u0712"-"\u072c",
         "\u0780"-"\u07a5",
         "\u0905"-"\u0939",
         "\u093d",
         "\u0950",
         "\u0958"-"\u0961",
         "\u0985"-"\u098c",
         "\u098f"-"\u0990",
         "\u0993"-"\u09a8",
         "\u09aa"-"\u09b0",
         "\u09b2",
         "\u09b6"-"\u09b9",
         "\u09dc"-"\u09dd",
         "\u09df"-"\u09e1",
         "\u09f0"-"\u09f3",
         "\u0a05"-"\u0a0a",
         "\u0a0f"-"\u0a10",
         "\u0a13"-"\u0a28",
         "\u0a2a"-"\u0a30",
         "\u0a32"-"\u0a33",
         "\u0a35"-"\u0a36",
         "\u0a38"-"\u0a39",
         "\u0a59"-"\u0a5c",
         "\u0a5e",
         "\u0a72"-"\u0a74",
         "\u0a85"-"\u0a8b",
         "\u0a8d",
         "\u0a8f"-"\u0a91",
         "\u0a93"-"\u0aa8",
         "\u0aaa"-"\u0ab0",
         "\u0ab2"-"\u0ab3",
         "\u0ab5"-"\u0ab9",
         "\u0abd",
         "\u0ad0",
         "\u0ae0",
         "\u0b05"-"\u0b0c",
         "\u0b0f"-"\u0b10",
         "\u0b13"-"\u0b28",
         "\u0b2a"-"\u0b30",
         "\u0b32"-"\u0b33",
         "\u0b36"-"\u0b39",
         "\u0b3d",
         "\u0b5c"-"\u0b5d",
         "\u0b5f"-"\u0b61",
         "\u0b85"-"\u0b8a",
         "\u0b8e"-"\u0b90",
         "\u0b92"-"\u0b95",
         "\u0b99"-"\u0b9a",
         "\u0b9c",
         "\u0b9e"-"\u0b9f",
         "\u0ba3"-"\u0ba4",
         "\u0ba8"-"\u0baa",
         "\u0bae"-"\u0bb5",
         "\u0bb7"-"\u0bb9",
         "\u0c05"-"\u0c0c",
         "\u0c0e"-"\u0c10",
         "\u0c12"-"\u0c28",
         "\u0c2a"-"\u0c33",
         "\u0c35"-"\u0c39",
         "\u0c60"-"\u0c61",
         "\u0c85"-"\u0c8c",
         "\u0c8e"-"\u0c90",
         "\u0c92"-"\u0ca8",
         "\u0caa"-"\u0cb3",
         "\u0cb5"-"\u0cb9",
         "\u0cde",
         "\u0ce0"-"\u0ce1",
         "\u0d05"-"\u0d0c",
         "\u0d0e"-"\u0d10",
         "\u0d12"-"\u0d28",
         "\u0d2a"-"\u0d39",
         "\u0d60"-"\u0d61",
         "\u0d85"-"\u0d96",
         "\u0d9a"-"\u0db1",
         "\u0db3"-"\u0dbb",
         "\u0dbd",
         "\u0dc0"-"\u0dc6",
         "\u0e01"-"\u0e30",
         "\u0e32"-"\u0e33",
         "\u0e3f"-"\u0e46",
         "\u0e81"-"\u0e82",
         "\u0e84",
         "\u0e87"-"\u0e88",
         "\u0e8a",
         "\u0e8d",
         "\u0e94"-"\u0e97",
         "\u0e99"-"\u0e9f",
         "\u0ea1"-"\u0ea3",
         "\u0ea5",
         "\u0ea7",
         "\u0eaa"-"\u0eab",
         "\u0ead"-"\u0eb0",
         "\u0eb2"-"\u0eb3",
         "\u0ebd",
         "\u0ec0"-"\u0ec4",
         "\u0ec6",
         "\u0edc"-"\u0edd",
         "\u0f00",
         "\u0f40"-"\u0f47",
         "\u0f49"-"\u0f6a",
         "\u0f88"-"\u0f8b",
         "\u1000"-"\u1021",
         "\u1023"-"\u1027",
         "\u1029"-"\u102a",
         "\u1050"-"\u1055",
         "\u10a0"-"\u10c5",
         "\u10d0"-"\u10f6",
         "\u1100"-"\u1159",
         "\u115f"-"\u11a2",
         "\u11a8"-"\u11f9",
         "\u1200"-"\u1206",
         "\u1208"-"\u1246",
         "\u1248",
         "\u124a"-"\u124d",
         "\u1250"-"\u1256",
         "\u1258",
         "\u125a"-"\u125d",
         "\u1260"-"\u1286",
         "\u1288",
         "\u128a"-"\u128d",
         "\u1290"-"\u12ae",
         "\u12b0",
         "\u12b2"-"\u12b5",
         "\u12b8"-"\u12be",
         "\u12c0",
         "\u12c2"-"\u12c5",
         "\u12c8"-"\u12ce",
         "\u12d0"-"\u12d6",
         "\u12d8"-"\u12ee",
         "\u12f0"-"\u130e",
         "\u1310",
         "\u1312"-"\u1315",
         "\u1318"-"\u131e",
         "\u1320"-"\u1346",
         "\u1348"-"\u135a",
         "\u13a0"-"\u13f4",
         "\u1401"-"\u166c",
         "\u166f"-"\u1676",
         "\u1681"-"\u169a",
         "\u16a0"-"\u16ea",
         "\u1780"-"\u17b3",
         "\u17db",
         "\u1820"-"\u1877",
         "\u1880"-"\u18a8",
         "\u1e00"-"\u1e9b",
         "\u1ea0"-"\u1ef9",
         "\u1f00"-"\u1f15",
         "\u1f18"-"\u1f1d",
         "\u1f20"-"\u1f45",
         "\u1f48"-"\u1f4d",
         "\u1f50"-"\u1f57",
         "\u1f59",
         "\u1f5b",
         "\u1f5d",
         "\u1f5f"-"\u1f7d",
         "\u1f80"-"\u1fb4",
         "\u1fb6"-"\u1fbc",
         "\u1fbe",
         "\u1fc2"-"\u1fc4",
         "\u1fc6"-"\u1fcc",
         "\u1fd0"-"\u1fd3",
         "\u1fd6"-"\u1fdb",
         "\u1fe0"-"\u1fec",
         "\u1ff2"-"\u1ff4",
         "\u1ff6"-"\u1ffc",
         "\u203f"-"\u2040",
         "\u207f",
         "\u20a0"-"\u20af",
         "\u2102",
         "\u2107",
         "\u210a"-"\u2113",
         "\u2115",
         "\u2119"-"\u211d",
         "\u2124",
         "\u2126",
         "\u2128",
         "\u212a"-"\u212d",
         "\u212f"-"\u2131",
         "\u2133"-"\u2139",
         "\u2160"-"\u2183",
         "\u3005"-"\u3007",
         "\u3021"-"\u3029",
         "\u3031"-"\u3035",
         "\u3038"-"\u303a",
         "\u3041"-"\u3094",
         "\u309d"-"\u309e",
         "\u30a1"-"\u30fe",
         "\u3105"-"\u312c",
         "\u3131"-"\u318e",
         "\u31a0"-"\u31b7",
         "\u3400"-"\u4db5",
         "\u4e00"-"\u9fa5",
         "\ua000"-"\ua48c",
         "\uac00"-"\ud7a3",
         "\uf900"-"\ufa2d",
         "\ufb00"-"\ufb06",
         "\ufb13"-"\ufb17",
         "\ufb1d",
         "\ufb1f"-"\ufb28",
         "\ufb2a"-"\ufb36",
         "\ufb38"-"\ufb3c",
         "\ufb3e",
         "\ufb40"-"\ufb41",
         "\ufb43"-"\ufb44",
         "\ufb46"-"\ufbb1",
         "\ufbd3"-"\ufd3d",
         "\ufd50"-"\ufd8f",
         "\ufd92"-"\ufdc7",
         "\ufdf0"-"\ufdfb",
         "\ufe33"-"\ufe34",
         "\ufe4d"-"\ufe4f",
         "\ufe69",
         "\ufe70"-"\ufe72",
         "\ufe74",
         "\ufe76"-"\ufefc",
         "\uff04",
         "\uff21"-"\uff3a",
         "\uff3f",
         "\uff41"-"\uff5a",
         "\uff65"-"\uffbe",
         "\uffc2"-"\uffc7",
         "\uffca"-"\uffcf",
         "\uffd2"-"\uffd7",
         "\uffda"-"\uffdc",
         "\uffe0"-"\uffe1",
         "\uffe5"-"\uffe6"
      ]
  >
|
  < #PART_LETTER:
      [  // all chars for which Character.isIdentifierPart is true
         "\u0000"-"\u0008",
         "\u000e"-"\u001b",
         "0"-"9",
         "A"-"Z",
         "_",
         "a"-"z",
         "\u007f"-"\u009f",
         "\u00a2"-"\u00a5",
         "\u00aa",
         "\u00b5",
         "\u00ba",
         "\u00c0"-"\u00d6",
         "\u00d8"-"\u00f6",
         "\u00f8"-"\u021f",
         "\u0222"-"\u0233",
         "\u0250"-"\u02ad",
         "\u02b0"-"\u02b8",
         "\u02bb"-"\u02c1",
         "\u02d0"-"\u02d1",
         "\u02e0"-"\u02e4",
         "\u02ee",
         "\u0300"-"\u034e",
         "\u0360"-"\u0362",
         "\u037a",
         "\u0386",
         "\u0388"-"\u038a",
         "\u038c",
         "\u038e"-"\u03a1",
         "\u03a3"-"\u03ce",
         "\u03d0"-"\u03d7",
         "\u03da"-"\u03f3",
         "\u0400"-"\u0481",
         "\u0483"-"\u0486",
         "\u048c"-"\u04c4",
         "\u04c7"-"\u04c8",
         "\u04cb"-"\u04cc",
         "\u04d0"-"\u04f5",
         "\u04f8"-"\u04f9",
         "\u0531"-"\u0556",
         "\u0559",
         "\u0561"-"\u0587",
         "\u0591"-"\u05a1",
         "\u05a3"-"\u05b9",
         "\u05bb"-"\u05bd",
         "\u05bf",
         "\u05c1"-"\u05c2",
         "\u05c4",
         "\u05d0"-"\u05ea",
         "\u05f0"-"\u05f2",
         "\u0621"-"\u063a",
         "\u0640"-"\u0655",
         "\u0660"-"\u0669",
         "\u0670"-"\u06d3",
         "\u06d5"-"\u06dc",
         "\u06df"-"\u06e8",
         "\u06ea"-"\u06ed",
         "\u06f0"-"\u06fc",
         "\u070f"-"\u072c",
         "\u0730"-"\u074a",
         "\u0780"-"\u07b0",
         "\u0901"-"\u0903",
         "\u0905"-"\u0939",
         "\u093c"-"\u094d",
         "\u0950"-"\u0954",
         "\u0958"-"\u0963",
         "\u0966"-"\u096f",
         "\u0981"-"\u0983",
         "\u0985"-"\u098c",
         "\u098f"-"\u0990",
         "\u0993"-"\u09a8",
         "\u09aa"-"\u09b0",
         "\u09b2",
         "\u09b6"-"\u09b9",
         "\u09bc",
         "\u09be"-"\u09c4",
         "\u09c7"-"\u09c8",
         "\u09cb"-"\u09cd",
         "\u09d7",
         "\u09dc"-"\u09dd",
         "\u09df"-"\u09e3",
         "\u09e6"-"\u09f3",
         "\u0a02",
         "\u0a05"-"\u0a0a",
         "\u0a0f"-"\u0a10",
         "\u0a13"-"\u0a28",
         "\u0a2a"-"\u0a30",
         "\u0a32"-"\u0a33",
         "\u0a35"-"\u0a36",
         "\u0a38"-"\u0a39",
         "\u0a3c",
         "\u0a3e"-"\u0a42",
         "\u0a47"-"\u0a48",
         "\u0a4b"-"\u0a4d",
         "\u0a59"-"\u0a5c",
         "\u0a5e",
         "\u0a66"-"\u0a74",
         "\u0a81"-"\u0a83",
         "\u0a85"-"\u0a8b",
         "\u0a8d",
         "\u0a8f"-"\u0a91",
         "\u0a93"-"\u0aa8",
         "\u0aaa"-"\u0ab0",
         "\u0ab2"-"\u0ab3",
         "\u0ab5"-"\u0ab9",
         "\u0abc"-"\u0ac5",
         "\u0ac7"-"\u0ac9",
         "\u0acb"-"\u0acd",
         "\u0ad0",
         "\u0ae0",
         "\u0ae6"-"\u0aef",
         "\u0b01"-"\u0b03",
         "\u0b05"-"\u0b0c",
         "\u0b0f"-"\u0b10",
         "\u0b13"-"\u0b28",
         "\u0b2a"-"\u0b30",
         "\u0b32"-"\u0b33",
         "\u0b36"-"\u0b39",
         "\u0b3c"-"\u0b43",
         "\u0b47"-"\u0b48",
         "\u0b4b"-"\u0b4d",
         "\u0b56"-"\u0b57",
         "\u0b5c"-"\u0b5d",
         "\u0b5f"-"\u0b61",
         "\u0b66"-"\u0b6f",
         "\u0b82"-"\u0b83",
         "\u0b85"-"\u0b8a",
         "\u0b8e"-"\u0b90",
         "\u0b92"-"\u0b95",
         "\u0b99"-"\u0b9a",
         "\u0b9c",
         "\u0b9e"-"\u0b9f",
         "\u0ba3"-"\u0ba4",
         "\u0ba8"-"\u0baa",
         "\u0bae"-"\u0bb5",
         "\u0bb7"-"\u0bb9",
         "\u0bbe"-"\u0bc2",
         "\u0bc6"-"\u0bc8",
         "\u0bca"-"\u0bcd",
         "\u0bd7",
         "\u0be7"-"\u0bef",
         "\u0c01"-"\u0c03",
         "\u0c05"-"\u0c0c",
         "\u0c0e"-"\u0c10",
         "\u0c12"-"\u0c28",
         "\u0c2a"-"\u0c33",
         "\u0c35"-"\u0c39",
         "\u0c3e"-"\u0c44",
         "\u0c46"-"\u0c48",
         "\u0c4a"-"\u0c4d",
         "\u0c55"-"\u0c56",
         "\u0c60"-"\u0c61",
         "\u0c66"-"\u0c6f",
         "\u0c82"-"\u0c83",
         "\u0c85"-"\u0c8c",
         "\u0c8e"-"\u0c90",
         "\u0c92"-"\u0ca8",
         "\u0caa"-"\u0cb3",
         "\u0cb5"-"\u0cb9",
         "\u0cbe"-"\u0cc4",
         "\u0cc6"-"\u0cc8",
         "\u0cca"-"\u0ccd",
         "\u0cd5"-"\u0cd6",
         "\u0cde",
         "\u0ce0"-"\u0ce1",
         "\u0ce6"-"\u0cef",
         "\u0d02"-"\u0d03",
         "\u0d05"-"\u0d0c",
         "\u0d0e"-"\u0d10",
         "\u0d12"-"\u0d28",
         "\u0d2a"-"\u0d39",
         "\u0d3e"-"\u0d43",
         "\u0d46"-"\u0d48",
         "\u0d4a"-"\u0d4d",
         "\u0d57",
         "\u0d60"-"\u0d61",
         "\u0d66"-"\u0d6f",
         "\u0d82"-"\u0d83",
         "\u0d85"-"\u0d96",
         "\u0d9a"-"\u0db1",
         "\u0db3"-"\u0dbb",
         "\u0dbd",
         "\u0dc0"-"\u0dc6",
         "\u0dca",
         "\u0dcf"-"\u0dd4",
         "\u0dd6",
         "\u0dd8"-"\u0ddf",
         "\u0df2"-"\u0df3",
         "\u0e01"-"\u0e3a",
         "\u0e3f"-"\u0e4e",
         "\u0e50"-"\u0e59",
         "\u0e81"-"\u0e82",
         "\u0e84",
         "\u0e87"-"\u0e88",
         "\u0e8a",
         "\u0e8d",
         "\u0e94"-"\u0e97",
         "\u0e99"-"\u0e9f",
         "\u0ea1"-"\u0ea3",
         "\u0ea5",
         "\u0ea7",
         "\u0eaa"-"\u0eab",
         "\u0ead"-"\u0eb9",
         "\u0ebb"-"\u0ebd",
         "\u0ec0"-"\u0ec4",
         "\u0ec6",
         "\u0ec8"-"\u0ecd",
         "\u0ed0"-"\u0ed9",
         "\u0edc"-"\u0edd",
         "\u0f00",
         "\u0f18"-"\u0f19",
         "\u0f20"-"\u0f29",
         "\u0f35",
         "\u0f37",
         "\u0f39",
         "\u0f3e"-"\u0f47",
         "\u0f49"-"\u0f6a",
         "\u0f71"-"\u0f84",
         "\u0f86"-"\u0f8b",
         "\u0f90"-"\u0f97",
         "\u0f99"-"\u0fbc",
         "\u0fc6",
         "\u1000"-"\u1021",
         "\u1023"-"\u1027",
         "\u1029"-"\u102a",
         "\u102c"-"\u1032",
         "\u1036"-"\u1039",
         "\u1040"-"\u1049",
         "\u1050"-"\u1059",
         "\u10a0"-"\u10c5",
         "\u10d0"-"\u10f6",
         "\u1100"-"\u1159",
         "\u115f"-"\u11a2",
         "\u11a8"-"\u11f9",
         "\u1200"-"\u1206",
         "\u1208"-"\u1246",
         "\u1248",
         "\u124a"-"\u124d",
         "\u1250"-"\u1256",
         "\u1258",
         "\u125a"-"\u125d",
         "\u1260"-"\u1286",
         "\u1288",
         "\u128a"-"\u128d",
         "\u1290"-"\u12ae",
         "\u12b0",
         "\u12b2"-"\u12b5",
         "\u12b8"-"\u12be",
         "\u12c0",
         "\u12c2"-"\u12c5",
         "\u12c8"-"\u12ce",
         "\u12d0"-"\u12d6",
         "\u12d8"-"\u12ee",
         "\u12f0"-"\u130e",
         "\u1310",
         "\u1312"-"\u1315",
         "\u1318"-"\u131e",
         "\u1320"-"\u1346",
         "\u1348"-"\u135a",
         "\u1369"-"\u1371",
         "\u13a0"-"\u13f4",
         "\u1401"-"\u166c",
         "\u166f"-"\u1676",
         "\u1681"-"\u169a",
         "\u16a0"-"\u16ea",
         "\u1780"-"\u17d3",
         "\u17db",
         "\u17e0"-"\u17e9",
         "\u180b"-"\u180e",
         "\u1810"-"\u1819",
         "\u1820"-"\u1877",
         "\u1880"-"\u18a9",
         "\u1e00"-"\u1e9b",
         "\u1ea0"-"\u1ef9",
         "\u1f00"-"\u1f15",
         "\u1f18"-"\u1f1d",
         "\u1f20"-"\u1f45",
         "\u1f48"-"\u1f4d",
         "\u1f50"-"\u1f57",
         "\u1f59",
         "\u1f5b",
         "\u1f5d",
         "\u1f5f"-"\u1f7d",
         "\u1f80"-"\u1fb4",
         "\u1fb6"-"\u1fbc",
         "\u1fbe",
         "\u1fc2"-"\u1fc4",
         "\u1fc6"-"\u1fcc",
         "\u1fd0"-"\u1fd3",
         "\u1fd6"-"\u1fdb",
         "\u1fe0"-"\u1fec",
         "\u1ff2"-"\u1ff4",
         "\u1ff6"-"\u1ffc",
         "\u200c"-"\u200f",
         "\u202a"-"\u202e",
         "\u203f"-"\u2040",
         "\u206a"-"\u206f",
         "\u207f",
         "\u20a0"-"\u20af",
         "\u20d0"-"\u20dc",
         "\u20e1",
         "\u2102",
         "\u2107",
         "\u210a"-"\u2113",
         "\u2115",
         "\u2119"-"\u211d",
         "\u2124",
         "\u2126",
         "\u2128",
         "\u212a"-"\u212d",
         "\u212f"-"\u2131",
         "\u2133"-"\u2139",
         "\u2160"-"\u2183",
         "\u3005"-"\u3007",
         "\u3021"-"\u302f",
         "\u3031"-"\u3035",
         "\u3038"-"\u303a",
         "\u3041"-"\u3094",
         "\u3099"-"\u309a",
         "\u309d"-"\u309e",
         "\u30a1"-"\u30fe",
         "\u3105"-"\u312c",
         "\u3131"-"\u318e",
         "\u31a0"-"\u31b7",
         "\u3400"-"\u4db5",
         "\u4e00"-"\u9fa5",
         "\ua000"-"\ua48c",
         "\uac00"-"\ud7a3",
         "\uf900"-"\ufa2d",
         "\ufb00"-"\ufb06",
         "\ufb13"-"\ufb17",
         "\ufb1d"-"\ufb28",
         "\ufb2a"-"\ufb36",
         "\ufb38"-"\ufb3c",
         "\ufb3e",
         "\ufb40"-"\ufb41",
         "\ufb43"-"\ufb44",
         "\ufb46"-"\ufbb1",
         "\ufbd3"-"\ufd3d",
         "\ufd50"-"\ufd8f",
         "\ufd92"-"\ufdc7",
         "\ufdf0"-"\ufdfb",
         "\ufe20"-"\ufe23",
         "\ufe33"-"\ufe34",
         "\ufe4d"-"\ufe4f",
         "\ufe69",
         "\ufe70"-"\ufe72",
         "\ufe74",
         "\ufe76"-"\ufefc",
         "\ufeff",
         "\uff04",
         "\uff10"-"\uff19",
         "\uff21"-"\uff3a",
         "\uff3f",
         "\uff41"-"\uff5a",
         "\uff65"-"\uffbe",
         "\uffc2"-"\uffc7",
         "\uffca"-"\uffcf",
         "\uffd2"-"\uffd7",
         "\uffda"-"\uffdc",
         "\uffe0"-"\uffe1",
         "\uffe5"-"\uffe6",
         "\ufff9"-"\ufffb"
      ]
  >
}

TOKEN :
{
  < ARROW_LINE: ["\u002d", "\u00ad", "\u2010", "\u2011", "\u2012", "\u2013", "\u2014", "\u2015", "\ufe58", "\ufe63", "\uff0d"] >
| < ARROW_LEFT_HEAD: ["\u27e8", "\u3008", "\ufe64", "\uff1c"] >
| < ARROW_RIGHT_HEAD: ["\u27e9", "\u3009", "\ufe65", "\uff1e"] >
}

<*> TOKEN : {  }

/** Root production. */
List Statements() throws Exception :
{
  STATEMENT x;
  List stmts = new ArrayList<>();
}
{
  try {
    x=Statement() { stmts.add(x); }
    ( LOOKAHEAD(2) ";" x=Statement() { stmts.add(x); } )* ( LOOKAHEAD(2) ";" )? 
    { return stmts; }
  } catch (ParseException e) {
    Token t = e.currentToken.next;
    if (e.getMessage().contains( "Encountered \"\"" )) {
        throw exceptionFactory.syntaxException(t.image, ParseExceptions.expected(e.expectedTokenSequences, e.tokenImage), e,
                                               t.endOffset + 1, t.endLine, t.endColumn + 1);
    } else  {
        throw exceptionFactory.syntaxException(t.image, ParseExceptions.expected(e.expectedTokenSequences, e.tokenImage), e,
                                               t.beginOffset, t.beginLine, t.beginColumn);
    }
  } catch (InvalidUnicodeLiteral e) {
    throw exceptionFactory.syntaxException(e, e.offset, e.line, e.column);
  }
}

STATEMENT Statement() :
{
    STATEMENT statement;
    USE_CLAUSE useClause = null;
}
{
    (
        statement=PeriodicCommitQuery()
        | ( useClause = UseClause() )? statement=SingleQueryOrAdministrationCommand(useClause)
    )
    {
        return statement;
    }
}

STATEMENT SingleQueryOrAdministrationCommand(USE_CLAUSE useClause):
{
    STATEMENT statement = null;
    QUERY query = null;
}
{
    (
        LOOKAHEAD(2) statement=CreateAdministrationCommand(useClause)
        | statement=AdministrationCommand(useClause)
        | query=SingleQuery(useClause) ( query=Union(query) )*
    )
    {
        if (query != null) {
            return query;
        }
        return statement;
    }
}

QUERY PeriodicCommitQuery() :
{
  Token t;
  Token batchSize = null;
  CLAUSE loadCsv;
  List queryBody;
}
{
   t=  ( batchSize= )?
  loadCsv=LoadCSVClause()
  queryBody=PeriodicCommitQueryBody()
  { return astFactory.periodicCommitQuery(pos(t), batchSize == null ? null : batchSize.image, loadCsv, queryBody); }
}

List PeriodicCommitQueryBody() :
{
  CLAUSE x;
  List clauses = new ArrayList<>();
}
{
  ( x=Clause() { clauses.add(x); } )*
  { return clauses; }
}

QUERY RegularQuery() :
{QUERY x;}
{
  x=SingleQuery(null) ( x=Union(x) )*
  { return x; }
}

QUERY Union(QUERY lhs) :
{
  Token t;
  QUERY rhs;
  boolean all = false;
}
{
  t= (  { all = true; } )? rhs=SingleQuery(null)
  { return astFactory.newUnion(pos(t), lhs, rhs, all); }
}

QUERY SingleQuery(CLAUSE useClause) :
{
  CLAUSE x;
  List clauses = new ArrayList<>();
  if (useClause != null) {
      clauses.add(useClause);
  }
}
{
  ( x=Clause() { clauses.add(x); } )+
  { return astFactory.newSingleQuery(clauses); }
}

CLAUSE Clause() :
{CLAUSE x = null;}
{
  (
    x=FromClause()
  | x=UseClause()
  | x=ReturnClause()
  | x=CreateClause() // because create index/constraint
  | x=DeleteClause()
  | x=SetClause()
  | x=RemoveClause()
  | x=MatchClause()
  | x=MergeClause()
  | x=WithClause()
  | x=UnwindClause()
  | LOOKAHEAD(2) x=CallClause() // because subqueries also start with CALL
  | x=SubqueryClause()
  | x=LoadCSVClause()
  | x=ForeachClause()
  )
  { return x; }
}

// FROM & USE

CLAUSE FromClause() :
{
  Token t;
  EXPRESSION e;
}
{
  t= ( LOOKAHEAD(2)  )? e=Expression()
  { return astFactory.fromClause(pos(t), e); }
}

USE_CLAUSE UseClause() :
{
  Token t;
  EXPRESSION e;
}
{
  t= ( LOOKAHEAD(2)  )? e=Expression()
  { return astFactory.useClause(pos(t), e); }
}

// RETURN

CLAUSE ReturnClause() :
{
  Token t;
  CLAUSE clause;
}
{
  t=
  (
    LOOKAHEAD(2) t= { return astFactory.newReturnGraphClause(pos(t)); }
  | clause=ReturnBody(t) { return clause; }
  )
}

RETURN_CLAUSE ReturnWithoutGraphClause() :
{
  Token t;
  RETURN_CLAUSE clause = null;
}
{
  t=
  clause=ReturnBody(t)
  {
    return clause;
  }
}

RETURN_CLAUSE ReturnBody(Token t) :
{
  boolean distinct = false;
  boolean returnAll = false;
  List order = new ArrayList<>();
  EXPRESSION skip = null;
  EXPRESSION limit = null;
  RETURN_ITEM x;
  List returnItems = new ArrayList<>();
}
{
  ( LOOKAHEAD(2)  { distinct = true; } )?
  (
            { returnAll = true; }      ( "," x=ReturnItem() { returnItems.add(x); } )*
  | x=ReturnItem() { returnItems.add(x); } ( "," x=ReturnItem() { returnItems.add(x); } )*
  ) ( order=Order() )? ( skip=Skip() )? ( limit=Limit() )?
  {
    return astFactory.newReturnClause(pos(t), distinct, returnAll, returnItems, order, skip, limit);
  }
}

RETURN_ITEM ReturnItem() :
{
  EXPRESSION e;
  VARIABLE v = null;
  Token eStart;
  Token eEnd;
}
{
  { eStart = token; }
  e=Expression() { eEnd = token; } (  v=Variable() )?
  {
    if (v != null) {
        return astFactory.newReturnItem(pos(eStart), e, v);
    }
    else {
        return astFactory.newReturnItem(pos(eStart), e, eStart.next.beginOffset, eEnd.endOffset );
    }
  }
}

List Order() :
{
  ORDER_ITEM o;
  List items = new ArrayList<>();
}
{
    o=OrderItem() {items.add(o);} ( "," o=OrderItem() {items.add(o);} )*
  { return items; }
}

ORDER_ITEM OrderItem() :
{EXPRESSION e;}
{
  e=Expression()
  (
     { return astFactory.orderDesc(e); }
  | (  )? { return astFactory.orderAsc(e); }
  )
}

EXPRESSION Skip() :
{ EXPRESSION e; }
{
   e=Expression()
  { return e; }
}

EXPRESSION Limit() :
{ EXPRESSION e; }
{
   e=Expression()
  { return e; }
}

// WITH

CLAUSE WithClause() :
{
  Token t;
  RETURN_CLAUSE returnClause;
  EXPRESSION where = null;
}
{
  t= returnClause=ReturnBody(t) ( where=Where() )?
  { return astFactory.withClause(pos(t), returnClause, where); }
}

// CREATE

CLAUSE CreateClause() :
{
 Token t;
 List patterns;
}
{
  t= patterns=PatternList()
  { return astFactory.createClause(pos(t), patterns); }
}

// SET

SET_CLAUSE SetClause() :
{
  Token t;
  SET_ITEM x;
  List items = new ArrayList<>();
}
{
  t= x=SetItem() {items.add(x);} ( "," x=SetItem() {items.add(x);} )*
  { return astFactory.setClause(pos(t), items); }
}

SET_ITEM SetItem() :
{
 EXPRESSION e;
 PROPERTY p;
 VARIABLE v;
 List> labels; }
{
  LOOKAHEAD(2) p=PropertyExpression()  e=Expression() { return astFactory.setProperty(p, e); }
| LOOKAHEAD(2) v=Variable()  e=Expression() { return astFactory.setVariable(v, e); }
| LOOKAHEAD(2) v=Variable() "+=" e=Expression() { return astFactory.addAndSetVariable(v, e); }
| v=Variable() labels=NodeLabels() { return astFactory.setLabels(v, labels); }
}

// REMOVE

CLAUSE RemoveClause() :
{
  Token t;
  REMOVE_ITEM x;
  List items = new ArrayList<>();
}
{
  t= x=RemoveItem() { items.add(x); } ( "," x=RemoveItem() { items.add(x); })*
  { return astFactory.removeClause(pos(t), items); }
}

REMOVE_ITEM RemoveItem() :
{
 EXPRESSION e;
 PROPERTY p;
 VARIABLE v;
 List> labels; }
{
  LOOKAHEAD(2) p=PropertyExpression() { return astFactory.removeProperty(p); }
| v=Variable() labels=NodeLabels() { return astFactory.removeLabels(v, labels); }
}

// DELETE

CLAUSE DeleteClause() :
{
  Token t;
  boolean detach = false;
  EXPRESSION e;
  List list = new ArrayList<>();
}
{
  (  {detach=true;} )? t= e=Expression() {list.add(e);} ( "," e=Expression() {list.add(e);} )*
  { return astFactory.deleteClause(pos(t), detach, list); }
}

// MATCH

CLAUSE MatchClause() :
{
  Token t;
  boolean optional = false;
  List patterns;
  List hints;
  EXPRESSION where = null;
}
{
  (  {optional = true;} )? t= patterns=PatternList() hints=Hints() ( where=Where() )?
  { return astFactory.matchClause(pos(t), optional, patterns, hints, where); }
}

List Hints() :
{
  Token t;
    boolean seek;
    VARIABLE v;
    Token label;
    List propNames;
    List joinVariables;
  HINT h;
  List hints = null;
}
{
  ( t= (
       {seek=false;} ( LOOKAHEAD(2)  {seek=true;} )? v=Variable() label=NodeLabel()
         propNames=SymbolicNameList1() 
        { h=astFactory.usingIndexHint(pos(t), v, label.image, propNames, seek); }
    |   joinVariables=VariableList1() { h=astFactory.usingJoin(pos(t), joinVariables); }
    |  v=Variable() label=NodeLabel() { h=astFactory.usingScan(pos(t), v, label.image); }
    )
    {
        if (hints == null) {
            hints = new ArrayList<>();
        }
        hints.add(h);
    }
  )*
  { return hints; }
}

// MERGE

CLAUSE MergeClause() :
{
  Token t;
  PATTERN p;
  SET_CLAUSE c;
  ArrayList clauses = new ArrayList<>();
  ArrayList actionTypes = new ArrayList<>();
}
{
  t= p=Pattern()
  (
     (
      c=SetClause() {clauses.add(c); actionTypes.add(ASTFactory.MergeActionType.OnMatch);}
    |  c=SetClause() {clauses.add(c); actionTypes.add(ASTFactory.MergeActionType.OnCreate);}
    )
  )*
  { return astFactory.mergeClause(pos(t), p, clauses, actionTypes); }
}

// UNWIND

CLAUSE UnwindClause() :
{Token t; EXPRESSION e; VARIABLE v;}
{
  t= e=Expression()  v=Variable()
  { return astFactory.unwindClause(pos(t), e, v); }
}

// CALL

CLAUSE CallClause() :
{
  Token t;
  List namespace;
  String name;
  EXPRESSION e;
  List arguments = null;
  boolean yieldAll = false;
  CALL_RESULT_ITEM x;
  List items = null;
  EXPRESSION where = null;
}
{
  t= namespace=Namespace() name=ProcedureName()
  (  { arguments = new ArrayList<>(); }
    ( LOOKAHEAD(2) e=Expression() { arguments.add(e); })? ( "," e=Expression() { arguments.add(e); })*
    
  )?
  ( (  {yieldAll = true;} |
    { items = new ArrayList<>(); }
        x=ProcedureResultItem() { items.add(x); }
        ( "," x=ProcedureResultItem() { items.add(x); })*
        ( where=Where() )?
  ))?
  {
    return astFactory.callClause(pos(t),
                                namespace,
                                name,
                                arguments,
                                yieldAll,
                                items,
                                where);
  }
}

String ProcedureName() :
{ Token t; }
{
  t=SymbolicNameString()
  { return t.image; }
}

CALL_RESULT_ITEM ProcedureResultItem() :
{
  Token t;
  VARIABLE v = null;
}
{
  t=SymbolicNameString() (  v=Variable() )?
  {
    return astFactory.callResultItem(pos(t), t.image,  v);
  }
}

// LOAD CSV

CLAUSE LoadCSVClause() :
{
  Token t;
  boolean headers = false;
  EXPRESSION source;
  VARIABLE v;
  Token sep = null;
}
{
  t= 
  (   {headers=true;} )?
   source=Expression()  v=Variable()
  (  ( sep= | sep= ) )?
  {
    return astFactory.loadCsvClause(pos(t), headers, source, v, sep == null ? null : sep.image );
  }
}

// FOREACH

CLAUSE ForeachClause() :
{
  Token t;
  VARIABLE v;
  EXPRESSION list;
  CLAUSE c;
  List clauses = new ArrayList<>();
}
{
  t=  v=Variable()  list=Expression() 
  ( c=Clause() { clauses.add(c); } )+
  
  { return astFactory.foreachClause(pos(t), v, list, clauses); }
}

CLAUSE SubqueryClause() :
{
  Token t;
  QUERY q;
}
{
  t=
  
  ( q=PeriodicCommitQuery() | q=RegularQuery() )
  
  { return astFactory.subqueryClause(pos(t), q); }
}

// WHERE

EXPRESSION Where() :
{ EXPRESSION e; }
{
   e=Expression()
  { return e; }
}

// PATTERN

List PatternList() :
{
  PATTERN p;
  List patterns = new ArrayList<>();
}
{
  p=Pattern() {patterns.add(p);} ( "," p=Pattern() {patterns.add(p);} )*
  { return patterns; }
}

PATTERN Pattern() :
{
  VARIABLE v;
  PATTERN p;
}
{
  LOOKAHEAD(2) v=Variable()  p=AnonymousPattern() { return astFactory.namedPattern(v, p); }
| p=AnonymousPattern() { return p; }
}

PATTERN AnonymousPattern() :
{PATTERN p;}
{
  (
    p=ShortestPathPattern()
  | LOOKAHEAD(3) p=EveryPathPattern()
  |  p=AnonymousPattern() 
  )
  { return p; }
}

PATTERN ShortestPathPattern() :
{ Token t; PATTERN p; }
{
  t=  p=EveryPathPattern()  { return astFactory.shortestPathPattern(pos(t), p); }
| t=  p=EveryPathPattern()  { return astFactory.allShortestPathsPattern(pos(t), p); }
}

PATTERN EveryPathPattern() :
{
  NODE_PATTERN n;
  REL_PATTERN r;
  List relationships = new ArrayList<>();
  List nodes = new ArrayList<>();
}
{
  n=NodePattern() {nodes.add(n);} ( LOOKAHEAD(2) r=RelationshipPattern() {relationships.add(r);} n=NodePattern() {nodes.add(n);} )*
  { return astFactory.everyPathPattern(nodes, relationships); }
}

PATTERN EveryPathPatternNonEmpty() :
{
  NODE_PATTERN n;
  REL_PATTERN r;
  List relationships = new ArrayList<>();
  List nodes = new ArrayList<>();
}
{
  n=NodePattern() {nodes.add(n);} ( LOOKAHEAD(2) r=RelationshipPattern() {relationships.add(r);} n=NodePattern() {nodes.add(n);} )+
  { return astFactory.everyPathPattern(nodes, relationships); }
}

NODE_PATTERN NodePattern() :
{
  Token t;
  VARIABLE v = null;
  List> labels = new ArrayList<>();
  EXPRESSION properties = null;
}
{
  t= ( v=Variable() )? ( labels=NodeLabels() )? ( properties=Properties() )? 
  { return astFactory.nodePattern(pos(t), v, labels, properties); }
}

List> NodeLabels() :
{
  Token label;
  List> labels = new ArrayList<>();
}
{
  ( LOOKAHEAD(2) label=NodeLabel() { labels.add(new StringPos<>(label.image, pos(label))); } )+
  { return labels; }
}

EXPRESSION HasLabels(EXPRESSION subject) :
{
  List> labels;
}
{
  labels=NodeLabels()
  { return astFactory.hasLabelsOrTypes(subject, labels); }
}

Token NodeLabel() :
{Token t;}
{
  ":" t=SymbolicNameString()
  {return t;}
}

EXPRESSION Properties() :
{ EXPRESSION e; }
{
  (
    LOOKAHEAD(3) e=MapLiteral()
  | e=Parameter()
  | e=OldParameter()
  )
  { return e; }
}

REL_PATTERN RelationshipPattern() :
{
  Token firstToken = token.next;
  Token t;
  boolean left = false;
  boolean right = false;
  VARIABLE v = null;
  List> relTypes = new ArrayList<>();
  boolean legacyTypeSeparator = false;
  PATH_LENGTH pathLength = null;
  EXPRESSION properties = null;
}
{
  ( LeftArrow() { left = true; })? ArrowLine()
  (  ( v=Variable() )?
    ( ":" t=SymbolicNameString()
        {
                relTypes = new ArrayList<>();
                relTypes.add(new StringPos<>(t.image, pos(t)));
        }
        (  ( ":" {legacyTypeSeparator = true; })? t=SymbolicNameString() { relTypes.add(new StringPos<>(t.image, pos(t))); })*
    )?
    ( pathLength=PathLength() )?
    ( properties=Properties() )?
    
  )?
  ArrowLine() ( RightArrow() { right = true; } )?
  { return astFactory.relationshipPattern(pos(firstToken), left, right, v, relTypes, pathLength, properties, legacyTypeSeparator); }
}

void LeftArrow() :
{}
{
   | 
}

void ArrowLine() :
{}
{
   | 
}

void RightArrow() :
{}
{
   | 
}

PATH_LENGTH PathLength() :
{ Token t; PATH_LENGTH p = null; }
{
  t= (
    p=PathLengthLiteral(t)
  )?
  { return p == null ? astFactory.pathLength(pos(t), null, null) : p; }
}

PATH_LENGTH PathLengthLiteral(Token t) :
{
  Token v1 = null;
  Token v2 = null;
}
{
  LOOKAHEAD(2) ( v1= )?  ( v2= )?
    { return astFactory.pathLength(pos(t), v1 == null ? "" : v1.image, v2 == null ? "" : v2.image); }
| v1=
    { String v = v1 == null ? "" : v1.image; return astFactory.pathLength(pos(t), v, v); }
}

// EXPRESSIONS

EXPRESSION Expression() :
{EXPRESSION e;}
{
  e=Expression12()
  {return e;}
}

EXPRESSION Expression12() :
{
  Token t;
  EXPRESSION e;
  EXPRESSION temp;
}
{
  e=Expression11() (t= temp=Expression11() { e = astFactory.or(pos(t), e, temp); } )*
  {return e;}
}

EXPRESSION Expression11() :
{
  Token t;
  EXPRESSION e;
  EXPRESSION temp;
}
{
  e=Expression10() (t= temp=Expression10() { e = astFactory.xor(pos(t), e, temp); } )*
  {return e;}
}

EXPRESSION Expression10() :
{
  Token t;
  EXPRESSION e;
  EXPRESSION temp;
}
{
  e=Expression9() (t= temp=Expression9() { e = astFactory.and(pos(t), e, temp); } )*
  {return e;}
}

EXPRESSION Expression9() :
{
  EXPRESSION e;
}
{
  (
    LOOKAHEAD(3)  e=Expression9() { e = astFactory.not(e); }
  | e=Expression8()
  )
  { return e; }
}

EXPRESSION Expression8() :
{
  Token t;
  EXPRESSION e;
  EXPRESSION lhs;
  EXPRESSION rhs;
  List expressions = null;
}
{
  e=Expression7() {lhs = e;} ( LOOKAHEAD(2)
      t=  rhs=Expression7() { if (expressions == null) {expressions = new ArrayList<>();} expressions.add(astFactory.eq(pos(t), lhs, rhs)); lhs = rhs; }
    | t= rhs=Expression7() { if (expressions == null) {expressions = new ArrayList<>();} expressions.add(astFactory.neq(pos(t), lhs, rhs)); lhs = rhs; }
    | t= rhs=Expression7() { if (expressions == null) {expressions = new ArrayList<>();} expressions.add(astFactory.neq2(pos(t), lhs, rhs)); lhs = rhs; }
    | t= rhs=Expression7() { if (expressions == null) {expressions = new ArrayList<>();} expressions.add(astFactory.lte(pos(t), lhs, rhs)); lhs = rhs; }
    | t= rhs=Expression7() { if (expressions == null) {expressions = new ArrayList<>();} expressions.add(astFactory.gte(pos(t), lhs, rhs)); lhs = rhs; }
    | t=  rhs=Expression7() { if (expressions == null) {expressions = new ArrayList<>();} expressions.add(astFactory.lt(pos(t), lhs, rhs)); lhs = rhs; }
    | t=  rhs=Expression7() { if (expressions == null) {expressions = new ArrayList<>();} expressions.add(astFactory.gt(pos(t), lhs, rhs)); lhs = rhs; }
  )*
  {
    if (expressions == null) return e;
    else if (expressions.size() == 1) return expressions.get(0);
    else return astFactory.ands(expressions);
  }
}

EXPRESSION Expression7() :
{
  EXPRESSION e;
}
{
  e=Expression6() ( e=ComparisonExpression6(e) )?
  { return e; }
}

EXPRESSION ComparisonExpression6(EXPRESSION lhs) :
{
  Token t;
  EXPRESSION rhs;
}
{
  LOOKAHEAD(2)
  t= rhs=Expression6() { return astFactory.regeq(pos(t), lhs, rhs); }
| t=  rhs=Expression6() { return astFactory.startsWith(pos(t), lhs, rhs); }
| t=  rhs=Expression6() { return astFactory.endsWith(pos(t), lhs, rhs); }
| t= rhs=Expression6() { return astFactory.contains(pos(t), lhs, rhs); }
| t= rhs=Expression6() { return astFactory.in(pos(t), lhs, rhs); }
| t= (
     { return astFactory.isNull(lhs); }
  |   { return astFactory.not(astFactory.isNull(lhs)); }
  )
}

EXPRESSION Expression6() :
{
  Token t;
  EXPRESSION lhs;
  EXPRESSION rhs;
}
{
  lhs=Expression5() (
    t= rhs=Expression5() { lhs = astFactory.plus(pos(t), lhs, rhs); }
  | t= rhs=Expression5() { lhs = astFactory.minus(pos(t), lhs, rhs); }
  )*
  { return lhs; }
}

EXPRESSION Expression5() :
{
  Token t;
  EXPRESSION lhs;
  EXPRESSION rhs;
}
{
  lhs=Expression4() (
    t= rhs=Expression4() { lhs = astFactory.multiply(pos(t), lhs, rhs); }
  | t= rhs=Expression4() { lhs = astFactory.divide(pos(t), lhs, rhs); }
  | t= rhs=Expression4() { lhs = astFactory.modulo(pos(t), lhs, rhs); }
  )*
  { return lhs; }
}

EXPRESSION Expression4() :
{
  Token t;
  EXPRESSION lhs;
  EXPRESSION rhs;
}
{
  lhs=Expression3() ( t= rhs=Expression3() { lhs = astFactory.pow(pos(t), lhs, rhs); } )*
  { return lhs; }
}

EXPRESSION Expression3() :
{
  EXPRESSION e;
}
{
  (
    LOOKAHEAD(3) e=Expression2()
  |  e=Expression2() { e = astFactory.unaryPlus(e); }
  |  e=Expression2() { e = astFactory.unaryMinus(e); }
  )
  { return e; }
}

EXPRESSION Expression2() :
{
  EXPRESSION e;
}
{
  e=Expression1() ( e=PostFix1(e) )*
  { return e; }
}

EXPRESSION PostFix1(EXPRESSION subject) :
{
  Token t;
  EXPRESSION e1 = null;
  EXPRESSION e2 = null;
  EXPRESSION ret;
}
{
  (
    ret=Property(subject)
  | ret=HasLabels(subject)
  | LOOKAHEAD( Expression() )  e1=Expression()  { ret=astFactory.listLookup(subject, e1); }
  | t= ( e1=Expression() )?  ( e2=Expression() )?  { ret=astFactory.listSlice(pos(t), subject, e1, e2); }
  )
  { return ret; }
}

PROPERTY Property(EXPRESSION subject) :
{
  EXPRESSION e;
  StringPos propKeyName;
}
{
   propKeyName=PropertyKeyName() { return astFactory.property(subject, propKeyName); }
}

PROPERTY PropertyExpression() :
{
  EXPRESSION subject;
  PROPERTY p;
}
{
  subject=Expression1() ( p=Property(subject) { subject = p; } )+
  { return p; }
}

EXPRESSION Expression1() :
{EXPRESSION e = null; Token t;}
{
  (
    e=NumberLiteral()
  | e=StringLiteral()
  | e=Parameter()
  | t= { e = astFactory.newTrueLiteral(pos(t)); }
  | t= { e = astFactory.newFalseLiteral(pos(t)); }
  | LOOKAHEAD(2) t= { e = astFactory.newNullLiteral(pos(t)); }
  | LOOKAHEAD(3) e=CaseExpression()
  | LOOKAHEAD(3) t=    { e = astFactory.newCountStar(pos(t)); }
  | LOOKAHEAD(3) e=MapLiteral()
  | LOOKAHEAD(3) e=ExistsSubQuery() // `exists { match` should not be a map-projection
  | LOOKAHEAD(2) e=MapProjection()
  | e=OldParameter()
  | LOOKAHEAD(3) e=ListComprehension() // before literal because it takes precedence
  | LOOKAHEAD(PatternComprehensionPrefix()) e=PatternComprehension() // Only after matching up to "WHERE" or "|" can we be sure it is a PatternComprehension and not a ListLiteral.
  | LOOKAHEAD(3) e=ListLiteral()
  | LOOKAHEAD(3) e=FilterExpression()
  | LOOKAHEAD(3) e=ExtractExpression()
  | LOOKAHEAD(3) e=ReduceExpression()
  | LOOKAHEAD(3) e=AllExpression()
  | LOOKAHEAD(3) e=AnyExpression()
  | LOOKAHEAD(3) e=NoneExpression()
  | LOOKAHEAD(3) e=SingleExpression()
  | LOOKAHEAD(NodePattern() RelationshipPattern()) e=PatternExpression()
  | LOOKAHEAD(2) e=ShortestPathExpression()
  |  e=Expression() 
  | LOOKAHEAD((SymbolicNameString() )* SymbolicNameString() ) e=FunctionInvocation()
  | e=Variable()
  )
  { return e; }
}

EXPRESSION CaseExpression() :
{
  Token t;
  EXPRESSION e = null;
  EXPRESSION x;
  List when = new ArrayList<>();
  List then = new ArrayList<>();
  EXPRESSION elseCase = null;
}
{
  t= (
    LOOKAHEAD(2) e=Expression() 
  |  )
  x=Expression() {when.add(x);}  x=Expression() {then.add(x);}
  (  x=Expression() {when.add(x);}  x=Expression() {then.add(x);} )*
  (  elseCase=Expression() )?
  
  { return astFactory.caseExpression(pos(t), e, when, then, elseCase); }
}

EXPRESSION ListComprehension() :
{
  Token t;
  VARIABLE v;
  EXPRESSION e;
  EXPRESSION where = null;
  EXPRESSION projection = null;
}
{
  t= v=Variable()  e=Expression() ( where=Where() )? (  projection=Expression() )? 
  { return astFactory.listComprehension(pos(t), v, e, where, projection); }
}

EXPRESSION PatternComprehension() :
{
  Token t;
  VARIABLE v = null;
  PATTERN p;
  EXPRESSION where = null;
  EXPRESSION projection = null;
}
{
  t= ( v=Variable()  )? p=EveryPathPatternNonEmpty() ( where=Where() )?  projection=Expression() 
  { return astFactory.patternComprehension(pos(t), v, p, where, projection); }
}

void PatternComprehensionPrefix() :
{}
{
   ( Variable()  )? EveryPathPattern() ( | )
}

EXPRESSION FilterExpression() :
{
  Token t;
  VARIABLE v;
  EXPRESSION e;
  EXPRESSION where = null;
}
{
  t=  v=Variable()  e=Expression() ( where=Where() )? 
  { return astFactory.filterExpression(pos(t), v, e, where); }
}

EXPRESSION ExtractExpression() :
{
  Token t;
  VARIABLE v;
  EXPRESSION e;
  EXPRESSION where = null;
  EXPRESSION projection = null;
}
{
  t=  v=Variable()  e=Expression() ( where=Where() )? (  projection=Expression() )? 
  { return astFactory.extractExpression(pos(t), v, e, where, projection); }
}

EXPRESSION ReduceExpression() :
{
  Token t;
  VARIABLE acc;
  EXPRESSION accExpr;
  VARIABLE v;
  EXPRESSION vExpr;
  EXPRESSION innerExpr;
}
{
  t= 
    acc=Variable()  accExpr=Expression()
    "," v=Variable()  vExpr=Expression()
     innerExpr=Expression()
  
  { return astFactory.reduceExpression(pos(t), acc, accExpr, v, vExpr, innerExpr); }
}

EXPRESSION AllExpression() :
{
  Token t;
  VARIABLE v;
  EXPRESSION e;
  EXPRESSION where = null;
}
{
  t=  v=Variable()  e=Expression() ( where=Where() )? 
  { return astFactory.allExpression(pos(t), v, e, where); }
}

EXPRESSION AnyExpression() :
{
  Token t;
  VARIABLE v;
  EXPRESSION e;
  EXPRESSION where = null;
}
{
  t=  v=Variable()  e=Expression() ( where=Where() )? 
  { return astFactory.anyExpression(pos(t), v, e, where); }
}

EXPRESSION NoneExpression() :
{
  Token t;
  VARIABLE v;
  EXPRESSION e;
  EXPRESSION where = null;
}
{
  t=  v=Variable()  e=Expression() ( where=Where() )? 
  { return astFactory.noneExpression(pos(t), v, e, where); }
}

EXPRESSION SingleExpression() :
{
  Token t;
  VARIABLE v;
  EXPRESSION e;
  EXPRESSION where = null;
}
{
  t=  v=Variable()  e=Expression() ( where=Where() )? 
  { return astFactory.singleExpression(pos(t), v, e, where); }
}

EXPRESSION PatternExpression() :
{ PATTERN p; Token t; }
{
  { t = token; }
  p=EveryPathPatternNonEmpty()
  { return astFactory.patternExpression(pos(t.next), p); }
}

EXPRESSION ShortestPathExpression() :
{ PATTERN p; Token t; }
{
  { t = token; }
  p=ShortestPathPattern()
  { return astFactory.patternExpression(pos(t.next), p); }
}

EXPRESSION MapProjection() :
{
  Token t;
  VARIABLE v;
  MAP_PROJECTION_ITEM x;
  List items = new ArrayList<>();
}
{
  v=Variable() t= ( x=MapProjectionItem() {items.add(x);} )? ( "," x=MapProjectionItem() {items.add(x);} )* 
  { return astFactory.mapProjection(pos(t), v, items); }
}

MAP_PROJECTION_ITEM MapProjectionItem() :
{
  Token t;
  StringPos p;
  EXPRESSION e;
  VARIABLE v;
}
{
  LOOKAHEAD(2) p=PropertyKeyName() ":" e=Expression() { return astFactory.mapProjectionLiteralEntry(p, e); }
| LOOKAHEAD(2)  p=PropertyKeyName() { return astFactory.mapProjectionProperty(p); }
| v=Variable() { return astFactory.mapProjectionVariable(v); }
|  t= { return astFactory.mapProjectionAll(pos(t)); }
}

EXPRESSION ExistsSubQuery() :
{
  Token t;
  List patterns;
  EXPRESSION where = null;
}
{
  t=  ( LOOKAHEAD(2)  )? patterns=PatternList() ( where=Where() )? 
  { return astFactory.existsSubQuery(pos(t), patterns, where); }
}

EXPRESSION Literal() :
{Token t; EXPRESSION e;}
{
  (
    e=NumberLiteral()
  | e=StringLiteral()
  | e=Parameter()
  | t= { e = astFactory.newTrueLiteral(pos(t)); }
  | t= { e = astFactory.newFalseLiteral(pos(t)); }
  | LOOKAHEAD(2) t= { e = astFactory.newNullLiteral(pos(t)); }
  | e=ListLiteralOfLiterals()
  | e=MapLiteralOfLiterals()
  | e=FunctionInvocation() // for spatial and temporal constructors
  )
  { return e; }
}

EXPRESSION ListLiteralOfLiterals() :
{
  Token t;
  EXPRESSION e;
  List list = new ArrayList<>();
}
{
  t= ( e=Literal() {list.add(e);} )? ( "," e=Literal() {list.add(e);} )* 
  { return astFactory.listLiteral(pos(t), list); }
}

EXPRESSION MapLiteralOfLiterals() :
{
  Token t;
  StringPos key;
  EXPRESSION value;
  List> keys = new ArrayList<>();
  List values = new ArrayList<>();
}
{
  t= ( key=PropertyKeyName() ":" value=Literal() {keys.add(key); values.add(value);} )?
           ( "," key=PropertyKeyName() ":" value=Literal() {keys.add(key); values.add(value);} )* 
  { return astFactory.mapLiteral(pos(t), keys, values); }
}

EXPRESSION StringLiteral() :
{ Token t; }
{
  t= { return astFactory.newString(pos(t), token.image); }
| t= { return astFactory.newString(pos(t), token.image); }
}

EXPRESSION NumberLiteral() :
{Token t; boolean negated = false;}
{
  t= { return astFactory.newDouble(pos(t), token.image); }
| (  {negated = true;})?
  ( t= { return astFactory.newDecimalInteger(pos(t), token.image, negated); }
  | t= { return astFactory.newHexInteger(pos(t), token.image, negated); }
  | t= { return astFactory.newOctalInteger(pos(t), token.image, negated); }
  )
}

EXPRESSION SignedIntegerLiteral():
{
 Token sign = null;
 Token number;
 boolean negated = false;
}
{
  ( sign= { negated = true; })?
  number=
  {
    return astFactory.newDecimalInteger(pos(sign != null ? sign : number), token.image, negated);
  }
}

EXPRESSION ListLiteral() :
{
  Token t;
  EXPRESSION e;
  List list = new ArrayList<>();
}
{
  t= ( e=Expression() {list.add(e);} )? ( "," e=Expression() {list.add(e);} )* 
  { return astFactory.listLiteral(pos(t), list); }
}

EXPRESSION MapLiteral() :
{
  Token t;
  StringPos key;
  EXPRESSION value;
  List> keys = new ArrayList<>();
  List values = new ArrayList<>();
}
{
  t= ( key=PropertyKeyName() ":" value=Expression() {keys.add(key); values.add(value);} )?
           ( "," key=PropertyKeyName() ":" value=Expression() {keys.add(key); values.add(value);} )* 
  { return astFactory.mapLiteral(pos(t), keys, values); }
}

StringPos PropertyKeyName() :
{Token t;}
{
  t=SymbolicNameString()
  { return new StringPos(t.image, pos(t)); }
}

EXPRESSION Parameter() :
{
    Token t;
    VARIABLE v;
}
{
  t="$" (
    v=Variable() { return astFactory.newParameter(pos(t), v); }
  |  { return astFactory.newParameter(pos(t), token.image); }
  )
}

PARAMETER StringParameter() :
{
    Token t;
    VARIABLE v;
}
{
  t="$" (
    v=Variable() { return astFactory.newStringParameter(pos(t), v); }
  |  { return astFactory.newStringParameter(pos(t), token.image); }
  )
}

EXPRESSION OldParameter() :
{Token t; VARIABLE v;}
{
  t= v=Variable() 
  { return astFactory.oldParameter(pos(t), v); }
}

EXPRESSION FunctionInvocation() :
{
  Token before = token;
  List namespace;
  String name;
  boolean distinct = false;
  EXPRESSION e;
  List arguments = new ArrayList<>();
}
{
  namespace=Namespace() name=FunctionName()
  
  ( LOOKAHEAD(2)  { distinct=true; })?
  ( e=Expression() {arguments.add(e);} )? ( "," e=Expression() {arguments.add(e);} )*
  
  { return astFactory.functionInvocation(pos(before.next), namespace, name, distinct, arguments);}
}

List Namespace() :
{
  Token t;
  List parts = new ArrayList<>();
}
{
  ( LOOKAHEAD(2) t=SymbolicNameString() { parts.add(t.image); }  )*
  { return parts; }
}

String FunctionName() :
{ Token t; }
{
  t=SymbolicNameString()
  { return t.image; }
}

List VariableList1() :
{
  Token t;
  List list = new ArrayList<>();
}
{
  t=SymbolicNameString() { list.add(astFactory.newVariable(pos(t), t.image)); }
  ( "," t=SymbolicNameString() { list.add(astFactory.newVariable(pos(t), t.image)); })*
  {
    return list;
  }
}

VARIABLE Variable() :
{Token t;}
{
  t=SymbolicNameString()
  {
    return astFactory.newVariable(pos(t), t.image);
  }
}

List SymbolicNameList1() :
{
  Token n;
  List list = new ArrayList<>();
}
{
  n=SymbolicNameString() {list.add(n.image);} ( "," n=SymbolicNameString() {list.add(n.image);} )*
  {
    return list;
  }
}

STATEMENT CreateAdministrationCommand(USE_CLAUSE useClause):
{
    Token start;
    boolean replace = false;
    ADMINISTRATION_COMMAND command;
}
{
    ()?
    start= (  { replace = true; })? (
        command=CreateRole(start, replace)
        | command=CreateDatabase(start, replace)
    )
    {
        return astFactory.useGraph( command, useClause );
    }
}

STATEMENT AdministrationCommand(USE_CLAUSE useClause):
{
    ADMINISTRATION_COMMAND s;
}
{
    ()?
    (
        s = ShowCommand()
        | s = DropCommand()
        | s = GrantRole()
        | s = RevokeRole()
        | s = StartDatabase()
        | s = StopDatabase()
    )
    {
        return astFactory.useGraph( s, useClause );
    }
}


ADMINISTRATION_COMMAND ShowCommand():
{
    Token start;
    ADMINISTRATION_COMMAND command;
}
{
    start= (
        command=ShowRoles(start)
        | command=ShowDatabase(start)
    )
    {
        return command;
    }
}

ADMINISTRATION_COMMAND ShowRoles(Token start):
{
  boolean withUsers = false;
  boolean showAll = true;
  YIELD yield = null;
  RETURN_CLAUSE returnClause = null;
  EXPRESSION where = null;
}
{
    (( { showAll = false; }) | )? 
    (  { withUsers = true; })?
     ( ( yield = YieldClause() (returnClause = ReturnWithoutGraphClause())? )
       | (where = Where()) )?
    {
        return astFactory.showRoles( pos(start), withUsers, showAll, yield, returnClause, where );
    }
}

ADMINISTRATION_COMMAND ShowDatabase(Token start):
{
    DATABASE_SCOPE scope;
    YIELD yield = null;
    RETURN_CLAUSE returnClause = null;
    EXPRESSION where = null;
}
{
   scope = DatabaseScope()
        ( ( yield = YieldClause() (returnClause = ReturnWithoutGraphClause())? )
          | (where = Where()) )?
   {
        return astFactory.showDatabase(pos(start), scope, yield, returnClause, where);
   }
}

DATABASE_SCOPE DatabaseScope():
{
  Token start = null;
  Either name = null;
  boolean isDefault = false;
}
{

  (
        start= name=SymbolicDatabaseNameStringOrParameter()
      | start=
      | start=  { isDefault = true; }
  )
  {
    return astFactory.databaseScope(pos(start), name, isDefault);
  }
}

YIELD YieldClause():
{
    Token start;
    boolean returnAll = false;
    RETURN_ITEM item;
    List returnItems = new ArrayList<>();
    List orders = new ArrayList<>();
    EXPRESSION skip = null;
    EXPRESSION limit = null;
    EXPRESSION where = null;
}
{
    start=
    (  { returnAll = true; }  |
    ( item=ReturnItem() { returnItems.add(item); } ("," item=ReturnItem() { returnItems.add(item); } )*))?
    ( orders=Order() )?
    (  skip=SignedIntegerLiteral() )?
    (  limit=SignedIntegerLiteral() )?
    ( where = Where() ) ?
    {
        return astFactory.yieldClause(pos(start), returnAll, returnItems, orders, skip, limit, where);
    }
}

ADMINISTRATION_COMMAND CreateRole(Token start, boolean replace):
{
    Either roleName = null;
    Either  sourceRoleName = null;
    boolean ifNotExists = false;
}
{
    
    roleName=SymbolicNameOrStringParameter()
    (   { ifNotExists = true; })?
    (   sourceRoleName=SymbolicNameOrStringParameter())?
    {
        return astFactory.createRole( pos(start), replace, roleName, sourceRoleName, ifNotExists );
    }
}

ADMINISTRATION_COMMAND CreateDatabase(Token start, boolean replace):
{
    Either databaseName = null;
    boolean ifNotExists = false;
    WAIT_CLAUSE wait = astFactory.wait(false, -1);
}
{
    
    databaseName=SymbolicDatabaseNameStringOrParameter()
    (   { ifNotExists = true; })?
    (wait = WaitClause())?
    {
       return astFactory.createDatabase( pos(start), replace, databaseName, ifNotExists, wait );
    }
}

WAIT_CLAUSE WaitClause():
{
 Token number = null;
 boolean wait = false;
}
{
    (
         { wait = true; } (number= ( |  | )? )?
        | 
    )
    {
        if (number != null) {
            return astFactory.wait(wait, Long.parseLong(number.image));
        }
        return astFactory.wait(wait, -1) ;
    }
}

ADMINISTRATION_COMMAND DropCommand():
{
    Token start;
    ADMINISTRATION_COMMAND c;
}
{
    start=
    (
        c =DropRole(start)
        | c = DropDatabase(start)
    )
    {
        return c;
    }
}

ADMINISTRATION_COMMAND DropRole(Token start):
{
    Either roleName = null;
    boolean ifExists = false;
}
{
    
    roleName=SymbolicNameOrStringParameter()
    (  {ifExists = true;})?
    {
        return astFactory.dropRole( pos(start), roleName, ifExists );
    }
}

ADMINISTRATION_COMMAND DropDatabase(Token start):
{
    Either databaseName = null;
    boolean ifExists = false;
    WAIT_CLAUSE wait = astFactory.wait(false, -1);
    boolean dumpData = false;
}
{
    
    databaseName=SymbolicDatabaseNameStringOrParameter()
    (  {ifExists = true;})?
    (( { dumpData = true; } | ) )?
    (wait = WaitClause())?
    {
        return astFactory.dropDatabase( pos(start), databaseName, ifExists, dumpData, wait );
    }
}

ADMINISTRATION_COMMAND GrantRole():
{
    Token start;
    List> roles;
    List> users;
}
{
    start =  ( | ) roles=SymbolicNamerOrStringParameterList()  users=SymbolicNamerOrStringParameterList()
    {
        return astFactory.grantRoles( pos(start), roles, users );
    }
}

ADMINISTRATION_COMMAND RevokeRole():
{
    Token start;
    List> roles;
    List> users;
}
{
    start =  ( | ) roles=SymbolicNamerOrStringParameterList()  users=SymbolicNamerOrStringParameterList()
    {
        return astFactory.revokeRoles( pos(start), roles, users  );
    }
}

ADMINISTRATION_COMMAND StartDatabase():
{
    Token start;
    Either databaseName;
    WAIT_CLAUSE wait = astFactory.wait(false, -1);
}
{
    start=  databaseName=SymbolicDatabaseNameStringOrParameter() (wait=WaitClause())?
    {
      return astFactory.startDatabase(pos(start), databaseName, wait);
    }
}

ADMINISTRATION_COMMAND StopDatabase():
{
    Token start;
    Either databaseName;
    WAIT_CLAUSE wait = astFactory.wait(false, -1);
}
{
    start=  databaseName=SymbolicDatabaseNameStringOrParameter() (wait=WaitClause())?
    {
      return astFactory.stopDatabase(pos(start), databaseName, wait);
    }
}

List> SymbolicNamerOrStringParameterList() :
{
    Either entry;
    List> list = new ArrayList<>();
}
{
    entry=SymbolicNameOrStringParameter() {list.add(entry);} ( "," entry=SymbolicNameOrStringParameter() {list.add(entry);} )*
    {
        return list;
    }
}

Either SymbolicNameOrStringParameter():
{
   Token name;
   PARAMETER parameter;
}
{
   name=SymbolicNameString() { return new Left(name.image); }
   | parameter=StringParameter() { return new Right(parameter); }
}

Either SymbolicDatabaseNameStringOrParameter():
{
   Token nameToken;
   StringBuilder nameBuilder;
   PARAMETER parameter;
}
{
   nameToken=SymbolicNameString() { nameBuilder =new StringBuilder(nameToken.image); }
   ( nameToken=SymbolicNameString() { nameBuilder.append("."); nameBuilder.append(nameToken.image);})* { return new Left(nameBuilder.toString()); }
   | parameter=StringParameter() { return new Right(parameter); }
}

Token SymbolicNameString() :
{Token t;}
{
  (

    t=
    | t=

    //list of allowed keywords
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
    | t=
  ) { return t; }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy