diff --git a/.gitignore b/.gitignore index 3e759b7..989fa36 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,9 @@ ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore +# Project specific ignores +**/*.private.* + # User-specific files *.suo *.user diff --git a/README.md b/README.md index b81a84e..ba0239d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,54 @@ +# openCypher Transpiler -# Contributing + +This library help you to build an [openCypher](http://www.opencypher.org/) query layer on top of a relational database or structured data in data lakes. Built on top of this library, you can transpile openCypher query into a target query language used by the relational database. We have provided a sample target language renderer for [T-SQL](https://docs.microsoft.com/en-us/sql/t-sql/language-reference?view=sql-server-2017). + +Originally we built this library to provide a [Property Graph](https://neo4j.com/developer/graph-database/#property-graph) data-layer for the petabyte-scale data assets in the Azure Data Lake. The property graph enables us to organize a vast catalog of data in an intuitive and traceable way. The openCypher query language allows data users that are already familiar with SQL-alike declarative query language to query the data assets with ease: in a graph where the relationship between data entities is a first class citizen, the data users no longer need to spend time on figuring out how individual data assets should be joined together. The data producers who are experts on their data would be the one to help define the relationship and is able to ensure its quality for downstream consumptions. + +This library has three main components: + +* A openCypher parser built on top of ANTLR4 and official openCypher grammar to parse and create an [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) to abstract the syntactical structure of the graph query; +* A logic planner transforms the AST into relational query logical plan similar to the [Relational Algebra](https://en.wikipedia.org/wiki/Relational_algebra); +* A query code renderer produces the actual query code from the logical plan. In this repository, we provides a T-SQL renderer. + +The library, written in [.Net Core](https://dotnet.microsoft.com/download), is cross-platform. + + +## Using the library + +```CSharp +// To Be Provided +``` + + +## Build on top of this library + +```CSharp +// To Be Provided +``` + + +## Test designs + +Transpiler is tested using the T-SQL target renderer and its results are compared against what is produced by Cypher from the [Neo4j Graph Database](https://neo4j.com/graph-database). Each test compares the query results from the transpiled query on [Microsoft SQL for Linux](https://www.microsoft.com/en-us/sql-server/sql-server-2017) against Cypher on Neo4j 3.x to ensure they are consistent in term of data type and contents. + +To run the tests, simply run under the project root folder: +```batch +dotnet test +``` + + +## Limitations To Be Addressed + +* MATCH pattern with unspecified labels which cannot be implied to a single label/relationship type +* MATCH pattern with variable-length relationship +* The logical plan is currently not further optimized with assumption the underlying RDBMS engine does this work +* list,collect,UNWIND is currently not supported +* Source table must already been normalized to be used as graph node/edge +* Readonly query is supported. CALL and write (such as MERGE) is not supported. + + +## Contributing This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us diff --git a/oCTranspiler.sln b/oCTranspiler.sln new file mode 100644 index 0000000..11b6127 --- /dev/null +++ b/oCTranspiler.sln @@ -0,0 +1,72 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.572 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "openCypherParser", "src\openCypherParser\openCypherParser.csproj", "{81AECE85-4C3D-4921-93F3-0619B4691B9E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common", "src\Common\Common.csproj", "{7BAC3CBC-9B05-4E3D-A530-F909E2D1BE95}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogicalPlanner", "src\LogicalPlanner\LogicalPlanner.csproj", "{ECA217C3-9DAF-48CF-93B3-43B150D06434}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "openCypherParser.Test", "tests\openCypherParser.Test\openCypherParser.Test.csproj", "{1B8A8206-1D57-483E-8F62-C9E0E3DEC2A1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommonTest", "tests\CommonTest\CommonTest.csproj", "{D61781A2-CEAC-45E5-A16F-C07C76AB5B58}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogicalPlanner.Test", "tests\LogicalPlanner.Test\LogicalPlanner.Test.csproj", "{9FE97D48-A6A2-40B2-B373-BB6FC9E03989}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SQLRenderer", "src\SQLRenderer\SQLRenderer.csproj", "{6B944CB5-0E6E-41A8-A19B-CB9AC23FA65A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E43CA3A8-7668-47D1-ABD1-07A3F2497C59}" + ProjectSection(SolutionItems) = preProject + README.md = README.md + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLRenderer.Test", "tests\SQLRenderer.Test\SQLRenderer.Test.csproj", "{A4874F73-84FF-4633-925D-BB80823FF8CD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {81AECE85-4C3D-4921-93F3-0619B4691B9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {81AECE85-4C3D-4921-93F3-0619B4691B9E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {81AECE85-4C3D-4921-93F3-0619B4691B9E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {81AECE85-4C3D-4921-93F3-0619B4691B9E}.Release|Any CPU.Build.0 = Release|Any CPU + {7BAC3CBC-9B05-4E3D-A530-F909E2D1BE95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7BAC3CBC-9B05-4E3D-A530-F909E2D1BE95}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7BAC3CBC-9B05-4E3D-A530-F909E2D1BE95}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7BAC3CBC-9B05-4E3D-A530-F909E2D1BE95}.Release|Any CPU.Build.0 = Release|Any CPU + {ECA217C3-9DAF-48CF-93B3-43B150D06434}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ECA217C3-9DAF-48CF-93B3-43B150D06434}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ECA217C3-9DAF-48CF-93B3-43B150D06434}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ECA217C3-9DAF-48CF-93B3-43B150D06434}.Release|Any CPU.Build.0 = Release|Any CPU + {1B8A8206-1D57-483E-8F62-C9E0E3DEC2A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1B8A8206-1D57-483E-8F62-C9E0E3DEC2A1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1B8A8206-1D57-483E-8F62-C9E0E3DEC2A1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1B8A8206-1D57-483E-8F62-C9E0E3DEC2A1}.Release|Any CPU.Build.0 = Release|Any CPU + {D61781A2-CEAC-45E5-A16F-C07C76AB5B58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D61781A2-CEAC-45E5-A16F-C07C76AB5B58}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D61781A2-CEAC-45E5-A16F-C07C76AB5B58}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D61781A2-CEAC-45E5-A16F-C07C76AB5B58}.Release|Any CPU.Build.0 = Release|Any CPU + {9FE97D48-A6A2-40B2-B373-BB6FC9E03989}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9FE97D48-A6A2-40B2-B373-BB6FC9E03989}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9FE97D48-A6A2-40B2-B373-BB6FC9E03989}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9FE97D48-A6A2-40B2-B373-BB6FC9E03989}.Release|Any CPU.Build.0 = Release|Any CPU + {6B944CB5-0E6E-41A8-A19B-CB9AC23FA65A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6B944CB5-0E6E-41A8-A19B-CB9AC23FA65A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6B944CB5-0E6E-41A8-A19B-CB9AC23FA65A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6B944CB5-0E6E-41A8-A19B-CB9AC23FA65A}.Release|Any CPU.Build.0 = Release|Any CPU + {A4874F73-84FF-4633-925D-BB80823FF8CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4874F73-84FF-4633-925D-BB80823FF8CD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4874F73-84FF-4633-925D-BB80823FF8CD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4874F73-84FF-4633-925D-BB80823FF8CD}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {927270C0-4539-450F-B889-E8FF08FDAE54} + EndGlobalSection +EndGlobal diff --git a/src/Common/Common.csproj b/src/Common/Common.csproj new file mode 100644 index 0000000..735a003 --- /dev/null +++ b/src/Common/Common.csproj @@ -0,0 +1,14 @@ + + + + netcoreapp2.1 + Microsoft.GraphPlatform.Transpiler.Common + + + + + + + + + diff --git a/src/Common/Exceptions/TranspilerBindingException.cs b/src/Common/Exceptions/TranspilerBindingException.cs new file mode 100644 index 0000000..a9d92fe --- /dev/null +++ b/src/Common/Exceptions/TranspilerBindingException.cs @@ -0,0 +1,19 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +namespace openCypherTranspiler.Common.Exceptions +{ + /// + /// Exception during data source binding + /// + public class TranspilerBindingException : TranspilerException + { + public TranspilerBindingException(string bindingErrorMsg) : + base($"Data binding error error: {bindingErrorMsg}") + { + + } + } +} diff --git a/src/Common/Exceptions/TranspilerException.cs b/src/Common/Exceptions/TranspilerException.cs new file mode 100644 index 0000000..d10cd2e --- /dev/null +++ b/src/Common/Exceptions/TranspilerException.cs @@ -0,0 +1,21 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using System; + +namespace openCypherTranspiler.Common.Exceptions +{ + /// + /// General exception thrown by the Transpiler + /// + public abstract class TranspilerException : Exception + { + public TranspilerException(string exceptionMsg) : + base(exceptionMsg) + { + + } + } +} diff --git a/src/Common/Exceptions/TranspilerInternalErrorException.cs b/src/Common/Exceptions/TranspilerInternalErrorException.cs new file mode 100644 index 0000000..9e35da7 --- /dev/null +++ b/src/Common/Exceptions/TranspilerInternalErrorException.cs @@ -0,0 +1,18 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +namespace openCypherTranspiler.Common.Exceptions +{ + /// + /// Exception representing unexpected internal errors thrown by the transpiler + /// + public class TranspilerInternalErrorException : TranspilerException + { + public TranspilerInternalErrorException(string intErrMsg) : base($"Unexpected internal error: {intErrMsg}") + { + } + } +} diff --git a/src/Common/Exceptions/TranspilerNotSupportedException.cs b/src/Common/Exceptions/TranspilerNotSupportedException.cs new file mode 100644 index 0000000..bb5f4f4 --- /dev/null +++ b/src/Common/Exceptions/TranspilerNotSupportedException.cs @@ -0,0 +1,21 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using System; + +namespace openCypherTranspiler.Common.Exceptions +{ + /// + /// Specific exception thrown by scenarios that were explicitly blocked + /// + public class TranspilerNotSupportedException : Exception + { + public TranspilerNotSupportedException(string functionNotSupported) : + base($"{functionNotSupported} is not supported by the code generator.") + { + + } + } +} diff --git a/src/Common/Exceptions/TranspilerSyntaxErrorException.cs b/src/Common/Exceptions/TranspilerSyntaxErrorException.cs new file mode 100644 index 0000000..1667ef2 --- /dev/null +++ b/src/Common/Exceptions/TranspilerSyntaxErrorException.cs @@ -0,0 +1,21 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using System; + +namespace openCypherTranspiler.Common.Exceptions +{ + /// + /// Exceptions raised from language syntax error + /// + public class TranspilerSyntaxErrorException : Exception + { + public TranspilerSyntaxErrorException(string syntaxErrorMsg) : + base($"Syntax error: {syntaxErrorMsg}") + { + + } + } +} diff --git a/src/Common/GraphSchema/EdgeSchema.cs b/src/Common/GraphSchema/EdgeSchema.cs new file mode 100644 index 0000000..06f15c3 --- /dev/null +++ b/src/Common/GraphSchema/EdgeSchema.cs @@ -0,0 +1,44 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +namespace openCypherTranspiler.Common.GraphSchema +{ + public class EdgeSchema : EntitySchema + { + public static char Separator = '@'; + + public static string GetEdgeId(string verb, string nodeFromName, string nodeToName) + { + return $"{nodeFromName}{Separator}{verb}{Separator}{nodeToName}"; + } + + /// + /// The identifier of edge + /// + public override string Id + { + get + { + return GetEdgeId(Name, SourceNodeId, SinkNodeId); + } + } + + public EntityProperty SourceIdProperty { get; set; } + + public EntityProperty SinkIdProperty { get; set; } + + /// + /// The identifier of the source node schema this edge schema links to + /// + public string SourceNodeId { get; set; } + + /// + /// The identifier of the sink node schema this edge schema links to + /// + public string SinkNodeId { get; set; } + + } +} diff --git a/src/Common/GraphSchema/EntityProperty.cs b/src/Common/GraphSchema/EntityProperty.cs new file mode 100644 index 0000000..9047b8d --- /dev/null +++ b/src/Common/GraphSchema/EntityProperty.cs @@ -0,0 +1,32 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +using System; + +namespace openCypherTranspiler.Common.GraphSchema +{ + public class EntityProperty + { + public enum PropertyDefinitionType + { + NodeJoinKey, + SourceNodeJoinKey, + SinkNodeJoinKey, + RegularProperty, + Label, + SourceNodeLabel, + SinkNodeLabel, + NodeSampleKey, + SourceNodeSampleKey, + SinkNodeSampleKey + }; + + public string PropertyName { get; set; } + public Type DataType { get; set; } + public PropertyDefinitionType PropertyType { get; set; } + + } +} diff --git a/src/Common/GraphSchema/EntitySchema.cs b/src/Common/GraphSchema/EntitySchema.cs new file mode 100644 index 0000000..04c3c74 --- /dev/null +++ b/src/Common/GraphSchema/EntitySchema.cs @@ -0,0 +1,32 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +using System.Collections.Generic; + +namespace openCypherTranspiler.Common.GraphSchema +{ + /// + /// Base class to descript a graph schema entity (can be a node or edge) + /// + public abstract class EntitySchema + { + /// + /// Unique name to the node/edge. For node it is nodename, for edge it is unique + /// combination of node from/to plus edge verb + /// + public abstract string Id { get; } + + /// + /// Name of the node or edge. In case of edge it is the 'verb' only + /// + public string Name { get; set; } + + /// + /// List of all properties on the node/edge (combining all parts) + /// + public IList Properties { get; set; } + } +} diff --git a/src/Common/GraphSchema/IGraphSchemaProvider.cs b/src/Common/GraphSchema/IGraphSchemaProvider.cs new file mode 100644 index 0000000..df34b25 --- /dev/null +++ b/src/Common/GraphSchema/IGraphSchemaProvider.cs @@ -0,0 +1,35 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace openCypherTranspiler.Common.GraphSchema +{ + /// + /// Implements by the Graph Schema provider to allow query the graph definition + /// + public interface IGraphSchemaProvider + { + /// + /// Return a NodeDefinition for the given node name. + /// + /// + /// if node name was not found + /// + NodeSchema GetNodeDefinition(string nodeName); + + /// + /// Return a NodeDefinition for the given edge verb, source and sink entity name. + /// + /// + /// + /// + /// if node name was not found + /// + EdgeSchema GetEdgeDefinition(string edgeVerb, string fromNodeName, string toNodeName); + } +} diff --git a/src/Common/GraphSchema/NodeSchema.cs b/src/Common/GraphSchema/NodeSchema.cs new file mode 100644 index 0000000..d4bc7bc --- /dev/null +++ b/src/Common/GraphSchema/NodeSchema.cs @@ -0,0 +1,21 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +namespace openCypherTranspiler.Common.GraphSchema +{ + public class NodeSchema : EntitySchema + { + public override string Id + { + get + { + return Name; + } + } + public EntityProperty NodeIdProperty { get; set; } + } +} + diff --git a/src/Common/Logging/BaseLogger.cs b/src/Common/Logging/BaseLogger.cs new file mode 100644 index 0000000..caf0a5c --- /dev/null +++ b/src/Common/Logging/BaseLogger.cs @@ -0,0 +1,99 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +namespace openCypherTranspiler.Common.Logging +{ + public abstract class BaseLogger : ILoggable + { + protected LoggingLevel _currentLogLevel = LoggingLevel.Normal; + + public void SetLoggingLevel(LoggingLevel logLevel) + { + _currentLogLevel = logLevel; + } + + public void Log(string msgFormat, params object[] msgArgs) + { + if (_currentLogLevel >= LoggingLevel.Normal) + { + LogMessage(msgFormat, msgArgs); + } + } + + public void LogCritical(string msgFormat, params object[] msgArgs) + { + if (_currentLogLevel >= LoggingLevel.CriticalOnly) + { + LogMessage(msgFormat, msgArgs); + } + } + + public void LogVerbose(string msgFormat, params object[] msgArgs) + { + if (_currentLogLevel >= LoggingLevel.Verbose) + { + LogMessage(msgFormat, msgArgs); + } + } + + public void LogCritical(string msg) + { + LogCritical("{0}", msg); + } + + public void Log(string msg) + { + Log("{0}", msg); + } + + public void LogVerbose(string msg) + { + LogVerbose("{0}", msg); + } + + public void LogFuncVerbose( + string msg, + [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", + [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", + [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0 + ) + { + if (_currentLogLevel >= LoggingLevel.Verbose) + { + LogMessage("{0}: {1}", memberName, msg); + } + } + + public void LogFunc( + string msg, + [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", + [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", + [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0 + ) + { + if (_currentLogLevel >= LoggingLevel.Normal) + { + LogMessage("{0}: {1}", memberName, msg); + } + } + + public void LogFuncCritical(string msg, + [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", + [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", + [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0 + ) + { + LogMessage("{0}: {1}", memberName, msg); + } + + /// + /// This is the only method that child logger class need to implement + /// + /// + /// + abstract protected void LogMessage(string msgFormat, params object[] msgArgs); + } +} diff --git a/src/Common/Logging/ILoggable.cs b/src/Common/Logging/ILoggable.cs new file mode 100644 index 0000000..8dea8e9 --- /dev/null +++ b/src/Common/Logging/ILoggable.cs @@ -0,0 +1,52 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +namespace openCypherTranspiler.Common.Logging +{ + public enum LoggingLevel + { + CriticalOnly, + Normal, + Verbose, + } + + /// + /// Inteface for the logger used through out this project + /// + public interface ILoggable + { + void SetLoggingLevel(LoggingLevel logLevel); + + + // LogFunc* calls with log the msg with the function name as well + + void LogFuncCritical( + string msg, + [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", + [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", + [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0 + ); + void LogFunc( + string msg, + [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", + [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", + [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0 + ); + void LogFuncVerbose( + string msg, + [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", + [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", + [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0 + ); + + void LogCritical(string msg); + void LogCritical(string msgFormat, params object[] msgArgs); + void Log(string msg); + void Log(string msgFormat, params object[] msgArgs); + void LogVerbose(string msg); + void LogVerbose(string msgFormat, params object[] msgArgs); + } +} diff --git a/src/Common/Utils/FNVHash.cs b/src/Common/Utils/FNVHash.cs new file mode 100644 index 0000000..0e971f1 --- /dev/null +++ b/src/Common/Utils/FNVHash.cs @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace openCypherTranspiler.Common.Utils +{ + public static class FNVHash + { + public static int GetFNVHash(params object[] objs) + { + // FNV hash + unchecked + { + int hash = (int)2166136261; + if (objs != null) + { + foreach (var o in objs) + { + hash = hash * 23 + (o?.GetHashCode() ?? 0); + } + return hash; + } + } + return 0; + } + + public static int GetFNVHash(IEnumerable objs) + { + // FNV hash + unchecked + { + int hash = (int)2166136261; + if (objs != null) + { + foreach (var o in objs) + { + hash = hash * 23 + (o?.GetHashCode() ?? 0); + } + return hash; + } + } + return 0; + } + + public static uint GetFNVHashUInt(params object[] objs) + { + int hash = GetFNVHash(objs); + return (uint)hash; // this will, for example, convert -1 to 4294967295 + } + + public static uint GetFNVHashUInt(IEnumerable objs) + { + int hash = GetFNVHash(objs); + return (uint)hash; // this will, for example, convert -1 to 4294967295 + } + + } +} diff --git a/src/Common/Utils/TextHelper.cs b/src/Common/Utils/TextHelper.cs new file mode 100644 index 0000000..d2b36ca --- /dev/null +++ b/src/Common/Utils/TextHelper.cs @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace openCypherTranspiler.Common.Utils +{ + public static class TextHelper + { + /// + /// Helper function to use a regex pattern to clean up a dirty string for + /// certain restriction by another system/api + /// + /// + /// + /// + public static string MakeCompliantString(string originalStr, string regexPat) + { + string compStr = ""; + foreach (Match m in Regex.Matches(originalStr, regexPat)) + { + compStr += m.Value; + } + return compStr; + } + + /// + /// Add or remove indentation at line level + /// + /// + /// Positive means adding indentation of delta unit, Negative means remove indentation of delta unit + /// + /// + /// + public static string ChangeIndentation(this string text, int delta, char indentChar = ' ', int indentUnitCnt = 4) + { + var lines = Regex.Split(text, "\r\n|\r|\n"); + + if (delta > 0) + { + var indentation = new string(indentChar, delta * indentUnitCnt); + return string.Join("\r\n", lines.Select(l => $"{indentation}{l}")); + } + else if (delta < 0) + { + var indentationUnit = new string(indentChar, indentUnitCnt); + return string.Join("\r\n", lines.Select(l => Regex.Replace(l, $"^({indentationUnit}){{0,{delta}}}", string.Empty))); + } + else + { + return text; + } + } + } +} diff --git a/src/Common/Utils/TypeHelper.cs b/src/Common/Utils/TypeHelper.cs new file mode 100644 index 0000000..856e0f0 --- /dev/null +++ b/src/Common/Utils/TypeHelper.cs @@ -0,0 +1,115 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace openCypherTranspiler.Common.Utils +{ + public class TypeHelper + { + /// + /// Check if null value can be assigned + /// E.g. IsNullableType(string) = true, IsNullableType(DateTime) = false + /// IsNullableType( + /// + /// + /// + public static bool CanAssignNullToType(Type type) + { + if (!type.IsValueType) + { + return true; // ref-type can assign null value + } + if (IsSystemNullableType(type)) + { + return true; // Nullable can assign null value + } + return false; + } + + /// + /// Check if a type is System.Nullable or derived from System.Nullable + /// E.g. IsNullableType(string) = false, IsNullableType(System.Nullable) = true + /// + /// + /// + public static bool IsSystemNullableType(Type type) + { + // NOTE: Nullable is sealed type, so no class can derive from it + if (type != default(Type) && Nullable.GetUnderlyingType(type) != null) + { + return true; + } + return false; + } + + /// + /// Given an non-nullable type, wrap it in a System.Nullable<> generic type + /// + /// Non nullable type + /// + /// Throws InvalidCastException, if type is already nullable. + public static Type GetNullableTypeForType(Type type) + { + if (CanAssignNullToType(type)) + { + throw new InvalidCastException($"Type: {type} is already nullable"); + } + return typeof(Nullable<>).MakeGenericType(type); + } + + /// + /// Check if a type is derived from a generic type + /// E.g. class SubClass : Node {} ; + /// IsSubclassOfRawGeneric(typeof(SubClass), Node<>) == true + /// + /// + /// + /// + public static bool IsSubclassOfRawGeneric(Type toCheck, Type generic) + { + while (toCheck != null && toCheck != typeof(object)) + { + var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck; + if (generic == cur) + { + return true; + } + toCheck = toCheck.BaseType; + } + return false; + } + + /// + /// Return the type itself, or for a nullable type, its unboxed type + /// + /// + /// + public static Type GetUnderlyingTypeIfNullable(Type t) + { + var isNullable = IsSystemNullableType(t); + return isNullable ? Nullable.GetUnderlyingType(t) : t; + } + + /// + /// Wrap unnullable type to nullable + /// + /// + /// + public static Type MakeNullableIfNotAlready(Type t) + { + if (!CanAssignNullToType(t)) + { + return typeof(Nullable<>).MakeGenericType(t); + } + else + { + return t; + } + } + } +} diff --git a/src/LogicalPlanner/Logical/IBindable.cs b/src/LogicalPlanner/Logical/IBindable.cs new file mode 100644 index 0000000..8f184ae --- /dev/null +++ b/src/LogicalPlanner/Logical/IBindable.cs @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using openCypherTranspiler.Common.GraphSchema; + +namespace openCypherTranspiler.LogicalPlanner +{ + interface IBindable + { + void Bind(IGraphSchemaProvider graphDefinition); + } +} diff --git a/src/LogicalPlanner/Logical/LogicalOperator.cs b/src/LogicalPlanner/Logical/LogicalOperator.cs new file mode 100644 index 0000000..7ef4008 --- /dev/null +++ b/src/LogicalPlanner/Logical/LogicalOperator.cs @@ -0,0 +1,1137 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using openCypherTranspiler.Common.GraphSchema; +using openCypherTranspiler.Common.Utils; +using openCypherTranspiler.Common.Exceptions; +using openCypherTranspiler.openCypherParser.AST; +using openCypherTranspiler.openCypherParser.Common; + +namespace openCypherTranspiler.LogicalPlanner +{ + /// + /// Logical operator representing the relational algebra to evaluate graph queries + /// The logical plan is a DAG (directed acyclic graph) of logical operators + /// This is the base type + /// + public abstract class LogicalOperator + { + private List _inOperators = new List(); + private List _outOperators = new List(); + + /// + /// The schema this operator takes in + /// + /// Note: we thought about making this a getter of fields from output from it's in operator + /// however, for certain operators, it is not always a combination of all output, making + /// it awkard in some cases to implement field reference propagate + /// hence for now, we keep this a separate instanced list to maintain + public Schema InputSchema { get; set; } + + /// + /// The schema this operator outputs + /// + public Schema OutputSchema { get; set; } + + /// + /// The level of this particular operator + /// + public abstract int Depth { get; } + + /// + /// Debug field: the id of the operator during creation + /// + public int OperatorDebugId { get; set; } + + /// + /// Downstream operators + /// + public IEnumerable InOperators + { + get + { + return _inOperators; + } + } + + /// + /// Downstream operators + /// + public IEnumerable OutOperators + { + get + { + return _outOperators; + } + } + + internal virtual void AddInOperator(LogicalOperator op) + { + if (_inOperators.Contains(op)) + { + throw new TranspilerInternalErrorException($"Internal error: operator {op} has already been added"); + } + _inOperators.Add(op); + } + + internal virtual void AddOutOperator(LogicalOperator op) + { + if (_outOperators.Contains(op)) + { + throw new TranspilerInternalErrorException($"Internal error: operator {op} has already been added"); + } + _outOperators.Add(op); + } + + public override string ToString() + { + var sb = new StringBuilder(); + sb.AppendLine($"{this.GetType().Name}: "); + sb.AppendLine($"In Schema: {string.Join(", ", InputSchema ?? Enumerable.Empty())};"); + sb.AppendLine($"Out Schema: {string.Join(", ", OutputSchema ?? Enumerable.Empty())};"); + return sb.ToString(); + } + + /// + /// Operator graph traverse: get all downstream operators of a particular type + /// + /// + /// + public IEnumerable GetAllDownstreamOperatorsOfType() where T : LogicalOperator + { + var opList = new List(); + + if (OutOperators.Count() > 0) + { + opList.AddRange(OutOperators.SelectMany(op => op.GetAllDownstreamOperatorsOfType())); + } + + if (this is T) + { + opList.Add(this as T); + } + + return opList; + } + + /// + /// Operator graph traverse: get all upstream operators of a particular type + /// + /// + /// + public IEnumerable GetAllUpstreamOperatorsOfType() where T : LogicalOperator + { + var opList = new List(); + + if (InOperators.Count() > 0) + { + opList.AddRange( + InOperators + .SelectMany(op => op.GetAllUpstreamOperatorsOfType()) + .Distinct() // we do have multiplexing (multiple output) for operators in some scenarios, so we need to distinct here + ); + } + + if (this is T) + { + opList.Add(this as T); + } + + return opList; + } + + + /// + /// Used by logic planner to propagate input schema + /// + internal abstract void PropagateSchema(); + + /// + /// Used by logic planner to update the list of ReferencedFields + /// + internal virtual void PropagateReferencedPropertiesForEntityFields() + { + // lift the referenced fields from the next layer of operators back to this one's output entity fields + var referedFieldsInDownstreamOps = OutOperators.SelectMany(op => op.InputSchema) + .Where(f => f is EntityField) + .Cast() + .GroupBy(f => f.FieldAlias) + .ToDictionary(kv => kv.Key, kv => kv.SelectMany(fn => fn.ReferencedFieldAliases).Distinct().ToList()); + + foreach (var field in OutputSchema.Where(f => f is EntityField).Cast()) + { + Debug.Assert(referedFieldsInDownstreamOps.ContainsKey(field.FieldAlias)); + field.AddReferenceFieldAliases(referedFieldsInDownstreamOps[field.FieldAlias]); + } + + // lift the referenced fields in the entity fields from output to input schema of this operator, if + // applicable + if ((InputSchema?.Count ?? 0) > 0) + { + // handle entity name renamed cases by creating a map from field alias before projection to after + // projection + var aliasMap = new Dictionary(); + + if (this is ProjectionOperator) + { + var aliasMap1 = (this as ProjectionOperator).ProjectionMap + .Where(u => OutputSchema.Where(n => n is EntityField).Any(k => k.FieldAlias == u.Key)); + aliasMap = aliasMap1?.ToDictionary(n => n.Value.GetChildrenQueryExpressionType().First().VariableName, n => n.Key); + } + else + { + // create a dummy alias map ( A -> A, B -> B; not alias name modified) for non-projection operator + aliasMap = OutputSchema.Where(n => n is EntityField).ToDictionary(n => n.FieldAlias, n=> n.FieldAlias); + + } + + foreach (var field in InputSchema.Where(f => f is EntityField).Cast()) + { + var mappedAlias = (aliasMap.ContainsKey(field.FieldAlias) ?aliasMap[field.FieldAlias]:null); + + if (mappedAlias != null && referedFieldsInDownstreamOps.ContainsKey(mappedAlias)) + { + field.AddReferenceFieldAliases(referedFieldsInDownstreamOps[mappedAlias]); + } + } + + var referedFieldsForUpstream = InputSchema + .Where(f => f is EntityField).Cast() + .ToDictionary(kv => kv.FieldAlias, kv => kv); + + // Some operators has additional fields may get referenced even they are not in output schema + // Such as in WHERE + // Child logical operator class implement this and does the addition + AppendReferencedProperties(referedFieldsForUpstream); + } + } + + /// + /// Incremental addition of reference fields by the logical operator (E.g. WHERE/JOIN can add field references + /// in addition to those already in the outschema when propagating to inschema) + /// To be implemented by each Logical Operator class + /// + /// A list of avaialble entities (with bound fields) in the input for this operator + internal abstract void AppendReferencedProperties(IDictionary entityFields); + + /// + /// Helper function to propagate content of fields + /// + /// + /// + internal static void CopyFieldInfoHelper(IEnumerable targetFields, IEnumerable srcFields) + { + // Select operator does not alter schema, so the output should map to input perfectly + Debug.Assert(targetFields.All(f => srcFields.Any(f2 => f2.FieldAlias == f.FieldAlias && f2.GetType() == f.GetType()))); + + var fieldMapping = new Dictionary(); + foreach (var tarF in targetFields) + { + var matchSrcF = srcFields.Where(f => f.FieldAlias == tarF.FieldAlias); + Debug.Assert(matchSrcF.Count() == 1); + tarF.Copy(matchSrcF.First()); + } + } + } + + /// + /// Base type for starting operator in a Logical Plan, equivalent to source tuples in RelationAlgebra + /// + public abstract class StartLogicalOperator : LogicalOperator + { + internal override void AddInOperator(LogicalOperator op) + { + throw new TranspilerInternalErrorException("StartLogicalOperator derived types does not take any InOperator"); + } + + public override int Depth + { + get + { + return 0; + } + } + + internal override void PropagateSchema() + { + // No input, so nothing need to be done + } + + internal override void AppendReferencedProperties(IDictionary entityFields) + { + throw new TranspilerInternalErrorException("DataSourceOperator does not have a input source. Not expected to get called here"); + } + } + + /// + /// Base type for operator that takes just one input + /// + public abstract class UnaryLogicalOperator : LogicalOperator + { + public LogicalOperator InOperator + { + get + { + return InOperators.FirstOrDefault(); + } + } + + protected void SetInOperator(LogicalOperator op) + { + if (InOperators.Count() > 0) + { + throw new TranspilerInternalErrorException("InOperator is already set"); + } + op.AddOutOperator(this); + AddInOperator(op); + } + + public override int Depth + { + get + { + return InOperator.Depth + 1; + } + } + + internal abstract void PropagateOutSchema(); + + internal override void PropagateSchema() + { + // For unary operator, the input schema is the output of its input operator's schema without any changes + var prevOutSchema = InOperator.OutputSchema; + var fieldMapping = new Dictionary(); + + foreach (var inF in InputSchema) + { + var matchOutFields = prevOutSchema.Where(f => f.FieldAlias == inF.FieldAlias); + if (matchOutFields.Count() > 1) + { + throw new TranspilerInternalErrorException($"Ambiguous match of field with alias '{inF.FieldAlias}'"); + } + if (matchOutFields.Count() == 0) + { + throw new TranspilerInternalErrorException($"Failed to match field with alias '{inF.FieldAlias}'"); + } + fieldMapping.Add(inF, matchOutFields.First()); + } + + CopyFieldInfoHelper(fieldMapping.Keys, fieldMapping.Values); + + PropagateOutSchema(); + } + } + + /// + /// Base type for operator that takes two inputs + /// + public abstract class BinaryLogicalOperator : LogicalOperator + { + public LogicalOperator InOperatorLeft + { + get + { + return InOperators.First(); + } + } + public LogicalOperator InOperatorRight + { + get + { + return InOperators.Last(); + } + } + + protected void SetInOperators(LogicalOperator opLeft, LogicalOperator opRight) + { + if (InOperators.Count() > 0) + { + throw new TranspilerInternalErrorException("InOperatorLeft or InOperatorRight is already set."); + } + opLeft.AddOutOperator(this); + opRight.AddOutOperator(this); + AddInOperator(opLeft); + AddInOperator(opRight); + } + + public override int Depth + { + get + { + return Math.Max(InOperatorLeft.Depth, InOperatorRight.Depth) + 1; + } + } + + internal abstract void PropagateInSchema(); + + internal virtual void PropagateOutSchema() + { + // Default implmementation is that output schema doesn't change + CopyFieldInfoHelper(OutputSchema, InputSchema); + } + + internal override void PropagateSchema() + { + PropagateInSchema(); + PropagateOutSchema(); + } + } + + /// + /// Starting operator representing an entity data source of the graph + /// + public sealed class DataSourceOperator : StartLogicalOperator, IBindable + { + public DataSourceOperator(Entity entity) + { + Entity = entity; + } + + public Entity Entity { get; set; } + + /// + /// This function bind the data source to a given graph definitions + /// + /// + public void Bind(IGraphSchemaProvider graphDefinition) + { + // During binding, we read graph definition of the entity + // and populate the EntityField object in the output + // with the list of fields that the node/edge definition can expose + var properties = new List(); + string entityUniqueName; + string sourceEntityName = null; + string sinkEntityName = null; + SingleField nodeIdField = null; + SingleField edgeSrcIdField = null; + SingleField edgeSinkIdField = null; + + try + { + if (Entity is NodeEntity) + { + NodeSchema nodeDef = graphDefinition.GetNodeDefinition(Entity.EntityName); + entityUniqueName = nodeDef.Id; + nodeIdField = new SingleField(nodeDef.NodeIdProperty.PropertyName, nodeDef.NodeIdProperty.DataType); + + properties.AddRange(nodeDef.Properties.Select(p => new SingleField(p.PropertyName, p.DataType))); + properties.Add(nodeIdField); + } + else + { + var edgeEnt = Entity as RelationshipEntity; + EdgeSchema edgeDef = null; + + switch (edgeEnt.RelationshipDirection) + { + case RelationshipEntity.Direction.Forward: + edgeDef = graphDefinition.GetEdgeDefinition(edgeEnt.EntityName, edgeEnt.LeftEntityName, edgeEnt.RightEntityName); + break; + case RelationshipEntity.Direction.Backward: + edgeDef = graphDefinition.GetEdgeDefinition(edgeEnt.EntityName, edgeEnt.RightEntityName, edgeEnt.LeftEntityName); + break; + default: + // either direction + // TODO: we don't handle 'both' direction yet + Debug.Assert(edgeEnt.RelationshipDirection == RelationshipEntity.Direction.Both); + edgeDef = graphDefinition.GetEdgeDefinition(edgeEnt.EntityName, edgeEnt.LeftEntityName, edgeEnt.RightEntityName); + if (edgeDef == null) + { + edgeDef = graphDefinition.GetEdgeDefinition(edgeEnt.EntityName, edgeEnt.RightEntityName, edgeEnt.LeftEntityName); + } + break; + } + + entityUniqueName = edgeDef.Id; + sourceEntityName = edgeDef.SourceNodeId; + sinkEntityName = edgeDef.SinkNodeId; + edgeSrcIdField = new SingleField(edgeDef.SourceIdProperty.PropertyName, edgeDef.SourceIdProperty.DataType); + edgeSinkIdField = new SingleField(edgeDef.SinkIdProperty.PropertyName, edgeDef.SinkIdProperty.DataType); + + properties.AddRange(edgeDef.Properties.Select(p => new SingleField(p.PropertyName, p.DataType))); + properties.Add(edgeSrcIdField); + properties.Add(edgeSinkIdField); + } + } + catch (KeyNotFoundException e) + { + throw new TranspilerBindingException($"Failed to binding entity with alias '{Entity.Alias}' of type '{Entity.EntityName}' to graph definition. Inner error: {e.GetType().Name}: {e.Message}"); + } + + Debug.Assert(OutputSchema.Count == 1 + && OutputSchema.First() is EntityField + && (OutputSchema.First() as EntityField).EntityName == Entity.EntityName); + + var field = OutputSchema.First() as EntityField; + field.BoundEntityName = entityUniqueName; + field.BoundSourceEntityName = sourceEntityName; + field.BoundSinkEntityName = sinkEntityName; + field.EncapsulatedFields = properties; + field.NodeJoinField = nodeIdField; + field.RelSourceJoinField = edgeSrcIdField; + field.RelSinkJoinField = edgeSinkIdField; + } + + public override string ToString() + { + var sb = new StringBuilder(base.ToString()); + sb.AppendLine($"DataEntitySource: {Entity};"); + return sb.ToString(); + } + } + + /// + /// Operator to satisfy WHERE + /// + public sealed class SelectionOperator : UnaryLogicalOperator + { + public SelectionOperator(LogicalOperator inOp, QueryExpression filterExpr) + { + FilterExpression = filterExpr; + UnexpandedEntityInequalityConditions = null; + SetInOperator(inOp); + } + public SelectionOperator(LogicalOperator inOp,IList orderExpr, IList limitExpr) + { + FilterExpression = null; + UnexpandedEntityInequalityConditions = null; + SetInOperator(inOp); + OrderByExpressions = orderExpr; + LimitExpressions = limitExpr; + } + + public SelectionOperator(LogicalOperator inOp, IEnumerable<(string, string)> entityInquityConds) + { + FilterExpression = null; + UnexpandedEntityInequalityConditions = entityInquityConds.ToList(); + SetInOperator(inOp); + } + + public QueryExpression FilterExpression { get; private set; } + + /// + /// use to store ORDER BY expression under WITH or RETURN clause + /// + public IList OrderByExpressions { get; private set; } + + /// + /// use to store LIMIT expression under WITH or RETURN clause + /// + public IList LimitExpressions { get; private set; } + + /// + /// Inequality conditions to be added after binding, specificially reserved for the implied inequality + /// conditions from MATCH clauses like MATCH (p:Person)-[a1:Acted_In]-(m:Movie)-[a2:Acted_In]-(p2:Person) + /// where implicity condition of a1 <> a2 must be added + /// + public IEnumerable<(string RelAlias1, string RelAlias2)> UnexpandedEntityInequalityConditions { get; private set; } + + public override string ToString() + { + var sb = new StringBuilder(base.ToString()); + sb.AppendLine($"Filtering Condition: {FilterExpression};"); + return sb.ToString(); + } + + internal override void PropagateOutSchema() + { + // Select operator does not alter schema, so the output should map to input perfectly + Debug.Assert(OutputSchema.All(f => InputSchema.Any(f2 => f2.FieldAlias == f.FieldAlias && f2.GetType() == f.GetType()))); + CopyFieldInfoHelper(OutputSchema, InputSchema); + + // Additional step for Select operator is to check if additional conditions + // should be added if UnexpandedEntityInequalityConditions is specified + if (UnexpandedEntityInequalityConditions != null) + { + Debug.Assert(FilterExpression == null); + FilterExpression = UnexpandedEntityInequalityConditions.Aggregate( + FilterExpression, + (expr, c) => + { + var relEnt1 = InputSchema.First(e => e.FieldAlias == c.RelAlias1) as EntityField; + var relEnt2 = InputSchema.First(e => e.FieldAlias == c.RelAlias2) as EntityField; + Debug.Assert(relEnt1 != null && relEnt2 != null); + + var condExpr1 = new QueryExpressionBinary() + { + Operator = OperatorHelper.GetOperator(BinaryOperator.NEQ), + LeftExpression = new QueryExpressionProperty() + { + VariableName = c.RelAlias1, + PropertyName = relEnt1.RelSourceJoinField.FieldAlias + }, + RightExpression = new QueryExpressionProperty() + { + VariableName = c.RelAlias2, + PropertyName = relEnt2.RelSourceJoinField.FieldAlias + } + }; + var condExpr2 = new QueryExpressionBinary() + { + Operator = OperatorHelper.GetOperator(BinaryOperator.NEQ), + LeftExpression = new QueryExpressionProperty() + { + VariableName = c.RelAlias1, + PropertyName = relEnt1.RelSinkJoinField.FieldAlias + }, + RightExpression = new QueryExpressionProperty() + { + VariableName = c.RelAlias2, + PropertyName = relEnt2.RelSinkJoinField.FieldAlias + } + }; + var binExpr = new QueryExpressionBinary() + { + Operator = OperatorHelper.GetOperator(BinaryOperator.OR), + LeftExpression = condExpr1, + RightExpression = condExpr2 + }; + + return expr == null ? + binExpr : + new QueryExpressionBinary() + { + Operator = OperatorHelper.GetOperator(BinaryOperator.AND), + LeftExpression = expr, + RightExpression = binExpr + }; + }); + } + } + + internal override void AppendReferencedProperties(IDictionary entityFields) + { + // Selection operator may have additional field references in the where/order by conditions that were not referenced in output + // Add these as well to the input + + Debug.Assert(FilterExpression != null || OrderByExpressions != null || LimitExpressions != null ); + var allPropertyReferences = new List(); + + var propsFromFilterExprs = FilterExpression?.GetChildrenQueryExpressionType(); + var propsFromOrderByExprs = OrderByExpressions?.SelectMany(n => n.GetChildrenQueryExpressionType()); + + if(propsFromOrderByExprs != null) + { + allPropertyReferences.AddRange(propsFromOrderByExprs); + } + if (propsFromFilterExprs != null) + { + allPropertyReferences.AddRange(propsFromFilterExprs); + } + + foreach (var prop in allPropertyReferences) + { + var varName = prop.VariableName; + var fieldName = prop.PropertyName; + + if (prop.Entity != null) + { + if(!entityFields.ContainsKey(varName)) + { + throw new TranspilerInternalErrorException($"Entity field: '{varName}' does not exsit"); + } + + var entity = entityFields[varName]; + + // for entity reference, such as MATCH (d:device) RETURN count(d) + // we can by default, for node, does count(d.id) instead, and edge does count(d._vertexId) instead + if (entity.Type == EntityField.EntityType.Node) + { + entity.AddReferenceFieldAlias(entity.NodeJoinField.FieldAlias); + } + else + { + entity.AddReferenceFieldAlias(entity.RelSourceJoinField.FieldAlias); + } + } + else if (fieldName != null) + { + // field dereference, just append to list + var propName = prop.PropertyName; + if (!entityFields.ContainsKey(varName)) + { + throw new TranspilerSyntaxErrorException($"entity field: \"{varName}\" not exsit"); + } + var entity = entityFields[varName]; + entity.AddReferenceFieldAlias(fieldName); + } + else + { + // reference to an existing field + // nothing need to be done + // add a check if expression alias did exist + if(OutOperators.First().OutputSchema.All(n => n.FieldAlias != varName)) + { + throw new TranspilerSyntaxErrorException($"single field name: {varName} not existed in output schema of depth {Depth} selection operator."); + } + } + } + } + } + + /// + /// Operator to satisfy SELECT + /// + public sealed class ProjectionOperator : UnaryLogicalOperator + { + public bool IsDistinct { get; private set; } + public bool HasAggregationField { get; private set; } = false; + public ProjectionOperator(LogicalOperator inOp, IDictionary projectionMap, bool isDistinct) + { + ProjectionMap = projectionMap; + IsDistinct = isDistinct; + SetInOperator(inOp); + } + + // projection map, from source expression to projection result (indexed by its FieldName) + public IDictionary ProjectionMap { get; private set; } + + internal override void PropagateOutSchema() + { + // projection alters the schema, we need to look into the query expressions + // to do type propagation + + var exprToOutputMap = ProjectionMap.ToDictionary( + kv => kv.Key, // key is output alias + kv => new { Expr = kv.Value, Field = OutputSchema.First(f => f.FieldAlias == kv.Key) } // value is the corresponding field object and expression + ); + + foreach (var map in exprToOutputMap) + { + // if any aggregation function, set the flag to be true + var allPropertyReferences = map.Value.Expr.GetChildrenQueryExpressionType(); + if(map.Value.Expr.GetChildrenQueryExpressionType().Count() > 0) + { + HasAggregationField = true; + } + + if (map.Value.Field is EntityField) + { + // This can only be direct exposure of entity (as opposed to deference of a particular property) + // We just copy of the fields that the entity can potentially be deferenced + Debug.Assert(allPropertyReferences.Count() == 1); + + var varName = allPropertyReferences.First().VariableName; + var matchInputField = InputSchema.First(f => f.FieldAlias == varName); + map.Value.Field.Copy(matchInputField); + } + else + { + // This can be a complex expression involve multiple field/column references + // We will compute the type of the expression + Debug.Assert(map.Value.Field is SingleField); + + // first of all, bind the type to the variable references + foreach (var prop in allPropertyReferences) + { + var varName = prop.VariableName; + var propName = prop.PropertyName; + Debug.Assert(prop.VariableName != null); + var matchedField = InputSchema.FirstOrDefault(f => f.FieldAlias == varName); + + if (matchedField == null) + { + throw new TranspilerBindingException($"Failed to find input matching field alias {varName}"); + } + + if (string.IsNullOrEmpty(propName)) + { + // refer to a already aliased column exposed from piped data + if (matchedField is SingleField) + { + prop.DataType = (matchedField as SingleField).FieldType; + } + else + { + // entity field reference in a single field expression + // this is valid only in handful situaions, such as Count(d), Count(distinct(d)) + // in such case, we populate the Entity object with correct entity type so that code generator can use it later + Debug.Assert(matchedField is EntityField); + var matchedEntity = matchedField as EntityField; + prop.Entity = matchedEntity.Type == EntityField.EntityType.Node ? + new NodeEntity() { EntityName = matchedEntity.EntityName, Alias = matchedEntity.FieldAlias } as Entity: + new RelationshipEntity() { EntityName = matchedEntity.EntityName, Alias = matchedEntity.FieldAlias } as Entity; + } + } + else + { + // property reference of an entity + if (!(matchedField is EntityField)) + { + throw new TranspilerBindingException($"Failed to dereference property {propName} for alias {varName}, which is not an alias of entity type as expected"); + } + var entField = matchedField as EntityField; + var entPropField = entField.EncapsulatedFields.FirstOrDefault(f => f.FieldAlias == propName); + if (entPropField == null) + { + throw new TranspilerBindingException($"Failed to dereference property {propName} for alias {varName}, Entity type {entField.BoundEntityName} does not have a property named {propName}"); + } + entField.AddReferenceFieldAlias(propName); + prop.DataType = entPropField.FieldType; + } + } + + // do data type evaluation + var evalutedType = map.Value.Expr.EvaluateType(); + var outField = map.Value.Field as SingleField; + outField.FieldType = evalutedType; + } + } + } + internal override void AppendReferencedProperties(IDictionary entityFields) + { + + // Adding more logic here, as some of upstream selection operator is selection operator, then the extra field in order + // by clause need to flow down to the referenced field. + if(InOperator is SelectionOperator) + { + var preSelectionOp = (InOperator as SelectionOperator); + var orderExpr = preSelectionOp?.OrderByExpressions; + if (orderExpr?.Count() > 0) + { + var propList = orderExpr + .SelectMany(n => n.GetChildrenQueryExpressionType()) + .Where(p => p.PropertyName != null && p.VariableName != null) + .GroupBy(l => l.VariableName) + ?.ToDictionary(p => p.Key, p => p.Select(n => n.PropertyName)); + //looking for new entity fields in the slection operrator and then add to the entity field reference dictionary + if (propList != null) + { + foreach(var entry in propList) + { + foreach(var propertyName in entry.Value) + { + if (entityFields.ContainsKey(entry.Key) && !entityFields[entry.Key].ReferencedFieldAliases.Contains(propertyName)) + { + var entity = entityFields[entry.Key]; + entity.AddReferenceFieldAlias(propertyName); + // update output schema reference field at the same time. + var outputEntity = OutputSchema.Where(n => n is EntityField && n.FieldAlias == entry.Key); + Debug.Assert(outputEntity.Count() == 1); + outputEntity.Cast().First().AddReferenceFieldAlias(propertyName); + } + } + } + } + } + } + } + } + + /// + /// Operator to satisfy UNION + /// + public sealed class SetOperator : BinaryLogicalOperator + { + public SetOperator(LogicalOperator leftOp, LogicalOperator rightOp, SetOperationType setOpType) + { + SetOperation = setOpType; + SetInOperators(leftOp, rightOp); + } + + public enum SetOperationType + { + Union, + UnionAll, + } + + public SetOperationType SetOperation { get; set; } + + public override string ToString() + { + var sb = new StringBuilder(base.ToString()); + sb.AppendLine($"Set Operation Type: {SetOperation};"); + return sb.ToString(); + } + + internal override void PropagateInSchema() + { + // For SetOperator, out schema should be the same for union from 2 source of input + + var leftSchema = InOperatorLeft.OutputSchema; + var rightSchema = InOperatorRight.OutputSchema; + + if (leftSchema.Count != rightSchema.Count) + { + throw new TranspilerSyntaxErrorException("All sub queries in an UNION must have the same column names"); + } + + // validate left schema and see if it is compatible with right schema + foreach (var z in leftSchema.Zip(rightSchema, (l, r) => (LeftField: l, RightField: r))) + { + if (z.LeftField.FieldAlias != z.RightField.FieldAlias) + { + throw new TranspilerSyntaxErrorException($"Column name mismatch: left='{z.LeftField.FieldAlias}', right='{z.LeftField.FieldAlias}'"); + } + + if (z.LeftField.GetType() != z.RightField.GetType()) + { + throw new TranspilerSyntaxErrorException($"Column type mismatch for column '{z.LeftField.FieldAlias}'"); + } + + if (z.LeftField is EntityField) + { + var l = z.LeftField as EntityField; + var r = z.RightField as EntityField; + + if (l.BoundEntityName != r.BoundEntityName) + { + throw new TranspilerSyntaxErrorException($"Column type mismatch for column '{z.LeftField.FieldAlias}': left='{l.BoundEntityName}', right='{r.BoundEntityName}'"); + } + } + else + { + Debug.Assert(z.LeftField is SingleField && z.RightField is SingleField); + var l = z.LeftField as SingleField; + var r = z.RightField as SingleField; + if (l.FieldType != r.FieldType) + { + throw new TranspilerSyntaxErrorException($"Column type mismatch for column '{z.LeftField.FieldAlias}': left='{l.FieldType}', right='{r.FieldType}'"); + } + } + } + + // Snap to the column names, type and order of the later sub-query + CopyFieldInfoHelper(OutputSchema, rightSchema); + } + + internal override void AppendReferencedProperties(IDictionary entityFields) + { + // NOOP. Set operators does not have addition referenced properties than those already on the output + } + } + + /// + /// Operator to satisfy JOIN + /// + public sealed class JoinOperator : BinaryLogicalOperator + { + /// + /// Keeps track of what entities are joint together + /// + private List _joinPairs = new List(); + + /// + /// Structure designate how two entity instance should be joined together + /// + public class JoinKeyPair + { + public enum JoinKeyPairType + { + None, + Source, // Node join to Rel's SourceId + Sink, // Node join to Rel's SinkId + Either, // Node allowed to join either Source or Sink, whichever is applicable + Both, // Node join to both source and sink + NodeId, // Node to node join + } + + public string NodeAlias { get; set; } + public string RelationshipOrNodeAlias { get; set; } + public JoinKeyPairType Type { get; set; } + + #region Equality comparison overrides + public override bool Equals(object obj) + { + var compObj = obj as JoinKeyPair; + return compObj?.Type == Type && + compObj?.NodeAlias == NodeAlias && + compObj?.RelationshipOrNodeAlias == RelationshipOrNodeAlias; + } + + public override int GetHashCode() + { + return FNVHash.GetFNVHash(Type, NodeAlias, RelationshipOrNodeAlias); + } + + public static bool operator ==(JoinKeyPair lhs, JoinKeyPair rhs) => lhs.Equals(rhs); + public static bool operator !=(JoinKeyPair lhs, JoinKeyPair rhs) => !lhs.Equals(rhs); + + #endregion Equality comparison overrides + + public override string ToString() + { + return $"JoinPair: Node={NodeAlias} RelOrNode={RelationshipOrNodeAlias} Type=({Type})"; + } + + } + + /// + /// Type of join + /// + public enum JoinType + { + // ordered from least constrained to most + Cross = 0, + Left = 1, + Inner = 2, + } + + public JoinOperator(LogicalOperator leftOp, LogicalOperator rightOp, JoinType joinType) + { + Type = joinType; + SetInOperators(leftOp, rightOp); + } + + /// + /// Type of join to be performed for this JOIN operator for all the join key pairs + /// + public JoinType Type { get; set; } + + /// + /// List of joins needed by this operator between entities from the input + /// + public IReadOnlyCollection JoinPairs { get { return _joinPairs.AsReadOnly(); } } + + public override string ToString() + { + var sb = new StringBuilder(base.ToString()); + sb.AppendLine($"Join Type: {Type};"); + sb.AppendLine($"Join Operations: {string.Join(", ", JoinPairs.Select(kv => $"{kv.NodeAlias} |><|_{kv.Type.ToString().First()} {kv.RelationshipOrNodeAlias}"))};"); + return sb.ToString(); + } + + internal override void PropagateInSchema() + { + // Input for JOIN is the combination of both sources + + var prevLeftSchema = InOperatorLeft.OutputSchema; + var prevRightSchema = InOperatorRight.OutputSchema; + var prevOutFields = prevLeftSchema.Union(prevRightSchema); + var fieldMapping = new Dictionary(); + + foreach (var inF in InputSchema) + { + var matchOutFields = prevOutFields.Where(f => f.FieldAlias == inF.FieldAlias); + if (matchOutFields.Count() > 1) + { + // In case of join by node ids between left and right input (such as in MATCH .. OPTIONAL MATCH ... WHERE case) + // we will take the from left side and ignore dups + // otherwise throws exception + if (!JoinPairs.All(jp => jp.Type == JoinKeyPair.JoinKeyPairType.NodeId)) + { + throw new TranspilerInternalErrorException($"Ambiguous match of field with alias '{inF.FieldAlias}'"); + } + } + if (matchOutFields.Count() == 0) + { + throw new TranspilerInternalErrorException($"Failed to match field with alias '{inF.FieldAlias}'"); + } + fieldMapping.Add(inF, matchOutFields.First()); + } + + CopyFieldInfoHelper(InputSchema, fieldMapping.Values); + + // additional validation on if relationships can satisfy the joins if directional traversal is explicitly specified + foreach (var joinPair in JoinPairs) + { + var nodeEntity = InputSchema.First(s => s.FieldAlias == joinPair.NodeAlias) as EntityField; + var relEntity = InputSchema.First(s => s.FieldAlias == joinPair.RelationshipOrNodeAlias) as EntityField; + switch (joinPair.Type) + { + case JoinKeyPair.JoinKeyPairType.Source: + if (relEntity.BoundSourceEntityName != nodeEntity.BoundEntityName) + { + throw new TranspilerBindingException($"Cannot find relationship ({nodeEntity.BoundEntityName})-[{relEntity.BoundSourceEntityName}]->(*), for {joinPair.NodeAlias} and {joinPair.RelationshipOrNodeAlias}"); + } + break; + case JoinKeyPair.JoinKeyPairType.Sink: + if (relEntity.BoundSinkEntityName != nodeEntity.BoundEntityName) + { + throw new TranspilerBindingException($"Cannot find relationship ({nodeEntity.BoundEntityName})<-[{relEntity.BoundSourceEntityName}]-(*), for {joinPair.NodeAlias} and {joinPair.RelationshipOrNodeAlias}"); + } + break; + default: + // in .Either, or .Both case + // no validation need to be done as Binding should already enforce the existence of the relationships + break; + } + } + } + + internal override void PropagateOutSchema() + { + // Output for JOIN depends on type of the join + // For LEFT join, attributes becomes non-nullable + // For CROSS join or INNER join, attributes type remains unchanged after join + if (Type == JoinType.Left) + { + var prevLeftSchema = InOperatorLeft.OutputSchema; + var prevRightSchema = InOperatorRight.OutputSchema; + + var fieldMapping = new Dictionary(); + foreach (var outField in OutputSchema) + { + var inFieldMatches = InputSchema.Where(f => f.FieldAlias == outField.FieldAlias); + Debug.Assert(InputSchema.Where(f => f.FieldAlias == outField.FieldAlias).Count() == 1); // must have match in IN for any OUT field + var inField = inFieldMatches.First(); + // we made it that left schema LEFT OUTTER JOIN with right schema always + var isFromRight = !prevLeftSchema.Any(f => f.FieldAlias == inField.FieldAlias); + + // copy over the schema first + outField.Copy(inField); + + // make adjustment for outter join + if (inField is SingleField) + { + Debug.Assert(outField.GetType() == inField.GetType()); // join doesn't alter field types + var outFieldSingleField = outField as SingleField; + + if (isFromRight && !TypeHelper.CanAssignNullToType(outFieldSingleField.FieldType)) + { + // make it nullable variant of the original type + outFieldSingleField.FieldType = TypeHelper.GetNullableTypeForType(outFieldSingleField.FieldType); + } + } + else + { + Debug.Assert(outField is EntityField); + var outEntCapFields = (outField as EntityField).EncapsulatedFields; + + if (isFromRight) + { + foreach (var outEntCapField in outEntCapFields) + { + if (!TypeHelper.CanAssignNullToType(outEntCapField.FieldType)) + { + // make it nullable variant of the original type + outEntCapField.FieldType = TypeHelper.GetNullableTypeForType(outEntCapField.FieldType); + } + } + } + } + } + + } + else + { + base.PropagateOutSchema(); + } + } + + internal override void AppendReferencedProperties(IDictionary entityFields) + { + // NOOP. Besides join keys, JOIN operator does not introduce any additionally referenced fields + // The handling of join key is left for later stage + } + + /// + /// For adding to the maintained list of what entities are joint together by this operator + /// + /// the alias on the left side of the join + /// the alias on the right side of the join + internal void AddJoinPair(JoinKeyPair joinKeyPair) + { + Debug.Assert(InputSchema.Where(f => f is EntityField && f.FieldAlias == joinKeyPair.NodeAlias).Count() == 1); + Debug.Assert(InputSchema.Where(f => f is EntityField && f.FieldAlias == joinKeyPair.RelationshipOrNodeAlias).Count() == 1); + _joinPairs.Add(joinKeyPair); + } + } +} diff --git a/src/LogicalPlanner/Logical/Schema.cs b/src/LogicalPlanner/Logical/Schema.cs new file mode 100644 index 0000000..a9c8769 --- /dev/null +++ b/src/LogicalPlanner/Logical/Schema.cs @@ -0,0 +1,237 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using openCypherTranspiler.Common.Exceptions; + +namespace openCypherTranspiler.LogicalPlanner +{ + /// + /// a field of a schema + /// + public abstract class Field + { + public Field(string alias) + { + FieldAlias = alias; + } + + /// + /// The local unique name (in current operator's context) to refer this field + /// + public string FieldAlias { get; set; } + + /// + /// Create a deep copy of this Field object + /// + /// + public abstract Field Clone(); + + /// + /// Copy the information from another field to itself (except for alias) + /// + public abstract void Copy(Field f); + } + + /// + /// A field which is an entity (a set of columns forming a node or edge stream/stream group) + /// + public class EntityField : Field + { + private ISet _referencedAliases = new HashSet(); + + public EntityField(string alias, string entityName, EntityType type) : base(alias) + { + EntityName = entityName; + Type = type; + } + + /// + /// Copy constructor + /// + /// + public EntityField(EntityField field) : base(field.FieldAlias) + { + Copy(field); + } + + public override void Copy(Field field) + { + var fieldSrc = field as EntityField; + Debug.Assert(fieldSrc != null); + this.EntityName = fieldSrc.EntityName; + this.Type = fieldSrc.Type; + this.BoundEntityName = fieldSrc.BoundEntityName; + this.BoundSourceEntityName = fieldSrc.BoundSourceEntityName; + this.BoundSinkEntityName = fieldSrc.BoundSinkEntityName; + this.NodeJoinField = fieldSrc.NodeJoinField?.Clone() as SingleField; + this.RelSinkJoinField = fieldSrc.RelSinkJoinField?.Clone() as SingleField; + this.RelSourceJoinField = fieldSrc.RelSourceJoinField?.Clone() as SingleField; + this.EncapsulatedFields = fieldSrc.EncapsulatedFields?.Select(f => f.Clone() as SingleField).ToList(); + _referencedAliases.Clear(); + this.AddReferenceFieldAliases(fieldSrc.ReferencedFieldAliases?.ToList()); + } + + public enum EntityType + { + Node, + Relationship + } + + /// + /// For node this is node name, for edge this is the edge verb + /// + public string EntityName { get; set; } + + /// + /// This is the name of the entity that this is eventually bound to in the graph definition + /// For node, it is usually same as EntityName, but for edge, it is the unique entity name + /// from the graph definition which is in the format of node_in-verb-node_out + /// + public string BoundEntityName { get; set; } + + /// + /// This is the name of the source entity name for this relationship (in the graph definition) + /// Only non null for edge type of entity + /// + public string BoundSourceEntityName { get; set; } + + /// + /// This is the name of the sink entity name for this relationship (in the graph definition) + /// Only non null for edge type of entity + /// + public string BoundSinkEntityName { get; set; } + + /// + /// If this entity is node or edge + /// + public EntityType Type { get; set; } + + /// + /// List of fields that this entity can expand into (namely, property reference) + /// + public IList EncapsulatedFields { get; set; } + + /// + /// Used for keep tracking what properties of this entity were actually accessed + /// + public IReadOnlyCollection ReferencedFieldAliases { get { return _referencedAliases.ToList().AsReadOnly(); } } + + /// + /// The field name for the node's join key + /// + public SingleField NodeJoinField { get; set; } + + /// + /// The field name for the edge's source join key + /// + public SingleField RelSourceJoinField { get; set; } + + /// + /// The field name for the relationship's sink join key + /// + public SingleField RelSinkJoinField { get; set; } + + + public override string ToString() + { + return $"{Type}Field: {FieldAlias}({EntityName})"; + } + + public override Field Clone() + { + return new EntityField(this); + } + + public void AddReferenceFieldAlias(string fieldAlias) + { + if(EncapsulatedFields.All(n => n.FieldAlias != fieldAlias)) + { + throw new TranspilerSyntaxErrorException($"field alias {fieldAlias} not existed in entity:{EntityName}."); + } + else if(!_referencedAliases.Contains(fieldAlias)) + { + _referencedAliases.Add(fieldAlias); + } + } + + public void AddReferenceFieldAliases(IEnumerable fieldAliases) + { + fieldAliases.ToList().ForEach(a => AddReferenceFieldAlias(a)); + } + + } + + /// + /// A field which is a column + /// + public class SingleField : Field + { + public SingleField(string alias) : base(alias) { } + + /// + /// Copy constructor + /// + /// + public SingleField(SingleField field) : base(field.FieldAlias) + { + Copy(field); + } + + public SingleField(string alias, Type fieldType) : base(alias) + { + FieldType = fieldType; + } + + public override void Copy(Field field) + { + var fieldSrc = field as SingleField; + Debug.Assert(fieldSrc != null); + this.FieldType = fieldSrc.FieldType; + } + + public Type FieldType { get; set; } + + + public override string ToString() + { + return $"Field: {FieldAlias}{(FieldType == default(Type) ? "(?)" : $"({FieldType.Name})")}"; + } + + public override Field Clone() + { + return new SingleField(this); + } + } + + + /// + /// a collection of fields represent the schema of input or output of a logical operator + /// + public class Schema : List + { + public Schema() + { + } + + /// + /// Copy constructor + /// + /// + public Schema(Schema schema) + { + AddRange(schema.Select(f => f.Clone()).ToList()); + } + + public Schema(IEnumerable fields) + { + AddRange(fields.ToList()); + } + + } +} diff --git a/src/LogicalPlanner/LogicalPlan.cs b/src/LogicalPlanner/LogicalPlan.cs new file mode 100644 index 0000000..0c356f7 --- /dev/null +++ b/src/LogicalPlanner/LogicalPlan.cs @@ -0,0 +1,1099 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using openCypherTranspiler.Common.Exceptions; +using openCypherTranspiler.Common.GraphSchema; +using openCypherTranspiler.Common.Logging; +using openCypherTranspiler.Common.Utils; +using openCypherTranspiler.openCypherParser.AST; +using openCypherTranspiler.LogicalPlanner.Utils; + +namespace openCypherTranspiler.LogicalPlanner +{ + public class LogicalPlan + { + private ILoggable _logger; + + public LogicalPlan(ILoggable logger) + { + _logger = logger; + } + + /// + /// return a set of operators that are starting points of the logical plan + /// + public IEnumerable StartingOperators { get; private set; } + + /// + /// return a set of operators that are terminal of the logical plan (representing the output) + /// + public IEnumerable TerminalOperators { get; private set; } + + /// + /// Create an instance of LogicalPlanner with a given query AST tree + /// + /// + /// + /// + public static LogicalPlan ProcessQueryTree(QueryTreeNode treeRoot, IGraphSchemaProvider graphDef, ILoggable logger = null) + { + var logicalPlanner = new LogicalPlan(logger); + var allLogicalOps = new HashSet(); + + // from AST, create the logical plan + var logicalRoot = logicalPlanner.CreateLogicalTree(treeRoot, allLogicalOps); + logicalPlanner.StartingOperators = logicalRoot.GetAllUpstreamOperatorsOfType().ToList(); + logicalPlanner.TerminalOperators = new List(1) { logicalRoot }; + + // bind logical tree with the graph schema + var bindableStartingOp = logicalPlanner.StartingOperators.Where(op => op is IBindable); + bindableStartingOp.ToList().ForEach(op => (op as IBindable).Bind(graphDef)); + + // propagate down the schema from starting operator and data types (top down) + logicalPlanner.PropagateDataTypes(); + + // expand and optimize out columns not used (bottom up) + logicalPlanner.UpdateActualFieldReferencesForEntityFields(); + + // note: in this function, we only deal with graph definition. + // later in code generatation phase, we deal with Cosmos storage descriptors + // which then worries the details of what streams to pull + + // verify that no dangling operator exists + var i = 0; + foreach (var op in allLogicalOps) + { + op.OperatorDebugId = ++i; + } + + var allOpsFromTraversal = logicalPlanner.StartingOperators.SelectMany(op => op.GetAllDownstreamOperatorsOfType()).Distinct().OrderBy(op => op.OperatorDebugId).ToList(); + var allOpsFromBuildingTree = allLogicalOps.OrderBy(op => op.OperatorDebugId).ToList(); + Debug.Assert(allOpsFromTraversal.Count == allOpsFromBuildingTree.Count); + + return logicalPlanner; + } + + /// + /// Dump textual format of the logical plan + /// + /// + public virtual string DumpGraph() + { + var sb = new StringBuilder(); + var allOperators = StartingOperators + .SelectMany(op => op.GetAllDownstreamOperatorsOfType()) + .Distinct() + .GroupBy(op => op.Depth) + .OrderBy(g => g.Key); + + foreach (var opGrp in allOperators) + { + sb.AppendLine($"Level {opGrp.Key}:"); + sb.AppendLine("--------------------------------------------------------------------------"); + foreach (var op in opGrp) + { + sb.AppendLine($"OpId={op.OperatorDebugId} Op={op.GetType().Name}; InOpIds={string.Join(",", op.InOperators.Select(n => n.OperatorDebugId))}; OutOpIds={string.Join(",", op.OutOperators.Select(n => n.OperatorDebugId))};"); + sb.AppendLine(op.ToString().ChangeIndentation(1)); + sb.AppendLine("*"); + } + sb.AppendLine("--------------------------------------------------------------------------"); + } + return sb.ToString(); + } + + /// + /// Create logical operator tree for a given query AST tree + /// + /// + /// + private LogicalOperator CreateLogicalTree(QueryTreeNode treeNode, ISet allLogicalOps) + { + // Example of logical tree to be created: + // MATCH (a:n1)-[b:r1]-(c:n2) + // WITH a as c, c as a + // OPTIONAL MATCH (c)-[:r2]-(a) + // WHERE a.id = "some id" + // RETURN a.id as Id + // + // The logical tree looks like: + // DS(a:n1) DS(b:r1) DS(c:n2) + // \ / / + // \ / / + // InJoin(a:n1, b:r1) / + // \ / + // \ / + // InJoin(InJoin(...), c:n2) + // | + // Projection(a->c, c->a) DS(:r2) + // \ / + // \ / + // LfJoin(Proj, :r2) + // | + // Sel(a.id = 'some id') + // | + // Projection(a.id -> Id) + + + // inorder walk of the tree to evaulate individual queries + if (treeNode is SingleQueryTreeNode) + { + // single query + return CreateLogicalTree(treeNode as SingleQueryTreeNode, allLogicalOps); + } + else + { + Debug.Assert(treeNode is InfixQueryTreeNode); + return CreateLogicalTree(treeNode as InfixQueryTreeNode, allLogicalOps); + } + } + + /// + /// Create logical oeprator tree for sub-tree node type InfixQueryTreeNode + /// + /// + /// + private BinaryLogicalOperator CreateLogicalTree(InfixQueryTreeNode treeNode, ISet allLogicalOps) + { + var left = CreateLogicalTree(treeNode.LeftQueryTreeNode, allLogicalOps); + var right = CreateLogicalTree(treeNode.RightQueryTreeNode, allLogicalOps); + + // TODO: better way of ensure schema is the same + Debug.Assert(left.OutputSchema.Count == left.OutputSchema.Count); + + SetOperator.SetOperationType op; + switch (treeNode.Operator) + { + case InfixQueryTreeNode.QueryOperator.Union: + op = SetOperator.SetOperationType.Union; + break; + case InfixQueryTreeNode.QueryOperator.UnionAll: + op = SetOperator.SetOperationType.UnionAll; + break; + default: + throw new TranspilerInternalErrorException($"Unimplemented operator type: {treeNode.Operator}"); + } + + var setOp = new SetOperator(left, right, op); + setOp.InputSchema = new Schema(left.InputSchema); + setOp.OutputSchema = new Schema(left.InputSchema); // the schema remains the same for setoperator + allLogicalOps.Add(setOp); + + return setOp; + } + + /// + /// Create logical operator for AST node type SingleQueryTreeNode + /// + /// + /// + private LogicalOperator CreateLogicalTree(SingleQueryTreeNode treeNode, ISet allLogicalOps) + { + var stack = new Stack(); + PartialQueryTreeNode lastVisited = treeNode.PipedData; + + while (lastVisited != null) + { + stack.Push(lastVisited); + lastVisited = lastVisited.PipedData; + } + + // maintain a list of query parts that we may collapse for optimization + var pureMatchChainQueries = new List(); + // maintain a pointer to the last logical operator that need to chained into next operator to be created + LogicalOperator lastOperator = null; + PartialQueryTreeNode curNode = null; + PartialQueryTreeNode prevNode = null; + var finalProjectedExprs = treeNode.EntityPropertySelected; + while (stack.Any()) + { + prevNode = curNode; + curNode = stack.Pop(); + lastOperator = CreateLogicalTree(curNode, lastOperator, allLogicalOps, prevNode); + } + + // chain with another selection operator there are ORDER BY + LIMIT combination clause + // Single ORDER BY or Single LIMIT will not be compiled in SCOPE, skipped here + if (treeNode.EntityRowsLimit?.Count() > 0 && treeNode.EntityPropertyOrderBy?.Count() > 0) + { + var limitExpr = treeNode.EntityRowsLimit; + var orderExpr = treeNode.EntityPropertyOrderBy; + lastOperator = CreateLogicalTree(orderExpr, limitExpr, lastOperator, allLogicalOps); + + // TODO: Add more expression that came from previous partial query tree node + var appendedProjExpr = treeNode.EntityPropertySelected; + var newProjExpr = curNode?.ProjectedExpressions?.Where(n => appendedProjExpr.All(p => p.Alias != n.Alias)); + + // flag true if any selected properties has aggregation function. + var hasAggregationExpression = false; + if (treeNode.EntityPropertySelected.Any(n => n.GetChildrenQueryExpressionType().Count() > 0)) + { + hasAggregationExpression = true; + } + + appendedProjExpr = (newProjExpr == null || treeNode.IsDistinct || hasAggregationExpression? appendedProjExpr : appendedProjExpr.Union(newProjExpr).ToList()); + lastOperator = CreateLogicalTree(appendedProjExpr, treeNode.IsDistinct, lastOperator, allLogicalOps); + + finalProjectedExprs = finalProjectedExprs.Select(n => + { + var property = n.GetChildrenQueryExpressionType().FirstOrDefault(); + if (property?.Entity == null) + { + return new QueryExpressionWithAlias + { + Alias = n.Alias, + InnerExpression = new QueryExpressionProperty() + { + VariableName = n.Alias, + DataType = null, + Entity = null, + PropertyName = null + } + }; + } + else + { + return n; + } + }).ToList(); + + // if distinct case, we currently don't support entity field in the order by statement. + // For example: + // RETURN DISTINCT a.Name as Name, b.Address as Address + // ORDER BY a.Name + // LIMIT 10 + if ((treeNode.IsDistinct || hasAggregationExpression) && orderExpr.Any(n => + { + var properties = n.GetChildrenQueryExpressionType(); + if(properties != null && properties.Any(k => k.PropertyName!=null && k.VariableName != null)) + { + return true; + } + return false; + })) + { + throw new TranspilerNotSupportedException("ORDER BY X.XXX under RETURN DISTINCT clause/RETURN with aggregation function"); + } + + } + + // add the final projection operator for the fields select in the wrapping Single Query tree node, which + // has only Projection and PipedData + Debug.Assert(lastOperator != null); + Debug.Assert((treeNode.EntityPropertySelected?.Count ?? 0) > 0); + + // Block the attempt to return entities as we don't support this anywhere today + if (treeNode.EntityPropertySelected.Any(p => p.TryGetDirectlyExposedEntity() != null)) + { + throw new TranspilerNotSupportedException + ($"Query final return body returns the whole entity {treeNode.EntityPropertySelected.First(p => p.TryGetDirectlyExposedEntity() != null).Alias} instead of its fields"); + } + + var finalProjOperator = CreateLogicalTree(finalProjectedExprs, treeNode.IsDistinct, lastOperator, allLogicalOps); + return finalProjOperator; + } + + /// + /// Create filtering operator for query expressions + /// + /// + /// + /// + /// + private LogicalOperator CreateLogicalTree(QueryExpression exp, LogicalOperator pipedData, ISet allLogicalOps) + { + var selectionOp = new SelectionOperator(pipedData, exp); + selectionOp.InputSchema = new Schema(pipedData.OutputSchema); + selectionOp.OutputSchema = new Schema(pipedData.OutputSchema); // the schema remains the same for SelectionOperator + allLogicalOps.Add(selectionOp); + return selectionOp; + } + + /// + /// creating selection operator for ORDER BY ... LIMIT clause + /// + /// + /// + /// + /// + private LogicalOperator CreateLogicalTree( + IList orderExp, + IList limitExp, + LogicalOperator pipedData, + ISet allLogicalOps) + { + var selectionOp = new SelectionOperator(pipedData, orderExp, limitExp); + var selectionSchema = new Schema(pipedData.OutputSchema); + + // append new property from ORDER BY clause to the the input and output schema + + selectionOp.InputSchema = new Schema(selectionSchema); + selectionOp.OutputSchema = new Schema(selectionSchema); + allLogicalOps.Add(selectionOp); + return selectionOp; + } + + /// + /// Create filtering operator for unexpanded inequality expression + /// + /// + /// + /// + /// + private LogicalOperator CreateLogicalTree(IEnumerable<(string RelAlias1, string RelAlias2)> conds, LogicalOperator pipedData, ISet allLogicalOps) + { + var selectionOp = new SelectionOperator(pipedData, conds); + selectionOp.InputSchema = new Schema(pipedData.OutputSchema); + selectionOp.OutputSchema = new Schema(pipedData.OutputSchema); // the schema remains the same for SelectionOperator + allLogicalOps.Add(selectionOp); + return selectionOp; + } + + /// + /// Create projection operator + /// + /// + /// + /// + /// + /// + private LogicalOperator CreateLogicalTree(IList projExprs, bool isDistinct, LogicalOperator pipedData, ISet allLogicalOps) + { + // Do a projection + var outputSchemaFields = pipedData.OutputSchema.OrderBy(f => f.FieldAlias); + var expectedOutputSchemaFields = projExprs.Select(expr => + { + var innerExpr = expr.InnerExpression; + var entity = innerExpr.TryGetDirectlyExposedEntity(); + if (entity != null) + { + return new EntityField( + expr.Alias, + entity.EntityName, + entity is NodeEntity ? EntityField.EntityType.Node : EntityField.EntityType.Relationship + ) as Field; + } + else + { + return new SingleField( + expr.Alias + ) as Field; + } + }).ToList(); + + // TODO: + // verify that we are able to honor the projection by comparing In and OutFields + + // construct the projection logical operator + var inSchema = new Schema(pipedData.OutputSchema.Select(f => f.Clone())); + var outSchema = new Schema(expectedOutputSchemaFields); + var projOperator = new ProjectionOperator( + pipedData, + projExprs.ToDictionary(exp => exp.Alias, exp => exp.InnerExpression), + isDistinct + ); + projOperator.InputSchema = inSchema; + projOperator.OutputSchema = outSchema; + allLogicalOps.Add(projOperator); + + return projOperator; + } + + /// + /// Create join operator to join two set of operators with a list of entity aliases of instances of node which their id should be used in equi-join + /// + /// + /// + /// the list of aliases (in the output of left/right) that represents entity instances and should be used in nodeid equi-join + /// if false, the join type assumed to be would be inner instead + /// + /// + private LogicalOperator CreateLogicalTree(LogicalOperator left, LogicalOperator right, IEnumerable entityAliasesToJoin, bool isLeftOutterJoin, ISet allLogicalOps) + { + var joinPairs = entityAliasesToJoin + .Select(a => new JoinOperator.JoinKeyPair() + { + NodeAlias = a, + RelationshipOrNodeAlias = a, + Type = JoinOperator.JoinKeyPair.JoinKeyPairType.NodeId + }) + .ToList(); + + if (joinPairs.Count > 0) + { + // left outter join or inner join (depending on the parameter) + var newOp = new JoinOperator(left, right, isLeftOutterJoin ? JoinOperator.JoinType.Left : JoinOperator.JoinType.Inner); + var fields = left.OutputSchema.Union(right.OutputSchema) + .Select(f => f.Clone()) + .GroupBy(f => f.FieldAlias) + .Select(f => f.First()); + newOp.InputSchema = new Schema(fields); + newOp.OutputSchema = new Schema(fields); + joinPairs.ForEach(jp => newOp.AddJoinPair(jp)); + allLogicalOps.Add(newOp); + return newOp; + } + else + { + // cross join + var newOp = new JoinOperator(left, right, JoinOperator.JoinType.Cross); + var fields = left.OutputSchema.Union(right.OutputSchema) + .Select(f => f.Clone()) + .GroupBy(f => f.FieldAlias) + .Select(f => f.First()); + newOp.InputSchema = new Schema(fields); + newOp.OutputSchema = new Schema(fields); + allLogicalOps.Add(newOp); + return newOp; + } + } + + /// + /// Create logical operators for a partial query part + /// + /// + /// + /// + /// + private LogicalOperator CreateLogicalTree(PartialQueryTreeNode treeNode, LogicalOperator pipedData, ISet allLogicalOps, PartialQueryTreeNode previousNode) + { + LogicalOperator lastOperator = pipedData; + + if (treeNode.MatchData != null) + { + // comes with additional Match statements + var isOptionalMatch = treeNode.MatchData.MatchPatterns.Any(p => p.IsOptionalMatch); + Debug.Assert(treeNode.MatchData.MatchPatterns.All(p => p.IsOptionalMatch == isOptionalMatch)); + + if (treeNode.PostCondition != null) + { + // with filtering conditions, optional match requires a fork to apply filtering first and then rejoin with piped data, + // where non-optional doesn't require it + // e.g. MATCH ... OPTIONAL MATCH ... WHERE ... WITH/RETURN ... + if (isOptionalMatch) + { + // apply filtering conditions to the optional match pattern then left outter join back with the piped data + var modifiedMatch = new MatchDataSource() + { + MatchPatterns = treeNode.MatchData.MatchPatterns.Select(p => new MatchPattern(false, p)).ToList() + }; + var omOperator = CreateLogicalTree(modifiedMatch, lastOperator, allLogicalOps); + var condOmOperator = CreateLogicalTree(treeNode.PostCondition, omOperator, allLogicalOps); + + var leftEntityAliases = lastOperator.OutputSchema + .Where(f => f is EntityField).Select(f => (f as EntityField).FieldAlias); + var explicitlyMatchedAliasesToJoinWithLeft = modifiedMatch.AllEntitiesOrdered + .Select(e => e.Alias) + .Where(a => a != null) + .Intersect(leftEntityAliases); + lastOperator = CreateLogicalTree(lastOperator, condOmOperator, explicitlyMatchedAliasesToJoinWithLeft, true, allLogicalOps); + } + else + { + // join with match data + lastOperator = CreateLogicalTree(treeNode.MatchData, lastOperator, allLogicalOps); + // apply filtering + lastOperator = CreateLogicalTree(treeNode.PostCondition, lastOperator, allLogicalOps); + } + } + else + { + // without filtering conditions, optional and non-optional match are processed similarly (except for the join type) + // e.g. MATCH ... OPTIONAL MATCH ... WITH/RETURN ... + lastOperator = CreateLogicalTree(treeNode.MatchData, lastOperator, allLogicalOps); + } + // Do projection + lastOperator = CreateLogicalTree(treeNode.ProjectedExpressions, treeNode.IsDistinct, lastOperator, allLogicalOps); + } + else + { + // Order By need to pair with limit in order to compilable in scope + var isValidOrderByClausePair = (treeNode.LimitExpression?.Count() > 0 && treeNode.OrderByExpression?.Count() > 0); + var isExtraCollectionProjectionNeeded = (treeNode.PostCondition != null || isValidOrderByClausePair); + var appendedProjExpr = treeNode.ProjectedExpressions; + var hasAggregationExpression = false; + + if (treeNode.ProjectedExpressions.SelectMany(n => n.GetChildrenQueryExpressionType()).Count() > 0) + { + hasAggregationExpression = true; + } + + // "DISTINCT" acted like another "WITH" clause: downstream ORDER BY, WHERE can only use field from WITH clause + // if no DISTINCT, collect field information from previous tree node + // if has DISTINCT, no need to collect from previous one for the behavior of DISTINCT descrived above + // Example: + // WITH DISTINCT a.Name as Name, b.Title as Title + // ORDER BY Name, Title + // WHERE Name <> "Tom" + // RETURN Name, Title + // ** ORDER BY/WHERE can only refer Name, Title as there is a DISTINCT + // + // if no distinct + // WITH a.Name as Name, b.Title as Title + // ORDER BY a.Tagline, n.Price + // WHERE Name <> "Tom" + // RETURN Name, Title + // ** ORDER BY/WHERE can refer any field in a and b + + + if (!treeNode.IsDistinct && previousNode != null && !hasAggregationExpression) + { + var newProjExpr = previousNode.ProjectedExpressions.Where(n => appendedProjExpr.All(p =>p.Alias!= n.Alias)); + appendedProjExpr = (newProjExpr== null? appendedProjExpr: appendedProjExpr.Union(newProjExpr).ToList()); + lastOperator = CreateLogicalTree(appendedProjExpr, treeNode.IsDistinct, lastOperator, allLogicalOps); + } + else + { + lastOperator = CreateLogicalTree(treeNode.ProjectedExpressions, treeNode.IsDistinct, lastOperator, allLogicalOps); + } + + // Do trimming the non-entity field by removing redundant calculation and changed it to Alias AS Alias + // The reason for trimming: related calculation was already done in previous steps. Only need to refer the alias and return. + var trimmedProjExpr = appendedProjExpr.Select(n => + { + var property = n.GetChildrenQueryExpressionType().FirstOrDefault(); + if (property?.Entity == null) + { + return new QueryExpressionWithAlias + { + Alias = n.Alias, + InnerExpression = new QueryExpressionProperty() + { + VariableName = n.Alias, + DataType = null, + Entity = null, + PropertyName = null + } + }; + } + else + { + return n; + } + }).ToList(); + + // chain with another selection operator there are ORDER BY + LIMIT combination clause + // Single ORDER BY or Single LIMIT will not be compiled in SCOPE, skipped here + if (isValidOrderByClausePair) + { + var limitExpr = treeNode.LimitExpression; + var orderExpr = treeNode.OrderByExpression; + lastOperator = CreateLogicalTree(orderExpr, limitExpr, lastOperator, allLogicalOps); + // projection operator "after order by" selection operator + lastOperator = CreateLogicalTree(trimmedProjExpr, treeNode.IsDistinct, lastOperator, allLogicalOps); + } + + if (treeNode.PostCondition != null) + { + // without match, we can just apply filtering if needed (e.g. WITH ... WHERE ...) + lastOperator = CreateLogicalTree(treeNode.PostCondition, lastOperator, allLogicalOps); + // projection operator after "where" selection operator + lastOperator = CreateLogicalTree(trimmedProjExpr, treeNode.IsDistinct, lastOperator, allLogicalOps); + } + // Do the last projection in the WITH statement. + // Since all the schema was already mapped to the target aliases in the previous projection operators, only direct mapping needed. + // target -> target + // eg. a.Name as Name : Name -> Name + // a as b: b -> b (at here 'a' can be a entity or can be a property. + var finalProjExpr = treeNode.ProjectedExpressions.Select(n => + { + var property = n.GetChildrenQueryExpressionType().FirstOrDefault(); + return new QueryExpressionWithAlias + { + Alias = n.Alias, + InnerExpression = new QueryExpressionProperty() + { + VariableName = n.Alias, + DataType = null, + Entity = property?.Entity, + PropertyName = null + } + }; + }).ToList(); + + lastOperator = CreateLogicalTree(finalProjExpr, treeNode.IsDistinct, lastOperator, allLogicalOps); + } + return lastOperator; + } + + /// + /// This function takes 2 entities and returns in a determinstic order of their aliases: + /// It guarantees that the order is that if node is the src of edge, then [node, edge] + /// otherwise [edge, node] + /// + /// + /// + /// + private JoinOperator.JoinKeyPair GetJoinKeyPairInProperOrder(Entity prevEnt, Entity ent) + { + Debug.Assert(prevEnt.GetType() != ent.GetType()); // must be one node and one relationship + var relEntity = (prevEnt is RelationshipEntity ? prevEnt : ent) as RelationshipEntity; + var nodeEntity = (prevEnt is RelationshipEntity ? ent : prevEnt) as NodeEntity; + JoinOperator.JoinKeyPair.JoinKeyPairType joinKeyType; + + if (relEntity.RelationshipDirection == RelationshipEntity.Direction.Both) + { + if (relEntity.LeftEntityName == relEntity.RightEntityName) + { + // TODO: in future, we can support this and set the joinKeyType to .Both. This requires + // we add support in codegen to produce a data source that has src/sink key reversed unioned with itself + throw new TranspilerNotSupportedException("Consider specifying the direction of traversal <-[]- or -[]->. Directionless traversal for relationship with same type of source and sink entity"); + } + joinKeyType = JoinOperator.JoinKeyPair.JoinKeyPairType.Either; + } + else + { + if (prevEnt == nodeEntity) + { + joinKeyType = relEntity.RelationshipDirection == RelationshipEntity.Direction.Forward ? + JoinOperator.JoinKeyPair.JoinKeyPairType.Source : + JoinOperator.JoinKeyPair.JoinKeyPairType.Sink; + } + else + { + joinKeyType = relEntity.RelationshipDirection == RelationshipEntity.Direction.Forward ? + JoinOperator.JoinKeyPair.JoinKeyPairType.Sink : + JoinOperator.JoinKeyPair.JoinKeyPairType.Source; + } + } + + return new JoinOperator.JoinKeyPair() + { + NodeAlias = nodeEntity.Alias, + RelationshipOrNodeAlias = relEntity.Alias, + Type = joinKeyType + }; + } + + /// + /// Create logical operators for MatchDataSource + /// + /// + /// + /// + /// + private LogicalOperator CreateLogicalTree(MatchDataSource matchData, LogicalOperator pipedData, ISet allLogicalOps) + { + // turn linear match patterns into logical operators + + var boolComparer = Comparer.Create((b1, b2) => b1 ? (b2 ? 0 : 1) : (!b2 ? 0 : -1)); // comparer is true > false + var anonVarPrefix = "__unnamed_"; + + // first build a table of alias to entity, and make sure that every entity + // reference has a previously given or assigned alias + var namedMatchData = matchData.AssignGeneratedEntityAliasToAnonEntities(anonVarPrefix); + var aliasGroups = namedMatchData + .AllEntitiesOrdered + .Select((p, i) => new { Order = i, Entity = p }) + .GroupBy(p => p.Entity.Alias); + var firstDupRelAlias = aliasGroups + .Where(g => g.Any(e => e.Entity is RelationshipEntity)) + .FirstOrDefault(g => g.Count() > 1); + if (firstDupRelAlias != null) + { + // relationship label should not be repeated in the same MATCH clause + throw new TranspilerNotSupportedException($"Cannot use the same relationship variable '{firstDupRelAlias.Key}' for multiple patterns"); + } + var aliasTable = aliasGroups + .Select(p => + { + // Assert that we only have one type of entity per alias + Debug.Assert(p.Select(e => e.Entity.EntityName).Distinct().Count() == 1); + Debug.Assert(p.Select(e => e.GetType()).Distinct().Count() == 1); + return p.First(); + }) + .OrderBy(p => p.Order) + .Select((p, i) => new { Order = i, Entity = p.Entity }) + .ToDictionary(kv => kv.Entity.Alias, kv => kv); + + // build an adjancency matrix represent the DAG for the join logical operator each alias in the form of an array[Dim1, Dim2] + // note that the list of DataSourceOperator are added to allLogicalOps later in the code after recociling with inherited entities + var logicOpSrcTable = aliasTable.ToDictionary(kv => kv.Key, kv => new DataSourceOperator(kv.Value.Entity) as LogicalOperator); + + // build adjancency matrix with element being the join type between the two entities + // alias1, alias2, alias3, ... (Dim 1) + // alias1 NA INNER LEFT + // alias2 NA LEFT + // alias3 NA + // ... + // (Dim 2) + var entityJoinMatrix = new JoinOperator.JoinType[logicOpSrcTable.Count, logicOpSrcTable.Count]; + + // build join operator matrix to record the state if logical join operator already created or not + // between two alias (this will be used later to construct the logical join op creation) + var hasJoined = new bool[logicOpSrcTable.Count, logicOpSrcTable.Count]; + + for (int k = 0; k < entityJoinMatrix.GetLength(0); k++) + { + for (int l = 0; l < entityJoinMatrix.GetLength(1); l++) + { + entityJoinMatrix[k, l] = (k == l ? JoinOperator.JoinType.Inner : JoinOperator.JoinType.Cross); + hasJoined[k, l] = (k == l ? true : false); + } + } + + // if some of the entity referenced are inherited from previous query, such as following overlapping case + // where some entities returned from previous query parts are referenced in current MATCH patterns + // MATCH (a) + // WITH a as b + // MATCH (b)-[c]->(d) ... + // we will + // - update the logical operator table to replace the DataSource with the inherited logical operator instead of + // the default DS(n) + // - update hasJoined table to indicate those entities piped in were already in the inherited logical operater + // then we will get the transitive closure of the hasJoined table to show what are the group of entities that + // are linked together + var additionalCrossJoinOp = new List(); + var inheritedEntityAliases = pipedData?.OutputSchema + .Where(f => f is EntityField).Select(f => (f as EntityField).FieldAlias) + .Intersect(aliasTable.Keys).ToList(); + if (pipedData != null) + { + if (inheritedEntityAliases.Count > 0) + { + string prevEntAlias = inheritedEntityAliases.First(); + logicOpSrcTable[prevEntAlias] = pipedData; + + foreach (var entAlias in inheritedEntityAliases.Skip(1)) + { + logicOpSrcTable[entAlias] = pipedData; + + var prevEntityAliasIdx = aliasTable[prevEntAlias].Order; + var entityAliasIdx = aliasTable[entAlias].Order; + hasJoined[prevEntityAliasIdx, entityAliasIdx] = true; + hasJoined[entityAliasIdx, prevEntityAliasIdx] = true; + } + } + else + { + // there's no overlapping, the piped data will be cross joined + additionalCrossJoinOp.Add(pipedData); + } + } + hasJoined = hasJoined.TransitiveClosure(boolComparer); + logicOpSrcTable.Values.Where(op => op is DataSourceOperator).Cast().ToList() + .ForEach(op => + { + op.OutputSchema = new Schema + ( + new List(1) + { + new EntityField( + op.Entity.Alias, + op.Entity.EntityName, + op.Entity is NodeEntity ? EntityField.EntityType.Node : EntityField.EntityType.Relationship + ) as Field + } + ); + allLogicalOps.Add(op); + }); + + // process the matching patterns to update the adjancency matrix + var entitiesPartOfNonOptionalMatch = namedMatchData.MatchPatterns + .Where(p => p.IsOptionalMatch == false) + .SelectMany(p => p) + .Select(e => e.Alias) + .Union(inheritedEntityAliases ?? Enumerable.Empty()) + .Distinct(); + foreach (var matchPattern in namedMatchData.MatchPatterns) + { + Entity prevEnt = matchPattern.First(); + int prevEntIdx = aliasTable[prevEnt.Alias].Order; + + foreach (var ent in matchPattern.Skip(1)) + { + var curEntIdx = aliasTable[ent.Alias].Order; + // left join only if current is pattern is optional match + // and one of the entity already appears in non-optional match + // pattern or is inhertied from previous query part + bool isLeftJoin = + matchPattern.IsOptionalMatch && + (entitiesPartOfNonOptionalMatch.Contains(prevEnt.Alias) != entitiesPartOfNonOptionalMatch.Contains(ent.Alias)); + switch (entityJoinMatrix[prevEntIdx, curEntIdx]) + { + case JoinOperator.JoinType.Cross: + case JoinOperator.JoinType.Left: + // if CROSS or LEFT, left it up to LEFT or INNER, respectively + entityJoinMatrix[prevEntIdx, curEntIdx] = isLeftJoin ? JoinOperator.JoinType.Left : JoinOperator.JoinType.Inner; + entityJoinMatrix[curEntIdx, prevEntIdx] = entityJoinMatrix[prevEntIdx, curEntIdx]; + break; + default: + // do nothing if it is INNER, already highest constrained join + break; + } + + prevEnt = ent; + prevEntIdx = aliasTable[ent.Alias].Order; + } + } + + // get the transitive closure of the DAG + var entityJoinMatrixClosure = entityJoinMatrix.TransitiveClosure(); + + // we update the logical operator table (logicOpSrcTable) based on the match patterns + // we do it in 3 passes: + // - inner join first + // - left join second + // - cross join last + // + // e.g. Match (a)-[b]-(c), (e), (a)-[d]-(c) + // Start: + // a, DataSource(a) + // b, DataSource(b) + // c, DataSource(c) + // d, DataSource(d) + // e, DataSource(e) + // After processing the first MatchPattern: (a)-[b]-(c): + // a, Join(Join(DataSource(a), DataSource(b)), DataSource(c)) + // b, Join(Join(DataSource(a), DataSource(b)), DataSource(c)) + // c, Join(Join(DataSource(a), DataSource(b)), DataSource(c)) + // d, DataSource(d) + // e, DataSource(e) + // After processin the second MatchPattern: (e) + // // no change as (e) does not have + // After processing the third MatchPattern: (a)-[d]-(c) + // a, Join(Join(Join(DataSource(a), DataSource(b)), DataSource(c)), DataSource(d)) + // b, Join(Join(Join(DataSource(a), DataSource(b)), DataSource(c)), DataSource(d)) + // c, Join(Join(Join(DataSource(a), DataSource(b)), DataSource(c)), DataSource(d)) + // d, Join(Join(Join(DataSource(a), DataSource(b)), DataSource(c)), DataSource(d)) + // e, DataSource(e) + // Post processing by cross product any disjoint parts: + // a, CrossJoin(Join(Join(Join(DataSource(a), DataSource(b)), DataSource(c)), DataSource(d)), DataSource(e)) + // b, CrossJoin(Join(Join(Join(DataSource(a), DataSource(b)), DataSource(c)), DataSource(d)), DataSource(e)) + // c, CrossJoin(Join(Join(Join(DataSource(a), DataSource(b)), DataSource(c)), DataSource(d)), DataSource(e)) + // d, CrossJoin(Join(Join(Join(DataSource(a), DataSource(b)), DataSource(c)), DataSource(d)), DataSource(e)) + // e, CrossJoin(Join(Join(Join(DataSource(a), DataSource(b)), DataSource(c)), DataSource(d)), DataSource(e)) + + // get a list of unique field joins need to be performed from the traversals + var joinPairs = new Dictionary, JoinOperator.JoinKeyPair>(); + foreach (var matchPattern in namedMatchData.MatchPatterns) + { + for (var patIdx = 1; patIdx < matchPattern.Count; patIdx++) + { + // the order is that if node is the src of edge, then [node, edge] + // otherwise [edge, node] + Entity prevEnt = matchPattern[patIdx-1]; + var ent = matchPattern[patIdx]; + var joinPair = GetJoinKeyPairInProperOrder(prevEnt, ent); + var key = new KeyValuePair(joinPair.NodeAlias, joinPair.RelationshipOrNodeAlias); + JoinOperator.JoinKeyPair existingJoinPair; + if (joinPairs.TryGetValue(key, out existingJoinPair)) + { + // update/validate if already observed the same join and maybe of differen type + // update paths: + // either -> { left, right, both } + // left -> {both} + // right -> {both} + // all others are invalid if not equal + if (existingJoinPair.Type != joinPair.Type) + { + if (existingJoinPair.Type == JoinOperator.JoinKeyPair.JoinKeyPairType.Either || + joinPair.Type == JoinOperator.JoinKeyPair.JoinKeyPairType.Both) + { + joinPairs[key] = joinPair; + } + else + { + // conflict + throw new TranspilerBindingException($"Conflicting traversal detected between '{joinPair.NodeAlias}' and '{joinPair.RelationshipOrNodeAlias}'"); + } + } + } + else + { + joinPairs.Add(key, joinPair); + } + } + } + + // pass 'inner join' then pass 'left join' + for (var passType = JoinOperator.JoinType.Inner; passType >= JoinOperator.JoinType.Left; passType--) + { + foreach (var matchPattern in namedMatchData.MatchPatterns) + { + Entity prevEnt = matchPattern.First(); + int prevEntIdx = aliasTable[prevEnt.Alias].Order; + + for (var patIdx = 1; patIdx < matchPattern.Count; patIdx++) + { + var ent = matchPattern[patIdx]; + var curEntIdx = aliasTable[ent.Alias].Order; + var joinType = entityJoinMatrixClosure[prevEntIdx, curEntIdx]; + var joinPair = GetJoinKeyPairInProperOrder(prevEnt, ent); + + if (hasJoined[prevEntIdx, curEntIdx] || joinType < passType) + { + // skip if already joined or passtype delays the join to later pass + } + else + { + // create a new join operator, with the left side operator + // be the left side of the LEFT OUTTER JOIN if it is outter join (inner join order doesn't matter) + var leftOp = logicOpSrcTable[prevEnt.Alias]; + var rightOp = logicOpSrcTable[ent.Alias]; + var newOp = new JoinOperator( + leftOp, + rightOp, + entityJoinMatrixClosure[prevEntIdx, curEntIdx] // join type + ); + var fields = leftOp.OutputSchema.Union(rightOp.OutputSchema) + .Select(f => f.Clone()) + .GroupBy(f => f.FieldAlias) + .Select(f => f.First()); + newOp.InputSchema = new Schema(fields); + newOp.OutputSchema = new Schema(fields); + + // caculate join needed by this operator + var entAliasesJointTogether = leftOp.OutputSchema.Where(s => s is EntityField).Select(s => s.FieldAlias) + .Union( + rightOp.OutputSchema.Where(s => s is EntityField).Select(s => s.FieldAlias) + ).Distinct(); + var joinKeysRequiredForThisJoin = joinPairs + .Where(kv => entAliasesJointTogether.Contains(kv.Key.Key) && entAliasesJointTogether.Contains(kv.Key.Value)) + .ToList(); + joinKeysRequiredForThisJoin.ForEach(kv => + { + // add join to this particular operator + newOp.AddJoinPair(kv.Value); + // remove from unsatisified join key list + joinPairs.Remove(kv.Key); + }); + + // add newly created logical operator to the all logical operator list + allLogicalOps.Add(newOp); + + // update the Logical Operator lookup table + var aliasToUpdateOp = logicOpSrcTable.Where(kv => kv.Value == leftOp || kv.Value == rightOp).Select(kv => kv.Key).ToList(); + aliasToUpdateOp.ForEach(a => logicOpSrcTable[a] = newOp); + + // update the fact if two table already jointed not + hasJoined[prevEntIdx, curEntIdx] = true; + hasJoined[curEntIdx, prevEntIdx] = true; + hasJoined = hasJoined.TransitiveClosure(boolComparer); + } + + prevEnt = ent; + prevEntIdx = aliasTable[ent.Alias].Order; + } + } + } + + // pass 'cross join': all the remaining segments to create the logical operators + var joiningSegments = logicOpSrcTable.Values.Union(additionalCrossJoinOp).Distinct(); + LogicalOperator finalOp = joiningSegments.Count() > 1 ? joiningSegments.Aggregate( + (x, delta) => + { + var newOp = new JoinOperator(x, delta, JoinOperator.JoinType.Cross); + var fields = x.OutputSchema.Union(delta.OutputSchema) + .Select(f => f.Clone()) + .GroupBy(f => f.FieldAlias) + .Select(f => f.First()); + newOp.InputSchema = new Schema(fields); + newOp.OutputSchema = new Schema(fields); + allLogicalOps.Add(newOp); + return newOp; + } + ) : joiningSegments.First(); + + // for any relationships of same type appearing in the same match statement, adding + // a condition that it should not be repeated. E.g., for + // MATCH (p:Person)-[a1:Acted_In]->(m:Movie)<-[a2:Acted_In]-(p2:Person) ... + // we will add a condition that + // a1.SrcId <> a2.SrcId AND a1.SinkId <> a2.SinkId + var relationshipTypeGroups = namedMatchData + .AllEntitiesOrdered + .Where(e => e is RelationshipEntity) + .Cast() + .SelectMany(e => + { + switch (e.RelationshipDirection) + { + case RelationshipEntity.Direction.Forward: + return new(string Alias, string EntityFullName)[1] { (e.Alias, $"{e.LeftEntityName}@{e.EntityName}@{e.RightEntityName}") }; + case RelationshipEntity.Direction.Backward: + return new(string Alias, string EntityFullName)[1] { (e.Alias, $"{e.RightEntityName}@{e.EntityName}@{e.LeftEntityName}") }; + default: + Debug.Assert(e.RelationshipDirection == RelationshipEntity.Direction.Both); + return new(string Alias, string EntityFullName)[2] + { + (e.Alias, $"{e.LeftEntityName}@{e.EntityName}@{e.RightEntityName}"), + (e.Alias, $"{e.RightEntityName}@{e.EntityName}@{e.LeftEntityName}"), + }; + } + }) + .GroupBy(e => e.EntityFullName) + .Where(e => e.Count() > 1) + .ToList(); + + if (relationshipTypeGroups.Count > 0) + { + var unexpandedInequalityConditions = relationshipTypeGroups + .Aggregate( + new List<(string RelAlias1, string RelAlias2)>(), + (list, g) => { + var cond = g.ToList(); + for (int i = 0; i < cond.Count-1; i++) + { + for (int j = i + 1; j < cond.Count; j++) + { + list.Add((cond[i].Alias, cond[j].Alias)); + } + } + return list; + } + ); + finalOp = CreateLogicalTree(unexpandedInequalityConditions, finalOp, allLogicalOps); + } + + return finalOp; + } + + /// + /// Evaluate field data types for each operators' output schema (after data schema is bound) + /// + private void PropagateDataTypes() + { + // we go top down for each layers in the logical plan to propagate field's data types + + var allOperators = StartingOperators + .SelectMany(op => op.GetAllDownstreamOperatorsOfType()) + .Distinct() + .GroupBy(op => op.Depth) + .OrderBy(g => g.Key); + + Debug.Assert(allOperators.First().All(op => op is StartLogicalOperator)); + + // We assume that first level is taken care off in previous stage (data binding) + // We start from second level and down to propagate data types + foreach (var opGrp in allOperators.Skip(1)) + { + opGrp.ToList().ForEach(op => op.PropagateSchema()); + } + } + + /// + /// Update the list of actual properties that got referenced for each entity field + /// + private void UpdateActualFieldReferencesForEntityFields() + { + // we go bottom up to propagate entity fields referenced in return body or condition clauses + // that each operator's input/ouput schema must carry + + var allOperators = StartingOperators + .SelectMany(op => op.GetAllDownstreamOperatorsOfType()) + .Distinct() + .GroupBy(op => op.Depth) + .OrderByDescending(g => g.Key); + foreach (var opGrp in allOperators) + { + opGrp.ToList().ForEach(op => op.PropagateReferencedPropertiesForEntityFields()); + } + } + } +} diff --git a/src/LogicalPlanner/LogicalPlanner.csproj b/src/LogicalPlanner/LogicalPlanner.csproj new file mode 100644 index 0000000..4ef5058 --- /dev/null +++ b/src/LogicalPlanner/LogicalPlanner.csproj @@ -0,0 +1,12 @@ + + + + netcoreapp2.1 + Microsoft.GraphPlatform.Transpiler.LogicalPlanner + + + + + + + diff --git a/src/LogicalPlanner/Utils/ArrayExt.cs b/src/LogicalPlanner/Utils/ArrayExt.cs new file mode 100644 index 0000000..f32e1c6 --- /dev/null +++ b/src/LogicalPlanner/Utils/ArrayExt.cs @@ -0,0 +1,90 @@ +// Copyright(c) Microsoft Corporation +// All rights reserved. +// +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +namespace openCypherTranspiler.LogicalPlanner.Utils +{ + public static class ArrayExt + { + private static T Max(T x, T y, IComparer comparer) + { + if (comparer == null) + { + comparer = Comparer.Default; + } + return (comparer.Compare(x, y) > 0) ? x : y; + } + + private static T Min(T x, T y, IComparer comparer) + { + if (comparer == null) + { + comparer = Comparer.Default; + } + return (comparer.Compare(x, y) < 0) ? x : y; + } + + private static T[,] TransitiveClosureOnce(this T[,] graph, IComparer comparer = null) where T : IComparable + { + Debug.Assert(graph.GetLength(0) == graph.GetLength(1)); + var dim = graph.GetLength(0); + + var reach = new T[dim, dim]; + int i, j, k; + for (i = 0; i < dim; i++) + { + for (j = 0; j < dim; j++) + { + reach[i, j] = graph[i, j]; + } + } + for (k = 0; k < dim; k++) + { + for (i = 0; i < dim; i++) + { + for (j = 0; j < dim; j++) + { + reach[i, j] = Max(reach[i, j], Min(reach[i, k], reach[k, j], comparer), comparer); + } + } + } + + return reach; + } + + public static T[,] TransitiveClosure(this T[,] graph, IComparer comparer = null) where T : IComparable + { + return graph.TransitiveClosure(Math.Max(graph.GetLength(0), graph.GetLength(1)), comparer); + } + + public static T[,] TransitiveClosure(this T[,] graph, int folds, IComparer comparer = null) where T: IComparable + { + var reach = graph; + for (var i = 0; i < folds; i++) + { + var newReach = reach.TransitiveClosureOnce(comparer); + var equal = Enumerable.Range(0, newReach.Rank).All(dimension => newReach.GetLength(dimension) == reach.GetLength(dimension)) + && newReach.Cast().SequenceEqual(reach.Cast()); + if (equal) + { + return newReach; + } + else + { + reach = newReach; + } + } + return reach; + } + } +} diff --git a/src/SQLRenderer/ISQLDBSchemaProvider.cs b/src/SQLRenderer/ISQLDBSchemaProvider.cs new file mode 100644 index 0000000..84894c5 --- /dev/null +++ b/src/SQLRenderer/ISQLDBSchemaProvider.cs @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using openCypherTranspiler.Common.GraphSchema; +using System.Collections.Generic; + +namespace openCypherTranspiler.SQLRenderer +{ + public interface ISQLDBSchemaProvider : IGraphSchemaProvider + { + SQLTableDescriptor GetSQLTableDescriptors(string entityId); + } +} diff --git a/src/SQLRenderer/README.md b/src/SQLRenderer/README.md new file mode 100644 index 0000000..3b50726 --- /dev/null +++ b/src/SQLRenderer/README.md @@ -0,0 +1,3 @@ +# SQL Renderer + +This project is an example code renderer that produces T-SQL code for parsed openCypher graph query logical plan. diff --git a/src/SQLRenderer/SQLRenderer.cs b/src/SQLRenderer/SQLRenderer.cs new file mode 100644 index 0000000..1aa386f --- /dev/null +++ b/src/SQLRenderer/SQLRenderer.cs @@ -0,0 +1,1082 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +using System; +using System.Collections.Generic; +using System.Data; +using System.Diagnostics; +using System.Linq; +using System.Text; +using openCypherTranspiler.Common.Exceptions; +using openCypherTranspiler.Common.Logging; +using openCypherTranspiler.Common.Utils; +using openCypherTranspiler.LogicalPlanner; +using openCypherTranspiler.openCypherParser.AST; +using openCypherTranspiler.openCypherParser.Common; + +namespace openCypherTranspiler.SQLRenderer +{ + public class SQLRenderer + { + // Cached graph definition object + private readonly ISQLDBSchemaProvider _graphDef; + + // Cached logger + private readonly ILoggable _logger; + + // Map from operator type to the pattern need to used to render valid SQL + private static readonly IDictionary OperatorRenderPattern = new Dictionary() + { + { BinaryOperator.Plus, "({0})+({1})" }, + { BinaryOperator.Minus, "({0})-({1})" }, + { BinaryOperator.Multiply, "({0})*({1})" }, + { BinaryOperator.Divide, "({0})/({1})" }, + { BinaryOperator.Modulo, "({0})%({1})" }, + { BinaryOperator.Exponentiation, "CAST(POWER({0},{1}) AS float)" }, + + { BinaryOperator.AND, "({0}) AND ({1})" }, + { BinaryOperator.OR, "({0}) OR ({1})" }, + { BinaryOperator.XOR, "(({0}) AND NOT ({1})) OR (NOT ({0}) AND ({1}))" }, + + { BinaryOperator.LT, "({0})<({1})" }, + { BinaryOperator.LEQ, "({0})<=({1})" }, + { BinaryOperator.GT, "({0})>({1})" }, + { BinaryOperator.GEQ, "({0})>=({1})" }, + { BinaryOperator.EQ, "({0})=({1})" }, + { BinaryOperator.NEQ, "({0})!=({1})" }, + { BinaryOperator.REGMATCH, "PATINDEX('%{1}%', {0})" }, + { BinaryOperator.IN, "({0}) IN {1}" }, + }; + + // Map from operator type for CAST statement when need arises in some situlations such as CASE WHEN + private static readonly IDictionary TypeToSQLTypeMapping = new Dictionary() + { + // https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-data-type-mappings + { typeof(int), SqlDbType.Int}, + { typeof(short), SqlDbType.SmallInt}, + { typeof(long), SqlDbType.BigInt}, + { typeof(double), SqlDbType.Float}, + { typeof(string), SqlDbType.NVarChar}, + { typeof(float), SqlDbType.Float}, + { typeof(DateTime), SqlDbType.DateTime2}, // https://docs.microsoft.com/en-us/sql/t-sql/data-types/datetime-transact-sql?view=sql-server-2017 + { typeof(bool), SqlDbType.Bit}, + { typeof(Guid), SqlDbType.UniqueIdentifier}, + { typeof(uint), SqlDbType.Int}, + { typeof(ushort), SqlDbType.SmallInt}, + { typeof(ulong), SqlDbType.BigInt}, + { typeof(byte), SqlDbType.TinyInt}, + { typeof(byte[]), SqlDbType.Binary}, + { typeof(decimal), SqlDbType.Decimal}, + }; + + private static readonly IDictionary SQLTypeRenderingMapping = new Dictionary() + { + // Doc: https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-data-type-mappings + { SqlDbType.Int, "int" }, + { SqlDbType.SmallInt, "smallint" }, + { SqlDbType.BigInt, "bigint" }, + { SqlDbType.Float, "float" }, + { SqlDbType.NVarChar, "nvarchar(MAX)" }, + { SqlDbType.DateTime2, "datetime2" }, + { SqlDbType.Bit, "bit"}, + { SqlDbType.UniqueIdentifier, "uniqueidentifier" }, + { SqlDbType.TinyInt, "tinyint" }, + { SqlDbType.Binary, "binary" }, + { SqlDbType.Decimal, "decimal" }, + }; + + // Map from Aggregation Function to its equivalent in SQL + private static readonly IDictionary AggregationFunctionRenderPattern = new Dictionary() + { + { AggregationFunction.Avg, "AVG(CAST({0} AS float))"}, + { AggregationFunction.Sum, "SUM({0})"}, + { AggregationFunction.Min, "MIN({0})"}, + { AggregationFunction.Max, "MAX({0})"}, + { AggregationFunction.First, "MIN({0})"}, + { AggregationFunction.Last, "MAX({0})"}, + { AggregationFunction.StDev, "STDEV({0})" }, + { AggregationFunction.StDevP, "STDEVP({0})" }, + }; + + enum ConversionType + { + NoNeed, + Convert, + Cast, + Invalid + } + + private static readonly IDictionary<(SqlDbType, SqlDbType), ConversionType> SQLTypeConversionType = new Dictionary<(SqlDbType, SqlDbType), ConversionType>() + { + // Doc: https://docs.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-2017 + { (SqlDbType.Int, SqlDbType.Int), ConversionType.NoNeed }, + { (SqlDbType.Int, SqlDbType.SmallInt), ConversionType.Cast }, + { (SqlDbType.Int, SqlDbType.BigInt), ConversionType.Cast }, + { (SqlDbType.Int, SqlDbType.Float), ConversionType.Cast }, + { (SqlDbType.Int, SqlDbType.NVarChar), ConversionType.Cast }, + { (SqlDbType.Int, SqlDbType.DateTime2), ConversionType.Invalid }, + { (SqlDbType.Int, SqlDbType.Bit), ConversionType.Cast }, + { (SqlDbType.Int, SqlDbType.UniqueIdentifier), ConversionType.Invalid }, + { (SqlDbType.Int, SqlDbType.TinyInt), ConversionType.Cast }, + { (SqlDbType.Int, SqlDbType.Binary), ConversionType.Cast }, + { (SqlDbType.Int, SqlDbType.Decimal), ConversionType.Cast }, + { (SqlDbType.SmallInt, SqlDbType.Int), ConversionType.Cast }, + { (SqlDbType.SmallInt, SqlDbType.SmallInt), ConversionType.NoNeed }, + { (SqlDbType.SmallInt, SqlDbType.BigInt), ConversionType.Cast }, + { (SqlDbType.SmallInt, SqlDbType.Float), ConversionType.Cast }, + { (SqlDbType.SmallInt, SqlDbType.NVarChar), ConversionType.Cast }, + { (SqlDbType.SmallInt, SqlDbType.DateTime2), ConversionType.Invalid }, + { (SqlDbType.SmallInt, SqlDbType.Bit), ConversionType.Cast }, + { (SqlDbType.SmallInt, SqlDbType.UniqueIdentifier), ConversionType.Invalid }, + { (SqlDbType.SmallInt, SqlDbType.TinyInt), ConversionType.Cast }, + { (SqlDbType.SmallInt, SqlDbType.Binary), ConversionType.Cast }, + { (SqlDbType.SmallInt, SqlDbType.Decimal), ConversionType.Cast }, + { (SqlDbType.BigInt, SqlDbType.Int), ConversionType.Cast }, + { (SqlDbType.BigInt, SqlDbType.SmallInt), ConversionType.Cast }, + { (SqlDbType.BigInt, SqlDbType.BigInt), ConversionType.NoNeed }, + { (SqlDbType.BigInt, SqlDbType.Float), ConversionType.Cast }, + { (SqlDbType.BigInt, SqlDbType.NVarChar), ConversionType.Cast }, + { (SqlDbType.BigInt, SqlDbType.DateTime2), ConversionType.Invalid }, + { (SqlDbType.BigInt, SqlDbType.Bit), ConversionType.Cast }, + { (SqlDbType.BigInt, SqlDbType.UniqueIdentifier), ConversionType.Invalid }, + { (SqlDbType.BigInt, SqlDbType.TinyInt), ConversionType.Cast }, + { (SqlDbType.BigInt, SqlDbType.Binary), ConversionType.Cast }, + { (SqlDbType.BigInt, SqlDbType.Decimal), ConversionType.Cast }, + { (SqlDbType.Float, SqlDbType.Int), ConversionType.Cast }, + { (SqlDbType.Float, SqlDbType.SmallInt), ConversionType.Cast }, + { (SqlDbType.Float, SqlDbType.BigInt), ConversionType.Cast }, + { (SqlDbType.Float, SqlDbType.Float), ConversionType.NoNeed }, + { (SqlDbType.Float, SqlDbType.NVarChar), ConversionType.Cast }, + { (SqlDbType.Float, SqlDbType.DateTime2), ConversionType.Invalid }, + { (SqlDbType.Float, SqlDbType.Bit), ConversionType.Cast }, + { (SqlDbType.Float, SqlDbType.UniqueIdentifier), ConversionType.Invalid }, + { (SqlDbType.Float, SqlDbType.TinyInt), ConversionType.Cast }, + { (SqlDbType.Float, SqlDbType.Binary), ConversionType.Cast }, + { (SqlDbType.Float, SqlDbType.Decimal), ConversionType.Cast }, + { (SqlDbType.NVarChar, SqlDbType.Int), ConversionType.Cast }, + { (SqlDbType.NVarChar, SqlDbType.SmallInt), ConversionType.Cast }, + { (SqlDbType.NVarChar, SqlDbType.BigInt), ConversionType.Cast }, + { (SqlDbType.NVarChar, SqlDbType.Float), ConversionType.Cast }, + { (SqlDbType.NVarChar, SqlDbType.NVarChar), ConversionType.NoNeed }, + { (SqlDbType.NVarChar, SqlDbType.DateTime2), ConversionType.Cast }, + { (SqlDbType.NVarChar, SqlDbType.Bit), ConversionType.Cast }, + { (SqlDbType.NVarChar, SqlDbType.UniqueIdentifier), ConversionType.Cast }, + { (SqlDbType.NVarChar, SqlDbType.TinyInt), ConversionType.Cast }, + { (SqlDbType.NVarChar, SqlDbType.Binary), ConversionType.Convert }, + { (SqlDbType.NVarChar, SqlDbType.Decimal), ConversionType.Cast }, + { (SqlDbType.DateTime2, SqlDbType.Int), ConversionType.Invalid }, + { (SqlDbType.DateTime2, SqlDbType.SmallInt), ConversionType.Invalid }, + { (SqlDbType.DateTime2, SqlDbType.BigInt), ConversionType.Invalid }, + { (SqlDbType.DateTime2, SqlDbType.Float), ConversionType.Invalid }, + { (SqlDbType.DateTime2, SqlDbType.NVarChar), ConversionType.Cast }, + { (SqlDbType.DateTime2, SqlDbType.DateTime2), ConversionType.NoNeed }, + { (SqlDbType.DateTime2, SqlDbType.Bit), ConversionType.Invalid }, + { (SqlDbType.DateTime2, SqlDbType.UniqueIdentifier), ConversionType.Invalid }, + { (SqlDbType.DateTime2, SqlDbType.TinyInt), ConversionType.Invalid }, + { (SqlDbType.DateTime2, SqlDbType.Binary), ConversionType.Convert }, + { (SqlDbType.DateTime2, SqlDbType.Decimal), ConversionType.Invalid }, + { (SqlDbType.Bit, SqlDbType.Int), ConversionType.Cast }, + { (SqlDbType.Bit, SqlDbType.SmallInt), ConversionType.Cast }, + { (SqlDbType.Bit, SqlDbType.BigInt), ConversionType.Cast }, + { (SqlDbType.Bit, SqlDbType.Float), ConversionType.Cast }, + { (SqlDbType.Bit, SqlDbType.NVarChar), ConversionType.Cast }, + { (SqlDbType.Bit, SqlDbType.DateTime2), ConversionType.Invalid }, + { (SqlDbType.Bit, SqlDbType.Bit), ConversionType.NoNeed }, + { (SqlDbType.Bit, SqlDbType.UniqueIdentifier), ConversionType.Invalid }, + { (SqlDbType.Bit, SqlDbType.TinyInt), ConversionType.Cast }, + { (SqlDbType.Bit, SqlDbType.Binary), ConversionType.Cast }, + { (SqlDbType.Bit, SqlDbType.Decimal), ConversionType.Cast }, + { (SqlDbType.UniqueIdentifier, SqlDbType.Int), ConversionType.Invalid }, + { (SqlDbType.UniqueIdentifier, SqlDbType.SmallInt), ConversionType.Invalid }, + { (SqlDbType.UniqueIdentifier, SqlDbType.BigInt), ConversionType.Invalid }, + { (SqlDbType.UniqueIdentifier, SqlDbType.Float), ConversionType.Invalid }, + { (SqlDbType.UniqueIdentifier, SqlDbType.NVarChar), ConversionType.Cast }, + { (SqlDbType.UniqueIdentifier, SqlDbType.DateTime2), ConversionType.Invalid }, + { (SqlDbType.UniqueIdentifier, SqlDbType.Bit), ConversionType.Invalid }, + { (SqlDbType.UniqueIdentifier, SqlDbType.UniqueIdentifier), ConversionType.NoNeed }, + { (SqlDbType.UniqueIdentifier, SqlDbType.TinyInt), ConversionType.Invalid }, + { (SqlDbType.UniqueIdentifier, SqlDbType.Binary), ConversionType.Cast }, + { (SqlDbType.UniqueIdentifier, SqlDbType.Decimal), ConversionType.Invalid }, + { (SqlDbType.TinyInt, SqlDbType.Int), ConversionType.Cast }, + { (SqlDbType.TinyInt, SqlDbType.SmallInt), ConversionType.Cast }, + { (SqlDbType.TinyInt, SqlDbType.BigInt), ConversionType.Cast }, + { (SqlDbType.TinyInt, SqlDbType.Float), ConversionType.Cast }, + { (SqlDbType.TinyInt, SqlDbType.NVarChar), ConversionType.Cast }, + { (SqlDbType.TinyInt, SqlDbType.DateTime2), ConversionType.Invalid }, + { (SqlDbType.TinyInt, SqlDbType.Bit), ConversionType.Cast }, + { (SqlDbType.TinyInt, SqlDbType.UniqueIdentifier), ConversionType.Invalid }, + { (SqlDbType.TinyInt, SqlDbType.TinyInt), ConversionType.NoNeed }, + { (SqlDbType.TinyInt, SqlDbType.Binary), ConversionType.Cast }, + { (SqlDbType.TinyInt, SqlDbType.Decimal), ConversionType.Cast }, + { (SqlDbType.Binary, SqlDbType.Int), ConversionType.Cast }, + { (SqlDbType.Binary, SqlDbType.SmallInt), ConversionType.Cast }, + { (SqlDbType.Binary, SqlDbType.BigInt), ConversionType.Cast }, + { (SqlDbType.Binary, SqlDbType.Float), ConversionType.Invalid }, + { (SqlDbType.Binary, SqlDbType.NVarChar), ConversionType.Cast }, + { (SqlDbType.Binary, SqlDbType.DateTime2), ConversionType.Convert }, + { (SqlDbType.Binary, SqlDbType.Bit), ConversionType.Cast }, + { (SqlDbType.Binary, SqlDbType.UniqueIdentifier), ConversionType.Cast }, + { (SqlDbType.Binary, SqlDbType.TinyInt), ConversionType.Cast }, + { (SqlDbType.Binary, SqlDbType.Binary), ConversionType.NoNeed }, + { (SqlDbType.Binary, SqlDbType.Decimal), ConversionType.Cast }, + { (SqlDbType.Decimal, SqlDbType.Int), ConversionType.Cast }, + { (SqlDbType.Decimal, SqlDbType.SmallInt), ConversionType.Cast }, + { (SqlDbType.Decimal, SqlDbType.BigInt), ConversionType.Cast }, + { (SqlDbType.Decimal, SqlDbType.Float), ConversionType.Cast }, + { (SqlDbType.Decimal, SqlDbType.NVarChar), ConversionType.Cast }, + { (SqlDbType.Decimal, SqlDbType.DateTime2), ConversionType.Invalid }, + { (SqlDbType.Decimal, SqlDbType.Bit), ConversionType.Cast }, + { (SqlDbType.Decimal, SqlDbType.UniqueIdentifier), ConversionType.Invalid }, + { (SqlDbType.Decimal, SqlDbType.TinyInt), ConversionType.Cast }, + { (SqlDbType.Decimal, SqlDbType.Binary), ConversionType.Cast }, + { (SqlDbType.Decimal, SqlDbType.Decimal), ConversionType.Cast }, + }; + + class ExpressionRenderingContext + { + public ExpressionRenderingContext() + { + + } + public ExpressionRenderingContext(ExpressionRenderingContext ctx) + { + ExpectConditionExpression = ctx.ExpectConditionExpression; + EnclosingOperator = ctx.EnclosingOperator; + } + public bool ExpectConditionExpression { get; set; } = false; + public ExpressionRenderingContext ModifyExpectConditionExpression(bool newVal) + { + ExpectConditionExpression = newVal; + return this; + } + public LogicalOperator EnclosingOperator { get; set; } + } + + /// + /// Constructor + /// + /// + /// A set of parameters and its default value + /// Optional. If provided, a true VC url is provided, or empty, for local testing + /// Optional. For logging + public SQLRenderer + ( + ISQLDBSchemaProvider graphDef, + ILoggable logger = null + ) + { + _graphDef = graphDef; + _logger = logger; + } + + #region Helpers + private string GetFieldNameForEntityField(string prefix, string singleFieldName) + { + var prefixClean = TextHelper.MakeCompliantString(prefix, "[A-Za-z0-9_]+"); + return $"__{prefixClean}_{singleFieldName}"; + } + + /// + /// Returns a list of fields that are + /// - stand alone single field + /// - single field that are part of entity and got referenced + /// + /// + private IEnumerable<(string EntityAlias, string PropertyName, Type FieldType, bool IsKeyfield)> ExpandSchema(Schema schema) + { + return schema + .Where(f => f is EntityField).Cast() + .SelectMany(ef => ef.ReferencedFieldAliases + .Select(fn => ( + EntityAlias: ef.FieldAlias, + PropertyName: fn, + FieldType: ef.EncapsulatedFields.First(f2 => fn == f2.FieldAlias).FieldType, + IsKeyfield: fn == ef.NodeJoinField?.FieldAlias || fn == ef.RelSourceJoinField?.FieldAlias || fn == ef.RelSinkJoinField?.FieldAlias + ))) + .Union(schema + .Where(f => f is SingleField).Cast() + .Select(fn => (EntityAlias: (string)null, PropertyName: fn.FieldAlias, FieldType: fn.FieldType, IsKeyfield: false))); + } + + private string EscapeStringLiteral(string originalStr) + { + return originalStr.Replace("'", "''"); + } + + private string RenderTypeCastingForExpression(Type targetType, string expr) + { + var unboxedType = TypeHelper.GetUnderlyingTypeIfNullable(targetType); + var sqlTypeText = SQLTypeRenderingMapping[TypeToSQLTypeMapping[unboxedType]]; + if (targetType != unboxedType) + { + return $"CAST({expr} AS {sqlTypeText})"; + } + else + { + return $"ISNULL(CAST({expr} AS {sqlTypeText}), {expr})"; + } + } + + private string RenderTypeConversionForExpression(Type targetType, string expr) + { + var unboxedType = TypeHelper.GetUnderlyingTypeIfNullable(targetType); + var sqlTypeText = SQLTypeRenderingMapping[TypeToSQLTypeMapping[unboxedType]]; + return $"CONVERT({sqlTypeText}, {expr})"; + } + + private string RenderCaseValueExpression(Type targetType, QueryExpression expr, ExpressionRenderingContext exprCtx) + { + /// References: + /// - https://sqlsunday.com/2019/06/05/cast-convert-makes-expressions-nullable/ + /// + var renderedExpr = RenderExpression(expr, exprCtx); + var currentType = expr.EvaluateType(); + + // first check if the type conversion is allowed + var fromSQLType = TypeToSQLTypeMapping[TypeHelper.GetUnderlyingTypeIfNullable(currentType)]; + var toSQLType = TypeToSQLTypeMapping[TypeHelper.GetUnderlyingTypeIfNullable(targetType)]; + var conversionType = SQLTypeConversionType[(fromSQLType, toSQLType)]; + switch (conversionType) + { + case ConversionType.Cast: + return RenderTypeCastingForExpression(targetType, renderedExpr); + case ConversionType.Convert: + return RenderTypeConversionForExpression(targetType, renderedExpr); + case ConversionType.NoNeed: + return renderedExpr; + case ConversionType.Invalid: + throw new TranspilerNotSupportedException($"Converting from type {fromSQLType} to type {toSQLType}"); + default: + throw new TranspilerInternalErrorException($"Unexpected conversion type {conversionType}"); + } + } + #endregion Helpers + + #region Logical Operator Renderers + + private string RenderDataSource(DataSourceOperator dataSourceOp, int depth) + { + var codeSnip = new StringBuilder(); + + // Currently we support only single source data source + Debug.Assert( + dataSourceOp.OutputSchema.First() is EntityField && + dataSourceOp.OutputSchema.Count() == 1 + ); + + var ent = dataSourceOp.OutputSchema.First() as EntityField; + var storDesc = _graphDef.GetSQLTableDescriptors(ent.BoundEntityName); + var allReferencedFieldsWithAliasPrefix = ent.ReferencedFieldAliases.Select(f => GetFieldNameForEntityField(ent.EntityName, f)); + codeSnip.AppendLine(depth, $"SELECT"); + + // Render join key fields always and does it first + bool isFirstRow = true; + if (ent.Type == EntityField.EntityType.Node) + { + var nodeIdJoinKeyName = GetFieldNameForEntityField(ent.FieldAlias, ent.NodeJoinField.FieldAlias); + codeSnip.AppendLine(depth + 1, $"{(!isFirstRow ? ", " : " ")}{ent.NodeJoinField.FieldAlias} AS {nodeIdJoinKeyName}"); + isFirstRow = false; + } + else + { + var edgeSrcIdJoinKeyName = GetFieldNameForEntityField(ent.FieldAlias, ent.RelSourceJoinField.FieldAlias); + var edgeSinkIdJoinKeyName = GetFieldNameForEntityField(ent.FieldAlias, ent.RelSinkJoinField.FieldAlias); + codeSnip.AppendLine(depth + 1, $"{(!isFirstRow ? ", " : " ")}{ent.RelSourceJoinField.FieldAlias} AS {edgeSrcIdJoinKeyName}"); + codeSnip.AppendLine(depth + 1, $", {ent.RelSinkJoinField.FieldAlias} AS {edgeSinkIdJoinKeyName}"); + isFirstRow = false; + } + + // Render other non-joinkey fields + foreach (var field in ent.ReferencedFieldAliases + .Where(f => (ent.NodeJoinField?.FieldAlias != f && ent.RelSourceJoinField?.FieldAlias != f && ent.RelSinkJoinField?.FieldAlias != f))) + { + var fieldAlias = GetFieldNameForEntityField(ent.FieldAlias, field); + codeSnip.AppendLine(depth + 1, $", {field} AS {fieldAlias}"); + } + + codeSnip.AppendLine(depth, $"FROM"); + codeSnip.AppendLine(depth + 1, $"{ storDesc.TableOrViewName}"); + + return codeSnip.ToString(); + } + + private string RenderJoin(JoinOperator joinOp, int depth) + { + var codeSnip = new StringBuilder(); + + var leftOp = joinOp.InOperatorLeft; + var rightOp = joinOp.InOperatorRight; + + var leftVar = "_left"; + var rightVar = "_right"; + + // expand output schema + var allColsToOutput = ExpandSchema(joinOp.OutputSchema); + var allOutputEntities = joinOp.OutputSchema.Where(f => f is EntityField).Cast(); + + // expand left input schema + var leftInCols = ExpandSchema(leftOp.OutputSchema); + var leftInEntityAliases = leftOp.OutputSchema.Where(f => f is EntityField).Select(e => e.FieldAlias); + + // expand right input schema + var rightInCols = ExpandSchema(rightOp.OutputSchema); + var rightInEntityAliases = rightOp.OutputSchema.Where(f => f is EntityField).Select(e => e.FieldAlias); + + codeSnip.AppendLine(depth, $"SELECT"); + + // render join key fields always and does it first + bool isFirstRow = true; + Debug.Assert(allOutputEntities.Count() > 0); + foreach (var ent in allOutputEntities) + { + var isFromLeft = leftInEntityAliases.Contains(ent.FieldAlias); // prefer left side first (sometimes an alias would be in both left and right, such as in OPTIONAL MATCH case) + Debug.Assert(isFromLeft || rightInEntityAliases.Contains(ent.FieldAlias)); + if (ent.Type == EntityField.EntityType.Node) + { + var nodeIdJoinKeyName = GetFieldNameForEntityField(ent.FieldAlias, ent.NodeJoinField.FieldAlias); + codeSnip.AppendLine(depth + 1, $"{(!isFirstRow ? ", " : " ")}{(isFromLeft ? leftVar : rightVar)}.{nodeIdJoinKeyName} AS {nodeIdJoinKeyName}"); + isFirstRow = false; + } + else + { + var edgeSrcIdJoinKeyName = GetFieldNameForEntityField(ent.FieldAlias, ent.RelSourceJoinField.FieldAlias); + var edgeSinkIdJoinKeyName = GetFieldNameForEntityField(ent.FieldAlias, ent.RelSinkJoinField.FieldAlias); + codeSnip.AppendLine(depth + 1, $"{(!isFirstRow ? ", " : " ")}{(isFromLeft ? leftVar : rightVar)}.{edgeSrcIdJoinKeyName} AS {edgeSrcIdJoinKeyName}"); + codeSnip.AppendLine(depth + 1, $", {(isFromLeft ? leftVar : rightVar)}.{edgeSinkIdJoinKeyName} AS {edgeSinkIdJoinKeyName}"); + isFirstRow = false; + } + } + // render selected properties (except key fields, which will always be rendered above) + foreach (var col in allColsToOutput.Where(c => !c.IsKeyfield)) + { + var isFromLeft = leftInCols.Any(f => (!string.IsNullOrEmpty(col.EntityAlias) ? f.EntityAlias == col.EntityAlias : true) && f.PropertyName == col.PropertyName); + Debug.Assert(isFromLeft || rightInCols.Any(f => (!string.IsNullOrEmpty(col.EntityAlias) ? f.EntityAlias == col.EntityAlias : true) && f.PropertyName == col.PropertyName)); + if (!string.IsNullOrEmpty(col.EntityAlias)) + { + // entity member (not yet expanded into a single column) + var fieldAliasWrappedInEntity = GetFieldNameForEntityField(col.EntityAlias, col.PropertyName); + codeSnip.AppendLine(depth + 1, $", {(isFromLeft ? leftVar : rightVar)}.{fieldAliasWrappedInEntity} AS {fieldAliasWrappedInEntity}"); + } + else + { + // single column reference + codeSnip.AppendLine(depth + 1, $", {(isFromLeft ? leftVar : rightVar)}.{col.PropertyName} AS {col.PropertyName}"); + } + } + + codeSnip.AppendLine(depth, $"FROM ("); + codeSnip.AppendLine(RenderLogicalOperator(leftOp, depth+1)); + codeSnip.AppendLine(depth, $") AS {leftVar}"); + + if (joinOp.Type == JoinOperator.JoinType.Cross) + { + Debug.Assert(joinOp.JoinPairs.Count == 0); + codeSnip.AppendLine(depth, $"CROSS JOIN ("); + codeSnip.AppendLine(RenderLogicalOperator(rightOp, depth+1)); + codeSnip.AppendLine(depth, $") AS {rightVar}"); + } + else + { + Debug.Assert(joinOp.Type == JoinOperator.JoinType.Left || joinOp.Type == JoinOperator.JoinType.Inner); + Debug.Assert(joinOp.JoinPairs.Count > 0); + codeSnip.AppendLine(depth, $"{(joinOp.Type == JoinOperator.JoinType.Inner ? "INNER JOIN" : "LEFT JOIN")} ("); + codeSnip.AppendLine(RenderLogicalOperator(rightOp, depth+1)); + codeSnip.AppendLine(depth, $") AS {rightVar} ON"); + + bool isFirstJoinCond = true; + foreach (var joinKeyPair in joinOp.JoinPairs) + { + var isNodeFromLeft = leftInEntityAliases.Contains(joinKeyPair.NodeAlias); + Debug.Assert(isNodeFromLeft ? + rightInEntityAliases.Contains(joinKeyPair.RelationshipOrNodeAlias) : + leftInEntityAliases.Contains(joinKeyPair.RelationshipOrNodeAlias) && rightInEntityAliases.Contains(joinKeyPair.NodeAlias)); + var varWithNode = isNodeFromLeft ? leftVar : rightVar; + var varWithNodeEntity = joinOp.OutputSchema.First(n => n.FieldAlias == joinKeyPair.NodeAlias) as EntityField; + var nodeJoinKey = GetFieldNameForEntityField(joinKeyPair.NodeAlias, varWithNodeEntity.NodeJoinField.FieldAlias); + + string nodeOrRelJoinKey; + var varWithRelOrNode = isNodeFromLeft ? rightVar : leftVar; + var varWithRelOrNodeEntity = joinOp.OutputSchema.First(n => n.FieldAlias == joinKeyPair.RelationshipOrNodeAlias) as EntityField; + + switch (joinKeyPair.Type) + { + case JoinOperator.JoinKeyPair.JoinKeyPairType.Source: + nodeOrRelJoinKey = GetFieldNameForEntityField(joinKeyPair.RelationshipOrNodeAlias, varWithRelOrNodeEntity.RelSourceJoinField.FieldAlias); + codeSnip.AppendLine(depth + 1, $"{(isFirstJoinCond ? "" : "AND ")}{varWithNode}.{nodeJoinKey} = {varWithRelOrNode}.{nodeOrRelJoinKey}"); + break; + case JoinOperator.JoinKeyPair.JoinKeyPairType.Sink: + nodeOrRelJoinKey = GetFieldNameForEntityField(joinKeyPair.RelationshipOrNodeAlias, varWithRelOrNodeEntity.RelSinkJoinField.FieldAlias); + codeSnip.AppendLine(depth + 1, $"{(isFirstJoinCond ? "" : "AND ")}{varWithNode}.{nodeJoinKey} = {varWithRelOrNode}.{nodeOrRelJoinKey}"); + break; + case JoinOperator.JoinKeyPair.JoinKeyPairType.Both: + nodeOrRelJoinKey = GetFieldNameForEntityField(joinKeyPair.RelationshipOrNodeAlias, varWithRelOrNodeEntity.RelSourceJoinField.FieldAlias); + codeSnip.AppendLine(depth + 1, $"{(isFirstJoinCond ? "" : "AND ")}{varWithNode}.{nodeJoinKey} = {varWithRelOrNode}.{nodeOrRelJoinKey}"); + nodeOrRelJoinKey = GetFieldNameForEntityField(joinKeyPair.RelationshipOrNodeAlias, varWithRelOrNodeEntity.RelSinkJoinField.FieldAlias); + codeSnip.AppendLine(depth + 1, $"{"AND "}{varWithNode}.{nodeJoinKey} == {varWithRelOrNode}.{nodeOrRelJoinKey}"); + break; + case JoinOperator.JoinKeyPair.JoinKeyPairType.NodeId: + nodeOrRelJoinKey = GetFieldNameForEntityField(joinKeyPair.RelationshipOrNodeAlias, varWithRelOrNodeEntity.NodeJoinField.FieldAlias); + codeSnip.AppendLine(depth + 1, $"{(isFirstJoinCond ? "" : "AND ")}{varWithNode}.{nodeJoinKey} = {varWithRelOrNode}.{nodeOrRelJoinKey}"); + break; + default: + Debug.Assert(joinKeyPair.Type == JoinOperator.JoinKeyPair.JoinKeyPairType.Either); + var nodeField = joinOp.InputSchema.First(f => f.FieldAlias == joinKeyPair.NodeAlias) as EntityField; + var relField = joinOp.InputSchema.First(f => f.FieldAlias == joinKeyPair.RelationshipOrNodeAlias) as EntityField; + var isSrc = relField.BoundSourceEntityName == nodeField.BoundEntityName; + Debug.Assert(isSrc || relField.BoundSinkEntityName == nodeField.BoundEntityName); + nodeOrRelJoinKey = GetFieldNameForEntityField(joinKeyPair.RelationshipOrNodeAlias, isSrc ? varWithRelOrNodeEntity.RelSourceJoinField.FieldAlias : varWithRelOrNodeEntity.RelSinkJoinField.FieldAlias); + codeSnip.AppendLine(depth + 1, $"{(isFirstJoinCond ? "" : "AND ")}{varWithNode}.{nodeJoinKey} = {varWithRelOrNode}.{nodeOrRelJoinKey}"); + break; + } + + isFirstJoinCond = false; + } + } + + return codeSnip.ToString(); + } + + private string RenderBinaryOperator(BinaryOperatorInfo op, QueryExpression left, QueryExpression right, ExpressionRenderingContext exprCtx) + { + if (op.Name == BinaryOperator.Invalid) + { + throw new TranspilerInternalErrorException("Encountered an invalid operator"); + } + var pattern = OperatorRenderPattern[op.Name] ?? + throw new TranspilerNotSupportedException($"Operator {op.Name}"); + var leftExpr = RenderExpression(left, exprCtx); + var rightExpr = RenderExpression(right, exprCtx); + return string.Format(pattern, leftExpr, rightExpr); + } + + private string RenderFunction(FunctionInfo func, IEnumerable parameters, ExpressionRenderingContext exprCtx) + { + var exprRenderResult = parameters.Select(p => RenderExpression(p, exprCtx)); + switch (func.FunctionName) + { + case Function.ToFloat: + Debug.Assert(parameters.Count() == 1); + return RenderTypeCastingForExpression(typeof(float), exprRenderResult.First()); + case Function.ToString: + Debug.Assert(parameters.Count() == 1); + return RenderTypeCastingForExpression(typeof(string), exprRenderResult.First()); + case Function.ToBoolean: + Debug.Assert(parameters.Count() == 1); + return RenderTypeCastingForExpression(typeof(bool), exprRenderResult.First()); + case Function.ToInteger: + Debug.Assert(parameters.Count() == 1); + return RenderTypeCastingForExpression(typeof(int), exprRenderResult.First()); + case Function.ToDouble: + Debug.Assert(parameters.Count() == 1); + return RenderTypeCastingForExpression(typeof(double), exprRenderResult.First()); + case Function.ToLong: + Debug.Assert(parameters.Count() == 1); + return RenderTypeCastingForExpression(typeof(long), exprRenderResult.First()); + case Function.Not: + Debug.Assert(parameters.Count() == 1); + return $"NOT ({string.Join(", ", exprRenderResult)})"; + case Function.StringStartsWith: + Debug.Assert(parameters.Count() == 2); + return $"LEFT({exprRenderResult.First()}, LEN({exprRenderResult.Skip(1).First()})) = {exprRenderResult.Skip(1).First()}"; + case Function.StringEndsWith: + Debug.Assert(parameters.Count() == 2); + return $"RIGHT({exprRenderResult.First()}, LEN({exprRenderResult.Skip(1).First()})) = {exprRenderResult.Skip(1).First()}"; + case Function.StringContains: + Debug.Assert(parameters.Count() == 2); + return $"charindex({exprRenderResult.Skip(1).First()}, {exprRenderResult.First()}) >= 1"; + case Function.StringLeft: + Debug.Assert(parameters.Count() == 2); + return $"LEFT({exprRenderResult.First()}, {exprRenderResult.Skip(1).First()})"; + case Function.StringRight: + Debug.Assert(parameters.Count() == 2); + return $"RIGHT({exprRenderResult.First()}, {exprRenderResult.Skip(1).First()})"; + case Function.StringTrim: + Debug.Assert(parameters.Count() == 1); + return $"TRIM({exprRenderResult.First()})"; + case Function.StringLTrim: + Debug.Assert(parameters.Count() == 1); + return $"LTRIM({exprRenderResult.First()})"; + case Function.StringRTrim: + Debug.Assert(parameters.Count() == 1); + return $"RTRIM({exprRenderResult.First()})"; + case Function.StringToUpper: + Debug.Assert(parameters.Count() == 1); + return $"UPPER({exprRenderResult.First()})"; + case Function.StringToLower: + Debug.Assert(parameters.Count() == 1); + return $"LOWER({exprRenderResult.First()})"; + case Function.StringSize: + Debug.Assert(parameters.Count() == 1); + return $"LEN({exprRenderResult.First()})"; + case Function.IsNull: + return $"({string.Join(", ", exprRenderResult)}) IS NULL"; + case Function.IsNotNull: + return $"({string.Join(", ", exprRenderResult)}) IS NOT NULL"; + default: + throw new TranspilerNotSupportedException($"Function '{func.FunctionName}'"); + } + } + + private string RenderExpression(QueryExpression expr, ExpressionRenderingContext exprCtx) + { + if (expr is QueryExpressionBinary) + { + var exprTyped = expr as QueryExpressionBinary; + var opType = exprTyped.Operator.Type; + var exprCtxChild = new ExpressionRenderingContext(exprCtx) + .ModifyExpectConditionExpression(opType == BinaryOperatorType.Logical); + string exprText = RenderBinaryOperator( + exprTyped.Operator, + exprTyped.LeftExpression, + exprTyped.RightExpression, + exprCtxChild + ); + if (!exprCtx.ExpectConditionExpression && + (opType == BinaryOperatorType.Comparison || opType == BinaryOperatorType.Logical)) + { + return $"(CASE WHEN {exprText} THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END)"; + } + else + { + return exprText; + } + } + else if (expr is QueryExpressionAggregationFunction) + { + var exprTyped = expr as QueryExpressionAggregationFunction; + + // TODO: temporary block for some yet to be supported aggregation functions + if (exprTyped.AggregationFunction == AggregationFunction.PercentileCont || + exprTyped.AggregationFunction == AggregationFunction.PercentileDisc) + { + throw new TranspilerNotSupportedException($"Yet to implemented aggregation function {exprTyped.AggregationFunction}"); + } + + // special handling for count + if (exprTyped.AggregationFunction == AggregationFunction.Count) + { + if (exprTyped.InnerExpression is QueryExpressionProperty && + (exprTyped.InnerExpression as QueryExpressionProperty).Entity != null) + { + // special handling for Count(entity) or Count(distinct(entity)) + var innerPropExpr = exprTyped.InnerExpression as QueryExpressionProperty; + var entity = innerPropExpr.Entity; + if (entity is RelationshipEntity && exprTyped.IsDistinct) + { + // block a scenario we currently cannot support + throw new TranspilerNotSupportedException("COUNT DISTINCT applied to relationship entity"); + } + var entityField = exprCtx.EnclosingOperator.InputSchema.First(f => f.FieldAlias == entity.Alias) as EntityField; + Debug.Assert(entityField != null); + + // we use the key field as surrogate for counting entities + var surrogateFieldForCounting = GetFieldNameForEntityField( + innerPropExpr.VariableName, + entity is RelationshipEntity ? entityField.RelSourceJoinField.FieldAlias : entityField.NodeJoinField.FieldAlias + ); + return $"COUNT({(exprTyped.IsDistinct ? "DISTINCT(" : "")}{surrogateFieldForCounting}{(exprTyped.IsDistinct ? ")" : "")})"; + } + else + { + // default handling of count + if (exprTyped.InnerExpression.GetChildrenQueryExpressionType().Count() > 0) + { + throw new TranspilerNotSupportedException("Aggregation function inside aggregate function"); + } + var innerExprStr = RenderExpression(exprTyped.InnerExpression, exprCtx); + return $"COUNT({(exprTyped.IsDistinct ? "DISTINCT(" : "")}{innerExprStr}{(exprTyped.IsDistinct ? ")" : "")})"; + } + } + else + { + // default handling + if (exprTyped.InnerExpression.GetChildrenQueryExpressionType().Count() > 0) + { + throw new TranspilerNotSupportedException("Aggregation function inside aggregate function"); + } + if (exprTyped.IsDistinct) + { + throw new TranspilerNotSupportedException("Distinct applied to aggregation functions other than COUNT"); + } + var innerExprStr = RenderExpression(exprTyped.InnerExpression, exprCtx); + return string.Format(AggregationFunctionRenderPattern[exprTyped.AggregationFunction], innerExprStr); + } + } + else if (expr is QueryExpressionFunction) + { + var exprTyped = expr as QueryExpressionFunction; + var allExprs = (new List() { exprTyped.InnerExpression }) + .Union(exprTyped.AdditionalExpressions ?? Enumerable.Empty()); + return RenderFunction(exprTyped.Function, allExprs, exprCtx); + } + else if (expr is QueryExpressionProperty) + { + var exprTyped = expr as QueryExpressionProperty; + var expressionText = string.IsNullOrEmpty(exprTyped.PropertyName) ? + exprTyped.VariableName : + GetFieldNameForEntityField(exprTyped.VariableName, exprTyped.PropertyName); + return expressionText; + } + else if (expr is QueryExpressionList) + { + var exprTyped = expr as QueryExpressionList; + var exprRendered = exprTyped.ExpressionList.Select(e => RenderExpression(e, exprCtx)).ToList(); + return $"({string.Join(", ", exprRendered)})"; + } + else if (expr is QueryExpressionValue) + { + var exprTyped = expr as QueryExpressionValue; + if (exprTyped.ValueType == typeof(string)) + { + // add double quote for string value, and escape if needed + return $"'{EscapeStringLiteral(exprTyped.StringValue)}'"; + } + if (exprTyped.ValueType == typeof(bool)) + { + return exprTyped.StringValue.ToLower(); + } + else + { + return $"{exprTyped.StringValue}"; + } + } + else if (expr is QueryExpressionWithAlias) + { + throw new NotSupportedException("Does not support aliased expression at non-root level"); + } + else if (expr is QueryExpressionCaseExpression) + { + var caseExprText = RenderCaseExpression(expr as QueryExpressionCaseExpression, exprCtx); + return caseExprText; + } + else + { + throw new NotSupportedException($"Unsupported expression type: {expr.GetType().ToString()}"); + } + } + + private string RenderCaseExpression(QueryExpressionCaseExpression caseExpression, ExpressionRenderingContext exprCtx) + { + var caseAlternatives = caseExpression.CaseAlternatives; + var elseCondition = caseExpression.ElseExpression; + var targetType = caseExpression.EvaluateType(); + + var codeSnip = new StringBuilder(); + + + // Note: right now the code renderer does not support casing on an expression. The + // expression has to be put into the WHEN / ELSE statement like SQL. In future, + // we may support this by embed CASE expr into the WHEN exprs + if (caseExpression.InitialCaseExpression != null) + { + throw new TranspilerNotSupportedException("Please use CASE WHEN ... instead of CASE WHEN . The latter is"); + } + + if (caseAlternatives.Count == 0) + { + throw new TranspilerInternalErrorException("No casing statements provided for CASE"); + } + + codeSnip.Append("CASE "); + Debug.Assert(exprCtx.ExpectConditionExpression == false); + foreach (var alterExpr in caseAlternatives) + { + codeSnip.Append($"WHEN {RenderExpression(alterExpr.WhenExpression, new ExpressionRenderingContext(exprCtx).ModifyExpectConditionExpression(true))} "); + codeSnip.Append($"THEN {RenderCaseValueExpression(targetType, alterExpr.ThenExpression, exprCtx)}"); + } + if (elseCondition != null) + { + codeSnip.Append($" ELSE {RenderCaseValueExpression(targetType, elseCondition, exprCtx)} END"); + } + else + { + codeSnip.Append($" END"); + } + + return codeSnip.ToString(); + } + + private string RenderProjection(ProjectionOperator prjOp, int depth) + { + var codeSnip = new StringBuilder(); + + // expand output schema + var allColsToOutput = ExpandSchema(prjOp.OutputSchema); + var allOutputEntities = prjOp.OutputSchema.Where(f => f is EntityField).Cast(); + var allOutputSingleFields = prjOp.OutputSchema.Where(f => f is SingleField).Cast(); + var preCond = prjOp.InOperator as SelectionOperator; + var topXVal = preCond?.LimitExpressions?.FirstOrDefault()?.RowCount; + + codeSnip.AppendLine(depth, $"SELECT{(prjOp.IsDistinct ? " DISTINCT" : "")}{(topXVal.HasValue ? $" TOP {topXVal.Value}" : "")}"); + + // project entities and flow the join keys + // do group by if any aggregation functions used + var nonAggFieldExprs = new List(); + + bool isFirstRow = true; + foreach (var ent in allOutputEntities) + { + var entExpr = prjOp.ProjectionMap[ent.FieldAlias]; + Debug.Assert(entExpr is QueryExpressionProperty); + var inSchemaAlias = (entExpr as QueryExpressionProperty).VariableName; + + // project keys for entities that are exposed by the projection + if (ent.Type == EntityField.EntityType.Node) + { + var nodeIdJoinKeyName = GetFieldNameForEntityField(ent.FieldAlias, ent.NodeJoinField.FieldAlias); + var nodeIdInSchemaJoinKeyName = GetFieldNameForEntityField(inSchemaAlias, ent.NodeJoinField.FieldAlias); + codeSnip.AppendLine(depth+1, $"{(!isFirstRow ? ", " : " ")}{nodeIdInSchemaJoinKeyName} AS {nodeIdJoinKeyName}"); + nonAggFieldExprs.Add(nodeIdInSchemaJoinKeyName); + isFirstRow = false; + } + else + { + var edgeSrcIdJoinKeyName = GetFieldNameForEntityField(ent.FieldAlias, ent.RelSourceJoinField.FieldAlias); + var edgeSinkIdJoinKeyName = GetFieldNameForEntityField(ent.FieldAlias, ent.RelSinkJoinField.FieldAlias); + var edgeSrcIdInSchemaJoinKeyName = GetFieldNameForEntityField(inSchemaAlias, ent.RelSourceJoinField.FieldAlias); + var edgeSinkIdInSchemaJoinKeyName = GetFieldNameForEntityField(inSchemaAlias, ent.RelSinkJoinField.FieldAlias); + codeSnip.AppendLine(depth + 1, $"{(!isFirstRow ? ", " : " ")}{edgeSrcIdInSchemaJoinKeyName} AS {edgeSrcIdJoinKeyName}"); + codeSnip.AppendLine(depth + 1, $", {edgeSinkIdInSchemaJoinKeyName} AS {edgeSinkIdJoinKeyName}"); + nonAggFieldExprs.Add(edgeSrcIdInSchemaJoinKeyName); + nonAggFieldExprs.Add(edgeSinkIdInSchemaJoinKeyName); + isFirstRow = false; + } + + // referenced non-joinkey fields in the wrapped entities + var nonNullJoinKeyValues = new string[] { ent.NodeJoinField?.FieldAlias, ent.RelSourceJoinField?.FieldAlias, ent.RelSinkJoinField?.FieldAlias }.Where(a => !string.IsNullOrEmpty(a)); + foreach (var field in ent.ReferencedFieldAliases.Except(nonNullJoinKeyValues)) + { + var inSchemaFieldName = GetFieldNameForEntityField(inSchemaAlias, field); + var outSchemaFieldName = GetFieldNameForEntityField(ent.FieldAlias, field); + codeSnip.AppendLine(depth + 1, $", {inSchemaFieldName} AS {outSchemaFieldName}"); + nonAggFieldExprs.Add(inSchemaFieldName); + } + } + + // project single fields + foreach (var field in allOutputSingleFields) + { + // find corresponding expression + var expr = prjOp.ProjectionMap[field.FieldAlias]; + var exprText = RenderExpression( + expr, + new ExpressionRenderingContext() + { + ExpectConditionExpression = false, + EnclosingOperator = prjOp + }); + codeSnip.AppendLine(depth + 1, $"{(!isFirstRow ? ", " : " ")}{exprText} AS {field.FieldAlias}"); + if (expr.GetChildrenQueryExpressionType().Count() == 0) + { + nonAggFieldExprs.Add(exprText); + } + isFirstRow = false; + } + + codeSnip.AppendLine(depth, $"FROM ("); + + if (preCond != null) + { + var prevOp = preCond.InOperator; + codeSnip.AppendLine(RenderLogicalOperator(prevOp, depth + 1)); + codeSnip.AppendLine(depth, $") AS _proj"); + + // if there's precondition, render it too + // WHERE clause specifically + if (preCond?.FilterExpression != null) + { + // Assert that schema has not changed and matches + Debug.Assert(preCond.InputSchema.Count == preCond.OutputSchema.Count && preCond.OutputSchema.Count == prjOp.InputSchema.Count); + var condText = RenderExpression( + preCond.FilterExpression, + new ExpressionRenderingContext() + { + ExpectConditionExpression = true, // SQL does not allow value type to be in WHERE condition + EnclosingOperator = preCond + }); + codeSnip.AppendLine(depth, $"WHERE"); + codeSnip.AppendLine(depth+1, $"{condText}"); + } + } + else + { + codeSnip.AppendLine(RenderLogicalOperator(prjOp.InOperator, depth + 1)); + codeSnip.AppendLine(depth, $") AS _proj"); + } + + // add group by if aggregation is used and there are non aggregation columns + if (prjOp.HasAggregationField && nonAggFieldExprs.Count > 0) + { + codeSnip.AppendLine(depth, $"GROUP BY"); + var isFirstRowGrpBy = true; + foreach (var field in nonAggFieldExprs) + { + codeSnip.AppendLine(depth+1, $"{(isFirstRowGrpBy ? "" : ", ")}{field}"); + isFirstRowGrpBy = false; + } + } + + // order by clause must have limit statement, otherwise, won't compile in scope + if (topXVal.HasValue && preCond.OrderByExpressions?.Count() > 0) + { + // Assert that schema has not changed and matches + Debug.Assert(preCond.InputSchema.Count == preCond.OutputSchema.Count && preCond.OutputSchema.Count == prjOp.InputSchema.Count); + + codeSnip.AppendLine(depth, $"ORDER BY"); + var isFirstRowOrderBy = true; + foreach (var orderExpr in preCond.OrderByExpressions) + { + bool isDescending = orderExpr.IsDescending; + var childrenProperty = orderExpr.GetChildrenQueryExpressionType(); + foreach (var prop in childrenProperty) + { + var exprText = RenderExpression( + prop, + new ExpressionRenderingContext() + { + ExpectConditionExpression = false, + EnclosingOperator = preCond + }); + codeSnip.AppendLine(depth+1, $"{(isFirstRowOrderBy ? "" : ", ")}{exprText} {(isDescending ? "DESC" : "ASC")}"); + isFirstRowOrderBy = false; + } + } + } + + return codeSnip.ToString(); + } + + private string RenderSelection(SelectionOperator condOp, int depth) + { + var codeSnip = new StringBuilder(); + + // Assert that schema has not changed and matches + Debug.Assert(condOp.InputSchema.Count == condOp.OutputSchema.Count); + + // expand output schema + var allColsToOutput = ExpandSchema(condOp.OutputSchema); + var allOutputEntities = condOp.OutputSchema.Where(f => f is EntityField).Cast(); + var allOutputSingleFields = condOp.OutputSchema.Where(f => f is SingleField).Cast(); + bool isFirstRow = true; + + codeSnip.AppendLine(depth, $"SELECT"); + + // project entities and join keys need to be flowed + foreach (var ent in allOutputEntities) + { + // project keys for entities that are exposed by the projection + if (ent.Type == EntityField.EntityType.Node) + { + var nodeIdJoinKeyName = GetFieldNameForEntityField(ent.FieldAlias, ent.NodeJoinField.FieldAlias); + codeSnip.AppendLine(depth+1, $"{(!isFirstRow ? ", " : " ")}{nodeIdJoinKeyName} AS {nodeIdJoinKeyName}"); + isFirstRow = false; + } + else + { + var edgeSrcIdJoinKeyName = GetFieldNameForEntityField(ent.FieldAlias, ent.RelSourceJoinField.FieldAlias); + var edgeSinkIdJoinKeyName = GetFieldNameForEntityField(ent.FieldAlias, ent.RelSinkJoinField.FieldAlias); + codeSnip.AppendLine(depth + 1, $"{(!isFirstRow ? ", " : " ")}{edgeSrcIdJoinKeyName} AS {edgeSrcIdJoinKeyName}"); + codeSnip.AppendLine(depth + 1, $", {edgeSinkIdJoinKeyName} AS {edgeSinkIdJoinKeyName}"); + isFirstRow = false; + } + + // referenced fields in the wrapped entities + var nonNullJoinKeyValues = new string[] { ent.NodeJoinField?.FieldAlias, ent.RelSourceJoinField?.FieldAlias, ent.RelSinkJoinField?.FieldAlias }.Where(a => !string.IsNullOrEmpty(a)); + foreach (var field in ent.ReferencedFieldAliases.Except(nonNullJoinKeyValues)) + { + var fieldName = GetFieldNameForEntityField(ent.FieldAlias, field); + codeSnip.AppendLine(depth + 1, $", {fieldName} AS {fieldName}"); + } + } + + // project single properties (columns) + foreach (var field in allOutputSingleFields) + { + // find corresponding expression + codeSnip.AppendLine(depth + 1, $"{(!isFirstRow ? ", " : " ")}{field.FieldAlias} AS {field.FieldAlias}"); + isFirstRow = false; + } + + codeSnip.AppendLine(depth, $"FROM ("); + codeSnip.AppendLine(RenderLogicalOperator(condOp.InOperator, depth+1)); + codeSnip.AppendLine(depth, $") AS _select"); + + var condText = RenderExpression( + condOp.FilterExpression, + new ExpressionRenderingContext() + { + ExpectConditionExpression = true, // SQL does not allow value type to be in WHERE condition + EnclosingOperator = condOp + }); + codeSnip.AppendLine(depth, $"WHERE"); + codeSnip.AppendLine(depth+1, $"{condText}"); + + return codeSnip.ToString(); + } + + private string RenderSet(SetOperator opSel, int depth) + { + var codeSnip = new StringBuilder(); + codeSnip.AppendLine(depth, "("); + codeSnip.AppendLine(RenderLogicalOperator(opSel.InOperatorLeft, depth + 1)); + codeSnip.AppendLine(depth, $") {(opSel.SetOperation == SetOperator.SetOperationType.UnionAll ? "UNION ALL" : "UNION")}"); + codeSnip.AppendLine(depth, "("); + codeSnip.AppendLine(RenderLogicalOperator(opSel.InOperatorRight, depth + 1)); + codeSnip.AppendLine(depth, ")"); + + return codeSnip.ToString(); + } + + + /// + /// Called by subclass to render main portion of the code + /// + /// + /// + private string RenderLogicalOperator(LogicalOperator op, int depth) + { + switch (op) + { + case DataSourceOperator opDs: + return RenderDataSource(opDs, depth); + case ProjectionOperator opProj: + return RenderProjection(opProj, depth); + case SelectionOperator opSel: + return RenderSelection(opSel, depth); + case JoinOperator opSel: + return RenderJoin(opSel, depth); + case SetOperator opSet: + return RenderSet(opSet, depth); + default: + throw new TranspilerInternalErrorException($"Unexpected operator type: {op.GetType().Name}"); + } + } + + #endregion Logical Operator Renderers + + /// + /// Render the Scope code for a given plan and return the output variable names + /// + /// + /// + /// + public string RenderPlan(LogicalPlan logicalPlan) + { + var codeScript = new StringBuilder(); + + if (logicalPlan.TerminalOperators.Count() != 1) + { + throw new TranspilerNotSupportedException("Multi-output query"); + } + + var terminatingOperator = logicalPlan.TerminalOperators.First(); + + var queryCodeText = RenderLogicalOperator(terminatingOperator, 0); + return queryCodeText; + } + + } +} diff --git a/src/SQLRenderer/SQLRenderer.csproj b/src/SQLRenderer/SQLRenderer.csproj new file mode 100644 index 0000000..65402a7 --- /dev/null +++ b/src/SQLRenderer/SQLRenderer.csproj @@ -0,0 +1,12 @@ + + + + netcoreapp2.1 + Microsoft.GraphPlatform.Transpiler.SQLRenderer + + + + + + + diff --git a/src/SQLRenderer/SQLRendererHelper.cs b/src/SQLRenderer/SQLRendererHelper.cs new file mode 100644 index 0000000..cc5d222 --- /dev/null +++ b/src/SQLRenderer/SQLRendererHelper.cs @@ -0,0 +1,18 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +using System.Text; + +namespace openCypherTranspiler.SQLRenderer +{ + static class SQLRendererHelpers + { + public static StringBuilder AppendLine(this StringBuilder sb, int indentUnits, string line) + { + return sb.AppendLine($"{new string(' ', indentUnits * 4)}{line}"); + } + } +} diff --git a/src/SQLRenderer/SQLTableDescriptor.cs b/src/SQLRenderer/SQLTableDescriptor.cs new file mode 100644 index 0000000..5a1e8a6 --- /dev/null +++ b/src/SQLRenderer/SQLTableDescriptor.cs @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +namespace openCypherTranspiler.SQLRenderer +{ + public class SQLTableDescriptor + { + public string EntityId { get; set; } + + public string TableOrViewName { get; set; } + } +} \ No newline at end of file diff --git a/src/openCypherParser/AST/AggregationFunctionReturnTypeTable.cs b/src/openCypherParser/AST/AggregationFunctionReturnTypeTable.cs new file mode 100644 index 0000000..d4297df --- /dev/null +++ b/src/openCypherParser/AST/AggregationFunctionReturnTypeTable.cs @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using System; +using System.Collections.Generic; +using openCypherTranspiler.openCypherParser.Common; + +namespace openCypherTranspiler.openCypherParser.AST +{ + public static class AggregationFunctionReturnTypeTable + { + public static readonly IDictionary<(AggregationFunction, Type), Type> TypeMapTable = new Dictionary<(AggregationFunction, Type), Type>() + { + { (AggregationFunction.Count, Type.GetType("System.Int32")), Type.GetType("System.Int64")}, + { (AggregationFunction.Count, Type.GetType("System.Double")), Type.GetType("System.Int64")}, + { (AggregationFunction.Count, Type.GetType("System.Int64")), Type.GetType("System.Int64")}, + { (AggregationFunction.Count, Type.GetType("System.Int16")), Type.GetType("System.Int64")}, + { (AggregationFunction.Count, Type.GetType("System.UInt16")), Type.GetType("System.Int64")}, + { (AggregationFunction.Count, Type.GetType("System.UInt64")), Type.GetType("System.Int64")}, + { (AggregationFunction.Count, Type.GetType("System.Byte")), Type.GetType("System.Int64")}, + { (AggregationFunction.Count, Type.GetType("System.Single")), Type.GetType("System.Int64")}, + { (AggregationFunction.Count, Type.GetType("System.UInt32")), Type.GetType("System.Int64")}, + { (AggregationFunction.Count, Type.GetType("System.SByte")), Type.GetType("System.Int64")}, + { (AggregationFunction.Count, Type.GetType("System.Decimal")), Type.GetType("System.Int64")}, + { (AggregationFunction.Count, Type.GetType("System.String")), Type.GetType("System.Int64")}, + { (AggregationFunction.Count, Type.GetType("System.Boolean")), Type.GetType("System.Int64")}, + { (AggregationFunction.Count, Type.GetType("System.DateTime")), Type.GetType("System.Int64")}, + { (AggregationFunction.Count, Type.GetType("System.Byte[]")), Type.GetType("System.Int64")}, + { (AggregationFunction.Count, Type.GetType("System.Object")), Type.GetType("System.Int64")}, + { (AggregationFunction.Count, default(Type)), Type.GetType("System.Int64")}, + + { (AggregationFunction.Avg, Type.GetType("System.Int32")), Type.GetType("System.Nullable`1[System.Double]")}, + { (AggregationFunction.Avg, Type.GetType("System.Double")), Type.GetType("System.Nullable`1[System.Double]")}, + { (AggregationFunction.Avg, Type.GetType("System.Int64")), Type.GetType("System.Nullable`1[System.Double]")}, + { (AggregationFunction.Avg, Type.GetType("System.Int16")), Type.GetType("System.Nullable`1[System.Double]")}, + { (AggregationFunction.Avg, Type.GetType("System.UInt16")), Type.GetType("System.Nullable`1[System.Double]")}, + { (AggregationFunction.Avg, Type.GetType("System.UInt64")), Type.GetType("System.Nullable`1[System.Double]")}, + { (AggregationFunction.Avg, Type.GetType("System.Byte")), Type.GetType("System.Nullable`1[System.Double]")}, + { (AggregationFunction.Avg, Type.GetType("System.Single")), Type.GetType("System.Nullable`1[System.Double]")}, + { (AggregationFunction.Avg, Type.GetType("System.UInt32")), Type.GetType("System.Nullable`1[System.Double]")}, + { (AggregationFunction.Avg, Type.GetType("System.SByte")), Type.GetType("System.Nullable`1[System.Double]")}, + { (AggregationFunction.Avg, Type.GetType("System.Decimal")), Type.GetType("System.Nullable`1[System.Decimal]")}, + + { (AggregationFunction.Sum, Type.GetType("System.Int32")),Type.GetType("System.Int64") }, + { (AggregationFunction.Sum, Type.GetType("System.Double")),Type.GetType("System.Double")}, + { (AggregationFunction.Sum, Type.GetType("System.Int64")),Type.GetType("System.Int64") }, + { (AggregationFunction.Sum, Type.GetType("System.Int16")),Type.GetType("System.Int64") }, + { (AggregationFunction.Sum, Type.GetType("System.UInt16")),Type.GetType("System.Int64") }, + { (AggregationFunction.Sum, Type.GetType("System.UInt64")),Type.GetType("System.Double")}, + { (AggregationFunction.Sum, Type.GetType("System.Byte")),Type.GetType("System.Int64") }, + { (AggregationFunction.Sum, Type.GetType("System.Single")),Type.GetType("System.Double")}, + { (AggregationFunction.Sum, Type.GetType("System.UInt32")),Type.GetType("System.Int64") }, + { (AggregationFunction.Sum, Type.GetType("System.SByte")),Type.GetType("System.Int64") }, + { (AggregationFunction.Sum, Type.GetType("System.Decimal")),Type.GetType("System.Decimal")}, + + }; + } +} diff --git a/src/openCypherParser/AST/BinaryOperatorCoersionTable.cs b/src/openCypherParser/AST/BinaryOperatorCoersionTable.cs new file mode 100644 index 0000000..cbb87cc --- /dev/null +++ b/src/openCypherParser/AST/BinaryOperatorCoersionTable.cs @@ -0,0 +1,1598 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using System; +using System.Collections.Generic; +using openCypherTranspiler.openCypherParser.Common; + +namespace openCypherTranspiler.openCypherParser.AST +{ + /// + /// Lookup table for implicit conversions between primitive types + /// + public static class CoersionTables + { + public static readonly IDictionary<(BinaryOperator OpType, Type Op1Type, Type Op2Type), Type> CoersionTableForValueType = new Dictionary<(BinaryOperator OpType, Type Op1Type, Type Op2Type), Type>() + { + { (BinaryOperator.Plus, typeof(int), typeof(int)), typeof(int) }, + { (BinaryOperator.Plus, typeof(int), typeof(double)), typeof(double) }, + { (BinaryOperator.Plus, typeof(int), typeof(long)), typeof(long) }, + { (BinaryOperator.Plus, typeof(int), typeof(short)), typeof(int) }, + { (BinaryOperator.Plus, typeof(int), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Plus, typeof(int), typeof(ulong)), default(Type) }, + { (BinaryOperator.Plus, typeof(int), typeof(byte)), typeof(int) }, + { (BinaryOperator.Plus, typeof(int), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Plus, typeof(int), typeof(uint)), typeof(long) }, + { (BinaryOperator.Plus, typeof(int), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Plus, typeof(int), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Plus, typeof(int), typeof(string)), typeof(string) }, + { (BinaryOperator.Plus, typeof(int), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Plus, typeof(int), typeof(bool)), default(Type) }, + { (BinaryOperator.Plus, typeof(double), typeof(int)), typeof(double) }, + { (BinaryOperator.Plus, typeof(double), typeof(double)), typeof(double) }, + { (BinaryOperator.Plus, typeof(double), typeof(long)), typeof(double) }, + { (BinaryOperator.Plus, typeof(double), typeof(short)), typeof(double) }, + { (BinaryOperator.Plus, typeof(double), typeof(ushort)), typeof(double) }, + { (BinaryOperator.Plus, typeof(double), typeof(ulong)), typeof(double) }, + { (BinaryOperator.Plus, typeof(double), typeof(byte)), typeof(double) }, + { (BinaryOperator.Plus, typeof(double), typeof(Single)), typeof(double) }, + { (BinaryOperator.Plus, typeof(double), typeof(uint)), typeof(double) }, + { (BinaryOperator.Plus, typeof(double), typeof(SByte)), typeof(double) }, + { (BinaryOperator.Plus, typeof(double), typeof(decimal)), default(Type) }, + { (BinaryOperator.Plus, typeof(double), typeof(string)), typeof(string) }, + { (BinaryOperator.Plus, typeof(double), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Plus, typeof(double), typeof(bool)), default(Type) }, + { (BinaryOperator.Plus, typeof(long), typeof(int)), typeof(long) }, + { (BinaryOperator.Plus, typeof(long), typeof(double)), typeof(double) }, + { (BinaryOperator.Plus, typeof(long), typeof(long)), typeof(long) }, + { (BinaryOperator.Plus, typeof(long), typeof(short)), typeof(long) }, + { (BinaryOperator.Plus, typeof(long), typeof(ushort)), typeof(long) }, + { (BinaryOperator.Plus, typeof(long), typeof(ulong)), default(Type) }, + { (BinaryOperator.Plus, typeof(long), typeof(byte)), typeof(long) }, + { (BinaryOperator.Plus, typeof(long), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Plus, typeof(long), typeof(uint)), typeof(long) }, + { (BinaryOperator.Plus, typeof(long), typeof(SByte)), typeof(long) }, + { (BinaryOperator.Plus, typeof(long), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Plus, typeof(long), typeof(string)), typeof(string) }, + { (BinaryOperator.Plus, typeof(long), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Plus, typeof(long), typeof(bool)), default(Type) }, + { (BinaryOperator.Plus, typeof(short), typeof(int)), typeof(int) }, + { (BinaryOperator.Plus, typeof(short), typeof(double)), typeof(double) }, + { (BinaryOperator.Plus, typeof(short), typeof(long)), typeof(long) }, + { (BinaryOperator.Plus, typeof(short), typeof(short)), typeof(int) }, + { (BinaryOperator.Plus, typeof(short), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Plus, typeof(short), typeof(ulong)), default(Type) }, + { (BinaryOperator.Plus, typeof(short), typeof(byte)), typeof(int) }, + { (BinaryOperator.Plus, typeof(short), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Plus, typeof(short), typeof(uint)), typeof(long) }, + { (BinaryOperator.Plus, typeof(short), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Plus, typeof(short), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Plus, typeof(short), typeof(string)), typeof(string) }, + { (BinaryOperator.Plus, typeof(short), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Plus, typeof(short), typeof(bool)), default(Type) }, + { (BinaryOperator.Plus, typeof(ushort), typeof(int)), typeof(int) }, + { (BinaryOperator.Plus, typeof(ushort), typeof(double)), typeof(double) }, + { (BinaryOperator.Plus, typeof(ushort), typeof(long)), typeof(long) }, + { (BinaryOperator.Plus, typeof(ushort), typeof(short)), typeof(int) }, + { (BinaryOperator.Plus, typeof(ushort), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Plus, typeof(ushort), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Plus, typeof(ushort), typeof(byte)), typeof(int) }, + { (BinaryOperator.Plus, typeof(ushort), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Plus, typeof(ushort), typeof(uint)), typeof(uint) }, + { (BinaryOperator.Plus, typeof(ushort), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Plus, typeof(ushort), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Plus, typeof(ushort), typeof(string)), typeof(string) }, + { (BinaryOperator.Plus, typeof(ushort), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Plus, typeof(ushort), typeof(bool)), default(Type) }, + { (BinaryOperator.Plus, typeof(ulong), typeof(int)), default(Type) }, + { (BinaryOperator.Plus, typeof(ulong), typeof(double)), typeof(double) }, + { (BinaryOperator.Plus, typeof(ulong), typeof(long)), default(Type) }, + { (BinaryOperator.Plus, typeof(ulong), typeof(short)), default(Type) }, + { (BinaryOperator.Plus, typeof(ulong), typeof(ushort)), typeof(ulong) }, + { (BinaryOperator.Plus, typeof(ulong), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Plus, typeof(ulong), typeof(byte)), typeof(ulong) }, + { (BinaryOperator.Plus, typeof(ulong), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Plus, typeof(ulong), typeof(uint)), typeof(ulong) }, + { (BinaryOperator.Plus, typeof(ulong), typeof(SByte)), default(Type) }, + { (BinaryOperator.Plus, typeof(ulong), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Plus, typeof(ulong), typeof(string)), typeof(string) }, + { (BinaryOperator.Plus, typeof(ulong), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Plus, typeof(ulong), typeof(bool)), default(Type) }, + { (BinaryOperator.Plus, typeof(byte), typeof(int)), typeof(int) }, + { (BinaryOperator.Plus, typeof(byte), typeof(double)), typeof(double) }, + { (BinaryOperator.Plus, typeof(byte), typeof(long)), typeof(long) }, + { (BinaryOperator.Plus, typeof(byte), typeof(short)), typeof(int) }, + { (BinaryOperator.Plus, typeof(byte), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Plus, typeof(byte), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Plus, typeof(byte), typeof(byte)), typeof(int) }, + { (BinaryOperator.Plus, typeof(byte), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Plus, typeof(byte), typeof(uint)), typeof(uint) }, + { (BinaryOperator.Plus, typeof(byte), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Plus, typeof(byte), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Plus, typeof(byte), typeof(string)), typeof(string) }, + { (BinaryOperator.Plus, typeof(byte), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Plus, typeof(byte), typeof(bool)), default(Type) }, + { (BinaryOperator.Plus, typeof(Single), typeof(int)), typeof(Single) }, + { (BinaryOperator.Plus, typeof(Single), typeof(double)), typeof(double) }, + { (BinaryOperator.Plus, typeof(Single), typeof(long)), typeof(Single) }, + { (BinaryOperator.Plus, typeof(Single), typeof(short)), typeof(Single) }, + { (BinaryOperator.Plus, typeof(Single), typeof(ushort)), typeof(Single) }, + { (BinaryOperator.Plus, typeof(Single), typeof(ulong)), typeof(Single) }, + { (BinaryOperator.Plus, typeof(Single), typeof(byte)), typeof(Single) }, + { (BinaryOperator.Plus, typeof(Single), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Plus, typeof(Single), typeof(uint)), typeof(Single) }, + { (BinaryOperator.Plus, typeof(Single), typeof(SByte)), typeof(Single) }, + { (BinaryOperator.Plus, typeof(Single), typeof(decimal)), default(Type) }, + { (BinaryOperator.Plus, typeof(Single), typeof(string)), typeof(string) }, + { (BinaryOperator.Plus, typeof(Single), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Plus, typeof(Single), typeof(bool)), default(Type) }, + { (BinaryOperator.Plus, typeof(uint), typeof(int)), typeof(long) }, + { (BinaryOperator.Plus, typeof(uint), typeof(double)), typeof(double) }, + { (BinaryOperator.Plus, typeof(uint), typeof(long)), typeof(long) }, + { (BinaryOperator.Plus, typeof(uint), typeof(short)), typeof(long) }, + { (BinaryOperator.Plus, typeof(uint), typeof(ushort)), typeof(uint) }, + { (BinaryOperator.Plus, typeof(uint), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Plus, typeof(uint), typeof(byte)), typeof(uint) }, + { (BinaryOperator.Plus, typeof(uint), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Plus, typeof(uint), typeof(uint)), typeof(uint) }, + { (BinaryOperator.Plus, typeof(uint), typeof(SByte)), typeof(long) }, + { (BinaryOperator.Plus, typeof(uint), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Plus, typeof(uint), typeof(string)), typeof(string) }, + { (BinaryOperator.Plus, typeof(uint), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Plus, typeof(uint), typeof(bool)), default(Type) }, + { (BinaryOperator.Plus, typeof(SByte), typeof(int)), typeof(int) }, + { (BinaryOperator.Plus, typeof(SByte), typeof(double)), typeof(double) }, + { (BinaryOperator.Plus, typeof(SByte), typeof(long)), typeof(long) }, + { (BinaryOperator.Plus, typeof(SByte), typeof(short)), typeof(int) }, + { (BinaryOperator.Plus, typeof(SByte), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Plus, typeof(SByte), typeof(ulong)), default(Type) }, + { (BinaryOperator.Plus, typeof(SByte), typeof(byte)), typeof(int) }, + { (BinaryOperator.Plus, typeof(SByte), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Plus, typeof(SByte), typeof(uint)), typeof(long) }, + { (BinaryOperator.Plus, typeof(SByte), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Plus, typeof(SByte), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Plus, typeof(SByte), typeof(string)), typeof(string) }, + { (BinaryOperator.Plus, typeof(SByte), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Plus, typeof(SByte), typeof(bool)), default(Type) }, + { (BinaryOperator.Plus, typeof(decimal), typeof(int)), typeof(decimal) }, + { (BinaryOperator.Plus, typeof(decimal), typeof(double)), default(Type) }, + { (BinaryOperator.Plus, typeof(decimal), typeof(long)), typeof(decimal) }, + { (BinaryOperator.Plus, typeof(decimal), typeof(short)), typeof(decimal) }, + { (BinaryOperator.Plus, typeof(decimal), typeof(ushort)), typeof(decimal) }, + { (BinaryOperator.Plus, typeof(decimal), typeof(ulong)), typeof(decimal) }, + { (BinaryOperator.Plus, typeof(decimal), typeof(byte)), typeof(decimal) }, + { (BinaryOperator.Plus, typeof(decimal), typeof(Single)), default(Type) }, + { (BinaryOperator.Plus, typeof(decimal), typeof(uint)), typeof(decimal) }, + { (BinaryOperator.Plus, typeof(decimal), typeof(SByte)), typeof(decimal) }, + { (BinaryOperator.Plus, typeof(decimal), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Plus, typeof(decimal), typeof(string)), typeof(string) }, + { (BinaryOperator.Plus, typeof(decimal), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Plus, typeof(decimal), typeof(bool)), default(Type) }, + { (BinaryOperator.Plus, typeof(string), typeof(int)), typeof(string) }, + { (BinaryOperator.Plus, typeof(string), typeof(double)), typeof(string) }, + { (BinaryOperator.Plus, typeof(string), typeof(long)), typeof(string) }, + { (BinaryOperator.Plus, typeof(string), typeof(short)), typeof(string) }, + { (BinaryOperator.Plus, typeof(string), typeof(ushort)), typeof(string) }, + { (BinaryOperator.Plus, typeof(string), typeof(ulong)), typeof(string) }, + { (BinaryOperator.Plus, typeof(string), typeof(byte)), typeof(string) }, + { (BinaryOperator.Plus, typeof(string), typeof(Single)), typeof(string) }, + { (BinaryOperator.Plus, typeof(string), typeof(uint)), typeof(string) }, + { (BinaryOperator.Plus, typeof(string), typeof(SByte)), typeof(string) }, + { (BinaryOperator.Plus, typeof(string), typeof(decimal)), typeof(string) }, + { (BinaryOperator.Plus, typeof(string), typeof(string)), typeof(string) }, + { (BinaryOperator.Plus, typeof(string), typeof(DateTime)), typeof(string) }, + { (BinaryOperator.Plus, typeof(string), typeof(bool)), typeof(string) }, + { (BinaryOperator.Plus, typeof(DateTime), typeof(int)), default(Type) }, + { (BinaryOperator.Plus, typeof(DateTime), typeof(double)), default(Type) }, + { (BinaryOperator.Plus, typeof(DateTime), typeof(long)), default(Type) }, + { (BinaryOperator.Plus, typeof(DateTime), typeof(short)), default(Type) }, + { (BinaryOperator.Plus, typeof(DateTime), typeof(ushort)), default(Type) }, + { (BinaryOperator.Plus, typeof(DateTime), typeof(ulong)), default(Type) }, + { (BinaryOperator.Plus, typeof(DateTime), typeof(byte)), default(Type) }, + { (BinaryOperator.Plus, typeof(DateTime), typeof(Single)), default(Type) }, + { (BinaryOperator.Plus, typeof(DateTime), typeof(uint)), default(Type) }, + { (BinaryOperator.Plus, typeof(DateTime), typeof(SByte)), default(Type) }, + { (BinaryOperator.Plus, typeof(DateTime), typeof(decimal)), default(Type) }, + { (BinaryOperator.Plus, typeof(DateTime), typeof(string)), typeof(string) }, + { (BinaryOperator.Plus, typeof(DateTime), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Plus, typeof(DateTime), typeof(bool)), default(Type) }, + { (BinaryOperator.Plus, typeof(bool), typeof(int)), default(Type) }, + { (BinaryOperator.Plus, typeof(bool), typeof(double)), default(Type) }, + { (BinaryOperator.Plus, typeof(bool), typeof(long)), default(Type) }, + { (BinaryOperator.Plus, typeof(bool), typeof(short)), default(Type) }, + { (BinaryOperator.Plus, typeof(bool), typeof(ushort)), default(Type) }, + { (BinaryOperator.Plus, typeof(bool), typeof(ulong)), default(Type) }, + { (BinaryOperator.Plus, typeof(bool), typeof(byte)), default(Type) }, + { (BinaryOperator.Plus, typeof(bool), typeof(Single)), default(Type) }, + { (BinaryOperator.Plus, typeof(bool), typeof(uint)), default(Type) }, + { (BinaryOperator.Plus, typeof(bool), typeof(SByte)), default(Type) }, + { (BinaryOperator.Plus, typeof(bool), typeof(decimal)), default(Type) }, + { (BinaryOperator.Plus, typeof(bool), typeof(string)), typeof(string) }, + { (BinaryOperator.Plus, typeof(bool), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Plus, typeof(bool), typeof(bool)), default(Type) }, + { (BinaryOperator.Minus, typeof(int), typeof(int)), typeof(int) }, + { (BinaryOperator.Minus, typeof(int), typeof(double)), typeof(double) }, + { (BinaryOperator.Minus, typeof(int), typeof(long)), typeof(long) }, + { (BinaryOperator.Minus, typeof(int), typeof(short)), typeof(int) }, + { (BinaryOperator.Minus, typeof(int), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Minus, typeof(int), typeof(ulong)), default(Type) }, + { (BinaryOperator.Minus, typeof(int), typeof(byte)), typeof(int) }, + { (BinaryOperator.Minus, typeof(int), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Minus, typeof(int), typeof(uint)), typeof(long) }, + { (BinaryOperator.Minus, typeof(int), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Minus, typeof(int), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Minus, typeof(int), typeof(string)), default(Type) }, + { (BinaryOperator.Minus, typeof(int), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Minus, typeof(int), typeof(bool)), default(Type) }, + { (BinaryOperator.Minus, typeof(double), typeof(int)), typeof(double) }, + { (BinaryOperator.Minus, typeof(double), typeof(double)), typeof(double) }, + { (BinaryOperator.Minus, typeof(double), typeof(long)), typeof(double) }, + { (BinaryOperator.Minus, typeof(double), typeof(short)), typeof(double) }, + { (BinaryOperator.Minus, typeof(double), typeof(ushort)), typeof(double) }, + { (BinaryOperator.Minus, typeof(double), typeof(ulong)), typeof(double) }, + { (BinaryOperator.Minus, typeof(double), typeof(byte)), typeof(double) }, + { (BinaryOperator.Minus, typeof(double), typeof(Single)), typeof(double) }, + { (BinaryOperator.Minus, typeof(double), typeof(uint)), typeof(double) }, + { (BinaryOperator.Minus, typeof(double), typeof(SByte)), typeof(double) }, + { (BinaryOperator.Minus, typeof(double), typeof(decimal)), default(Type) }, + { (BinaryOperator.Minus, typeof(double), typeof(string)), default(Type) }, + { (BinaryOperator.Minus, typeof(double), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Minus, typeof(double), typeof(bool)), default(Type) }, + { (BinaryOperator.Minus, typeof(long), typeof(int)), typeof(long) }, + { (BinaryOperator.Minus, typeof(long), typeof(double)), typeof(double) }, + { (BinaryOperator.Minus, typeof(long), typeof(long)), typeof(long) }, + { (BinaryOperator.Minus, typeof(long), typeof(short)), typeof(long) }, + { (BinaryOperator.Minus, typeof(long), typeof(ushort)), typeof(long) }, + { (BinaryOperator.Minus, typeof(long), typeof(ulong)), default(Type) }, + { (BinaryOperator.Minus, typeof(long), typeof(byte)), typeof(long) }, + { (BinaryOperator.Minus, typeof(long), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Minus, typeof(long), typeof(uint)), typeof(long) }, + { (BinaryOperator.Minus, typeof(long), typeof(SByte)), typeof(long) }, + { (BinaryOperator.Minus, typeof(long), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Minus, typeof(long), typeof(string)), default(Type) }, + { (BinaryOperator.Minus, typeof(long), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Minus, typeof(long), typeof(bool)), default(Type) }, + { (BinaryOperator.Minus, typeof(short), typeof(int)), typeof(int) }, + { (BinaryOperator.Minus, typeof(short), typeof(double)), typeof(double) }, + { (BinaryOperator.Minus, typeof(short), typeof(long)), typeof(long) }, + { (BinaryOperator.Minus, typeof(short), typeof(short)), typeof(int) }, + { (BinaryOperator.Minus, typeof(short), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Minus, typeof(short), typeof(ulong)), default(Type) }, + { (BinaryOperator.Minus, typeof(short), typeof(byte)), typeof(int) }, + { (BinaryOperator.Minus, typeof(short), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Minus, typeof(short), typeof(uint)), typeof(long) }, + { (BinaryOperator.Minus, typeof(short), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Minus, typeof(short), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Minus, typeof(short), typeof(string)), default(Type) }, + { (BinaryOperator.Minus, typeof(short), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Minus, typeof(short), typeof(bool)), default(Type) }, + { (BinaryOperator.Minus, typeof(ushort), typeof(int)), typeof(int) }, + { (BinaryOperator.Minus, typeof(ushort), typeof(double)), typeof(double) }, + { (BinaryOperator.Minus, typeof(ushort), typeof(long)), typeof(long) }, + { (BinaryOperator.Minus, typeof(ushort), typeof(short)), typeof(int) }, + { (BinaryOperator.Minus, typeof(ushort), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Minus, typeof(ushort), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Minus, typeof(ushort), typeof(byte)), typeof(int) }, + { (BinaryOperator.Minus, typeof(ushort), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Minus, typeof(ushort), typeof(uint)), typeof(uint) }, + { (BinaryOperator.Minus, typeof(ushort), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Minus, typeof(ushort), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Minus, typeof(ushort), typeof(string)), default(Type) }, + { (BinaryOperator.Minus, typeof(ushort), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Minus, typeof(ushort), typeof(bool)), default(Type) }, + { (BinaryOperator.Minus, typeof(ulong), typeof(int)), default(Type) }, + { (BinaryOperator.Minus, typeof(ulong), typeof(double)), typeof(double) }, + { (BinaryOperator.Minus, typeof(ulong), typeof(long)), default(Type) }, + { (BinaryOperator.Minus, typeof(ulong), typeof(short)), default(Type) }, + { (BinaryOperator.Minus, typeof(ulong), typeof(ushort)), typeof(ulong) }, + { (BinaryOperator.Minus, typeof(ulong), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Minus, typeof(ulong), typeof(byte)), typeof(ulong) }, + { (BinaryOperator.Minus, typeof(ulong), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Minus, typeof(ulong), typeof(uint)), typeof(ulong) }, + { (BinaryOperator.Minus, typeof(ulong), typeof(SByte)), default(Type) }, + { (BinaryOperator.Minus, typeof(ulong), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Minus, typeof(ulong), typeof(string)), default(Type) }, + { (BinaryOperator.Minus, typeof(ulong), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Minus, typeof(ulong), typeof(bool)), default(Type) }, + { (BinaryOperator.Minus, typeof(byte), typeof(int)), typeof(int) }, + { (BinaryOperator.Minus, typeof(byte), typeof(double)), typeof(double) }, + { (BinaryOperator.Minus, typeof(byte), typeof(long)), typeof(long) }, + { (BinaryOperator.Minus, typeof(byte), typeof(short)), typeof(int) }, + { (BinaryOperator.Minus, typeof(byte), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Minus, typeof(byte), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Minus, typeof(byte), typeof(byte)), typeof(int) }, + { (BinaryOperator.Minus, typeof(byte), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Minus, typeof(byte), typeof(uint)), typeof(uint) }, + { (BinaryOperator.Minus, typeof(byte), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Minus, typeof(byte), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Minus, typeof(byte), typeof(string)), default(Type) }, + { (BinaryOperator.Minus, typeof(byte), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Minus, typeof(byte), typeof(bool)), default(Type) }, + { (BinaryOperator.Minus, typeof(Single), typeof(int)), typeof(Single) }, + { (BinaryOperator.Minus, typeof(Single), typeof(double)), typeof(double) }, + { (BinaryOperator.Minus, typeof(Single), typeof(long)), typeof(Single) }, + { (BinaryOperator.Minus, typeof(Single), typeof(short)), typeof(Single) }, + { (BinaryOperator.Minus, typeof(Single), typeof(ushort)), typeof(Single) }, + { (BinaryOperator.Minus, typeof(Single), typeof(ulong)), typeof(Single) }, + { (BinaryOperator.Minus, typeof(Single), typeof(byte)), typeof(Single) }, + { (BinaryOperator.Minus, typeof(Single), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Minus, typeof(Single), typeof(uint)), typeof(Single) }, + { (BinaryOperator.Minus, typeof(Single), typeof(SByte)), typeof(Single) }, + { (BinaryOperator.Minus, typeof(Single), typeof(decimal)), default(Type) }, + { (BinaryOperator.Minus, typeof(Single), typeof(string)), default(Type) }, + { (BinaryOperator.Minus, typeof(Single), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Minus, typeof(Single), typeof(bool)), default(Type) }, + { (BinaryOperator.Minus, typeof(uint), typeof(int)), typeof(long) }, + { (BinaryOperator.Minus, typeof(uint), typeof(double)), typeof(double) }, + { (BinaryOperator.Minus, typeof(uint), typeof(long)), typeof(long) }, + { (BinaryOperator.Minus, typeof(uint), typeof(short)), typeof(long) }, + { (BinaryOperator.Minus, typeof(uint), typeof(ushort)), typeof(uint) }, + { (BinaryOperator.Minus, typeof(uint), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Minus, typeof(uint), typeof(byte)), typeof(uint) }, + { (BinaryOperator.Minus, typeof(uint), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Minus, typeof(uint), typeof(uint)), typeof(uint) }, + { (BinaryOperator.Minus, typeof(uint), typeof(SByte)), typeof(long) }, + { (BinaryOperator.Minus, typeof(uint), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Minus, typeof(uint), typeof(string)), default(Type) }, + { (BinaryOperator.Minus, typeof(uint), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Minus, typeof(uint), typeof(bool)), default(Type) }, + { (BinaryOperator.Minus, typeof(SByte), typeof(int)), typeof(int) }, + { (BinaryOperator.Minus, typeof(SByte), typeof(double)), typeof(double) }, + { (BinaryOperator.Minus, typeof(SByte), typeof(long)), typeof(long) }, + { (BinaryOperator.Minus, typeof(SByte), typeof(short)), typeof(int) }, + { (BinaryOperator.Minus, typeof(SByte), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Minus, typeof(SByte), typeof(ulong)), default(Type) }, + { (BinaryOperator.Minus, typeof(SByte), typeof(byte)), typeof(int) }, + { (BinaryOperator.Minus, typeof(SByte), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Minus, typeof(SByte), typeof(uint)), typeof(long) }, + { (BinaryOperator.Minus, typeof(SByte), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Minus, typeof(SByte), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Minus, typeof(SByte), typeof(string)), default(Type) }, + { (BinaryOperator.Minus, typeof(SByte), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Minus, typeof(SByte), typeof(bool)), default(Type) }, + { (BinaryOperator.Minus, typeof(decimal), typeof(int)), typeof(decimal) }, + { (BinaryOperator.Minus, typeof(decimal), typeof(double)), default(Type) }, + { (BinaryOperator.Minus, typeof(decimal), typeof(long)), typeof(decimal) }, + { (BinaryOperator.Minus, typeof(decimal), typeof(short)), typeof(decimal) }, + { (BinaryOperator.Minus, typeof(decimal), typeof(ushort)), typeof(decimal) }, + { (BinaryOperator.Minus, typeof(decimal), typeof(ulong)), typeof(decimal) }, + { (BinaryOperator.Minus, typeof(decimal), typeof(byte)), typeof(decimal) }, + { (BinaryOperator.Minus, typeof(decimal), typeof(Single)), default(Type) }, + { (BinaryOperator.Minus, typeof(decimal), typeof(uint)), typeof(decimal) }, + { (BinaryOperator.Minus, typeof(decimal), typeof(SByte)), typeof(decimal) }, + { (BinaryOperator.Minus, typeof(decimal), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Minus, typeof(decimal), typeof(string)), default(Type) }, + { (BinaryOperator.Minus, typeof(decimal), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Minus, typeof(decimal), typeof(bool)), default(Type) }, + { (BinaryOperator.Minus, typeof(string), typeof(int)), default(Type) }, + { (BinaryOperator.Minus, typeof(string), typeof(double)), default(Type) }, + { (BinaryOperator.Minus, typeof(string), typeof(long)), default(Type) }, + { (BinaryOperator.Minus, typeof(string), typeof(short)), default(Type) }, + { (BinaryOperator.Minus, typeof(string), typeof(ushort)), default(Type) }, + { (BinaryOperator.Minus, typeof(string), typeof(ulong)), default(Type) }, + { (BinaryOperator.Minus, typeof(string), typeof(byte)), default(Type) }, + { (BinaryOperator.Minus, typeof(string), typeof(Single)), default(Type) }, + { (BinaryOperator.Minus, typeof(string), typeof(uint)), default(Type) }, + { (BinaryOperator.Minus, typeof(string), typeof(SByte)), default(Type) }, + { (BinaryOperator.Minus, typeof(string), typeof(decimal)), default(Type) }, + { (BinaryOperator.Minus, typeof(string), typeof(string)), default(Type) }, + { (BinaryOperator.Minus, typeof(string), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Minus, typeof(string), typeof(bool)), default(Type) }, + { (BinaryOperator.Minus, typeof(DateTime), typeof(int)), default(Type) }, + { (BinaryOperator.Minus, typeof(DateTime), typeof(double)), default(Type) }, + { (BinaryOperator.Minus, typeof(DateTime), typeof(long)), default(Type) }, + { (BinaryOperator.Minus, typeof(DateTime), typeof(short)), default(Type) }, + { (BinaryOperator.Minus, typeof(DateTime), typeof(ushort)), default(Type) }, + { (BinaryOperator.Minus, typeof(DateTime), typeof(ulong)), default(Type) }, + { (BinaryOperator.Minus, typeof(DateTime), typeof(byte)), default(Type) }, + { (BinaryOperator.Minus, typeof(DateTime), typeof(Single)), default(Type) }, + { (BinaryOperator.Minus, typeof(DateTime), typeof(uint)), default(Type) }, + { (BinaryOperator.Minus, typeof(DateTime), typeof(SByte)), default(Type) }, + { (BinaryOperator.Minus, typeof(DateTime), typeof(decimal)), default(Type) }, + { (BinaryOperator.Minus, typeof(DateTime), typeof(string)), default(Type) }, + { (BinaryOperator.Minus, typeof(DateTime), typeof(DateTime)), Type.GetType("System.TimeSpan") }, + { (BinaryOperator.Minus, typeof(DateTime), typeof(bool)), default(Type) }, + { (BinaryOperator.Minus, typeof(bool), typeof(int)), default(Type) }, + { (BinaryOperator.Minus, typeof(bool), typeof(double)), default(Type) }, + { (BinaryOperator.Minus, typeof(bool), typeof(long)), default(Type) }, + { (BinaryOperator.Minus, typeof(bool), typeof(short)), default(Type) }, + { (BinaryOperator.Minus, typeof(bool), typeof(ushort)), default(Type) }, + { (BinaryOperator.Minus, typeof(bool), typeof(ulong)), default(Type) }, + { (BinaryOperator.Minus, typeof(bool), typeof(byte)), default(Type) }, + { (BinaryOperator.Minus, typeof(bool), typeof(Single)), default(Type) }, + { (BinaryOperator.Minus, typeof(bool), typeof(uint)), default(Type) }, + { (BinaryOperator.Minus, typeof(bool), typeof(SByte)), default(Type) }, + { (BinaryOperator.Minus, typeof(bool), typeof(decimal)), default(Type) }, + { (BinaryOperator.Minus, typeof(bool), typeof(string)), default(Type) }, + { (BinaryOperator.Minus, typeof(bool), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Minus, typeof(bool), typeof(bool)), default(Type) }, + { (BinaryOperator.Multiply, typeof(int), typeof(int)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(int), typeof(double)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(int), typeof(long)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(int), typeof(short)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(int), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(int), typeof(ulong)), default(Type) }, + { (BinaryOperator.Multiply, typeof(int), typeof(byte)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(int), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Multiply, typeof(int), typeof(uint)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(int), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(int), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Multiply, typeof(int), typeof(string)), default(Type) }, + { (BinaryOperator.Multiply, typeof(int), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Multiply, typeof(int), typeof(bool)), default(Type) }, + { (BinaryOperator.Multiply, typeof(double), typeof(int)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(double), typeof(double)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(double), typeof(long)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(double), typeof(short)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(double), typeof(ushort)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(double), typeof(ulong)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(double), typeof(byte)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(double), typeof(Single)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(double), typeof(uint)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(double), typeof(SByte)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(double), typeof(decimal)), default(Type) }, + { (BinaryOperator.Multiply, typeof(double), typeof(string)), default(Type) }, + { (BinaryOperator.Multiply, typeof(double), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Multiply, typeof(double), typeof(bool)), default(Type) }, + { (BinaryOperator.Multiply, typeof(long), typeof(int)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(long), typeof(double)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(long), typeof(long)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(long), typeof(short)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(long), typeof(ushort)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(long), typeof(ulong)), default(Type) }, + { (BinaryOperator.Multiply, typeof(long), typeof(byte)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(long), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Multiply, typeof(long), typeof(uint)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(long), typeof(SByte)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(long), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Multiply, typeof(long), typeof(string)), default(Type) }, + { (BinaryOperator.Multiply, typeof(long), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Multiply, typeof(long), typeof(bool)), default(Type) }, + { (BinaryOperator.Multiply, typeof(short), typeof(int)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(short), typeof(double)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(short), typeof(long)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(short), typeof(short)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(short), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(short), typeof(ulong)), default(Type) }, + { (BinaryOperator.Multiply, typeof(short), typeof(byte)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(short), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Multiply, typeof(short), typeof(uint)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(short), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(short), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Multiply, typeof(short), typeof(string)), default(Type) }, + { (BinaryOperator.Multiply, typeof(short), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Multiply, typeof(short), typeof(bool)), default(Type) }, + { (BinaryOperator.Multiply, typeof(ushort), typeof(int)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(ushort), typeof(double)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(ushort), typeof(long)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(ushort), typeof(short)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(ushort), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(ushort), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Multiply, typeof(ushort), typeof(byte)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(ushort), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Multiply, typeof(ushort), typeof(uint)), typeof(uint) }, + { (BinaryOperator.Multiply, typeof(ushort), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(ushort), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Multiply, typeof(ushort), typeof(string)), default(Type) }, + { (BinaryOperator.Multiply, typeof(ushort), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Multiply, typeof(ushort), typeof(bool)), default(Type) }, + { (BinaryOperator.Multiply, typeof(ulong), typeof(int)), default(Type) }, + { (BinaryOperator.Multiply, typeof(ulong), typeof(double)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(ulong), typeof(long)), default(Type) }, + { (BinaryOperator.Multiply, typeof(ulong), typeof(short)), default(Type) }, + { (BinaryOperator.Multiply, typeof(ulong), typeof(ushort)), typeof(ulong) }, + { (BinaryOperator.Multiply, typeof(ulong), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Multiply, typeof(ulong), typeof(byte)), typeof(ulong) }, + { (BinaryOperator.Multiply, typeof(ulong), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Multiply, typeof(ulong), typeof(uint)), typeof(ulong) }, + { (BinaryOperator.Multiply, typeof(ulong), typeof(SByte)), default(Type) }, + { (BinaryOperator.Multiply, typeof(ulong), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Multiply, typeof(ulong), typeof(string)), default(Type) }, + { (BinaryOperator.Multiply, typeof(ulong), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Multiply, typeof(ulong), typeof(bool)), default(Type) }, + { (BinaryOperator.Multiply, typeof(byte), typeof(int)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(byte), typeof(double)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(byte), typeof(long)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(byte), typeof(short)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(byte), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(byte), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Multiply, typeof(byte), typeof(byte)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(byte), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Multiply, typeof(byte), typeof(uint)), typeof(uint) }, + { (BinaryOperator.Multiply, typeof(byte), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(byte), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Multiply, typeof(byte), typeof(string)), default(Type) }, + { (BinaryOperator.Multiply, typeof(byte), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Multiply, typeof(byte), typeof(bool)), default(Type) }, + { (BinaryOperator.Multiply, typeof(Single), typeof(int)), typeof(Single) }, + { (BinaryOperator.Multiply, typeof(Single), typeof(double)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(Single), typeof(long)), typeof(Single) }, + { (BinaryOperator.Multiply, typeof(Single), typeof(short)), typeof(Single) }, + { (BinaryOperator.Multiply, typeof(Single), typeof(ushort)), typeof(Single) }, + { (BinaryOperator.Multiply, typeof(Single), typeof(ulong)), typeof(Single) }, + { (BinaryOperator.Multiply, typeof(Single), typeof(byte)), typeof(Single) }, + { (BinaryOperator.Multiply, typeof(Single), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Multiply, typeof(Single), typeof(uint)), typeof(Single) }, + { (BinaryOperator.Multiply, typeof(Single), typeof(SByte)), typeof(Single) }, + { (BinaryOperator.Multiply, typeof(Single), typeof(decimal)), default(Type) }, + { (BinaryOperator.Multiply, typeof(Single), typeof(string)), default(Type) }, + { (BinaryOperator.Multiply, typeof(Single), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Multiply, typeof(Single), typeof(bool)), default(Type) }, + { (BinaryOperator.Multiply, typeof(uint), typeof(int)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(uint), typeof(double)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(uint), typeof(long)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(uint), typeof(short)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(uint), typeof(ushort)), typeof(uint) }, + { (BinaryOperator.Multiply, typeof(uint), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Multiply, typeof(uint), typeof(byte)), typeof(uint) }, + { (BinaryOperator.Multiply, typeof(uint), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Multiply, typeof(uint), typeof(uint)), typeof(uint) }, + { (BinaryOperator.Multiply, typeof(uint), typeof(SByte)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(uint), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Multiply, typeof(uint), typeof(string)), default(Type) }, + { (BinaryOperator.Multiply, typeof(uint), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Multiply, typeof(uint), typeof(bool)), default(Type) }, + { (BinaryOperator.Multiply, typeof(SByte), typeof(int)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(SByte), typeof(double)), typeof(double) }, + { (BinaryOperator.Multiply, typeof(SByte), typeof(long)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(SByte), typeof(short)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(SByte), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(SByte), typeof(ulong)), default(Type) }, + { (BinaryOperator.Multiply, typeof(SByte), typeof(byte)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(SByte), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Multiply, typeof(SByte), typeof(uint)), typeof(long) }, + { (BinaryOperator.Multiply, typeof(SByte), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Multiply, typeof(SByte), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Multiply, typeof(SByte), typeof(string)), default(Type) }, + { (BinaryOperator.Multiply, typeof(SByte), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Multiply, typeof(SByte), typeof(bool)), default(Type) }, + { (BinaryOperator.Multiply, typeof(decimal), typeof(int)), typeof(decimal) }, + { (BinaryOperator.Multiply, typeof(decimal), typeof(double)), default(Type) }, + { (BinaryOperator.Multiply, typeof(decimal), typeof(long)), typeof(decimal) }, + { (BinaryOperator.Multiply, typeof(decimal), typeof(short)), typeof(decimal) }, + { (BinaryOperator.Multiply, typeof(decimal), typeof(ushort)), typeof(decimal) }, + { (BinaryOperator.Multiply, typeof(decimal), typeof(ulong)), typeof(decimal) }, + { (BinaryOperator.Multiply, typeof(decimal), typeof(byte)), typeof(decimal) }, + { (BinaryOperator.Multiply, typeof(decimal), typeof(Single)), default(Type) }, + { (BinaryOperator.Multiply, typeof(decimal), typeof(uint)), typeof(decimal) }, + { (BinaryOperator.Multiply, typeof(decimal), typeof(SByte)), typeof(decimal) }, + { (BinaryOperator.Multiply, typeof(decimal), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Multiply, typeof(decimal), typeof(string)), default(Type) }, + { (BinaryOperator.Multiply, typeof(decimal), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Multiply, typeof(decimal), typeof(bool)), default(Type) }, + { (BinaryOperator.Multiply, typeof(string), typeof(int)), default(Type) }, + { (BinaryOperator.Multiply, typeof(string), typeof(double)), default(Type) }, + { (BinaryOperator.Multiply, typeof(string), typeof(long)), default(Type) }, + { (BinaryOperator.Multiply, typeof(string), typeof(short)), default(Type) }, + { (BinaryOperator.Multiply, typeof(string), typeof(ushort)), default(Type) }, + { (BinaryOperator.Multiply, typeof(string), typeof(ulong)), default(Type) }, + { (BinaryOperator.Multiply, typeof(string), typeof(byte)), default(Type) }, + { (BinaryOperator.Multiply, typeof(string), typeof(Single)), default(Type) }, + { (BinaryOperator.Multiply, typeof(string), typeof(uint)), default(Type) }, + { (BinaryOperator.Multiply, typeof(string), typeof(SByte)), default(Type) }, + { (BinaryOperator.Multiply, typeof(string), typeof(decimal)), default(Type) }, + { (BinaryOperator.Multiply, typeof(string), typeof(string)), default(Type) }, + { (BinaryOperator.Multiply, typeof(string), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Multiply, typeof(string), typeof(bool)), default(Type) }, + { (BinaryOperator.Multiply, typeof(DateTime), typeof(int)), default(Type) }, + { (BinaryOperator.Multiply, typeof(DateTime), typeof(double)), default(Type) }, + { (BinaryOperator.Multiply, typeof(DateTime), typeof(long)), default(Type) }, + { (BinaryOperator.Multiply, typeof(DateTime), typeof(short)), default(Type) }, + { (BinaryOperator.Multiply, typeof(DateTime), typeof(ushort)), default(Type) }, + { (BinaryOperator.Multiply, typeof(DateTime), typeof(ulong)), default(Type) }, + { (BinaryOperator.Multiply, typeof(DateTime), typeof(byte)), default(Type) }, + { (BinaryOperator.Multiply, typeof(DateTime), typeof(Single)), default(Type) }, + { (BinaryOperator.Multiply, typeof(DateTime), typeof(uint)), default(Type) }, + { (BinaryOperator.Multiply, typeof(DateTime), typeof(SByte)), default(Type) }, + { (BinaryOperator.Multiply, typeof(DateTime), typeof(decimal)), default(Type) }, + { (BinaryOperator.Multiply, typeof(DateTime), typeof(string)), default(Type) }, + { (BinaryOperator.Multiply, typeof(DateTime), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Multiply, typeof(DateTime), typeof(bool)), default(Type) }, + { (BinaryOperator.Multiply, typeof(bool), typeof(int)), default(Type) }, + { (BinaryOperator.Multiply, typeof(bool), typeof(double)), default(Type) }, + { (BinaryOperator.Multiply, typeof(bool), typeof(long)), default(Type) }, + { (BinaryOperator.Multiply, typeof(bool), typeof(short)), default(Type) }, + { (BinaryOperator.Multiply, typeof(bool), typeof(ushort)), default(Type) }, + { (BinaryOperator.Multiply, typeof(bool), typeof(ulong)), default(Type) }, + { (BinaryOperator.Multiply, typeof(bool), typeof(byte)), default(Type) }, + { (BinaryOperator.Multiply, typeof(bool), typeof(Single)), default(Type) }, + { (BinaryOperator.Multiply, typeof(bool), typeof(uint)), default(Type) }, + { (BinaryOperator.Multiply, typeof(bool), typeof(SByte)), default(Type) }, + { (BinaryOperator.Multiply, typeof(bool), typeof(decimal)), default(Type) }, + { (BinaryOperator.Multiply, typeof(bool), typeof(string)), default(Type) }, + { (BinaryOperator.Multiply, typeof(bool), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Multiply, typeof(bool), typeof(bool)), default(Type) }, + { (BinaryOperator.Divide, typeof(int), typeof(int)), typeof(int) }, + { (BinaryOperator.Divide, typeof(int), typeof(double)), typeof(double) }, + { (BinaryOperator.Divide, typeof(int), typeof(long)), typeof(long) }, + { (BinaryOperator.Divide, typeof(int), typeof(short)), typeof(int) }, + { (BinaryOperator.Divide, typeof(int), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Divide, typeof(int), typeof(ulong)), default(Type) }, + { (BinaryOperator.Divide, typeof(int), typeof(byte)), typeof(int) }, + { (BinaryOperator.Divide, typeof(int), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Divide, typeof(int), typeof(uint)), typeof(long) }, + { (BinaryOperator.Divide, typeof(int), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Divide, typeof(int), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Divide, typeof(int), typeof(string)), default(Type) }, + { (BinaryOperator.Divide, typeof(int), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Divide, typeof(int), typeof(bool)), default(Type) }, + { (BinaryOperator.Divide, typeof(double), typeof(int)), typeof(double) }, + { (BinaryOperator.Divide, typeof(double), typeof(double)), typeof(double) }, + { (BinaryOperator.Divide, typeof(double), typeof(long)), typeof(double) }, + { (BinaryOperator.Divide, typeof(double), typeof(short)), typeof(double) }, + { (BinaryOperator.Divide, typeof(double), typeof(ushort)), typeof(double) }, + { (BinaryOperator.Divide, typeof(double), typeof(ulong)), typeof(double) }, + { (BinaryOperator.Divide, typeof(double), typeof(byte)), typeof(double) }, + { (BinaryOperator.Divide, typeof(double), typeof(Single)), typeof(double) }, + { (BinaryOperator.Divide, typeof(double), typeof(uint)), typeof(double) }, + { (BinaryOperator.Divide, typeof(double), typeof(SByte)), typeof(double) }, + { (BinaryOperator.Divide, typeof(double), typeof(decimal)), default(Type) }, + { (BinaryOperator.Divide, typeof(double), typeof(string)), default(Type) }, + { (BinaryOperator.Divide, typeof(double), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Divide, typeof(double), typeof(bool)), default(Type) }, + { (BinaryOperator.Divide, typeof(long), typeof(int)), typeof(long) }, + { (BinaryOperator.Divide, typeof(long), typeof(double)), typeof(double) }, + { (BinaryOperator.Divide, typeof(long), typeof(long)), typeof(long) }, + { (BinaryOperator.Divide, typeof(long), typeof(short)), typeof(long) }, + { (BinaryOperator.Divide, typeof(long), typeof(ushort)), typeof(long) }, + { (BinaryOperator.Divide, typeof(long), typeof(ulong)), default(Type) }, + { (BinaryOperator.Divide, typeof(long), typeof(byte)), typeof(long) }, + { (BinaryOperator.Divide, typeof(long), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Divide, typeof(long), typeof(uint)), typeof(long) }, + { (BinaryOperator.Divide, typeof(long), typeof(SByte)), typeof(long) }, + { (BinaryOperator.Divide, typeof(long), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Divide, typeof(long), typeof(string)), default(Type) }, + { (BinaryOperator.Divide, typeof(long), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Divide, typeof(long), typeof(bool)), default(Type) }, + { (BinaryOperator.Divide, typeof(short), typeof(int)), typeof(int) }, + { (BinaryOperator.Divide, typeof(short), typeof(double)), typeof(double) }, + { (BinaryOperator.Divide, typeof(short), typeof(long)), typeof(long) }, + { (BinaryOperator.Divide, typeof(short), typeof(short)), typeof(int) }, + { (BinaryOperator.Divide, typeof(short), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Divide, typeof(short), typeof(ulong)), default(Type) }, + { (BinaryOperator.Divide, typeof(short), typeof(byte)), typeof(int) }, + { (BinaryOperator.Divide, typeof(short), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Divide, typeof(short), typeof(uint)), typeof(long) }, + { (BinaryOperator.Divide, typeof(short), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Divide, typeof(short), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Divide, typeof(short), typeof(string)), default(Type) }, + { (BinaryOperator.Divide, typeof(short), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Divide, typeof(short), typeof(bool)), default(Type) }, + { (BinaryOperator.Divide, typeof(ushort), typeof(int)), typeof(int) }, + { (BinaryOperator.Divide, typeof(ushort), typeof(double)), typeof(double) }, + { (BinaryOperator.Divide, typeof(ushort), typeof(long)), typeof(long) }, + { (BinaryOperator.Divide, typeof(ushort), typeof(short)), typeof(int) }, + { (BinaryOperator.Divide, typeof(ushort), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Divide, typeof(ushort), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Divide, typeof(ushort), typeof(byte)), typeof(int) }, + { (BinaryOperator.Divide, typeof(ushort), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Divide, typeof(ushort), typeof(uint)), typeof(uint) }, + { (BinaryOperator.Divide, typeof(ushort), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Divide, typeof(ushort), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Divide, typeof(ushort), typeof(string)), default(Type) }, + { (BinaryOperator.Divide, typeof(ushort), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Divide, typeof(ushort), typeof(bool)), default(Type) }, + { (BinaryOperator.Divide, typeof(ulong), typeof(int)), default(Type) }, + { (BinaryOperator.Divide, typeof(ulong), typeof(double)), typeof(double) }, + { (BinaryOperator.Divide, typeof(ulong), typeof(long)), default(Type) }, + { (BinaryOperator.Divide, typeof(ulong), typeof(short)), default(Type) }, + { (BinaryOperator.Divide, typeof(ulong), typeof(ushort)), typeof(ulong) }, + { (BinaryOperator.Divide, typeof(ulong), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Divide, typeof(ulong), typeof(byte)), typeof(ulong) }, + { (BinaryOperator.Divide, typeof(ulong), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Divide, typeof(ulong), typeof(uint)), typeof(ulong) }, + { (BinaryOperator.Divide, typeof(ulong), typeof(SByte)), default(Type) }, + { (BinaryOperator.Divide, typeof(ulong), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Divide, typeof(ulong), typeof(string)), default(Type) }, + { (BinaryOperator.Divide, typeof(ulong), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Divide, typeof(ulong), typeof(bool)), default(Type) }, + { (BinaryOperator.Divide, typeof(byte), typeof(int)), typeof(int) }, + { (BinaryOperator.Divide, typeof(byte), typeof(double)), typeof(double) }, + { (BinaryOperator.Divide, typeof(byte), typeof(long)), typeof(long) }, + { (BinaryOperator.Divide, typeof(byte), typeof(short)), typeof(int) }, + { (BinaryOperator.Divide, typeof(byte), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Divide, typeof(byte), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Divide, typeof(byte), typeof(byte)), typeof(int) }, + { (BinaryOperator.Divide, typeof(byte), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Divide, typeof(byte), typeof(uint)), typeof(uint) }, + { (BinaryOperator.Divide, typeof(byte), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Divide, typeof(byte), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Divide, typeof(byte), typeof(string)), default(Type) }, + { (BinaryOperator.Divide, typeof(byte), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Divide, typeof(byte), typeof(bool)), default(Type) }, + { (BinaryOperator.Divide, typeof(Single), typeof(int)), typeof(Single) }, + { (BinaryOperator.Divide, typeof(Single), typeof(double)), typeof(double) }, + { (BinaryOperator.Divide, typeof(Single), typeof(long)), typeof(Single) }, + { (BinaryOperator.Divide, typeof(Single), typeof(short)), typeof(Single) }, + { (BinaryOperator.Divide, typeof(Single), typeof(ushort)), typeof(Single) }, + { (BinaryOperator.Divide, typeof(Single), typeof(ulong)), typeof(Single) }, + { (BinaryOperator.Divide, typeof(Single), typeof(byte)), typeof(Single) }, + { (BinaryOperator.Divide, typeof(Single), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Divide, typeof(Single), typeof(uint)), typeof(Single) }, + { (BinaryOperator.Divide, typeof(Single), typeof(SByte)), typeof(Single) }, + { (BinaryOperator.Divide, typeof(Single), typeof(decimal)), default(Type) }, + { (BinaryOperator.Divide, typeof(Single), typeof(string)), default(Type) }, + { (BinaryOperator.Divide, typeof(Single), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Divide, typeof(Single), typeof(bool)), default(Type) }, + { (BinaryOperator.Divide, typeof(uint), typeof(int)), typeof(long) }, + { (BinaryOperator.Divide, typeof(uint), typeof(double)), typeof(double) }, + { (BinaryOperator.Divide, typeof(uint), typeof(long)), typeof(long) }, + { (BinaryOperator.Divide, typeof(uint), typeof(short)), typeof(long) }, + { (BinaryOperator.Divide, typeof(uint), typeof(ushort)), typeof(uint) }, + { (BinaryOperator.Divide, typeof(uint), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Divide, typeof(uint), typeof(byte)), typeof(uint) }, + { (BinaryOperator.Divide, typeof(uint), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Divide, typeof(uint), typeof(uint)), typeof(uint) }, + { (BinaryOperator.Divide, typeof(uint), typeof(SByte)), typeof(long) }, + { (BinaryOperator.Divide, typeof(uint), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Divide, typeof(uint), typeof(string)), default(Type) }, + { (BinaryOperator.Divide, typeof(uint), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Divide, typeof(uint), typeof(bool)), default(Type) }, + { (BinaryOperator.Divide, typeof(SByte), typeof(int)), typeof(int) }, + { (BinaryOperator.Divide, typeof(SByte), typeof(double)), typeof(double) }, + { (BinaryOperator.Divide, typeof(SByte), typeof(long)), typeof(long) }, + { (BinaryOperator.Divide, typeof(SByte), typeof(short)), typeof(int) }, + { (BinaryOperator.Divide, typeof(SByte), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Divide, typeof(SByte), typeof(ulong)), default(Type) }, + { (BinaryOperator.Divide, typeof(SByte), typeof(byte)), typeof(int) }, + { (BinaryOperator.Divide, typeof(SByte), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Divide, typeof(SByte), typeof(uint)), typeof(long) }, + { (BinaryOperator.Divide, typeof(SByte), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Divide, typeof(SByte), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Divide, typeof(SByte), typeof(string)), default(Type) }, + { (BinaryOperator.Divide, typeof(SByte), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Divide, typeof(SByte), typeof(bool)), default(Type) }, + { (BinaryOperator.Divide, typeof(decimal), typeof(int)), typeof(decimal) }, + { (BinaryOperator.Divide, typeof(decimal), typeof(double)), default(Type) }, + { (BinaryOperator.Divide, typeof(decimal), typeof(long)), typeof(decimal) }, + { (BinaryOperator.Divide, typeof(decimal), typeof(short)), typeof(decimal) }, + { (BinaryOperator.Divide, typeof(decimal), typeof(ushort)), typeof(decimal) }, + { (BinaryOperator.Divide, typeof(decimal), typeof(ulong)), typeof(decimal) }, + { (BinaryOperator.Divide, typeof(decimal), typeof(byte)), typeof(decimal) }, + { (BinaryOperator.Divide, typeof(decimal), typeof(Single)), default(Type) }, + { (BinaryOperator.Divide, typeof(decimal), typeof(uint)), typeof(decimal) }, + { (BinaryOperator.Divide, typeof(decimal), typeof(SByte)), typeof(decimal) }, + { (BinaryOperator.Divide, typeof(decimal), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Divide, typeof(decimal), typeof(string)), default(Type) }, + { (BinaryOperator.Divide, typeof(decimal), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Divide, typeof(decimal), typeof(bool)), default(Type) }, + { (BinaryOperator.Divide, typeof(string), typeof(int)), default(Type) }, + { (BinaryOperator.Divide, typeof(string), typeof(double)), default(Type) }, + { (BinaryOperator.Divide, typeof(string), typeof(long)), default(Type) }, + { (BinaryOperator.Divide, typeof(string), typeof(short)), default(Type) }, + { (BinaryOperator.Divide, typeof(string), typeof(ushort)), default(Type) }, + { (BinaryOperator.Divide, typeof(string), typeof(ulong)), default(Type) }, + { (BinaryOperator.Divide, typeof(string), typeof(byte)), default(Type) }, + { (BinaryOperator.Divide, typeof(string), typeof(Single)), default(Type) }, + { (BinaryOperator.Divide, typeof(string), typeof(uint)), default(Type) }, + { (BinaryOperator.Divide, typeof(string), typeof(SByte)), default(Type) }, + { (BinaryOperator.Divide, typeof(string), typeof(decimal)), default(Type) }, + { (BinaryOperator.Divide, typeof(string), typeof(string)), default(Type) }, + { (BinaryOperator.Divide, typeof(string), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Divide, typeof(string), typeof(bool)), default(Type) }, + { (BinaryOperator.Divide, typeof(DateTime), typeof(int)), default(Type) }, + { (BinaryOperator.Divide, typeof(DateTime), typeof(double)), default(Type) }, + { (BinaryOperator.Divide, typeof(DateTime), typeof(long)), default(Type) }, + { (BinaryOperator.Divide, typeof(DateTime), typeof(short)), default(Type) }, + { (BinaryOperator.Divide, typeof(DateTime), typeof(ushort)), default(Type) }, + { (BinaryOperator.Divide, typeof(DateTime), typeof(ulong)), default(Type) }, + { (BinaryOperator.Divide, typeof(DateTime), typeof(byte)), default(Type) }, + { (BinaryOperator.Divide, typeof(DateTime), typeof(Single)), default(Type) }, + { (BinaryOperator.Divide, typeof(DateTime), typeof(uint)), default(Type) }, + { (BinaryOperator.Divide, typeof(DateTime), typeof(SByte)), default(Type) }, + { (BinaryOperator.Divide, typeof(DateTime), typeof(decimal)), default(Type) }, + { (BinaryOperator.Divide, typeof(DateTime), typeof(string)), default(Type) }, + { (BinaryOperator.Divide, typeof(DateTime), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Divide, typeof(DateTime), typeof(bool)), default(Type) }, + { (BinaryOperator.Divide, typeof(bool), typeof(int)), default(Type) }, + { (BinaryOperator.Divide, typeof(bool), typeof(double)), default(Type) }, + { (BinaryOperator.Divide, typeof(bool), typeof(long)), default(Type) }, + { (BinaryOperator.Divide, typeof(bool), typeof(short)), default(Type) }, + { (BinaryOperator.Divide, typeof(bool), typeof(ushort)), default(Type) }, + { (BinaryOperator.Divide, typeof(bool), typeof(ulong)), default(Type) }, + { (BinaryOperator.Divide, typeof(bool), typeof(byte)), default(Type) }, + { (BinaryOperator.Divide, typeof(bool), typeof(Single)), default(Type) }, + { (BinaryOperator.Divide, typeof(bool), typeof(uint)), default(Type) }, + { (BinaryOperator.Divide, typeof(bool), typeof(SByte)), default(Type) }, + { (BinaryOperator.Divide, typeof(bool), typeof(decimal)), default(Type) }, + { (BinaryOperator.Divide, typeof(bool), typeof(string)), default(Type) }, + { (BinaryOperator.Divide, typeof(bool), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Divide, typeof(bool), typeof(bool)), default(Type) }, + { (BinaryOperator.Modulo, typeof(int), typeof(int)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(int), typeof(double)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(int), typeof(long)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(int), typeof(short)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(int), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(int), typeof(ulong)), default(Type) }, + { (BinaryOperator.Modulo, typeof(int), typeof(byte)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(int), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Modulo, typeof(int), typeof(uint)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(int), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(int), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Modulo, typeof(int), typeof(string)), default(Type) }, + { (BinaryOperator.Modulo, typeof(int), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Modulo, typeof(int), typeof(bool)), default(Type) }, + { (BinaryOperator.Modulo, typeof(double), typeof(int)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(double), typeof(double)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(double), typeof(long)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(double), typeof(short)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(double), typeof(ushort)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(double), typeof(ulong)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(double), typeof(byte)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(double), typeof(Single)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(double), typeof(uint)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(double), typeof(SByte)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(double), typeof(decimal)), default(Type) }, + { (BinaryOperator.Modulo, typeof(double), typeof(string)), default(Type) }, + { (BinaryOperator.Modulo, typeof(double), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Modulo, typeof(double), typeof(bool)), default(Type) }, + { (BinaryOperator.Modulo, typeof(long), typeof(int)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(long), typeof(double)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(long), typeof(long)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(long), typeof(short)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(long), typeof(ushort)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(long), typeof(ulong)), default(Type) }, + { (BinaryOperator.Modulo, typeof(long), typeof(byte)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(long), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Modulo, typeof(long), typeof(uint)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(long), typeof(SByte)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(long), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Modulo, typeof(long), typeof(string)), default(Type) }, + { (BinaryOperator.Modulo, typeof(long), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Modulo, typeof(long), typeof(bool)), default(Type) }, + { (BinaryOperator.Modulo, typeof(short), typeof(int)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(short), typeof(double)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(short), typeof(long)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(short), typeof(short)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(short), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(short), typeof(ulong)), default(Type) }, + { (BinaryOperator.Modulo, typeof(short), typeof(byte)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(short), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Modulo, typeof(short), typeof(uint)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(short), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(short), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Modulo, typeof(short), typeof(string)), default(Type) }, + { (BinaryOperator.Modulo, typeof(short), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Modulo, typeof(short), typeof(bool)), default(Type) }, + { (BinaryOperator.Modulo, typeof(ushort), typeof(int)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(ushort), typeof(double)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(ushort), typeof(long)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(ushort), typeof(short)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(ushort), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(ushort), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Modulo, typeof(ushort), typeof(byte)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(ushort), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Modulo, typeof(ushort), typeof(uint)), typeof(uint) }, + { (BinaryOperator.Modulo, typeof(ushort), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(ushort), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Modulo, typeof(ushort), typeof(string)), default(Type) }, + { (BinaryOperator.Modulo, typeof(ushort), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Modulo, typeof(ushort), typeof(bool)), default(Type) }, + { (BinaryOperator.Modulo, typeof(ulong), typeof(int)), default(Type) }, + { (BinaryOperator.Modulo, typeof(ulong), typeof(double)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(ulong), typeof(long)), default(Type) }, + { (BinaryOperator.Modulo, typeof(ulong), typeof(short)), default(Type) }, + { (BinaryOperator.Modulo, typeof(ulong), typeof(ushort)), typeof(ulong) }, + { (BinaryOperator.Modulo, typeof(ulong), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Modulo, typeof(ulong), typeof(byte)), typeof(ulong) }, + { (BinaryOperator.Modulo, typeof(ulong), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Modulo, typeof(ulong), typeof(uint)), typeof(ulong) }, + { (BinaryOperator.Modulo, typeof(ulong), typeof(SByte)), default(Type) }, + { (BinaryOperator.Modulo, typeof(ulong), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Modulo, typeof(ulong), typeof(string)), default(Type) }, + { (BinaryOperator.Modulo, typeof(ulong), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Modulo, typeof(ulong), typeof(bool)), default(Type) }, + { (BinaryOperator.Modulo, typeof(byte), typeof(int)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(byte), typeof(double)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(byte), typeof(long)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(byte), typeof(short)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(byte), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(byte), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Modulo, typeof(byte), typeof(byte)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(byte), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Modulo, typeof(byte), typeof(uint)), typeof(uint) }, + { (BinaryOperator.Modulo, typeof(byte), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(byte), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Modulo, typeof(byte), typeof(string)), default(Type) }, + { (BinaryOperator.Modulo, typeof(byte), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Modulo, typeof(byte), typeof(bool)), default(Type) }, + { (BinaryOperator.Modulo, typeof(Single), typeof(int)), typeof(Single) }, + { (BinaryOperator.Modulo, typeof(Single), typeof(double)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(Single), typeof(long)), typeof(Single) }, + { (BinaryOperator.Modulo, typeof(Single), typeof(short)), typeof(Single) }, + { (BinaryOperator.Modulo, typeof(Single), typeof(ushort)), typeof(Single) }, + { (BinaryOperator.Modulo, typeof(Single), typeof(ulong)), typeof(Single) }, + { (BinaryOperator.Modulo, typeof(Single), typeof(byte)), typeof(Single) }, + { (BinaryOperator.Modulo, typeof(Single), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Modulo, typeof(Single), typeof(uint)), typeof(Single) }, + { (BinaryOperator.Modulo, typeof(Single), typeof(SByte)), typeof(Single) }, + { (BinaryOperator.Modulo, typeof(Single), typeof(decimal)), default(Type) }, + { (BinaryOperator.Modulo, typeof(Single), typeof(string)), default(Type) }, + { (BinaryOperator.Modulo, typeof(Single), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Modulo, typeof(Single), typeof(bool)), default(Type) }, + { (BinaryOperator.Modulo, typeof(uint), typeof(int)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(uint), typeof(double)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(uint), typeof(long)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(uint), typeof(short)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(uint), typeof(ushort)), typeof(uint) }, + { (BinaryOperator.Modulo, typeof(uint), typeof(ulong)), typeof(ulong) }, + { (BinaryOperator.Modulo, typeof(uint), typeof(byte)), typeof(uint) }, + { (BinaryOperator.Modulo, typeof(uint), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Modulo, typeof(uint), typeof(uint)), typeof(uint) }, + { (BinaryOperator.Modulo, typeof(uint), typeof(SByte)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(uint), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Modulo, typeof(uint), typeof(string)), default(Type) }, + { (BinaryOperator.Modulo, typeof(uint), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Modulo, typeof(uint), typeof(bool)), default(Type) }, + { (BinaryOperator.Modulo, typeof(SByte), typeof(int)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(SByte), typeof(double)), typeof(double) }, + { (BinaryOperator.Modulo, typeof(SByte), typeof(long)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(SByte), typeof(short)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(SByte), typeof(ushort)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(SByte), typeof(ulong)), default(Type) }, + { (BinaryOperator.Modulo, typeof(SByte), typeof(byte)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(SByte), typeof(Single)), typeof(Single) }, + { (BinaryOperator.Modulo, typeof(SByte), typeof(uint)), typeof(long) }, + { (BinaryOperator.Modulo, typeof(SByte), typeof(SByte)), typeof(int) }, + { (BinaryOperator.Modulo, typeof(SByte), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Modulo, typeof(SByte), typeof(string)), default(Type) }, + { (BinaryOperator.Modulo, typeof(SByte), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Modulo, typeof(SByte), typeof(bool)), default(Type) }, + { (BinaryOperator.Modulo, typeof(decimal), typeof(int)), typeof(decimal) }, + { (BinaryOperator.Modulo, typeof(decimal), typeof(double)), default(Type) }, + { (BinaryOperator.Modulo, typeof(decimal), typeof(long)), typeof(decimal) }, + { (BinaryOperator.Modulo, typeof(decimal), typeof(short)), typeof(decimal) }, + { (BinaryOperator.Modulo, typeof(decimal), typeof(ushort)), typeof(decimal) }, + { (BinaryOperator.Modulo, typeof(decimal), typeof(ulong)), typeof(decimal) }, + { (BinaryOperator.Modulo, typeof(decimal), typeof(byte)), typeof(decimal) }, + { (BinaryOperator.Modulo, typeof(decimal), typeof(Single)), default(Type) }, + { (BinaryOperator.Modulo, typeof(decimal), typeof(uint)), typeof(decimal) }, + { (BinaryOperator.Modulo, typeof(decimal), typeof(SByte)), typeof(decimal) }, + { (BinaryOperator.Modulo, typeof(decimal), typeof(decimal)), typeof(decimal) }, + { (BinaryOperator.Modulo, typeof(decimal), typeof(string)), default(Type) }, + { (BinaryOperator.Modulo, typeof(decimal), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Modulo, typeof(decimal), typeof(bool)), default(Type) }, + { (BinaryOperator.Modulo, typeof(string), typeof(int)), default(Type) }, + { (BinaryOperator.Modulo, typeof(string), typeof(double)), default(Type) }, + { (BinaryOperator.Modulo, typeof(string), typeof(long)), default(Type) }, + { (BinaryOperator.Modulo, typeof(string), typeof(short)), default(Type) }, + { (BinaryOperator.Modulo, typeof(string), typeof(ushort)), default(Type) }, + { (BinaryOperator.Modulo, typeof(string), typeof(ulong)), default(Type) }, + { (BinaryOperator.Modulo, typeof(string), typeof(byte)), default(Type) }, + { (BinaryOperator.Modulo, typeof(string), typeof(Single)), default(Type) }, + { (BinaryOperator.Modulo, typeof(string), typeof(uint)), default(Type) }, + { (BinaryOperator.Modulo, typeof(string), typeof(SByte)), default(Type) }, + { (BinaryOperator.Modulo, typeof(string), typeof(decimal)), default(Type) }, + { (BinaryOperator.Modulo, typeof(string), typeof(string)), default(Type) }, + { (BinaryOperator.Modulo, typeof(string), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Modulo, typeof(string), typeof(bool)), default(Type) }, + { (BinaryOperator.Modulo, typeof(DateTime), typeof(int)), default(Type) }, + { (BinaryOperator.Modulo, typeof(DateTime), typeof(double)), default(Type) }, + { (BinaryOperator.Modulo, typeof(DateTime), typeof(long)), default(Type) }, + { (BinaryOperator.Modulo, typeof(DateTime), typeof(short)), default(Type) }, + { (BinaryOperator.Modulo, typeof(DateTime), typeof(ushort)), default(Type) }, + { (BinaryOperator.Modulo, typeof(DateTime), typeof(ulong)), default(Type) }, + { (BinaryOperator.Modulo, typeof(DateTime), typeof(byte)), default(Type) }, + { (BinaryOperator.Modulo, typeof(DateTime), typeof(Single)), default(Type) }, + { (BinaryOperator.Modulo, typeof(DateTime), typeof(uint)), default(Type) }, + { (BinaryOperator.Modulo, typeof(DateTime), typeof(SByte)), default(Type) }, + { (BinaryOperator.Modulo, typeof(DateTime), typeof(decimal)), default(Type) }, + { (BinaryOperator.Modulo, typeof(DateTime), typeof(string)), default(Type) }, + { (BinaryOperator.Modulo, typeof(DateTime), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Modulo, typeof(DateTime), typeof(bool)), default(Type) }, + { (BinaryOperator.Modulo, typeof(bool), typeof(int)), default(Type) }, + { (BinaryOperator.Modulo, typeof(bool), typeof(double)), default(Type) }, + { (BinaryOperator.Modulo, typeof(bool), typeof(long)), default(Type) }, + { (BinaryOperator.Modulo, typeof(bool), typeof(short)), default(Type) }, + { (BinaryOperator.Modulo, typeof(bool), typeof(ushort)), default(Type) }, + { (BinaryOperator.Modulo, typeof(bool), typeof(ulong)), default(Type) }, + { (BinaryOperator.Modulo, typeof(bool), typeof(byte)), default(Type) }, + { (BinaryOperator.Modulo, typeof(bool), typeof(Single)), default(Type) }, + { (BinaryOperator.Modulo, typeof(bool), typeof(uint)), default(Type) }, + { (BinaryOperator.Modulo, typeof(bool), typeof(SByte)), default(Type) }, + { (BinaryOperator.Modulo, typeof(bool), typeof(decimal)), default(Type) }, + { (BinaryOperator.Modulo, typeof(bool), typeof(string)), default(Type) }, + { (BinaryOperator.Modulo, typeof(bool), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Modulo, typeof(bool), typeof(bool)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(int), typeof(int)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(int), typeof(double)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(int), typeof(long)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(int), typeof(short)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(int), typeof(ushort)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(int), typeof(ulong)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(int), typeof(byte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(int), typeof(Single)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(int), typeof(uint)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(int), typeof(SByte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(int), typeof(decimal)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(int), typeof(string)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(int), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(int), typeof(bool)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(double), typeof(int)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(double), typeof(double)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(double), typeof(long)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(double), typeof(short)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(double), typeof(ushort)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(double), typeof(ulong)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(double), typeof(byte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(double), typeof(Single)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(double), typeof(uint)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(double), typeof(SByte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(double), typeof(decimal)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(double), typeof(string)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(double), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(double), typeof(bool)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(long), typeof(int)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(long), typeof(double)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(long), typeof(long)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(long), typeof(short)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(long), typeof(ushort)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(long), typeof(ulong)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(long), typeof(byte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(long), typeof(Single)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(long), typeof(uint)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(long), typeof(SByte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(long), typeof(decimal)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(long), typeof(string)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(long), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(long), typeof(bool)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(short), typeof(int)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(short), typeof(double)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(short), typeof(long)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(short), typeof(short)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(short), typeof(ushort)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(short), typeof(ulong)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(short), typeof(byte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(short), typeof(Single)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(short), typeof(uint)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(short), typeof(SByte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(short), typeof(decimal)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(short), typeof(string)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(short), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(short), typeof(bool)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(ushort), typeof(int)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ushort), typeof(double)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ushort), typeof(long)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ushort), typeof(short)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ushort), typeof(ushort)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ushort), typeof(ulong)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ushort), typeof(byte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ushort), typeof(Single)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ushort), typeof(uint)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ushort), typeof(SByte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ushort), typeof(decimal)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(ushort), typeof(string)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(ushort), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(ushort), typeof(bool)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(ulong), typeof(int)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ulong), typeof(double)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ulong), typeof(long)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ulong), typeof(short)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ulong), typeof(ushort)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ulong), typeof(ulong)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ulong), typeof(byte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ulong), typeof(Single)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ulong), typeof(uint)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ulong), typeof(SByte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(ulong), typeof(decimal)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(ulong), typeof(string)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(ulong), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(ulong), typeof(bool)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(byte), typeof(int)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(byte), typeof(double)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(byte), typeof(long)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(byte), typeof(short)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(byte), typeof(ushort)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(byte), typeof(ulong)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(byte), typeof(byte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(byte), typeof(Single)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(byte), typeof(uint)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(byte), typeof(SByte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(byte), typeof(decimal)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(byte), typeof(string)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(byte), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(byte), typeof(bool)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(Single), typeof(int)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(Single), typeof(double)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(Single), typeof(long)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(Single), typeof(short)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(Single), typeof(ushort)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(Single), typeof(ulong)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(Single), typeof(byte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(Single), typeof(Single)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(Single), typeof(uint)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(Single), typeof(SByte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(Single), typeof(decimal)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(Single), typeof(string)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(Single), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(Single), typeof(bool)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(uint), typeof(int)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(uint), typeof(double)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(uint), typeof(long)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(uint), typeof(short)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(uint), typeof(ushort)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(uint), typeof(ulong)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(uint), typeof(byte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(uint), typeof(Single)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(uint), typeof(uint)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(uint), typeof(SByte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(uint), typeof(decimal)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(uint), typeof(string)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(uint), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(uint), typeof(bool)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(SByte), typeof(int)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(SByte), typeof(double)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(SByte), typeof(long)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(SByte), typeof(short)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(SByte), typeof(ushort)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(SByte), typeof(ulong)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(SByte), typeof(byte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(SByte), typeof(Single)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(SByte), typeof(uint)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(SByte), typeof(SByte)), typeof(double) }, + { (BinaryOperator.Exponentiation, typeof(SByte), typeof(decimal)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(SByte), typeof(string)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(SByte), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(SByte), typeof(bool)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(decimal), typeof(int)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(decimal), typeof(double)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(decimal), typeof(long)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(decimal), typeof(short)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(decimal), typeof(ushort)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(decimal), typeof(ulong)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(decimal), typeof(byte)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(decimal), typeof(Single)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(decimal), typeof(uint)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(decimal), typeof(SByte)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(decimal), typeof(decimal)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(decimal), typeof(string)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(decimal), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(decimal), typeof(bool)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(string), typeof(int)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(string), typeof(double)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(string), typeof(long)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(string), typeof(short)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(string), typeof(ushort)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(string), typeof(ulong)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(string), typeof(byte)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(string), typeof(Single)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(string), typeof(uint)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(string), typeof(SByte)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(string), typeof(decimal)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(string), typeof(string)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(string), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(string), typeof(bool)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(DateTime), typeof(int)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(DateTime), typeof(double)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(DateTime), typeof(long)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(DateTime), typeof(short)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(DateTime), typeof(ushort)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(DateTime), typeof(ulong)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(DateTime), typeof(byte)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(DateTime), typeof(Single)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(DateTime), typeof(uint)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(DateTime), typeof(SByte)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(DateTime), typeof(decimal)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(DateTime), typeof(string)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(DateTime), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(DateTime), typeof(bool)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(bool), typeof(int)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(bool), typeof(double)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(bool), typeof(long)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(bool), typeof(short)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(bool), typeof(ushort)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(bool), typeof(ulong)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(bool), typeof(byte)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(bool), typeof(Single)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(bool), typeof(uint)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(bool), typeof(SByte)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(bool), typeof(decimal)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(bool), typeof(string)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(bool), typeof(DateTime)), default(Type) }, + { (BinaryOperator.Exponentiation, typeof(bool), typeof(bool)), default(Type) }, + }; + + public static readonly IDictionary<(Type O1Type, Type O2Type), Type> CoersionTableEqualityComparison = new Dictionary<(Type Op1Type, Type Op2Type), Type>() + { + { (typeof(int), typeof(int)), typeof(bool) }, + { (typeof(int), typeof(double)), typeof(bool) }, + { (typeof(int), typeof(long)), typeof(bool) }, + { (typeof(int), typeof(short)), typeof(bool) }, + { (typeof(int), typeof(ushort)), typeof(bool) }, + { (typeof(int), typeof(ulong)), default(Type) }, + { (typeof(int), typeof(byte)), typeof(bool) }, + { (typeof(int), typeof(Single)), typeof(bool) }, + { (typeof(int), typeof(uint)), typeof(bool) }, + { (typeof(int), typeof(SByte)), typeof(bool) }, + { (typeof(int), typeof(decimal)), typeof(bool) }, + { (typeof(int), typeof(string)), default(Type) }, + { (typeof(int), typeof(DateTime)), default(Type) }, + { (typeof(int), typeof(bool)), default(Type) }, + { (typeof(double), typeof(int)), typeof(bool) }, + { (typeof(double), typeof(double)), typeof(bool) }, + { (typeof(double), typeof(long)), typeof(bool) }, + { (typeof(double), typeof(short)), typeof(bool) }, + { (typeof(double), typeof(ushort)), typeof(bool) }, + { (typeof(double), typeof(ulong)), typeof(bool) }, + { (typeof(double), typeof(byte)), typeof(bool) }, + { (typeof(double), typeof(Single)), typeof(bool) }, + { (typeof(double), typeof(uint)), typeof(bool) }, + { (typeof(double), typeof(SByte)), typeof(bool) }, + { (typeof(double), typeof(decimal)), default(Type) }, + { (typeof(double), typeof(string)), default(Type) }, + { (typeof(double), typeof(DateTime)), default(Type) }, + { (typeof(double), typeof(bool)), default(Type) }, + { (typeof(long), typeof(int)), typeof(bool) }, + { (typeof(long), typeof(double)), typeof(bool) }, + { (typeof(long), typeof(long)), typeof(bool) }, + { (typeof(long), typeof(short)), typeof(bool) }, + { (typeof(long), typeof(ushort)), typeof(bool) }, + { (typeof(long), typeof(ulong)), default(Type) }, + { (typeof(long), typeof(byte)), typeof(bool) }, + { (typeof(long), typeof(Single)), typeof(bool) }, + { (typeof(long), typeof(uint)), typeof(bool) }, + { (typeof(long), typeof(SByte)), typeof(bool) }, + { (typeof(long), typeof(decimal)), typeof(bool) }, + { (typeof(long), typeof(string)), default(Type) }, + { (typeof(long), typeof(DateTime)), default(Type) }, + { (typeof(long), typeof(bool)), default(Type) }, + { (typeof(short), typeof(int)), typeof(bool) }, + { (typeof(short), typeof(double)), typeof(bool) }, + { (typeof(short), typeof(long)), typeof(bool) }, + { (typeof(short), typeof(short)), typeof(bool) }, + { (typeof(short), typeof(ushort)), typeof(bool) }, + { (typeof(short), typeof(ulong)), default(Type) }, + { (typeof(short), typeof(byte)), typeof(bool) }, + { (typeof(short), typeof(Single)), typeof(bool) }, + { (typeof(short), typeof(uint)), typeof(bool) }, + { (typeof(short), typeof(SByte)), typeof(bool) }, + { (typeof(short), typeof(decimal)), typeof(bool) }, + { (typeof(short), typeof(string)), default(Type) }, + { (typeof(short), typeof(DateTime)), default(Type) }, + { (typeof(short), typeof(bool)), default(Type) }, + { (typeof(ushort), typeof(int)), typeof(bool) }, + { (typeof(ushort), typeof(double)), typeof(bool) }, + { (typeof(ushort), typeof(long)), typeof(bool) }, + { (typeof(ushort), typeof(short)), typeof(bool) }, + { (typeof(ushort), typeof(ushort)), typeof(bool) }, + { (typeof(ushort), typeof(ulong)), typeof(bool) }, + { (typeof(ushort), typeof(byte)), typeof(bool) }, + { (typeof(ushort), typeof(Single)), typeof(bool) }, + { (typeof(ushort), typeof(uint)), typeof(bool) }, + { (typeof(ushort), typeof(SByte)), typeof(bool) }, + { (typeof(ushort), typeof(decimal)), typeof(bool) }, + { (typeof(ushort), typeof(string)), default(Type) }, + { (typeof(ushort), typeof(DateTime)), default(Type) }, + { (typeof(ushort), typeof(bool)), default(Type) }, + { (typeof(ulong), typeof(int)), default(Type) }, + { (typeof(ulong), typeof(double)), typeof(bool) }, + { (typeof(ulong), typeof(long)), default(Type) }, + { (typeof(ulong), typeof(short)), default(Type) }, + { (typeof(ulong), typeof(ushort)), typeof(bool) }, + { (typeof(ulong), typeof(ulong)), typeof(bool) }, + { (typeof(ulong), typeof(byte)), typeof(bool) }, + { (typeof(ulong), typeof(Single)), typeof(bool) }, + { (typeof(ulong), typeof(uint)), typeof(bool) }, + { (typeof(ulong), typeof(SByte)), default(Type) }, + { (typeof(ulong), typeof(decimal)), typeof(bool) }, + { (typeof(ulong), typeof(string)), default(Type) }, + { (typeof(ulong), typeof(DateTime)), default(Type) }, + { (typeof(ulong), typeof(bool)), default(Type) }, + { (typeof(byte), typeof(int)), typeof(bool) }, + { (typeof(byte), typeof(double)), typeof(bool) }, + { (typeof(byte), typeof(long)), typeof(bool) }, + { (typeof(byte), typeof(short)), typeof(bool) }, + { (typeof(byte), typeof(ushort)), typeof(bool) }, + { (typeof(byte), typeof(ulong)), typeof(bool) }, + { (typeof(byte), typeof(byte)), typeof(bool) }, + { (typeof(byte), typeof(Single)), typeof(bool) }, + { (typeof(byte), typeof(uint)), typeof(bool) }, + { (typeof(byte), typeof(SByte)), typeof(bool) }, + { (typeof(byte), typeof(decimal)), typeof(bool) }, + { (typeof(byte), typeof(string)), default(Type) }, + { (typeof(byte), typeof(DateTime)), default(Type) }, + { (typeof(byte), typeof(bool)), default(Type) }, + { (typeof(Single), typeof(int)), typeof(bool) }, + { (typeof(Single), typeof(double)), typeof(bool) }, + { (typeof(Single), typeof(long)), typeof(bool) }, + { (typeof(Single), typeof(short)), typeof(bool) }, + { (typeof(Single), typeof(ushort)), typeof(bool) }, + { (typeof(Single), typeof(ulong)), typeof(bool) }, + { (typeof(Single), typeof(byte)), typeof(bool) }, + { (typeof(Single), typeof(Single)), typeof(bool) }, + { (typeof(Single), typeof(uint)), typeof(bool) }, + { (typeof(Single), typeof(SByte)), typeof(bool) }, + { (typeof(Single), typeof(decimal)), default(Type) }, + { (typeof(Single), typeof(string)), default(Type) }, + { (typeof(Single), typeof(DateTime)), default(Type) }, + { (typeof(Single), typeof(bool)), default(Type) }, + { (typeof(uint), typeof(int)), typeof(bool) }, + { (typeof(uint), typeof(double)), typeof(bool) }, + { (typeof(uint), typeof(long)), typeof(bool) }, + { (typeof(uint), typeof(short)), typeof(bool) }, + { (typeof(uint), typeof(ushort)), typeof(bool) }, + { (typeof(uint), typeof(ulong)), typeof(bool) }, + { (typeof(uint), typeof(byte)), typeof(bool) }, + { (typeof(uint), typeof(Single)), typeof(bool) }, + { (typeof(uint), typeof(uint)), typeof(bool) }, + { (typeof(uint), typeof(SByte)), typeof(bool) }, + { (typeof(uint), typeof(decimal)), typeof(bool) }, + { (typeof(uint), typeof(string)), default(Type) }, + { (typeof(uint), typeof(DateTime)), default(Type) }, + { (typeof(uint), typeof(bool)), default(Type) }, + { (typeof(SByte), typeof(int)), typeof(bool) }, + { (typeof(SByte), typeof(double)), typeof(bool) }, + { (typeof(SByte), typeof(long)), typeof(bool) }, + { (typeof(SByte), typeof(short)), typeof(bool) }, + { (typeof(SByte), typeof(ushort)), typeof(bool) }, + { (typeof(SByte), typeof(ulong)), default(Type) }, + { (typeof(SByte), typeof(byte)), typeof(bool) }, + { (typeof(SByte), typeof(Single)), typeof(bool) }, + { (typeof(SByte), typeof(uint)), typeof(bool) }, + { (typeof(SByte), typeof(SByte)), typeof(bool) }, + { (typeof(SByte), typeof(decimal)), typeof(bool) }, + { (typeof(SByte), typeof(string)), default(Type) }, + { (typeof(SByte), typeof(DateTime)), default(Type) }, + { (typeof(SByte), typeof(bool)), default(Type) }, + { (typeof(decimal), typeof(int)), typeof(bool) }, + { (typeof(decimal), typeof(double)), default(Type) }, + { (typeof(decimal), typeof(long)), typeof(bool) }, + { (typeof(decimal), typeof(short)), typeof(bool) }, + { (typeof(decimal), typeof(ushort)), typeof(bool) }, + { (typeof(decimal), typeof(ulong)), typeof(bool) }, + { (typeof(decimal), typeof(byte)), typeof(bool) }, + { (typeof(decimal), typeof(Single)), default(Type) }, + { (typeof(decimal), typeof(uint)), typeof(bool) }, + { (typeof(decimal), typeof(SByte)), typeof(bool) }, + { (typeof(decimal), typeof(decimal)), typeof(bool) }, + { (typeof(decimal), typeof(string)), default(Type) }, + { (typeof(decimal), typeof(DateTime)), default(Type) }, + { (typeof(decimal), typeof(bool)), default(Type) }, + { (typeof(string), typeof(int)), default(Type) }, + { (typeof(string), typeof(double)), default(Type) }, + { (typeof(string), typeof(long)), default(Type) }, + { (typeof(string), typeof(short)), default(Type) }, + { (typeof(string), typeof(ushort)), default(Type) }, + { (typeof(string), typeof(ulong)), default(Type) }, + { (typeof(string), typeof(byte)), default(Type) }, + { (typeof(string), typeof(Single)), default(Type) }, + { (typeof(string), typeof(uint)), default(Type) }, + { (typeof(string), typeof(SByte)), default(Type) }, + { (typeof(string), typeof(decimal)), default(Type) }, + { (typeof(string), typeof(string)), typeof(bool) }, + { (typeof(string), typeof(DateTime)), default(Type) }, + { (typeof(string), typeof(bool)), default(Type) }, + { (typeof(DateTime), typeof(int)), default(Type) }, + { (typeof(DateTime), typeof(double)), default(Type) }, + { (typeof(DateTime), typeof(long)), default(Type) }, + { (typeof(DateTime), typeof(short)), default(Type) }, + { (typeof(DateTime), typeof(ushort)), default(Type) }, + { (typeof(DateTime), typeof(ulong)), default(Type) }, + { (typeof(DateTime), typeof(byte)), default(Type) }, + { (typeof(DateTime), typeof(Single)), default(Type) }, + { (typeof(DateTime), typeof(uint)), default(Type) }, + { (typeof(DateTime), typeof(SByte)), default(Type) }, + { (typeof(DateTime), typeof(decimal)), default(Type) }, + { (typeof(DateTime), typeof(string)), default(Type) }, + { (typeof(DateTime), typeof(DateTime)), typeof(bool) }, + { (typeof(DateTime), typeof(bool)), default(Type) }, + { (typeof(bool), typeof(int)), default(Type) }, + { (typeof(bool), typeof(double)), default(Type) }, + { (typeof(bool), typeof(long)), default(Type) }, + { (typeof(bool), typeof(short)), default(Type) }, + { (typeof(bool), typeof(ushort)), default(Type) }, + { (typeof(bool), typeof(ulong)), default(Type) }, + { (typeof(bool), typeof(byte)), default(Type) }, + { (typeof(bool), typeof(Single)), default(Type) }, + { (typeof(bool), typeof(uint)), default(Type) }, + { (typeof(bool), typeof(SByte)), default(Type) }, + { (typeof(bool), typeof(decimal)), default(Type) }, + { (typeof(bool), typeof(string)), default(Type) }, + { (typeof(bool), typeof(DateTime)), default(Type) }, + { (typeof(bool), typeof(bool)), typeof(bool) }, + }; + + public static readonly IDictionary<(Type O1Type, Type O2Type), Type> CoersionTableInequalityComparison = new Dictionary<(Type Op1Type, Type Op2Type), Type>() + { + { (typeof(int), typeof(int)), typeof(bool) }, + { (typeof(int), typeof(double)), typeof(bool) }, + { (typeof(int), typeof(long)), typeof(bool) }, + { (typeof(int), typeof(short)), typeof(bool) }, + { (typeof(int), typeof(ushort)), typeof(bool) }, + { (typeof(int), typeof(ulong)), default(Type) }, + { (typeof(int), typeof(byte)), typeof(bool) }, + { (typeof(int), typeof(Single)), typeof(bool) }, + { (typeof(int), typeof(uint)), typeof(bool) }, + { (typeof(int), typeof(SByte)), typeof(bool) }, + { (typeof(int), typeof(decimal)), typeof(bool) }, + { (typeof(int), typeof(string)), default(Type) }, + { (typeof(int), typeof(DateTime)), default(Type) }, + { (typeof(int), typeof(bool)), default(Type) }, + { (typeof(double), typeof(int)), typeof(bool) }, + { (typeof(double), typeof(double)), typeof(bool) }, + { (typeof(double), typeof(long)), typeof(bool) }, + { (typeof(double), typeof(short)), typeof(bool) }, + { (typeof(double), typeof(ushort)), typeof(bool) }, + { (typeof(double), typeof(ulong)), typeof(bool) }, + { (typeof(double), typeof(byte)), typeof(bool) }, + { (typeof(double), typeof(Single)), typeof(bool) }, + { (typeof(double), typeof(uint)), typeof(bool) }, + { (typeof(double), typeof(SByte)), typeof(bool) }, + { (typeof(double), typeof(decimal)), default(Type) }, + { (typeof(double), typeof(string)), default(Type) }, + { (typeof(double), typeof(DateTime)), default(Type) }, + { (typeof(double), typeof(bool)), default(Type) }, + { (typeof(long), typeof(int)), typeof(bool) }, + { (typeof(long), typeof(double)), typeof(bool) }, + { (typeof(long), typeof(long)), typeof(bool) }, + { (typeof(long), typeof(short)), typeof(bool) }, + { (typeof(long), typeof(ushort)), typeof(bool) }, + { (typeof(long), typeof(ulong)), default(Type) }, + { (typeof(long), typeof(byte)), typeof(bool) }, + { (typeof(long), typeof(Single)), typeof(bool) }, + { (typeof(long), typeof(uint)), typeof(bool) }, + { (typeof(long), typeof(SByte)), typeof(bool) }, + { (typeof(long), typeof(decimal)), typeof(bool) }, + { (typeof(long), typeof(string)), default(Type) }, + { (typeof(long), typeof(DateTime)), default(Type) }, + { (typeof(long), typeof(bool)), default(Type) }, + { (typeof(short), typeof(int)), typeof(bool) }, + { (typeof(short), typeof(double)), typeof(bool) }, + { (typeof(short), typeof(long)), typeof(bool) }, + { (typeof(short), typeof(short)), typeof(bool) }, + { (typeof(short), typeof(ushort)), typeof(bool) }, + { (typeof(short), typeof(ulong)), default(Type) }, + { (typeof(short), typeof(byte)), typeof(bool) }, + { (typeof(short), typeof(Single)), typeof(bool) }, + { (typeof(short), typeof(uint)), typeof(bool) }, + { (typeof(short), typeof(SByte)), typeof(bool) }, + { (typeof(short), typeof(decimal)), typeof(bool) }, + { (typeof(short), typeof(string)), default(Type) }, + { (typeof(short), typeof(DateTime)), default(Type) }, + { (typeof(short), typeof(bool)), default(Type) }, + { (typeof(ushort), typeof(int)), typeof(bool) }, + { (typeof(ushort), typeof(double)), typeof(bool) }, + { (typeof(ushort), typeof(long)), typeof(bool) }, + { (typeof(ushort), typeof(short)), typeof(bool) }, + { (typeof(ushort), typeof(ushort)), typeof(bool) }, + { (typeof(ushort), typeof(ulong)), typeof(bool) }, + { (typeof(ushort), typeof(byte)), typeof(bool) }, + { (typeof(ushort), typeof(Single)), typeof(bool) }, + { (typeof(ushort), typeof(uint)), typeof(bool) }, + { (typeof(ushort), typeof(SByte)), typeof(bool) }, + { (typeof(ushort), typeof(decimal)), typeof(bool) }, + { (typeof(ushort), typeof(string)), default(Type) }, + { (typeof(ushort), typeof(DateTime)), default(Type) }, + { (typeof(ushort), typeof(bool)), default(Type) }, + { (typeof(ulong), typeof(int)), default(Type) }, + { (typeof(ulong), typeof(double)), typeof(bool) }, + { (typeof(ulong), typeof(long)), default(Type) }, + { (typeof(ulong), typeof(short)), default(Type) }, + { (typeof(ulong), typeof(ushort)), typeof(bool) }, + { (typeof(ulong), typeof(ulong)), typeof(bool) }, + { (typeof(ulong), typeof(byte)), typeof(bool) }, + { (typeof(ulong), typeof(Single)), typeof(bool) }, + { (typeof(ulong), typeof(uint)), typeof(bool) }, + { (typeof(ulong), typeof(SByte)), default(Type) }, + { (typeof(ulong), typeof(decimal)), typeof(bool) }, + { (typeof(ulong), typeof(string)), default(Type) }, + { (typeof(ulong), typeof(DateTime)), default(Type) }, + { (typeof(ulong), typeof(bool)), default(Type) }, + { (typeof(byte), typeof(int)), typeof(bool) }, + { (typeof(byte), typeof(double)), typeof(bool) }, + { (typeof(byte), typeof(long)), typeof(bool) }, + { (typeof(byte), typeof(short)), typeof(bool) }, + { (typeof(byte), typeof(ushort)), typeof(bool) }, + { (typeof(byte), typeof(ulong)), typeof(bool) }, + { (typeof(byte), typeof(byte)), typeof(bool) }, + { (typeof(byte), typeof(Single)), typeof(bool) }, + { (typeof(byte), typeof(uint)), typeof(bool) }, + { (typeof(byte), typeof(SByte)), typeof(bool) }, + { (typeof(byte), typeof(decimal)), typeof(bool) }, + { (typeof(byte), typeof(string)), default(Type) }, + { (typeof(byte), typeof(DateTime)), default(Type) }, + { (typeof(byte), typeof(bool)), default(Type) }, + { (typeof(Single), typeof(int)), typeof(bool) }, + { (typeof(Single), typeof(double)), typeof(bool) }, + { (typeof(Single), typeof(long)), typeof(bool) }, + { (typeof(Single), typeof(short)), typeof(bool) }, + { (typeof(Single), typeof(ushort)), typeof(bool) }, + { (typeof(Single), typeof(ulong)), typeof(bool) }, + { (typeof(Single), typeof(byte)), typeof(bool) }, + { (typeof(Single), typeof(Single)), typeof(bool) }, + { (typeof(Single), typeof(uint)), typeof(bool) }, + { (typeof(Single), typeof(SByte)), typeof(bool) }, + { (typeof(Single), typeof(decimal)), default(Type) }, + { (typeof(Single), typeof(string)), default(Type) }, + { (typeof(Single), typeof(DateTime)), default(Type) }, + { (typeof(Single), typeof(bool)), default(Type) }, + { (typeof(uint), typeof(int)), typeof(bool) }, + { (typeof(uint), typeof(double)), typeof(bool) }, + { (typeof(uint), typeof(long)), typeof(bool) }, + { (typeof(uint), typeof(short)), typeof(bool) }, + { (typeof(uint), typeof(ushort)), typeof(bool) }, + { (typeof(uint), typeof(ulong)), typeof(bool) }, + { (typeof(uint), typeof(byte)), typeof(bool) }, + { (typeof(uint), typeof(Single)), typeof(bool) }, + { (typeof(uint), typeof(uint)), typeof(bool) }, + { (typeof(uint), typeof(SByte)), typeof(bool) }, + { (typeof(uint), typeof(decimal)), typeof(bool) }, + { (typeof(uint), typeof(string)), default(Type) }, + { (typeof(uint), typeof(DateTime)), default(Type) }, + { (typeof(uint), typeof(bool)), default(Type) }, + { (typeof(SByte), typeof(int)), typeof(bool) }, + { (typeof(SByte), typeof(double)), typeof(bool) }, + { (typeof(SByte), typeof(long)), typeof(bool) }, + { (typeof(SByte), typeof(short)), typeof(bool) }, + { (typeof(SByte), typeof(ushort)), typeof(bool) }, + { (typeof(SByte), typeof(ulong)), default(Type) }, + { (typeof(SByte), typeof(byte)), typeof(bool) }, + { (typeof(SByte), typeof(Single)), typeof(bool) }, + { (typeof(SByte), typeof(uint)), typeof(bool) }, + { (typeof(SByte), typeof(SByte)), typeof(bool) }, + { (typeof(SByte), typeof(decimal)), typeof(bool) }, + { (typeof(SByte), typeof(string)), default(Type) }, + { (typeof(SByte), typeof(DateTime)), default(Type) }, + { (typeof(SByte), typeof(bool)), default(Type) }, + { (typeof(decimal), typeof(int)), typeof(bool) }, + { (typeof(decimal), typeof(double)), default(Type) }, + { (typeof(decimal), typeof(long)), typeof(bool) }, + { (typeof(decimal), typeof(short)), typeof(bool) }, + { (typeof(decimal), typeof(ushort)), typeof(bool) }, + { (typeof(decimal), typeof(ulong)), typeof(bool) }, + { (typeof(decimal), typeof(byte)), typeof(bool) }, + { (typeof(decimal), typeof(Single)), default(Type) }, + { (typeof(decimal), typeof(uint)), typeof(bool) }, + { (typeof(decimal), typeof(SByte)), typeof(bool) }, + { (typeof(decimal), typeof(decimal)), typeof(bool) }, + { (typeof(decimal), typeof(string)), default(Type) }, + { (typeof(decimal), typeof(DateTime)), default(Type) }, + { (typeof(decimal), typeof(bool)), default(Type) }, + { (typeof(string), typeof(int)), default(Type) }, + { (typeof(string), typeof(double)), default(Type) }, + { (typeof(string), typeof(long)), default(Type) }, + { (typeof(string), typeof(short)), default(Type) }, + { (typeof(string), typeof(ushort)), default(Type) }, + { (typeof(string), typeof(ulong)), default(Type) }, + { (typeof(string), typeof(byte)), default(Type) }, + { (typeof(string), typeof(Single)), default(Type) }, + { (typeof(string), typeof(uint)), default(Type) }, + { (typeof(string), typeof(SByte)), default(Type) }, + { (typeof(string), typeof(decimal)), default(Type) }, + { (typeof(string), typeof(string)), typeof(bool) }, + { (typeof(string), typeof(DateTime)), default(Type) }, + { (typeof(string), typeof(bool)), default(Type) }, + { (typeof(DateTime), typeof(int)), default(Type) }, + { (typeof(DateTime), typeof(double)), default(Type) }, + { (typeof(DateTime), typeof(long)), default(Type) }, + { (typeof(DateTime), typeof(short)), default(Type) }, + { (typeof(DateTime), typeof(ushort)), default(Type) }, + { (typeof(DateTime), typeof(ulong)), default(Type) }, + { (typeof(DateTime), typeof(byte)), default(Type) }, + { (typeof(DateTime), typeof(Single)), default(Type) }, + { (typeof(DateTime), typeof(uint)), default(Type) }, + { (typeof(DateTime), typeof(SByte)), default(Type) }, + { (typeof(DateTime), typeof(decimal)), default(Type) }, + { (typeof(DateTime), typeof(string)), default(Type) }, + { (typeof(DateTime), typeof(DateTime)), typeof(bool) }, + { (typeof(DateTime), typeof(bool)), default(Type) }, + { (typeof(bool), typeof(int)), default(Type) }, + { (typeof(bool), typeof(double)), default(Type) }, + { (typeof(bool), typeof(long)), default(Type) }, + { (typeof(bool), typeof(short)), default(Type) }, + { (typeof(bool), typeof(ushort)), default(Type) }, + { (typeof(bool), typeof(ulong)), default(Type) }, + { (typeof(bool), typeof(byte)), default(Type) }, + { (typeof(bool), typeof(Single)), default(Type) }, + { (typeof(bool), typeof(uint)), default(Type) }, + { (typeof(bool), typeof(SByte)), default(Type) }, + { (typeof(bool), typeof(decimal)), default(Type) }, + { (typeof(bool), typeof(string)), default(Type) }, + { (typeof(bool), typeof(DateTime)), default(Type) }, + { (typeof(bool), typeof(bool)), typeof(Type) }, + }; + } + +} diff --git a/src/openCypherParser/AST/CypherVisitor.cs b/src/openCypherParser/AST/CypherVisitor.cs new file mode 100644 index 0000000..a1637e9 --- /dev/null +++ b/src/openCypherParser/AST/CypherVisitor.cs @@ -0,0 +1,2055 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Antlr4.Runtime; +using Antlr4.Runtime.Misc; +using Antlr4.Runtime.Tree; +using System.Text.RegularExpressions; +using openCypherTranspiler.Common.Exceptions; +using openCypherTranspiler.Common.Logging; +using openCypherTranspiler.openCypherParser.ANTLR; +using openCypherTranspiler.openCypherParser.AST; +using openCypherTranspiler.openCypherParser.Common; +using openCypherTranspiler.Common.Utils; + +namespace openCypherTranspiler.openCypherParser.AST +{ + /// + /// openCypher's ANTLR4 visitor to turn parsing result CST to AST + /// + internal class CypherVisitor : CypherBaseVisitor + { + private ILoggable _logger; + + private class Optional where T : ParserRuleContext { } + + #region Helper functions + + // check existence of parent nodes + private bool IsInsideContextType(Type type, RuleContext ctx) + { + var parentObj = ctx?.Parent; + while (parentObj != null) + { + if (parentObj.GetType() == type) + { + return true; + } + parentObj = parentObj?.Parent; + } + return false; + } + + private bool IsContextContainsTextToken(IParseTree context, string textToken) + { + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + if (child is ITerminalNode && string.Compare(child.GetText(), textToken, true) == 0) + { + return true; + } + } + return false; + } + + private bool IsContextSP(IParseTree context) + { + return (context is ITerminalNode && (context as ITerminalNode).Symbol.Type == CypherParser.SP); + } + + // 'take' the current state variable as a value but at same time reset it + private T TakeAndResetStateVariable(ref T variable) + { + T tempValue = variable; + variable = default(T); + return tempValue; + } + + // helper function to see if a context node's children match specfic pattern (useful when it supports more than one type of patterns) + private bool IsMatchSequence(ParserRuleContext ctx, params object[] seq) + { + List ctxChildren = new List(); + for (int i = 0; i < ctx.ChildCount; i++) + { + var ctxChild = ctx.GetChild(i); + if (ctxChild is ITerminalNode) + { + if (!IsContextSP(ctxChild)) + { + ctxChildren.Add(ctxChild.GetText()); + } + } + else + { + ctxChildren.Add(ctxChild.GetType()); + } + } + string matchSrc = string.Join("|", ctxChildren.Select(o => o is string ? (string)o : ((Type)o).Name)) + "|"; + string matchPat = string.Join("", + seq.Select(o => o is string ? $"{Regex.Escape((string)o)}\\|" : + TypeHelper.IsSubclassOfRawGeneric((Type)o, typeof(Optional<>)) ? $"(?:{Regex.Escape(((Type)o).Name)}\\|)?" : $"{Regex.Escape(((Type)o).Name)}\\|") + ); + return Regex.IsMatch(matchSrc, matchPat); + } + + private QueryExpressionBinary HandleChainedBinaryExpressions(IParseTree context) + { + var parentExpression = new QueryExpressionBinary(); + var supportedOperators = new string[] { "+", "-", "%", "*", "/" }; + + bool visitedLeft = false; + bool visitedOperator = false; + bool visitedRight = false; + + + // get left expression + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + + if (!visitedLeft && !(child is ITerminalNode)) + { + Debug.Assert( + // list of supported expressions in this form today: + child is CypherParser.OC_AddOrSubtractExpressionContext || + child is CypherParser.OC_MultiplyDivideModuloExpressionContext || + child is CypherParser.OC_PowerOfExpressionContext + ); + + var childExpr = Visit(child) as QueryExpression ?? throw new TranspilerSyntaxErrorException($"Expect valid left expression {child.GetText()}"); + parentExpression.LeftExpression = childExpr; + visitedLeft = true; + continue; + } + + if (child is ITerminalNode && supportedOperators.Contains(context.GetChild(i).GetText())) + { + var op = child.GetText(); + + if (parentExpression.Operator != null) + { + Debug.Assert(parentExpression.RightExpression != null); + // not the first right operator/expr pair. do chaining + var newParentExpression = new QueryExpressionBinary() + { + LeftExpression = parentExpression + }; + parentExpression = newParentExpression; + } + + var opEnum = OperatorHelper.TryGetOperator(op) + ?? throw new TranspilerSyntaxErrorException($"Unknown or unsupported operator {op}"); + parentExpression.Operator = opEnum; + visitedOperator = true; + // reset visited right as soon as we see another new operator + visitedRight = false; + continue; + } + + if (!visitedRight && !(child is ITerminalNode)) + { + Debug.Assert(visitedOperator); + var childExpr = Visit(child) as QueryExpression ?? throw new TranspilerSyntaxErrorException($"Expect valid right expression {child.GetText()}"); + parentExpression.RightExpression = childExpr; + visitedRight = true; + continue; + } + } + + Debug.Assert(visitedLeft && visitedOperator && visitedRight); + return parentExpression; + } + + private QueryExpressionBinary HandlesBinaryExpression(IParseTree context, string op) + { + var opEnum = OperatorHelper.TryGetOperator(op) + ?? throw new TranspilerSyntaxErrorException($"Unknown or unsupported operator {op}"); + + QueryExpression finalExp = null; + bool visitedLeft = false; + + // get left expression + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + + if (!visitedLeft && !(child is ITerminalNode)) + { + var childExpr = Visit(child) as QueryExpression + ?? throw new TranspilerSyntaxErrorException($"Expect valid left side expression {child.GetText()}"); + finalExp = childExpr; + visitedLeft = true; + continue; + } + + if (!(child is ITerminalNode)) + { + var childExpr = Visit(child) as QueryExpression + ?? throw new TranspilerSyntaxErrorException($"Expect valid right side expression {child.GetText()}"); + finalExp = new QueryExpressionBinary() + { + Operator = opEnum, + LeftExpression = finalExp, + RightExpression = childExpr + }; + continue; + } + } + + return finalExp as QueryExpressionBinary + ?? throw new TranspilerSyntaxErrorException($"Expecting at least 2 sides of a binary operator: {context.GetText()}"); + } + + private QueryExpressionFunction HandlesUnaryExpression(IParseTree context) + { + // We treat function and unary expression the same: + // e.g. +expr or -expr, or NOT expr + QueryExpression finalExpr = null; + var supportedOperators = new string[] { "+", "-'" }; + var unaryOpChain = new Stack(); + + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + + if (child is ITerminalNode && supportedOperators.Any(op => op == child.GetText())) + { + Debug.Assert(finalExpr == null); // operator should only appear before the expression + var fi = FunctionHelper.TryGetFunctionInfo(child.GetText().Trim()) + ?? throw new TranspilerInternalErrorException("Parsing function info"); // unexpected operator. should have stopped by caller + unaryOpChain.Push(fi); + continue; + } + + if (!(child is ITerminalNode)) + { + Debug.Assert(finalExpr == null); // expr should only appear once in unary operator + finalExpr = Visit(child) as QueryExpression + ?? throw new TranspilerSyntaxErrorException($"Expect valid right expression {child.GetText()}"); + } + } + + Debug.Assert(unaryOpChain.Count > 0); + Debug.Assert(finalExpr != null); + + while (unaryOpChain.Count > 0) + { + finalExpr = new QueryExpressionFunction() + { + Function = unaryOpChain.Pop(), + InnerExpression = finalExpr + }; + } + + return finalExpr as QueryExpressionFunction + ?? throw new TranspilerSyntaxErrorException($"Expect valid expression for an unary operator at least once: {context.GetText()}"); + } + + private QueryExpressionFunction HandlesUnaryFuncExpression(IParseTree context, string funcName) + { + // We treat function and unary expression the same: + // e.g. +expr or -expr, or NOT expr + var fi = FunctionHelper.TryGetFunctionInfo(funcName) + // unexpected function name: should have been stopped by the caller to HandlesUnaryFuncExpression + ?? throw new TranspilerInternalErrorException("Parsing function info"); + + var parentExpression = new QueryExpressionFunction() + { + Function = fi + }; + + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + + if (!(child is ITerminalNode)) + { + var childExpr = Visit(child) as QueryExpression ?? throw new TranspilerSyntaxErrorException($"Expect valid right expression {child.GetText()}"); + Debug.Assert(parentExpression.InnerExpression == null); + parentExpression.InnerExpression = childExpr; + } + } + + return parentExpression; + } + + /// + /// Helper function to get all direct entity reference from a return body item list ( [some expr] AS [alias] ) + /// E.g. MATCH (p:person) WITH p as q, p.id as Id, this will return just Entity with alias = p and type = erpson + /// + /// + /// A dictionary of the reference to the Entity object keyed by its alias (in AS [alias] expr) + private IDictionary GetEntitiesFromReturnBodyByRef(IEnumerable exprs) + { + return exprs + .Select(expr => new { Alias = expr.Alias, Entity = expr.InnerExpression.TryGetDirectlyExposedEntity() }) + .Where(e => e.Entity != null) + .ToDictionary(expr => expr.Alias, expr => expr.Entity); + } + + /// + /// Helper function to call GetEntitiesFromReturnBodyByRef but then replace the alias with the QueryExpressionWithAlias's alias + /// E.g. MATCH (p:person) WITH p as q. This will return entity type person with alias = q (instead of p) + /// + /// + /// + private IEnumerable GetEntitiesFromReturnBodyWithAliasApplied(IEnumerable exprs) + { + return GetEntitiesFromReturnBodyByRef(exprs) + .Select(kv => + { + var ent = kv.Value.Clone(); + ent.Alias = kv.Key; + return ent; + }); + } + + /// + /// Helper function to get all non entity fields from a return body item list ( [some expr] AS [alias] ) + /// E.g. ... WITH avg+1 as shift_avg. This will return QueryExprWithAlias: alias = shift_avg, expr = avg+1 + /// + /// + /// + private IEnumerable GetNonEntitiesAliasesFromReturnBody(IEnumerable exprs) + { + return exprs + .Where(expr => expr.InnerExpression.TryGetDirectlyExposedEntity() == null) + .Select(expr => expr.Alias); + } + + + private PartialQueryTreeNode CreateQueryPartFromReadingClauses( + CypherParser.OC_ReadingClauseContext readingClause, + PartialQueryTreeNode prevQueryPart + ) + { + // this function consolidates consolidate multiple matches, each is a list of MatchPattern, and + // enforce that optional match cannot be the first one + var matchParts = new List(); // consolidate multiple matches, each is a list of MatchPattern + + // returns valuetuple type (pass through): + // { MatchPatterns(IList), Condition(QueryExpression) } + var result = ((IList MatchPatterns, QueryExpression Condition))Visit(readingClause); + IList matchPatterns = result.MatchPatterns ?? throw new TranspilerInternalErrorException("Parsing oC_ReadingClause"); + + var isOptionalMatch = matchPatterns.Any(p => p.IsOptionalMatch); + Debug.Assert(matchPatterns.All(p => p.IsOptionalMatch == isOptionalMatch)); + + if (isOptionalMatch) + { + // if optional match, then it cannot be the first reading clause + if (prevQueryPart == null) + { + throw new TranspilerSyntaxErrorException("First MATCH cannot be OPTIONAL"); + } + } + else + { + // not optional match, then we cannot follow immediately after optional match + if (prevQueryPart != null && !prevQueryPart.CanChainNonOptionalMatch) + { + throw new TranspilerSyntaxErrorException("MATCH cannot follow OPTIONAL MATCH (perhaps use a WITH clause between them)"); + } + } + + matchParts.AddRange(matchPatterns); + + // construct the match data source (representing a group of matches) + MatchDataSource matchDs = null; + if (matchParts.Count > 0) + { + matchDs = new MatchDataSource() + { + MatchPatterns = matchParts + }; + } + + // A Match statment (not RET or WITH) has implied projection expressions as returned items of this partial query node: + // - includes all named entities in the match pattern (later, we can optimize out if some are not used at all) + // - includes all inherited returns + var allReturnedEntities = matchParts.SelectMany(l => l) + .Union(prevQueryPart != null ? GetEntitiesFromReturnBodyWithAliasApplied(prevQueryPart.ProjectedExpressions) : Enumerable.Empty()) + .Where(e => !string.IsNullOrEmpty(e.Alias)) + .GroupBy(e => e.Alias); + // TODO: missing alias duplicacy check here with entity + var allInheritedProperties = prevQueryPart != null ? GetNonEntitiesAliasesFromReturnBody(prevQueryPart.ProjectedExpressions) : Enumerable.Empty(); + + var returnedExprs = allReturnedEntities + .Select(g => + { + if (g.Select(e => e.EntityName).Where(en => !string.IsNullOrEmpty(en)).Distinct().Count() > 1) + { + throw new TranspilerSyntaxErrorException($"Multiple labels assigned to same alias {g.Key}: {string.Join(",", g.Select(e => e.EntityName).Where(en => !string.IsNullOrEmpty(en)))}"); + } + return new QueryExpressionWithAlias() + { + Alias = g.Key, + InnerExpression = new QueryExpressionProperty() + { + Entity = g.FirstOrDefault(en => !string.IsNullOrEmpty(en.EntityName)).Clone(), + VariableName = g.Key + } + }; + }) + .Union( + allInheritedProperties.Select(alias => + new QueryExpressionWithAlias() + { + Alias = alias, + InnerExpression = new QueryExpressionProperty() + { + VariableName = alias + } + } + ) + ) + .ToList(); + + return new PartialQueryTreeNode() + { + MatchData = matchDs, + PostCondition = result.Condition, + ProjectedExpressions = returnedExprs, + PipedData = prevQueryPart, + IsDistinct = false, // MATCH reading clause will not be come with DISTINCT keyword + CanChainNonOptionalMatch = !isOptionalMatch, + IsImplicitProjection = true, // MATCH's projection is always implied (returning all aliased nodes) + }; + } + + private SingleQueryTreeNode ConstructSingleQuery([NotNull] CypherParser.OC_SinglePartQueryContext context, PartialQueryTreeNode prevQueryPart) + { + Debug.Assert(context.oC_Return() != null); + + SingleQueryTreeNode queryNode = null; + + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + + if (child is CypherParser.OC_ReadingClauseContext) // MATCH (WHERE) + { + var partQueryTree = CreateQueryPartFromReadingClauses( + child as CypherParser.OC_ReadingClauseContext, + prevQueryPart + ); + + // set state for next clause + prevQueryPart = partQueryTree; + } + else if (child is CypherParser.OC_ReturnContext) // RETURN + { + // when we see an WITH, we know that we we are done with one query part of a multi-query part + // we will construct a new query part object, and if applicable, chain with previous query part + // and construct the MATCH patterns + if (prevQueryPart == null) + { + throw new TranspilerNotSupportedException("RETURN projection without reading clauses (a.k.a. Match)"); + } + + // returns valuetuple type: + // { IsDistinct(bool), ReturnItems(IList), OrderByItems(IList) } + var returnResult = (( + bool IsDistinct, + IList ReturnItems, + IList OrderByItems, + IList LimitItems))Visit(child); + var projectionExprs = returnResult.ReturnItems ?? throw new TranspilerSyntaxErrorException($"Expecting a valid list of items to be returned: {child.GetText()}"); + var orderedExprs = returnResult.OrderByItems; + var limitExprs = returnResult.LimitItems; + + bool isDistinct = returnResult.IsDistinct; + var singleQueryNode = new SingleQueryTreeNode() + { + PipedData = prevQueryPart, + EntityPropertySelected = projectionExprs, + IsDistinct = isDistinct, + EntityPropertyOrderBy = orderedExprs, + EntityRowsLimit = limitExprs, + }; + + // Check that return has no conflict + var firstDup = projectionExprs.GroupBy(expr => expr.Alias).FirstOrDefault(g => g.Count() > 1); + if (firstDup != null) + { + throw new TranspilerSyntaxErrorException($"Multiple result columns with the same name are not supported: {firstDup.Key}"); + } + + // propagate the entity types to the list of return items that are direct exposure of entities + // NOTE: currently we assume direct reference. Any function manipulation will cause it become + // a non-node reference so that it cannot be used as entity variables in next MATCH statement + // e.g. u as u or (u) as u is okay , AVG(u) as u is no longer an enity + Debug.Assert(projectionExprs.All(p => p is QueryExpressionWithAlias)); + UpdateReturnBodyWithEntityTypes( + projectionExprs.Cast(), + GetEntitiesFromReturnBodyWithAliasApplied(prevQueryPart.ProjectedExpressions) + ); + + queryNode = singleQueryNode; + } + else if (child is CypherParser.OC_UpdatingClauseContext) + { + throw new TranspilerNotSupportedException("Updaing clause"); + } + else + { + // skip the rest type nodes (e.g. SP) + } + } + + return queryNode; + } + + private void UpdateReturnBodyWithEntityTypes(IEnumerable exprsToUpdate, IEnumerable entities) + { + var projectionExprsReferingEntities = exprsToUpdate + .Where(p => p.InnerExpression is QueryExpressionProperty && + string.IsNullOrEmpty(((QueryExpressionProperty)p.InnerExpression).PropertyName)) + .Select(p => p.InnerExpression as QueryExpressionProperty) + .ToList(); + projectionExprsReferingEntities.ForEach(e => + { + var entityMatchedAlias = entities.FirstOrDefault(e2 => e2.Alias == e.VariableName); + if (entityMatchedAlias != null) + { + e.Entity = entityMatchedAlias.Clone(); + } + else + { + // if we cannot match alias, we treat is not as entity reference for now and ignore it + // later part of parsing should fail for any dangling reference + } + }); + } + + #endregion Helper functions + + public CypherVisitor(ILoggable logger) + { + _logger = logger; + } + + // this method returns the final tree + public override object VisitOC_Cypher([NotNull] CypherParser.OC_CypherContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_Cypher", context.GetText()); + // return the final parsed tree of type QueryTreeNode (pass through) + Debug.Assert(context.oC_Statement() != null); + return Visit(context.oC_Statement()) as QueryTreeNode ?? throw new TranspilerInternalErrorException("Parsing oC_Statement"); + } + + public override object VisitOC_Query([NotNull] CypherParser.OC_QueryContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_Query", context.GetText()); + if (context.oC_RegularQuery() != null) + { + // return the final parsed tree of type QueryTreeNode (pass through) + return Visit(context.oC_RegularQuery()) as QueryTreeNode ?? throw new TranspilerInternalErrorException("Parsing oc_RegularQuery"); + } + else + { + throw new TranspilerNotSupportedException("CALL statement"); + } + } + + public override object VisitOC_RegularQuery([NotNull] CypherParser.OC_RegularQueryContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_RegularQuery", context.GetText()); + // returns QueryTreeNode, can be a passed through SingleQueryTreeNode, or InfixQueryTreeNode + + Debug.Assert(context.oC_SingleQuery() != null); + var rootNode = Visit(context.oC_SingleQuery()) as QueryTreeNode ?? throw new TranspilerInternalErrorException("Parsing oC_SingleQuery"); + + if ((context.oC_Union()?.Length ?? 0) > 0) + { + foreach (var childCtx in context.oC_Union()) + { + Debug.Assert(childCtx.UNION() != null); + var unioned = new InfixQueryTreeNode() + { + LeftQueryTreeNode = rootNode, + RightQueryTreeNode = Visit(childCtx.oC_SingleQuery()) as QueryTreeNode ?? throw new TranspilerInternalErrorException("Parsing oC_SingleQuery of UNION"), + Operator = childCtx.ALL() != null ? InfixQueryTreeNode.QueryOperator.UnionAll : InfixQueryTreeNode.QueryOperator.Union + }; + rootNode = unioned; + } + } + + return Visit(context.oC_SingleQuery()) as QueryTreeNode ?? throw new TranspilerInternalErrorException("Parsing oC_SingleQuery"); + } + + public override object VisitOC_SingleQuery([NotNull] CypherParser.OC_SingleQueryContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_SingleQuery", context.GetText()); + // returns SingleQueryTreeNode + + // In this function, we fix up the chained query parts to populate all the inferred labels + // to do this, we walk down to the bottom (leaf node) of the tree and walk back, and each step we + // fix up the current query parts and update the returned entity types + // For any types we cannot infer, we throw exception + var singleQuery = VisitChildren(context) as SingleQueryTreeNode ?? throw new TranspilerInternalErrorException("Parsing oC_SinglePartQuery or oC_MultiPartQuery"); + + var queryChainTreeNode = singleQuery.PipedData as PartialQueryTreeNode; + Debug.Assert(queryChainTreeNode != null); // should be guaranteed by child visitor already + var queryChain = new Stack(); + queryChain.Push(queryChainTreeNode); + + while (queryChainTreeNode.PipedData != null) + { + queryChainTreeNode = queryChainTreeNode.PipedData; + queryChain.Push(queryChainTreeNode); + } + + // propagate entity names for all entity objects with same alias for each query part, from + // bottom up of the query tree + // for any conflict type (e.g. single alias assigned to 2 types), raise error + var inheritedEntities = Enumerable.Empty(); + while (queryChain.Count > 0) + { + var queryTreeNode = queryChain.Pop(); + var entitiesInReturn = GetEntitiesFromReturnBodyByRef(queryTreeNode.ProjectedExpressions); + var entitiesInMatchPatterns = queryTreeNode.MatchData?.AllEntitiesOrdered ?? Enumerable.Empty().ToList(); + + // first pass, propagate all node and edge labels for those sharing aliases + entitiesInReturn + .Values + .Union(entitiesInMatchPatterns) + .Where(e => !string.IsNullOrEmpty(e.Alias)) // skip over all anonymous node/edge. we later assert that they all have types already specified explictly + .GroupBy(e => e.Alias) + .ToList() + .ForEach(g => + { + // Ensure that aliases are assigned type and label consistently + var entityNames = g.Select(e => e.EntityName).Where(en => !string.IsNullOrEmpty(en)).Distinct(); + var entityTypes = g.Select(e => e.GetType()).Distinct(); + + if (entityTypes.Count() != 1) + { + throw new TranspilerSyntaxErrorException($"The same alias '{g.Key}' is assigned to both NODE and RELATIONSHIPS"); + } + if (entityNames.Count() > 1) + { + throw new TranspilerSyntaxErrorException($"The alias '{g.Key}' assigned to more than one labels {string.Join(", ", entityNames)}"); + } + if (entityNames.Count() == 0) + { + throw new TranspilerSyntaxErrorException($"Type label for alias '{g.Key}' cannot be deduced. Did you not give a label to it?"); + } + + g.ToList().ForEach(e => + { + e.EntityName = entityNames.First(); + }); + + }); + + // second pass, loop through all relationships and update the the source and sink entity name + for (int i = 0; i < entitiesInMatchPatterns.Count; i++) + { + var relEnt = entitiesInMatchPatterns[i] as RelationshipEntity; + + if (relEnt != null) + { + var prevEnt = entitiesInMatchPatterns[i - 1] as NodeEntity; + var nextEnt = entitiesInMatchPatterns[i + 1] as NodeEntity; + Debug.Assert(prevEnt != null && nextEnt != null); + relEnt.LeftEntityName = prevEnt.EntityName; + relEnt.RightEntityName = nextEnt.EntityName; + } + } + + // third pass, update all relationship entities' in/out node names + entitiesInReturn + .Values + .Union(inheritedEntities) + .Where(e => e is RelationshipEntity) + .Union(entitiesInMatchPatterns.Where(e => e is RelationshipEntity)) + .Where(e => !string.IsNullOrEmpty(e.Alias)) // skip over anonymous edges . we later assert that they all have types already specified explictly + .GroupBy(e => e.Alias) + .ToList() + .ForEach(g => + { + var entityTypes = g.Select(e => e.GetType()).Distinct(); + Debug.Assert(entityTypes.Count() == 1); + + if (entityTypes.First() == typeof(RelationshipEntity)) + { + var entityFromNames = g.Select(e => (e as RelationshipEntity).LeftEntityName).Where(en => !string.IsNullOrEmpty(en)).Distinct(); + var entityToNames = g.Select(e => (e as RelationshipEntity).RightEntityName).Where(en => !string.IsNullOrEmpty(en)).Distinct(); + + if (entityFromNames.Count() > 1 || entityToNames.Count() > 1) + { + var entNames = g.Select(e => $"({(e as RelationshipEntity).LeftEntityName})-[{e.EntityName}]-({(e as RelationshipEntity).RightEntityName})").Distinct(); + throw new TranspilerSyntaxErrorException($"The alias {g.Key} assigned to a different type of relationships: {string.Join(", ", entNames)}"); + } + + g.Cast().ToList().ForEach(e => + { + e.LeftEntityName = entityFromNames.First(); + e.RightEntityName = entityToNames.First(); + }); + } + }); + + // final pass: verify that all types are inferred + var firstUnknownTypeEntity = entitiesInReturn.Values + .FirstOrDefault(e => e is NodeEntity ? + string.IsNullOrEmpty((e as NodeEntity).EntityName) : + string.IsNullOrEmpty((e as RelationshipEntity).EntityName) || string.IsNullOrEmpty((e as RelationshipEntity).LeftEntityName) || string.IsNullOrEmpty((e as RelationshipEntity).RightEntityName) + ); + if (firstUnknownTypeEntity != null) + { + throw new TranspilerSyntaxErrorException($"Type label for alias '{firstUnknownTypeEntity.Alias}' cannot be deduced. Did you not give a label to it?"); + } + + // before moving to next query part, update inheritedEntities to the current query part's returned list of entities + inheritedEntities = GetEntitiesFromReturnBodyWithAliasApplied(queryTreeNode.ProjectedExpressions); + } + + // in the final return statement, we currently do not support return entities, so we fail any attempt to do so + var entitiesInFinalReturn = GetEntitiesFromReturnBodyWithAliasApplied(singleQuery.EntityPropertySelected); + if (entitiesInFinalReturn.Count() > 0) + { + throw new TranspilerNotSupportedException($"Entites ({string.Join(", ", entitiesInFinalReturn.Select(e => e.Alias))}) in return statement"); + } + + return singleQuery; + } + + public override object VisitOC_MultiPartQuery([NotNull] CypherParser.OC_MultiPartQueryContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_MultiPartQuery", context.GetText()); + // return SingleQueryTreeNode + // multipart query has several situations we need to handle + // - MATCH not followed by any with but termination (MATCH RETURN) + // - with immediately follows a MATCH (MATCH WITH RETURN) + // - with follows other WITH (MATCH WITH WITH RETURN) + // - standalone WITH (not supported for now) + + PartialQueryTreeNode prevQueryPart = null; + SingleQueryTreeNode queryNode = null; + + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + + if (child is CypherParser.OC_ReadingClauseContext) // MATCH (WHERE) + { + var partQueryTree = CreateQueryPartFromReadingClauses( + child as CypherParser.OC_ReadingClauseContext, + prevQueryPart + ); + + // set state for next clause + prevQueryPart = partQueryTree; + } + else if (child is CypherParser.OC_WithContext) // WITH (WHERE) + { + // when we see an WITH, we know that we we are done with one query part of a multi-query part + // we will construct a new query part object, and if applicable, chain with previous query part + // and construct the MATCH patterns + if (prevQueryPart == null) + { + throw new TranspilerNotSupportedException("WITH projection without reading clauses (a.k.a. Match)"); + } + + // child visit of OC_WITH returns valuetuple type representing the return body and flags: + // { IsDistinct(bool), ReturnItems(IList), Condition(QueryExpression) } + var withResult = (( + bool IsDistinct, + IList + ReturnItems, + QueryExpression Condition, + IList OrderByItems, + IList LimitItems))Visit(child); + + // WITH will mask out any entities from MATCH that was not explicity returned + // get a list of entities exposed from current query part and leave it for next query part (if any) + // for constructing the match pattern that refers to any of these entities + // If we have a previous query part, we get a list of variables from previous query that + // directly exposes node/relationship entities. E.g. + // MATCH (u:user) <-- prev query part + // WITH u as u2 + // MATCH (u)-[:some_rel]-(:some_node) <-- current query part, u is not the same u in previous MATCH but a new node + // ... + var projectionExprs = withResult.ReturnItems ?? throw new TranspilerSyntaxErrorException($"Expecting a valid list of items to be returned: {child.GetText()}"); + var partQueryTree = new PartialQueryTreeNode() + { + PipedData = prevQueryPart, + ProjectedExpressions = projectionExprs, + PostCondition = withResult.Condition, + IsDistinct = withResult.IsDistinct, + MatchData = null, + CanChainNonOptionalMatch = true, + IsImplicitProjection = false, + LimitExpression = withResult.LimitItems, + OrderByExpression = withResult.OrderByItems, + }; + + + // propagate the entity types (node/edge, if possible EntityName as well) to the list of return items that + // are direct exposure of entities + // NOTE: currently we assume direct reference. Any function manipulation will cause it become + // a non-node reference so that it cannot be used as entity variables in next MATCH statement + // e.g. u as u or (u) as u is okay , AVG(u) as u is no longer an enity + Debug.Assert(projectionExprs.All(p => p is QueryExpressionWithAlias)); + UpdateReturnBodyWithEntityTypes( + projectionExprs.Cast(), + GetEntitiesFromReturnBodyWithAliasApplied(prevQueryPart.ProjectedExpressions) + ); + + // set state for next clause + prevQueryPart = partQueryTree; + } + else if (child is CypherParser.OC_SinglePartQueryContext) // (ReadingClauses)* RETURN + { + Debug.Assert(prevQueryPart != null); + queryNode = ConstructSingleQuery(child as CypherParser.OC_SinglePartQueryContext, prevQueryPart); + } + else if (child is CypherParser.OC_UpdatingClauseContext) + { + throw new TranspilerNotSupportedException("Updaing clause"); + } + else + { + // skip the rest type nodes (e.g. SP) + } + } + + Debug.Assert(queryNode != null); + return queryNode; + } + + public override object VisitOC_SinglePartQuery([NotNull] CypherParser.OC_SinglePartQueryContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_SinglePartQuery", context.GetText()); + // return SingleQueryTreeNode + // single part query is the terminating part that contains RETURN + // it is either MATCH RETURN, MATCH MATCH ... RETURN, or just RETURN + var queryNode = ConstructSingleQuery(context as CypherParser.OC_SinglePartQueryContext, null); + return queryNode; + } + + public override object VisitOC_ReadingClause([NotNull] CypherParser.OC_ReadingClauseContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_ReadingClause", context.GetText()); + // reading clause lead to MATCH, which is supported, and Unwind/InQueryCall, which are not supported + // returns valuetuple type (pass through): + // { MatchPatterns(IList), Condition(QueryExpression) } + + if (context.oC_Unwind() != null || context.oC_InQueryCall() != null) + { + throw new TranspilerNotSupportedException("Unwind or Call"); + } + + if (context.oC_Match() != null) + { + // returns valuetuple type (MatchPatterns, Condition) (pass through): + return Visit(context.oC_Match()); + } + else + { + throw new TranspilerSyntaxErrorException("Match is required"); + } + } + + public override object VisitOC_Match([NotNull] CypherParser.OC_MatchContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_Match", context.GetText()); + // match has MATCH (WHERE) + // returns valuetuple type: + // ( MatchPatterns(IList), Condition(QueryExpression) ) + + var isOptional = IsContextContainsTextToken(context, "OPTIONAL"); + var patterns = Visit(context.oC_Pattern()) as IList> ?? throw new TranspilerInternalErrorException("Parsing oc_Pattern"); + QueryExpression condExpr = null; + + if (context.oC_Where() != null) + { + condExpr = Visit(context.oC_Where()) as QueryExpression ?? throw new TranspilerInternalErrorException("Parsing oc_Where"); + } + + return ( + MatchPatterns: patterns.Select(l => new MatchPattern(isOptional, l)).ToList() as IList, + Condition: condExpr // Condition + ); + } + + public override object VisitOC_Pattern([NotNull] CypherParser.OC_PatternContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_Pattern", context.GetText()); + // returns IList> type + + var patterns = new List>(); + + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + + if (child is CypherParser.OC_PatternPartContext) + { + var result = Visit(child) as IList; + Debug.Assert(result != null); + patterns.Add(result); + } + else + { + // skip the rest type nodes (e.g. SP) + } + } + return patterns; + } + + public override object VisitOC_PatternPart([NotNull] CypherParser.OC_PatternPartContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_PatternPart", context.GetText()); + // return IList (pass trhough) + IList matchPatternPart = null; + + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + + if (child is CypherParser.OC_AnonymousPatternPartContext) + { + var result = Visit(child) as IList; + Debug.Assert(result != null); + Debug.Assert(matchPatternPart == null); + matchPatternPart = result; + } + else if (child is CypherParser.OC_VariableContext) + { + var text = child.GetText(); + throw new TranspilerNotSupportedException($"Variable on the match pattern: {text}"); + } + else + { + // skip the rest type nodes (e.g. SP) + } + } + return matchPatternPart; + } + + public override object VisitOC_PatternElement([NotNull] CypherParser.OC_PatternElementContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_PatternElement", context.GetText()); + // returns IList + // an pattern element is node - chain or just node, or ( itself ) + var matchPatternPart = new List(); + + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + + if (child is CypherParser.OC_NodePatternContext) + { + var result = Visit(child) as NodeEntity; + Debug.Assert(result != null); + matchPatternPart.Add(result); + } + else if (child is CypherParser.OC_PatternElementChainContext || child is CypherParser.OC_PatternElementContext) + { + var result = Visit(child) as IList; + Debug.Assert(result != null); + Debug.Assert(matchPatternPart.Count % 2 == 1); // number of entity should always be odd, e.g. 1 node, 1 node + 1 rel + 1 node, ... + Debug.Assert(result.First() != null && result.First() is RelationshipEntity); + (result.First() as RelationshipEntity).LeftEntityName = matchPatternPart.Last().EntityName; + matchPatternPart.AddRange(result); + } + else + { + // skip the rest type nodes (e.g. SP) + } + } + return matchPatternPart; + } + public override object VisitOC_PatternElementChain([NotNull] CypherParser.OC_PatternElementChainContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_PatternElementChain", context.GetText()); + // returns IList + // a chain is the -rel-node part + RelationshipEntity rel = null; + NodeEntity sinkNode = null; + + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + + if (child is CypherParser.OC_RelationshipPatternContext) + { + var result = Visit(child) as RelationshipEntity; + Debug.Assert(rel == null); + rel = result; + } + else if (child is CypherParser.OC_NodePatternContext) + { + var result = Visit(child) as NodeEntity; + Debug.Assert(sinkNode == null); + Debug.Assert(rel != null); + sinkNode = result; + rel.RightEntityName = result.EntityName; + } + else + { + // skip the rest type nodes (e.g. SP) + } + } + + Debug.Assert(rel != null && sinkNode != null); + return new List() { rel, sinkNode }; + } + + public override object VisitOC_NodePattern([NotNull] CypherParser.OC_NodePatternContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_NodePattern", context.GetText()); + // returns a NodeEntity object + + NodeEntity node = new NodeEntity(); + + if (context.oC_NodeLabels() != null) + { + var result = (string)Visit(context.oC_NodeLabels()); + Debug.Assert(result != null); + node.EntityName = result; + } + + if (context.oC_Properties() != null) + { + throw new TranspilerNotSupportedException("Please consider WHERE. Properties set on the node match pattern"); + } + + if (context.oC_Variable() != null) + { + // variable for match pattern in node is optional + var result = (string)Visit(context.oC_Variable()); + Debug.Assert(result != null); + node.Alias = result; + } + + return node; + } + + public override object VisitOC_NodeLabels([NotNull] CypherParser.OC_NodeLabelsContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_NodeLabels", context.GetText()); + string labelName = null; + + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + + if (child is CypherParser.OC_NodeLabelContext) + { + var nextLabelName = (child as CypherParser.OC_NodeLabelContext).oC_LabelName().GetText(); + if (labelName != null) + { + throw new TranspilerNotSupportedException($"Multiple nodel labels: {labelName} {nextLabelName}"); + } + labelName = nextLabelName; + } + else + { + + } + } + return labelName; + } + + public override object VisitOC_RelationshipPattern([NotNull] CypherParser.OC_RelationshipPatternContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_RelationshipPattern", context.GetText()); + // returns a RelationshipEntity object + + RelationshipEntity relationship = new RelationshipEntity() + { + RelationshipDirection = + (context.oC_LeftArrowHead() != null ? + (context.oC_RightArrowHead() != null ? RelationshipEntity.Direction.Both : RelationshipEntity.Direction.Backward) : + (context.oC_RightArrowHead() != null ? RelationshipEntity.Direction.Forward : RelationshipEntity.Direction.Both)) + }; + + var result = ((string VarName, string RelName))Visit(context.oC_RelationshipDetail()); + relationship.EntityName = result.RelName; + relationship.Alias = result.VarName; + return relationship; + } + + public override object VisitOC_RelationshipDetail([NotNull] CypherParser.OC_RelationshipDetailContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_RelationshipDetail", context.GetText()); + // returns valuetuple type {VarName(string), RelName(string)} + + string varName = null; + string relationshipName = null; + + if (context.oC_Variable() != null) + { + varName = (string)Visit(context.oC_Variable()); + } + + if (context.oC_RelationshipTypes() != null) + { + relationshipName = (string)Visit(context.oC_RelationshipTypes()); + } + + if (context.oC_Properties() != null) + { + throw new TranspilerNotSupportedException("Please consider WHERE. Properties set on the relationship match pattern"); + } + + return (VarName: varName, RelName: relationshipName); + } + + public override object VisitOC_RelationshipTypes([NotNull] CypherParser.OC_RelationshipTypesContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_RelationshipTypes", context.GetText()); + string relationshipName = null; + + // the relationship is the type specified inside [] bracket + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + + if (child is CypherParser.OC_RelTypeNameContext) + { + var relName = child.GetText(); + // Does not support multiple re + if (relationshipName != null) + { + throw new TranspilerNotSupportedException($"Multiple relationship: {relationshipName}|{relName}"); + } + relationshipName = relName; + } + else + { + // ignore the rest of things + } + } + return relationshipName; + } + + public override object VisitOC_With([NotNull] CypherParser.OC_WithContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_With", context.GetText()); + // with can come with WITH , ... or WITH WHERE + // return valuetuple type: + // ( IsDistinct(bool), ReturnItems(IList), Condition(QueryExpression) ) + + var isDistinct = IsContextContainsTextToken(context, "DISTINCT"); + + Debug.Assert(context.oC_ReturnBody() != null); + var returnBodyResult = (( + IList ReturnItems, + IList OrderByItems, + IList LimitItems))Visit(context.oC_ReturnBody()); + + var queryExprs = returnBodyResult.ReturnItems ?? throw new TranspilerInternalErrorException("Parsing oC_ReturnBody"); + var orderByExprs = returnBodyResult.OrderByItems; + var limitExprs = returnBodyResult.LimitItems; + + QueryExpression condExpr = null; + if (context.oC_Where() != null) + { + condExpr = Visit(context.oC_Where()) as QueryExpression ?? throw new TranspilerInternalErrorException("Parsing oC_Where"); + } + + return (IsDistinct: isDistinct, ReturnItems: queryExprs, Conditions: condExpr, OrderByItems: orderByExprs, LimitItems: limitExprs); + } + + public override object VisitOC_Return([NotNull] CypherParser.OC_ReturnContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_Return", context.GetText()); + // returns valuetuple type: + // ( IsDistinct(bool), ReturnItems(IList) ) + var returnBody = context.oC_ReturnBody(); + + bool isDistinct = IsContextContainsTextToken(context, "DISTINCT"); + + var returnBodyResult = (( + IList ReturnItems, + IList OrderByItems, + IList LimitItems))Visit(returnBody); + + return (IsDistinct: isDistinct, + ReturnItems: returnBodyResult.ReturnItems, + OrderByItems: returnBodyResult.OrderByItems, + LimitItems: returnBodyResult.LimitItems); + } + + public override object VisitOC_ReturnItems([NotNull] CypherParser.OC_ReturnItemsContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_ReturnItems", context.GetText()); + // returns IList() + var expressions = new List(); + + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + if (child is CypherParser.OC_ReturnItemContext) + { + // child returns expression + var result = Visit(child) as QueryExpressionWithAlias ?? throw new TranspilerSyntaxErrorException($"{child.GetText()}. Expecting query expressions."); + expressions.Add(result); + } + } + return expressions; + } + + public override object VisitOC_ReturnItem([NotNull] CypherParser.OC_ReturnItemContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_ReturnItem", context.GetText()); + + var selectedProperty = new QueryExpressionWithAlias(); + bool visitedExpr = false; + bool visitedAlias = false; + + for (int i = 0; i < context.ChildCount; i++) + { + if (!visitedExpr && context.GetChild(i) is CypherParser.OC_ExpressionContext) + { + var expr = Visit(context.GetChild(i)) as QueryExpression; + Debug.Assert(expr != null); + selectedProperty.InnerExpression = expr; + visitedExpr = true; + continue; + } + + if (!visitedAlias && context.GetChild(i) is CypherParser.OC_VariableContext) + { + var varName = (string)Visit(context.GetChild(i)); + selectedProperty.Alias = varName; + visitedAlias = true; + continue; + } + } + + // if no alias is specified, then we infer from the property name / variable itself, or, if ambiguous, throw + // syntax exception + if (!visitedAlias) + { + var props = selectedProperty.InnerExpression.GetChildrenQueryExpressionType(); + if (props.Count() != 1) + { + throw new TranspilerSyntaxErrorException($"You must specify alias name for expression {context.GetText()}"); + } + else + { + selectedProperty.Alias = props.First().PropertyName ?? props.First().VariableName; + } + } + + Debug.Assert(visitedExpr); + return selectedProperty; + } + + public override object VisitOC_Where([NotNull] CypherParser.OC_WhereContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_Where", context.GetText()); + // where returns single expression object (pass through) + return VisitChildren(context) as QueryExpression ?? throw new TranspilerInternalErrorException("Parsing oc_Expression"); + } + + public override object VisitOC_Properties([NotNull] CypherParser.OC_PropertiesContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_Properties", context.GetText()); + // Properties are JSON attached to Node or Edge match patterns. e.g. + // MATCH (n:device { id: 'someid'}) + // not supported for now + throw new TranspilerNotSupportedException("Consider use WITH/WHERE. Properties specification"); + } + + public override object VisitOC_Expression([NotNull] CypherParser.OC_ExpressionContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_Expression", context.GetText()); + // returns single expression (pass through) + return VisitChildren(context) as QueryExpression ?? throw new TranspilerInternalErrorException("Parsing oC_OrExpression"); + } + public override object VisitOC_OrExpression([NotNull] CypherParser.OC_OrExpressionContext context) + { + // OR is a binary operator, so if we see more than 1 children, the actual statement is seem than a pass-thru + if ((context.OR()?.Length ?? 0) > 0) + { + Debug.Assert(context.oC_XorExpression().Length >= 2); + _logger?.LogVerbose("{0}: {1}", "VisitOC_OrExpression", context.GetText()); + return HandlesBinaryExpression(context, "OR") ?? throw new TranspilerInternalErrorException("Parsing two oC_XorExpression of OR"); + } + else + { + // pass through. this is not an OR expression + return VisitChildren(context) as QueryExpression ?? throw new TranspilerInternalErrorException("Parsing oC_XorExpression"); + } + } + public override object VisitOC_XorExpression([NotNull] CypherParser.OC_XorExpressionContext context) + { + // XOR is a binary operator, so if we see more than 1 children, the actual statement is seem than a pass-thru + if ((context.XOR()?.Length ?? 0) > 0) + { + Debug.Assert(context.oC_AndExpression().Length >= 2); + _logger?.LogVerbose("{0}: {1}", "VisitOC_XorExpression", context.GetText()); + return HandlesBinaryExpression(context, "XOR") ?? throw new TranspilerInternalErrorException("Parsing two oC_AndExpression of XOR"); + } + else + { + // pass through. this is not an XOR expression + return VisitChildren(context) as QueryExpression ?? throw new TranspilerInternalErrorException("Parsing oC_AndExpression"); + } + } + public override object VisitOC_AndExpression([NotNull] CypherParser.OC_AndExpressionContext context) + { + // AND is a binary operator, so if we see more than 1 children, the actual statement is seem than a pass-thru + if ((context.AND()?.Length ?? 0) > 0) + { + Debug.Assert(context.oC_NotExpression().Length >= 2); + _logger?.LogVerbose("{0}: {1}", "VisitOC_AndExpression", context.GetText()); + return HandlesBinaryExpression(context, "AND") ?? throw new TranspilerInternalErrorException("Parsing two oC_NotExpression inside AND"); + } + else + { + // pass through. this is not an AND expression + return VisitChildren(context) as QueryExpression ?? throw new TranspilerInternalErrorException("Parsing oC_NotExpression"); + } + } + public override object VisitOC_NotExpression([NotNull] CypherParser.OC_NotExpressionContext context) + { + if ((context.NOT()?.Length ?? 0) > 0) + { + Debug.Assert(context.NOT().Length == 1); + _logger?.LogVerbose("{0}: {1}", "VisitOC_NotExpression", context.GetText()); + return HandlesUnaryFuncExpression(context, "NOT") ?? throw new TranspilerInternalErrorException("Parsing oC_ComparisonExpression inside NOT"); + } + else + { + // pass through. this is not an Not expression + return VisitChildren(context) as QueryExpression ?? throw new TranspilerInternalErrorException("Parsing oC_ComparisonExpression"); + } + } + public override object VisitOC_ComparisonExpression([NotNull] CypherParser.OC_ComparisonExpressionContext context) + { + // If we see PartialComparison then it is a real comparison expr, otherwise pass through + if ((context.oC_PartialComparisonExpression()?.Length ?? 0) > 0) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_ComparisonExpression", context.GetText()); + Debug.Assert(context.oC_PartialComparisonExpression().Length == 1); + + var parentExpression = new QueryExpressionBinary(); + + bool visitedLeft = false; + bool visitedRight = false; + + // get left expression + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + + if (!visitedLeft && !(child is ITerminalNode)) + { + Debug.Assert(child is CypherParser.OC_AddOrSubtractExpressionContext); + + var childExpr = Visit(child) as QueryExpression ?? throw new TranspilerSyntaxErrorException($"Expect valid left expression {child.GetText()}"); + parentExpression.LeftExpression = childExpr; + visitedLeft = true; + continue; + } + + if (!visitedRight && !(context.GetChild(i) is ITerminalNode)) + { + var result = ((string OP, QueryExpression Expr))Visit(child); + var childExpr = result.Expr as QueryExpression ?? throw new TranspilerSyntaxErrorException($"Expect valid right expression {child.GetText()}"); + var op = (string)result.OP ?? throw new TranspilerSyntaxErrorException($"Expect valid comparison operator {child.GetText()}"); + parentExpression.RightExpression = childExpr; + + var opEnum = OperatorHelper.TryGetOperator(op) + ?? throw new TranspilerSyntaxErrorException($"Unknown or unsupported operator {op}"); + parentExpression.Operator = opEnum; + visitedRight = true; + continue; + } + } + + Debug.Assert(parentExpression.LeftExpression != null && parentExpression.RightExpression != null && parentExpression.Operator != null); + return parentExpression; + } + else + { + // pass through. this is not a comparison expression + return VisitChildren(context) as QueryExpression ?? throw new TranspilerInternalErrorException("Parsing oC_AddOrSubtractExpression"); + } + } + + public override object VisitOC_PartialComparisonExpression([NotNull] CypherParser.OC_PartialComparisonExpressionContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_PartialComparisonExpression", context.GetText()); + // returns valuetuple object that (OP(string), Expr(QueryExpression)) + + bool visitedOperator = false; + bool visitedExpr = false; + string op = null; + QueryExpression expr = null; + + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + + if (!visitedOperator && child is ITerminalNode && !IsContextSP(context)) + { + op = context.GetChild(i).GetText(); + visitedOperator = true; + continue; + } + + if (!visitedExpr && !(child is ITerminalNode)) + { + expr = Visit(child) as QueryExpression ?? throw new TranspilerSyntaxErrorException($"Expect valid right expression {child.GetText()}"); + visitedExpr = true; + continue; + } + } + + Debug.Assert(visitedOperator && visitedExpr); + return (OP: op, Expr: expr); + } + + public override object VisitOC_AddOrSubtractExpression([NotNull] CypherParser.OC_AddOrSubtractExpressionContext context) + { + // + or - is a binary operator and can chain up, so if we see more than 1 children, the actual statement is seem than a pass-thru + // MultipleDeviceModulo is immediately nested inside AddOrSub due to operator priority + if ((context.oC_MultiplyDivideModuloExpression()?.Length ?? 0) > 1) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_AddOrSubtractExpression", context.GetText()); + return HandleChainedBinaryExpressions(context) ?? throw new TranspilerInternalErrorException("Parsing multiple oC_MultiplyDivideModuloExpression inside +/-"); + } + else + { + // pass through. this is not an AddOrSub chain expression + return VisitChildren(context) as QueryExpression ?? throw new TranspilerInternalErrorException("Parsing oC_MultiplyDivideModuloExpression"); + } + } + public override object VisitOC_MultiplyDivideModuloExpression([NotNull] CypherParser.OC_MultiplyDivideModuloExpressionContext context) + { + if ((context.oC_PowerOfExpression()?.Length ?? 0) > 1) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_MultiplyDivideModuloExpression", context.GetText()); + return HandleChainedBinaryExpressions(context) ?? throw new TranspilerInternalErrorException("Parsing multiple oC_PowerOfExpression inside +/-"); + } + else + { + // pass through. this is not an MultiDeviceMod chain expression + return VisitChildren(context) as QueryExpression ?? throw new TranspilerInternalErrorException("Parsing oC_PowerOfExpression"); + } + } + public override object VisitOC_PowerOfExpression([NotNull] CypherParser.OC_PowerOfExpressionContext context) + { + if ((context.oC_UnaryAddOrSubtractExpression()?.Length ?? 0) > 1) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_PowerOfExpression", context.GetText()); + return HandlesBinaryExpression(context, "^") ?? throw new TranspilerInternalErrorException("Parsing multiple oC_UnaryAddOrSubtractExpression inside +/-"); + } + else + { + // pass through. this is not a Power chain expression + return VisitChildren(context) as QueryExpression ?? throw new TranspilerInternalErrorException("Parsing oC_UnaryAddOrSubtractExpression"); + } + } + public override object VisitOC_UnaryAddOrSubtractExpression([NotNull] CypherParser.OC_UnaryAddOrSubtractExpressionContext context) + { + var supportedOperators = new string[] { "+", "-" }; + bool isUnaryAddSub = false; + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + if (child is ITerminalNode && supportedOperators.Contains(child.GetText())) + { + isUnaryAddSub = true; + break; + } + } + + if (isUnaryAddSub) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_UnaryAddOrSubtractExpression", context.GetText()); + return HandlesUnaryExpression(context) ?? throw new TranspilerInternalErrorException("Parsing oC_StringListNullOperatorExpression inside unary +/-"); + } + else + { + // pass through. this is not an MultiDeviceMod chain expression + return VisitChildren(context) as QueryExpression ?? throw new TranspilerInternalErrorException("Parsing oC_StringListNullOperatorExpression"); + } + } + + public override object VisitOC_StringListNullOperatorExpression([NotNull] CypherParser.OC_StringListNullOperatorExpressionContext context) + { + // Handles PropertyOrLabelsExpression: + // + // oC_PropertyOrLabelsExpression + // ( + // ( SP? '[' oC_Expression ']' ) | <---- Label list or range is not supported today + // ( SP? '[' oC_Expression? '..' oC_Expression? ']' ) | <---- Label list or range is not supported today + // ( ( ( SP IN ) | ( SP STARTS SP WITH ) | ( SP ENDS SP WITH ) | ( SP CONTAINS ) ) SP? oC_PropertyOrLabelsExpression ) | + // ( SP IS SP NULL ) | ( SP IS SP NOT SP NULL ) + // )* + + if (IsMatchSequence(context, "[", typeof(CypherParser.OC_ExpressionContext), "]") || + IsMatchSequence(context, "[", typeof(Optional), "..", typeof(Optional), "]")) + { + throw new TranspilerNotSupportedException($"Label list or range: {context.GetText()}"); + } + else if (context.ChildCount > 1) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_StringListNullOperatorExpression", context.GetText()); + + QueryExpression funcOrOp = null; + + // handles string operators + if ((context.IN()?.Length ?? 0) > 0) + { + // operator type for 'IN' + funcOrOp = HandlesBinaryExpression(context, "in") ?? throw new TranspilerInternalErrorException("Parsing IN statement"); + } + else + { + // other alternatives such as STARTS WITH / ENDS WITH ... , we construct as function types + var strFunc = new QueryExpressionFunction(); + + if ((context.STARTS()?.Length ?? 0) > 0 && (context.WITH()?.Length ?? 0) > 0) + { + strFunc.Function = FunctionHelper.GetFunctionInfo(Function.StringStartsWith); + } + else if ((context.ENDS()?.Length ?? 0) > 0 && (context.WITH()?.Length ?? 0) > 0) + { + strFunc.Function = FunctionHelper.GetFunctionInfo(Function.StringEndsWith); + } + else if ((context.CONTAINS()?.Length ?? 0) > 0) + { + strFunc.Function = FunctionHelper.GetFunctionInfo(Function.StringContains); + } + else if ((context.IS()?.Length ?? 0) > 0 && (context.NULL()?.Length ?? 0) > 0 && (context.NOT()?.Length ?? 0) == 0) + { + // IS NULL + strFunc.Function = FunctionHelper.GetFunctionInfo(Function.IsNull); + } + else if ((context.IS()?.Length ?? 0) > 0 && (context.NULL()?.Length ?? 0) > 0 && (context.NOT()?.Length ?? 0) > 0) + { + // IS NOT NULL + strFunc.Function = FunctionHelper.GetFunctionInfo(Function.IsNotNull); + } + else + { + throw new TranspilerNotSupportedException($"String manipulation function/operator used in {context.GetText()}"); + } + + if (strFunc.Function.RequiredParameters + strFunc.Function.OptionalParameters > 0) + { + var parameters = new List(); + + for (int i = 0; i < context.ChildCount; i++) + { + if (!(context.GetChild(i) is ITerminalNode)) + { + parameters.Add(Visit(context.GetChild(i)) as QueryExpression + ?? throw new TranspilerInternalErrorException($"Parsing oC_PropertyOrLabelsExpression inside '{strFunc.Function.FunctionName}'")); + } + } + + if (strFunc.Function.RequiredParameters > parameters.Count) + { + throw new TranspilerSyntaxErrorException($"Function {strFunc.Function.FunctionName} expects at least {strFunc.Function.RequiredParameters} parameters"); + } + if (strFunc.Function.RequiredParameters + strFunc.Function.OptionalParameters > parameters.Count) + { + throw new TranspilerSyntaxErrorException($"Function {strFunc.Function.FunctionName} expects at most {strFunc.Function.RequiredParameters + strFunc.Function.OptionalParameters} parameters"); + } + + strFunc.InnerExpression = parameters.First(); + strFunc.AdditionalExpressions = parameters.Skip(1); + } + + funcOrOp = strFunc; + } + + return funcOrOp; + } + else + { + // pass through if this is not a stringlistnulloperator expression + return VisitChildren(context) as QueryExpression ?? throw new TranspilerInternalErrorException("Parsing oC_PropertyOrLabelsExpression"); + } + } + public override object VisitOC_PropertyOrLabelsExpression([NotNull] CypherParser.OC_PropertyOrLabelsExpressionContext context) + { + // this can be a Atom.PropertyLookup or just Atom, where Atom will be some lterial/param or bunch of other operations + // we will report unhandled case if NodeLabels appears (Atom NodeLabels or Atom.PropertyLookup.NodeLabels) + // supported Atom can be Literal, Parameter, ParenthesizedExpression, Variable and FunctionInvocationm or COUNT(*) + // currently, PatternComprehension, CaseExpression, Parameter (as in Printf style of writting OC query and literals) + _logger?.LogVerbose("{0}: {1}", "VisitOC_PropertyOrLabelsExpression", context.GetText()); + + if (context.oC_NodeLabels() != null) + { + throw new TranspilerNotSupportedException($"Node labels in the expression: {context.GetText()}"); + } + + if ((context.oC_PropertyLookup()?.Length ?? 0) > 0) + { + // this is a Atom.Property look up + if (context.oC_PropertyLookup().Length > 1) + { + throw new TranspilerNotSupportedException($"Nested property lookup in '{context.GetText()}'"); + } + + // we only support direct reference to variable name for now + var propertyObj = Visit(context.oC_Atom()) as QueryExpressionProperty ?? throw new TranspilerInternalErrorException("Parsing oC_Atom"); + var propName = context.oC_PropertyLookup().First().oC_PropertyKeyName().GetText() ?? throw new TranspilerInternalErrorException("Parsing oC_PropertyLookup"); + propertyObj.PropertyName = propName; + + return propertyObj; + } + else + { + // pass through (assuming it is an expression) + return Visit(context.oC_Atom()) as QueryExpression; + } + } + public override object VisitOC_FunctionInvocation([NotNull] CypherParser.OC_FunctionInvocationContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_FunctionInvocation", context.GetText()); + + QueryExpression funcExpr = null; + bool hasDistinct = IsContextContainsTextToken(context, "DISTINCT"); + var innerExprs = new List(); + + var funcName = context.oC_FunctionName().GetText(); + + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + if (child is CypherParser.OC_ExpressionContext) + { + var result = Visit(child) as QueryExpression; + Debug.Assert(result != null); + innerExprs.Add(result); + } + } + + Debug.Assert(innerExprs.Count > 0); + + AggregationFunction func; + if (AggregationFunctionHelper.TryParse(funcName, out func)) + { + // aggregation function + funcExpr = new QueryExpressionAggregationFunction() + { + AggregationFunction = func, + InnerExpression = innerExprs.First(), + IsDistinct = hasDistinct, + }; + + if (innerExprs.Count > 1) + { + throw new TranspilerSyntaxErrorException($"Aggregation function '{func}' with more than 1 parameters"); + } + } + else + { + // non aggregaton function + if (hasDistinct) + { + throw new TranspilerSyntaxErrorException($"Function '{funcName}' does not support 'DISTINCT' modifier"); + } + + var funcInfo = FunctionHelper.TryGetFunctionInfo(funcName) + ?? throw new TranspilerNotSupportedException($"Function: {funcName}"); + + funcExpr = new QueryExpressionFunction() + { + Function = funcInfo, + InnerExpression = innerExprs.First(), + AdditionalExpressions = innerExprs.Count > 1 ? innerExprs.Skip(1) : null + }; + } + + return funcExpr; + } + + public override object VisitOC_CaseExpression([NotNull] CypherParser.OC_CaseExpressionContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_CaseExpression", context.GetText()); + var caseNodeVisited = false; + var elseNodeVisited = false; + var childCount = context.ChildCount; + var caseExpression = new QueryExpressionCaseExpression(); + var caseAlterExprs = new List(); + if (childCount > 0) + { + for (int i = 0; i < childCount; i++) + { + // TODO: Add logic to handle case expresion + + var child = context.GetChild(i); + if (child.GetText().ToUpper() == "CASE") + { + caseNodeVisited = true; + } + else if (child.GetText().ToUpper() == "ELSE") + { + elseNodeVisited = true; + } + else if (child is CypherParser.OC_ExpressionContext) + { + if (caseNodeVisited && !elseNodeVisited) + { + var initialCondition = Visit(child) as QueryExpression; + throw new TranspilerNotSupportedException($"Please use Case When then format.{context.GetText()} ..."); + } + else if (elseNodeVisited) + { + var elseCondition = Visit(child) as QueryExpression; + caseExpression.ElseExpression = elseCondition; + } + else + { + throw new TranspilerInternalErrorException($"Unexpected blob in CASE expression: {child.GetText()}"); + } + } + else if (child is CypherParser.OC_CaseAlternativesContext) + { + caseAlterExprs.AddRange(Visit(child) as List); + } + else + { + // passing through other cases + } + } + } + caseExpression.CaseAlternatives = caseAlterExprs; + + + return caseExpression; + + } + public override object VisitOC_CaseAlternatives([NotNull] CypherParser.OC_CaseAlternativesContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_CaseAlternatives", context.GetText()); + + var childCount = context.ChildCount; + var caseAlternatives = new List(); + var isWhenState = false; + var isThenState = false; + + if (childCount > 0) + { + var caseAlterExpr = new QueryExpressionCaseAlternative(); + for (int i = 0; i < childCount; i++) + { + var child = context.GetChild(i); + if (child.GetText().ToUpper() == "WHEN") + { + isWhenState = true; + isThenState = false; + } + else if (child.GetText().ToUpper() == "THEN") + { + isWhenState = false; + isThenState = true; + } + else if (child is CypherParser.OC_ExpressionContext) + { + var expr = Visit(child) as QueryExpression; + if (isWhenState && !isThenState) + { + caseAlterExpr.WhenExpression = expr; + } + else if (!isWhenState && isThenState) + { + caseAlterExpr.ThenExpression = expr; + caseAlternatives.Add(caseAlterExpr); + caseAlterExpr = new QueryExpressionCaseAlternative(); + } + } + } + } + + return caseAlternatives; + } + + public override object VisitOC_Variable([NotNull] CypherParser.OC_VariableContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_Variable", context.GetText()); + // directly return text inside as variable name + return context.GetText(); + } + + public override object VisitOC_SchemaName([NotNull] CypherParser.OC_SchemaNameContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_SchemaName", context.GetText()); + // directly return text inside as schema name + return context.GetText(); + } + + public override object VisitOC_FunctionName([NotNull] CypherParser.OC_FunctionNameContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_FunctionName", context.GetText()); + // TODO: verify if a function is supported or not + // directly return text inside as function name + return context.GetText(); + } + + public override object VisitOC_Atom([NotNull] CypherParser.OC_AtomContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_Atom", context.GetText()); + + // returns a QueryExpression type + + if (context.oC_Variable() != null) + { + // this is variable reference. We treat it as either property or alias + return new QueryExpressionProperty() + { + VariableName = context.GetText(), + }; + } + else if ( + context.oC_Literal() != null || + context.oC_FunctionInvocation() != null || + context.oC_ParenthesizedExpression() != null || + context.oC_CaseExpression() != null + + ) + { + Debug.Assert(context.ChildCount == 1); + var result = Visit(context.GetChild(0)) as QueryExpression; + Debug.Assert(result != null); + return result; + } + else + { + // currently not supported: + // - oC_ListComprehension + // - oC_PatternComprehension + // - oC_RelationshipsPattern + // - COUNT * + // - FILTER / EXTRACT / ALL / ANY / NONE / SINGLE + throw new TranspilerNotSupportedException($"Expression '{context.GetText()}'"); + } + } + + public override object VisitOC_ParenthesizedExpression([NotNull] CypherParser.OC_ParenthesizedExpressionContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_ParenthesizedExpression", context.GetText()); + Debug.Assert(context.oC_Expression() != null); + return Visit(context.oC_Expression()) as QueryExpression ?? throw new TranspilerInternalErrorException("Parsing oC_Expression"); + } + + public override object VisitOC_Literal([NotNull] CypherParser.OC_LiteralContext context) + { + if (context.StringLiteral() != null) + { + _logger?.LogVerbose("{0}: {1}: {2}", "VisitOC_Literal", "STRING", context.GetText()); + + // cypher literal has single quote around it, removing it + var quotedText = context.StringLiteral().GetText(); + var quoteChar = quotedText[0]; + string unescapedRawText; + + if (quotedText.Last() != quoteChar || quotedText.Length < 2) + { + throw new TranspilerSyntaxErrorException($"Unrecognized string literal format: {quotedText}, expecting ' or \"."); + } + + if (quoteChar == '\'') + { + unescapedRawText = quotedText.Substring(1, quotedText.Length - 2).Replace("''", "'").Replace("\\\\", "\\"); + } + else if (quoteChar == '"') + { + unescapedRawText = quotedText.Substring(1, quotedText.Length - 2).Replace("\"\"", "\"").Replace("\\\\", "\\"); + } + else + { + throw new TranspilerSyntaxErrorException($"Unrecognized string literal format: {quotedText}, expecting ' or \"."); + } + + return new QueryExpressionValue() + { + Value = unescapedRawText + }; + } + else if (context.oC_BooleanLiteral() != null || context.oC_NumberLiteral() != null || context.oC_ListLiteral() != null) + { + // pass through for oC_* literals that are supported + return VisitChildren(context); + } + else + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_Literal", context.GetText()); + throw new TranspilerNotSupportedException($"Literal: {context.GetText()}"); + } + } + public override object VisitOC_BooleanLiteral([NotNull] CypherParser.OC_BooleanLiteralContext context) + { + if (context.TRUE() != null || context.FALSE() != null) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_BooleanLiteral", context.GetText()); + var booleanText = context.GetText(); + return new QueryExpressionValue() + { + Value = bool.Parse(booleanText) + }; + } + else + { + // pass through: it is not boolean literal but some other type of literal + _logger?.LogVerbose("{0}: {1}", "VisitOC_BooleanLiteral", context.GetText()); + return VisitChildren(context); + } + } + public override object VisitOC_ListLiteral([NotNull] CypherParser.OC_ListLiteralContext context) + { + if (context.oC_Expression() != null) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_ListLiteral", context.GetText()); + var childExps = new List(); + foreach (var child in context.oC_Expression()) + { + var exp = Visit(child) as QueryExpression ?? throw new TranspilerInternalErrorException("Parsing oC_Expression"); + childExps.Add(exp); + } + return new QueryExpressionList() + { + ExpressionList = childExps + }; + } + else + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_ListLiteral", context.GetText()); + // pass through if current type is not a list literal + return VisitChildren(context) as QueryExpressionValue; + } + } + public override object VisitOC_NumberLiteral([NotNull] CypherParser.OC_NumberLiteralContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_NumberLiteral", context.GetText()); + // return QueryExpressionLiteral (pass through) + return VisitChildren(context) as QueryExpressionValue; + } + public override object VisitOC_IntegerLiteral([NotNull] CypherParser.OC_IntegerLiteralContext context) + { + // one of the Integer rep has to be non-null as guaranteed by the Cypher g4 syntax + Debug.Assert(context.HexInteger() != null || context.OctalInteger() != null || context.DecimalInteger() != null); + + _logger?.LogVerbose("{0}: {1}", "VisitOC_IntegerLiteral", context.GetText()); + var intText = context.GetChild(0).GetText(); + return new QueryExpressionValue() + { + // TODO: improve the parsing for int number intead of using the C# built int default parser + Value = long.Parse(intText) + }; + } + public override object VisitOC_DoubleLiteral([NotNull] CypherParser.OC_DoubleLiteralContext context) + { + // one of the Real rep has to be non-null as guaranteed by the Cypher g4 syntax + Debug.Assert(context.ExponentDecimalReal() != null || context.RegularDecimalReal() != null); + _logger?.LogVerbose("{0}: {1}", "VisitOC_DoubleLiteral", context.GetText()); + var numberText = context.GetChild(0).GetText(); + return new QueryExpressionValue() + { + // TODO: improve the parsing for real number intead of using the C# built int default parser + Value = double.Parse(numberText) + }; + } + public override object VisitOC_RangeLiteral([NotNull] CypherParser.OC_RangeLiteralContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_RangeLiteral", context.GetText()); + throw new TranspilerNotSupportedException("Range literal"); + } + public override object VisitOC_MapLiteral([NotNull] CypherParser.OC_MapLiteralContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_MapLiteral", context.GetText()); + throw new TranspilerNotSupportedException("Map literal"); + } + public override object VisitOC_Order([NotNull] CypherParser.OC_OrderContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_Order", context.GetText()); + + Debug.Assert(context.oC_SortItem() != null); + var queryExprsOrderBy = new List(); + + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + if (child is CypherParser.OC_SortItemContext && child != null) + { + var queryExpr = Visit(child) as QueryExpressionOrderBy; + queryExprsOrderBy.Add(queryExpr); + } + } + + return queryExprsOrderBy; + } + public override object VisitOC_SortItem([NotNull] CypherParser.OC_SortItemContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_SortItem", context.GetText()); + + var expr = Visit(context.oC_Expression()) as QueryExpression; + bool isDescending = IsContextContainsTextToken(context, "DESC") || IsContextContainsTextToken(context, "DESCENDING"); + string alias = expr.GetChildrenQueryExpressionType().First().VariableName; + return new QueryExpressionOrderBy() + { + IsDescending = isDescending, + InnerExpression = expr, + Alias = alias, + }; + } + public override object VisitOC_Limit([NotNull] CypherParser.OC_LimitContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_Limit", context.GetText()); + var exprLimit = new QueryExpressionLimit(); + if (context.oC_Expression() != null) + { + var expr = Visit(context.oC_Expression()) as QueryExpression; + exprLimit.RowCount = expr.GetChildrenQueryExpressionType().First().IntValue; + } + return exprLimit; + } + public override object VisitOC_ReturnBody([NotNull] CypherParser.OC_ReturnBodyContext context) + { + _logger?.LogVerbose("{0}: {1}", "VisitOC_ReturnBody", context.GetText()); + // add specific implementation about visiting return body + + var aliasList = new List(); + var orderList = new List(); + var limitList = new List(); + for (int i = 0; i < context.ChildCount; i++) + { + var child = context.GetChild(i); + + if (child is CypherParser.OC_ReturnItemsContext) + { + var aliasResult = Visit(child) as IList; + aliasList.AddRange(aliasResult); + } + else if (child is CypherParser.OC_OrderContext) + { + var orderResult = Visit(child) as IList; + orderList.AddRange(orderResult); + } + else if (child is CypherParser.OC_LimitContext) + { + var limitResult = Visit(child) as QueryExpressionLimit; + limitList.Add(limitResult); + } + } + return ( + ReturnItems: aliasList as IList, + OrderByItems: orderList as IList, + LimitItems: limitList as IList); + } + + } + +} diff --git a/src/openCypherParser/AST/MatchDataSource.cs b/src/openCypherParser/AST/MatchDataSource.cs new file mode 100644 index 0000000..a873dc2 --- /dev/null +++ b/src/openCypherParser/AST/MatchDataSource.cs @@ -0,0 +1,190 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using System.Collections.Generic; +using System.Linq; +using openCypherTranspiler.Common.Exceptions; + +namespace openCypherTranspiler.openCypherParser.AST +{ + /// + /// represents the parsed group of matched patterns + /// + public class MatchDataSource : TreeNode + { + #region Implements TreeNode + protected override IEnumerable Children + { + get + { + return Enumerable.Empty(); + } + } + #endregion Implements TreeNode + + /// + /// Return all the entities refered by the Match statement + /// with the same order it appears + /// + public IList AllEntitiesOrdered + { + get + { + // can't use SelectMany if it doesn't guarantee order + // MatchPatterns?.SelectMany(p => p) ?? Enumerable.Empty(); + return MatchPatterns?.Aggregate(new List(), (p, l) => { p.AddRange(l); return p; }) ?? new List(0); + } + } + + /// + /// A list of match patterns: + /// e.g. (a:device)-[]->( + /// + public IList MatchPatterns { get; set; } + + /// + /// Return a new MatchDataSource mirrors the old one but with anonymous entities filled with + /// a place holder alias + /// + /// + /// + public MatchDataSource AssignGeneratedEntityAliasToAnonEntities(string anonVarPrefix) + { + var varIdx = 0; + var existingAliases = new HashSet(MatchPatterns.SelectMany(p => p.Select(e => e.Alias)).Where(a => !string.IsNullOrEmpty(a)).Distinct()); + + if (existingAliases.Any(p => p.StartsWith(anonVarPrefix))) + { + throw new TranspilerSyntaxErrorException($"Banned prefix for variable aliases: {anonVarPrefix}. Please consider a different prefix."); + } + + // creating a new DS with implied labels fixed up + var matchDsNew = new MatchDataSource() + { + MatchPatterns = MatchPatterns.Select(p => new MatchPattern(p.IsOptionalMatch, p.Select(e => + { + var alias = e.Alias ?? $"{anonVarPrefix}{varIdx++}"; + var entity = e.Clone(); + entity.Alias = alias; + return entity; + }))).ToList() + }; + + return matchDsNew; + } + + + public override string ToString() + { + return $"Matches: Count={MatchPatterns?.Count ?? 0}, Patterns={string.Join(" ", MatchPatterns)}"; + } + } + + /// + /// A single match pattern is a traversal of entities (node and relationships) + /// + public class MatchPattern : List, IList + { + public MatchPattern(bool isOptional, IEnumerable list) : base(list) + { + IsOptionalMatch = isOptional; + } + + public bool IsOptionalMatch { get; set; } + + public override string ToString() + { + return $"MatchPat: IsOptional={IsOptionalMatch}; Pattern={string.Join(",", this)}"; + } + } + + /// + /// Represents an entity of either node or edge + /// + public abstract class Entity + { + /// + /// Name of the entity, for edge this is just verb of the edge + /// + public string EntityName { get; set; } + + /// + /// Alias used for refering the entity + /// + public string Alias { get; set; } + + /// + /// Make a deep copy of the derived class of this type + /// + /// + public abstract Entity Clone(); + } + + public class NodeEntity : Entity + { + public override Entity Clone() + { + return new NodeEntity() + { + Alias = this.Alias, + EntityName = this.EntityName + }; + } + + public override string ToString() + { + return $"({Alias}:{EntityName})"; + } + } + + /// + /// Edge is not unique by its verb during binding but depends on the node it connects + /// E.g. (:device)-[:runs]-(:app) + /// so we capture the in node (left) and out node of this edge (right) + /// + public class RelationshipEntity : Entity + { + public enum Direction + { + Both, // -[]- + Forward, // -[]-> + Backward // <-[]- + } + + + /// + /// Left side node entity's name + /// Note that 'left' here the lexical order and not refelcting the direction + /// + public string LeftEntityName { get; set; } + + /// + /// Right side node entity's name + /// Note that 'right' here the lexical order and not refelcting the direction + /// + public string RightEntityName { get; set; } + + public override Entity Clone() + { + return new RelationshipEntity() + { + Alias = this.Alias, + EntityName = this.EntityName, + RelationshipDirection = this.RelationshipDirection, + LeftEntityName = this.LeftEntityName, + RightEntityName = this.RightEntityName, + }; + } + /// + /// Name of the entity, for edge this is just verb of the edge + /// + public Direction RelationshipDirection { get; set; } + + public override string ToString() + { + return $"{LeftEntityName}{(RelationshipDirection == Direction.Backward ? "<" : "")}-[{Alias}:{EntityName}]-{(RelationshipDirection == Direction.Forward ? ">" : "")}{RightEntityName}"; + } + } +} diff --git a/src/openCypherParser/AST/QueryExpression.cs b/src/openCypherParser/AST/QueryExpression.cs new file mode 100644 index 0000000..92326d2 --- /dev/null +++ b/src/openCypherParser/AST/QueryExpression.cs @@ -0,0 +1,638 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using openCypherTranspiler.Common.Exceptions; +using openCypherTranspiler.Common.Utils; +using openCypherTranspiler.openCypherParser.Common; + +namespace openCypherTranspiler.openCypherParser.AST +{ + /// + /// represents an expression appears in Graph Query language + /// + public abstract class QueryExpression : TreeNode + { + /// + /// Traversal helper to retrieve query expression of certain type + /// + /// + /// + public IEnumerable GetChildrenQueryExpressionType() where T : QueryExpression + { + return GetChildrenOfType(); + } + + /// + /// Compute the result's data type of the expression + /// + /// + abstract public Type EvaluateType(); + } + + /// + /// represents a expression with an explicit alias, e.g. a AS b + /// + public class QueryExpressionWithAlias : QueryExpression + { + #region Implements TreeNode + protected override IEnumerable Children + { + get + { + return new List() { InnerExpression }; + } + } + #endregion Implements TreeNode + + public QueryExpression InnerExpression { get; set; } + public string Alias { get; set; } + + public override string ToString() + { + return $"ExprWithAlias: {Alias}"; + } + + public override Type EvaluateType() + { + return InnerExpression.EvaluateType(); + } + } + + /// + /// represents a binary (a + b, or a = b, or a <= b) operation + /// + public partial class QueryExpressionBinary : QueryExpression + { + #region Implements TreeNode + protected override IEnumerable Children + { + get + { + return new List() { LeftExpression, RightExpression }; + } + } + #endregion Implements TreeNode + + public BinaryOperatorInfo Operator { get; set; } + public QueryExpression LeftExpression { get; set; } + public QueryExpression RightExpression { get; set; } + + public override string ToString() + { + return $"ExprBinary: Op='{Operator}'"; + } + + public override Type EvaluateType() + { + var leftType = LeftExpression.EvaluateType(); + var rightType = RightExpression.EvaluateType(); + var leftTypeUnboxed = TypeHelper.GetUnderlyingTypeIfNullable(leftType); + var rightTypeUnboxed = TypeHelper.GetUnderlyingTypeIfNullable(rightType); + var anyNullable = TypeHelper.IsSystemNullableType(leftType) || TypeHelper.IsSystemNullableType(rightType); + Type resultedTypeRaw; + + switch (Operator.Type) + { + case BinaryOperatorType.Logical: + // For logical comparison, we ensure that all operands' type are logical already + // The return type is always boolean (logical) + if (leftType != typeof(bool) || leftType != typeof(bool?) && + rightType != typeof(bool) || rightType != typeof(bool?)) + { + throw new TranspilerNotSupportedException($"Logical binary operator {Operator} operating must operate on bool types. Actual types: {leftType}, {rightType}"); + } + return (anyNullable ? TypeHelper.MakeNullableIfNotAlready(typeof(bool)) : typeof(bool)); + + case BinaryOperatorType.Value: + // For value type operator, use the value type coercion table + if (!CoersionTables.CoersionTableForValueType.TryGetValue((Operator.Name, leftTypeUnboxed, rightTypeUnboxed), out resultedTypeRaw)) + { + throw new TranspilerInternalErrorException($"Unexpected use of binary operator {Operator.Name} operating between types {leftTypeUnboxed} and {rightTypeUnboxed}"); + } + if (resultedTypeRaw == default(Type)) + { + throw new TranspilerNotSupportedException($"Binary operator {Operator.Name} operating between types {leftTypeUnboxed} and {rightTypeUnboxed}"); + } + return (anyNullable ? TypeHelper.MakeNullableIfNotAlready(resultedTypeRaw) : resultedTypeRaw); + + case BinaryOperatorType.Comparison: + // For comparison operators, use the equality/inequality type coercion table + if (Operator.Name == BinaryOperator.EQ || Operator.Name == BinaryOperator.NEQ) + { + if (!CoersionTables.CoersionTableEqualityComparison.TryGetValue((leftTypeUnboxed, rightTypeUnboxed), out resultedTypeRaw)) + { + throw new TranspilerInternalErrorException($"Unexpected use of binary operator {Operator.Name} operating between types {leftTypeUnboxed} and {rightTypeUnboxed}"); + } + } + else + { + if (!CoersionTables.CoersionTableInequalityComparison.TryGetValue((leftTypeUnboxed, rightTypeUnboxed), out resultedTypeRaw)) + { + throw new TranspilerInternalErrorException($"Unexpected use of binary operator {Operator.Name} operating between types {leftTypeUnboxed} and {rightTypeUnboxed}"); + } + } + if (resultedTypeRaw == default(Type)) + { + throw new TranspilerNotSupportedException($"Binary operator {Operator.Name} operating between types {leftTypeUnboxed} and {rightTypeUnboxed}"); + } + return (anyNullable ? TypeHelper.MakeNullableIfNotAlready(resultedTypeRaw) : resultedTypeRaw); + + case BinaryOperatorType.Invalid: + default: + throw new TranspilerInternalErrorException($"Unexpected operator type: {Operator.Type}"); + } + } + + } + + /// + /// represents a function call, like toFloat(expr) + /// + public class QueryExpressionFunction : QueryExpression + { + #region Implements TreeNode + protected override IEnumerable Children + { + get + { + return new List() { InnerExpression }; + } + } + #endregion Implements TreeNode + + public FunctionInfo Function { get; set; } + + public QueryExpression InnerExpression { get; set; } + + public IEnumerable AdditionalExpressions { get; set; } + + public override string ToString() + { + return $"ExprFunc: {Function}(a)"; + } + + public override Type EvaluateType() + { + var innerType = InnerExpression.EvaluateType(); + var isWrappedinNullable = TypeHelper.IsSystemNullableType(innerType); + switch (Function.FunctionName) + { + case Common.Function.ToFloat: + return isWrappedinNullable ? typeof(float?) : typeof(float); + case Common.Function.ToString: + return typeof(string); + case Common.Function.ToBoolean: + return isWrappedinNullable ? typeof(bool?) : typeof(bool); + case Common.Function.ToInteger: + return isWrappedinNullable ? typeof(int?) : typeof(int); + case Common.Function.ToDouble: + return isWrappedinNullable ? typeof(long?) : typeof(long); + case Common.Function.ToLong: + return isWrappedinNullable ? typeof(double?) : typeof(double); + case Common.Function.Not: + return isWrappedinNullable ? typeof(bool?) : typeof(bool); + case Common.Function.StringContains: + case Common.Function.StringStartsWith: + case Common.Function.StringEndsWith: + case Common.Function.IsNull: + case Common.Function.IsNotNull: + return typeof(bool); + case Common.Function.StringSize: + return typeof(int); + default: + // treat all the rest as type preserving, e.g. + // trim, ltrim .... + return InnerExpression.EvaluateType(); + } + } + + } + + /// + /// represents a aggregation function call, like avg(expr) + /// + public partial class QueryExpressionAggregationFunction : QueryExpression + { + #region Implements TreeNode + protected override IEnumerable Children + { + get + { + return new List() { InnerExpression }; + } + } + #endregion Implements TreeNode + + public AggregationFunction AggregationFunction { get; set; } + public bool IsDistinct { get; set; } + public QueryExpression InnerExpression { get; set; } + + public override string ToString() + { + return $"ExprAggFunc: {AggregationFunction}(a)"; + } + + public override Type EvaluateType() + { + var innerType = InnerExpression.EvaluateType(); + var innerTypeUnboxed = TypeHelper.GetUnderlyingTypeIfNullable(innerType); + + Type resultedType; + if (!AggregationFunctionReturnTypeTable.TypeMapTable.TryGetValue((AggregationFunction, innerTypeUnboxed), out resultedType)) + { + // for any aggregation function that were not having specially handling, then it is considered to preserve the original type + return innerType; + } + + return resultedType; + } + } + + /// + /// represents a reference to a property (column), e.g. r.Score + /// + public class QueryExpressionProperty : QueryExpression + { + #region Implements TreeNode + protected override IEnumerable Children + { + get + { + return Enumerable.Empty(); + } + } + #endregion Implements TreeNode + + /// + /// For a property reference, this is the variable part, namely alias of alias.field + /// + public string VariableName { get; set; } + + /// + /// For a property reference, this is the property part, namely alias of alias.field + /// + public string PropertyName { get; set; } + + + /// + /// For a node/relationship, this is the entity type reference + /// + /// + /// + public Entity Entity { get; set; } + + /// + /// For a single field, this is the data type + /// + /// + /// + public Type DataType { get; set; } + + public override string ToString() + { + if (Entity != null) + { + return $"ExprProperty: {VariableName} {Entity}"; + } + else + { + return $"ExprProperty: {VariableName}.{PropertyName}"; + } + } + public override Type EvaluateType() + { + return DataType; + } + + } + + /// + /// represent a list of expressions + /// + public class QueryExpressionList : QueryExpression + { + #region Implements TreeNode + protected override IEnumerable Children + { + get + { + return ExpressionList.Cast(); + } + } + #endregion Implements TreeNode + + public IList ExpressionList { get; set; } + + public override Type EvaluateType() + { + var types = ExpressionList?.Select(p => p.EvaluateType()).Distinct(); + if (types.Count() == 1) + { + return typeof(IEnumerable<>).MakeGenericType(types.First()); + } + else + { + return typeof(IEnumerable); + } + } + } + + /// + /// represents a literal value, such as a string, or number + /// + public class QueryExpressionValue : QueryExpression + { + #region Implements TreeNode + protected override IEnumerable Children + { + get + { + return Enumerable.Empty(); + } + } + #endregion Implements TreeNode + + private object _value; + + /// + /// Holding the object value in a supported value-type + /// + public object Value + { + get + { + return _value; + } + set + { + if (!(value is string || + value is bool || + value is int || + value is long || + value is float || + value is double || + value is DateTime)) + { + throw new TranspilerNotSupportedException($"Type {value.GetType()}"); + } + _value = value; + } + } + + public Type ValueType + { + get + { + return Value.GetType(); + } + } + public bool BoolValue + { + get + { + return (Value is bool ? (bool)Value : Convert.ToBoolean(Value)); + } + set + { + Value = value; + } + } + public int IntValue + { + get + { + return (Value is int ? (int)Value : Convert.ToInt32(Value)); + } + set + { + Value = value; + } + } + public long LongValue + { + get + { + return (Value is long ? (long)Value : Convert.ToInt64(Value)); + } + set + { + Value = value; + } + } + public double DoubleValue + { + get + { + return (Value is double ? (double)Value : Convert.ToDouble(Value)); + } + set + { + Value = value; + } + } + public DateTime DateTimeValue + { + get + { + return (Value is DateTime ? (DateTime)Value : Convert.ToDateTime(Value)); + } + set + { + Value = value; + } + } + public string StringValue + { + get + { + return (Value is string ? (string)Value : Value.ToString()); + } + set + { + Value = value; + } + } + + public override string ToString() + { + return $"ExprValue: t='{Value?.GetType()}'; v='{Value?.ToString()}'"; + } + + public override Type EvaluateType() + { + return ValueType; + } + } + + public class QueryExpressionOrderBy : QueryExpression + { + #region Implements TreeNode + protected override IEnumerable Children + { + get + { + return new List() { InnerExpression }; + } + } + #endregion Implements TreeNode + + public QueryExpression InnerExpression { get; set; } + + /// + /// indicator for sorting orders + /// + public bool IsDescending { get; set; } + + /// + /// sorting keys + /// + public string Alias { get; set; } + + public override string ToString() + { + return $"ExprOrderBy: {InnerExpression.GetChildrenQueryExpressionType().First().VariableName}"; + } + + public override Type EvaluateType() + { + return InnerExpression.EvaluateType(); + } + + } + public class QueryExpressionLimit : QueryExpression + { + #region Implements TreeNode + protected override IEnumerable Children + { + get + { + return new List() { InnerExpression }; + } + } + #endregion Implements TreeNode + + public QueryExpression InnerExpression { get; set; } + + /// + /// stores how many rows to keep in "LIMIT" clause + /// + public int RowCount { get; set; } + + public override string ToString() + { + return $"ExprLimit: {InnerExpression.GetChildrenQueryExpressionType().First().VariableName}"; + } + + public override Type EvaluateType() + { + return InnerExpression.EvaluateType(); + } + + } + + public class QueryExpressionCaseExpression : QueryExpression + { + #region Implements TreeNode + protected override IEnumerable Children + { + get + { + return new List() { InitialCaseExpression, ElseExpression }.Union(CaseAlternatives).Where(n => n != null); + } + } + #endregion Implements TreeNode + + // For "CASE" part in the case expression + public QueryExpression InitialCaseExpression { get; set; } + + // For :"WHEN ... THEN" part in the case expression + // Can be null if "WHEN ... THEN ..." not specified in the query + public List CaseAlternatives { get; set; } + + // For"ELSE ..." part in the case expression + public QueryExpression ElseExpression { get; set; } + + public override string ToString() + { + return $"CaseExpr: Case when {CaseAlternatives.ToString()} Else:{ElseExpression}"; + } + + public override Type EvaluateType() + { + var hasElseExpression = (ElseExpression != null); + var distinctTypes = hasElseExpression ? + CaseAlternatives.Select(n => n.EvaluateType()) + .Union(new List { ElseExpression.EvaluateType() }) + .Distinct() : + CaseAlternatives.Select(n => n.EvaluateType()) + .Distinct(); + var anyNullable = distinctTypes.Any(t => TypeHelper.IsSystemNullableType(t)) + // when Else statement is not provided resulting type becomes automatically nullable + || !hasElseExpression; + var distinctUnboxedTypes = distinctTypes + .Select(t => TypeHelper.GetUnderlyingTypeIfNullable(t)).Distinct(); + + Type resultUnboxedType; + if (distinctUnboxedTypes.Count() > 1) + { + // During parsing, type evalution allows the max extent of type coercion + // which is what a + operator would do + resultUnboxedType = distinctUnboxedTypes.Aggregate((resType, nextType) => + { + Type resultedTypeRaw; + if (!CoersionTables.CoersionTableForValueType.TryGetValue((BinaryOperator.Plus, resType, nextType), out resultedTypeRaw)) + { + throw new TranspilerInternalErrorException($"Unexpected use of CASE WHEN operating between types {resType} and {nextType}"); + } + if (resultedTypeRaw == default(Type)) + { + throw new TranspilerNotSupportedException($"Case WHEN operating between types {resType} and {nextType}"); + } + return resultedTypeRaw; + }); + } + else + { + resultUnboxedType = distinctUnboxedTypes.First(); + } + + return (anyNullable ? TypeHelper.MakeNullableIfNotAlready(resultUnboxedType) : resultUnboxedType); + } + } + + public class QueryExpressionCaseAlternative : QueryExpression + { + #region Implements TreeNode + protected override IEnumerable Children + { + get + { + return new List() { WhenExpression, ThenExpression }; + } + } + #endregion Implements TreeNode + + public QueryExpression WhenExpression { get; set; } + public QueryExpression ThenExpression { get; set; } + + public override string ToString() + { + return $"ExprCaseAlter: when ->{WhenExpression.ToString()} Then -> {ThenExpression.ToString()}"; + } + + public override Type EvaluateType() + { + return ThenExpression.EvaluateType(); + } + + + } + + +} diff --git a/src/openCypherParser/AST/QueryExpressionHelper.cs b/src/openCypherParser/AST/QueryExpressionHelper.cs new file mode 100644 index 0000000..694011f --- /dev/null +++ b/src/openCypherParser/AST/QueryExpressionHelper.cs @@ -0,0 +1,28 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using openCypherTranspiler.openCypherParser.AST; + +namespace openCypherTranspiler.openCypherParser.AST +{ + public static class QueryExpressionHelper + { + /// + /// If expr is a direct return of an entity, return it, otherwise, return null + /// + /// + /// + public static Entity TryGetDirectlyExposedEntity(this QueryExpression expr) + { + if (expr is QueryExpressionProperty) + { + var queryEntityExpr = expr as QueryExpressionProperty; + var entity = queryEntityExpr.Entity; + return entity; + } + return null; + } + } +} diff --git a/src/openCypherParser/AST/QueryTreeNode.cs b/src/openCypherParser/AST/QueryTreeNode.cs new file mode 100644 index 0000000..0bdc092 --- /dev/null +++ b/src/openCypherParser/AST/QueryTreeNode.cs @@ -0,0 +1,170 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +namespace openCypherTranspiler.openCypherParser.AST +{ + /// + /// holds a query or a union of sub queires + /// + public abstract class QueryTreeNode : TreeNode + { + } + + /// + /// represents union of leaf-node queries: multiple queries can be unioned or unioned_all together + /// + public class InfixQueryTreeNode : QueryTreeNode + { + #region Implements TreeNode + protected override IEnumerable Children + { + get + { + return new List() { LeftQueryTreeNode, RightQueryTreeNode }; + } + } + #endregion Implements TreeNode + + public enum QueryOperator + { + Union, // dup removal + UnionAll, // no dup removal + } + + public QueryOperator Operator { get; set; } + public QueryTreeNode LeftQueryTreeNode { get; set; } + public QueryTreeNode RightQueryTreeNode { get; set; } + + public override string ToString() + { + return $"QueryInfix: {Operator}"; + } + } + + /// + /// the final part of the query that has raw or nested input, conditions and output + /// + public class SingleQueryTreeNode : QueryTreeNode + { + #region Implements TreeNode + protected override IEnumerable Children + { + get + { + return new List() { PipedData } + .Union(EntityPropertySelected.Cast()) + .Union(EntityPropertyOrderBy??new List()) + .Union(EntityRowsLimit??new List()) + .Where(p => p != null); + } + } + #endregion Implements TreeNode + + /// + /// The input of the query. Can be either graph data (from a match statement) or output from an intermediate query + /// + public PartialQueryTreeNode PipedData { get; set; } + + /// + /// Expressions in the return or with + /// + public IList EntityPropertySelected { get; set; } + + /// + /// If return is called with DISTINCT modifier + /// + public bool IsDistinct { get; set; } + + /// + /// Order by items in return or in with clause + /// + public IList EntityPropertyOrderBy { get; set; } + + /// + /// For "LIMIT" modifier, holding numbers of rows to be selected in the data + /// + public IList EntityRowsLimit { get; set; } + public override string ToString() + { + return $"QuerySingle: Props={string.Join(",", EntityPropertySelected.Select(p => p.Alias))}; Distinct={IsDistinct} ;OrderBy={string.Join(",", EntityPropertyOrderBy?.Select(p => p.Alias))} ; Limit={string.Join(",", EntityRowsLimit?.Select(p => p.RowCount))} "; + } + } + + /// + /// represents match/querypart / match/querypart-with / match/querypart-with-where / match/querypart/where-with-where + /// + public class PartialQueryTreeNode : TreeNode + { + #region Implements TreeNode + protected override IEnumerable Children + { + get + { + return new List() { PipedData, MatchData } + .Union(ProjectedExpressions) + .Union(new List() { PostCondition}) + .Union(OrderByExpression??new List()) + .Union(LimitExpression??new List()) + .Where(p => p != null); + } + } + #endregion Implements TreeNode + + /// + /// represents the data flow from previous partial query in the chain + /// + public PartialQueryTreeNode PipedData { get; set; } + + /// + /// represents the (additional) match statements + /// + public MatchDataSource MatchData { get; set; } + + /// + /// the attributes/entities to be returned to next part of the query chain + /// + public IList ProjectedExpressions { get; set; } + + /// + /// Indicate if this query part has no WITH (hence the ProjectedExpressions are implied to be return all aliased nodes) + /// + public bool IsImplicitProjection { get; set; } + + /// + /// the attributes/entities to be returned to next part of the query chain + /// + public bool IsDistinct { get; set; } + + /// + /// if the next query part can be a non-optional match or not + /// + public bool CanChainNonOptionalMatch { get; set; } + + /// + /// query conditions post projection + /// + public QueryExpression PostCondition { get; set; } + + /// + /// ORDER BY under WITH statement + /// + public IList OrderByExpression { get; set; } + /// + /// LIMIT N under WITH statement + /// + public IList LimitExpression { get; set; } + + public override string ToString() + { + return $"QueryPart: HasMatch={MatchData != null}; IsImplicitProj={IsImplicitProjection}; HasCond={PostCondition != null}; Props={string.Join(",", ProjectedExpressions?.Select(p => p.Alias))}, Distinct={IsDistinct}, HasOrderBy={OrderByExpression!= null}, HasLimit = {LimitExpression != null}"; + } + } + +} diff --git a/src/openCypherParser/AST/TreeNode.cs b/src/openCypherParser/AST/TreeNode.cs new file mode 100644 index 0000000..6af1592 --- /dev/null +++ b/src/openCypherParser/AST/TreeNode.cs @@ -0,0 +1,53 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using System.Collections.Generic; +using System.Linq; +using System.Text; +using openCypherTranspiler.Common.Utils; + +namespace openCypherTranspiler.openCypherParser.AST +{ + public abstract class TreeNode + { + protected abstract IEnumerable Children { get; } + + /// + /// Debugging purpose: dump the tree in textual format into a string + /// + /// + /// + public virtual string DumpTree(int depth = 0) + { + var sb = new StringBuilder(); + sb.AppendLine($"+{this.GetType().Name}".ChangeIndentation(depth)); + sb.AppendLine($"|{this.ToString()}".ChangeIndentation(depth)); + foreach (var child in Children ?? Enumerable.Empty()) + { + sb.Append(child.DumpTree(depth + 1)); + } + return sb.ToString(); + } + + /// + /// Traversal helper to retrieve node of certain type + /// + /// + /// + public IEnumerable GetChildrenOfType() where T : TreeNode + { + if (this is T) + { + return new List(1) { this as T } + .Union(Children?.SelectMany(c => c.GetChildrenOfType()) ?? Enumerable.Empty()); + } + else + { + return Children? + .SelectMany(c => c.GetChildrenOfType()) ?? Enumerable.Empty(); + } + } + } +} diff --git a/src/openCypherParser/Common/AggregationFunction.cs b/src/openCypherParser/Common/AggregationFunction.cs new file mode 100644 index 0000000..99eee24 --- /dev/null +++ b/src/openCypherParser/Common/AggregationFunction.cs @@ -0,0 +1,87 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +namespace openCypherTranspiler.openCypherParser.Common +{ + /// + /// Enum type for aggregation functions supported by this code generator + /// + public enum AggregationFunction + { + Invalid, + None, + Sum, + Avg, + Count, + Max, + Min, + First, + Last, + PercentileCont, + PercentileDisc, + StDev, + StDevP + } + + class AggregationFunctionHelper + { + /// + /// Parse a function into aggregation function enum + /// + /// + /// + /// + public static bool TryParse(string functionName, out AggregationFunction aggFunc) + { + string lowerCaseFunctionName = functionName.ToLower(); + + switch (lowerCaseFunctionName) + { + case "avg": + aggFunc = AggregationFunction.Avg; + break; + case "sum": + aggFunc = AggregationFunction.Sum; + break; + case "count": + aggFunc = AggregationFunction.Count; + break; + case "max": + aggFunc = AggregationFunction.Max; + break; + case "min": + aggFunc = AggregationFunction.Min; + break; + case "first": + // not supported by cypher but cosmos + aggFunc = AggregationFunction.First; + break; + case "last": + // not supported by cypher but cosmos + aggFunc = AggregationFunction.Last; + break; + case "percentilecont": + aggFunc = AggregationFunction.PercentileCont; + break; + case "percentiledisc": + aggFunc = AggregationFunction.PercentileDisc; + break; + case "stdev": + aggFunc = AggregationFunction.StDev; + break; + case "stdevp": + aggFunc = AggregationFunction.StDevP; + break; + default: + // treat it as non-aggregating functions + aggFunc = AggregationFunction.Invalid; + return false; + } + + // indicating it is an aggregating function + return true; + } + } +} diff --git a/src/openCypherParser/Common/BinaryOperator.cs b/src/openCypherParser/Common/BinaryOperator.cs new file mode 100644 index 0000000..e6ae5c7 --- /dev/null +++ b/src/openCypherParser/Common/BinaryOperator.cs @@ -0,0 +1,106 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using System.Collections.Generic; +using System.Linq; + +namespace openCypherTranspiler.openCypherParser.Common +{ + public enum BinaryOperator + { + Invalid = 0, + + // numerical + Plus, + Minus, + Multiply, + Divide, + Modulo, + Exponentiation, + + // logical + AND, + OR, + XOR, + + // comparison + LT, + LEQ, + GT, + GEQ, + EQ, + NEQ, + REGMATCH, + IN + } + + public enum BinaryOperatorType + { + Invalid, + Value, // takes value type (string or numeric) and output value type + Logical, // takes logical type (bool) and output logical type + Comparison // takes value type (string or numeric) and output logical type + } + + public class BinaryOperatorInfo + { + public BinaryOperatorInfo(BinaryOperator name, BinaryOperatorType type) + { + Name = name; + Type = type; + } + public BinaryOperator Name { get; private set; } + public BinaryOperatorType Type { get; private set; } + + public override string ToString() + { + return Name.ToString(); + } + } + + public class OperatorHelper + { + private static Dictionary Operators = new Dictionary() + { + { "+", new BinaryOperatorInfo(name: BinaryOperator.Plus,type: BinaryOperatorType.Value) }, + { "-", new BinaryOperatorInfo(name: BinaryOperator.Minus, type: BinaryOperatorType.Value) }, + { "*", new BinaryOperatorInfo(name: BinaryOperator.Multiply, type: BinaryOperatorType.Value) }, + { "/", new BinaryOperatorInfo(name: BinaryOperator.Divide, type: BinaryOperatorType.Value) }, + { "%", new BinaryOperatorInfo(name: BinaryOperator.Modulo, type: BinaryOperatorType.Value) }, + { "^", new BinaryOperatorInfo(name: BinaryOperator.Exponentiation, type: BinaryOperatorType.Value) }, + + { "<>", new BinaryOperatorInfo(name: BinaryOperator.NEQ, type: BinaryOperatorType.Comparison) }, + { "=", new BinaryOperatorInfo(name: BinaryOperator.EQ, type: BinaryOperatorType.Comparison) }, + { "<", new BinaryOperatorInfo(name: BinaryOperator.LT, type: BinaryOperatorType.Comparison) }, + { ">", new BinaryOperatorInfo(name: BinaryOperator.GT, type: BinaryOperatorType.Comparison) }, + { "<=", new BinaryOperatorInfo(name: BinaryOperator.LEQ, type: BinaryOperatorType.Comparison) }, + { ">=", new BinaryOperatorInfo(name: BinaryOperator.GEQ, type: BinaryOperatorType.Comparison) }, + { "=~", new BinaryOperatorInfo(name: BinaryOperator.REGMATCH, type: BinaryOperatorType.Comparison) }, + { "in", new BinaryOperatorInfo(name: BinaryOperator.IN, type: BinaryOperatorType.Comparison) }, + + { "and", new BinaryOperatorInfo(name: BinaryOperator.AND, type: BinaryOperatorType.Logical) }, + { "or", new BinaryOperatorInfo(name: BinaryOperator.OR, type: BinaryOperatorType.Logical) }, + { "xor", new BinaryOperatorInfo(name: BinaryOperator.XOR, type: BinaryOperatorType.Logical) }, + }; + + public static BinaryOperatorInfo TryGetOperator(string op) + { + string lcOperator = op?.ToLower(); + BinaryOperatorInfo opInfo; + + if (Operators.TryGetValue(lcOperator, out opInfo)) + { + return opInfo; + } + + return null; + } + + public static BinaryOperatorInfo GetOperator(BinaryOperator opEnum) + { + return Operators.Values.FirstOrDefault(op => op.Name == opEnum); + } + } +} diff --git a/src/openCypherParser/Common/Function.cs b/src/openCypherParser/Common/Function.cs new file mode 100644 index 0000000..e2558c5 --- /dev/null +++ b/src/openCypherParser/Common/Function.cs @@ -0,0 +1,317 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using openCypherTranspiler.Common.Exceptions; + +namespace openCypherTranspiler.openCypherParser.Common +{ + public enum Function + { + Invalid = 0, + + // Unary operators + Positive, + Negative, + Not, + + // Type conversion functions: + ToFloat, + ToString, + ToBoolean, + ToInteger, + ToLong, // non standard oC functions but supported by us + ToDouble, // non standard oC functions but supported by us + + // String functions + StringStartsWith, + StringEndsWith, + StringContains, + StringLeft, + StringRight, + StringTrim, + StringLTrim, + StringRTrim, + StringToUpper, + StringToLower, + StringSize, + + // misc functions: + IsNull, + IsNotNull + } + + public class FunctionInfo + { + public Function FunctionName { get; set; } + public int RequiredParameters { get; set; } + public int OptionalParameters { get; set; } + + /// + /// A function that + /// + public Action> ParameterChecker { get; set; } + } + + public class FunctionHelper + { + private static void EnsureParameterCount(FunctionInfo info, int actCnt) + { + var paramCountMin = info.RequiredParameters; + var paramCountMax = paramCountMin + info.OptionalParameters; + if (actCnt <= paramCountMin || actCnt > paramCountMax) + { + throw new TranspilerSyntaxErrorException($"Function {info.FunctionName} expects {paramCountMin}{(paramCountMax > paramCountMin ? $" - {paramCountMax}" : "")} parameter(s)"); + } + } + + private static void EnsureNumericType(FunctionInfo info, Type type) + { + if (!( + type == typeof(int) || type == typeof(int?) || + type == typeof(long) || type == typeof(long?) || + type == typeof(float) || type == typeof(float?) || + type == typeof(double) || type == typeof(double?) + )) + { + throw new TranspilerNotSupportedException($"Function {info.FunctionName} parameter of type {type.Name}"); + } + } + + private static void EnsureBooleanType(FunctionInfo info, Type type) + { + if (!( + type == typeof(bool) || type == typeof(bool?) + )) + { + throw new TranspilerNotSupportedException($"Function {info.FunctionName} parameter of type {type.Name}"); + } + } + + private static Action> EnsureParameterCountChecker = (info, types) => + { + EnsureParameterCount(info, types.Count()); + }; + + private static Dictionary _funcInfoMap = new Dictionary() + { + { "+", new FunctionInfo() + { + FunctionName = Function.Positive, + RequiredParameters = 1, + OptionalParameters = 0, + ParameterChecker = (info, types) => + { + EnsureParameterCount(info, types.Count()); + EnsureNumericType(info, types.First()); + } + } + }, + { "-", new FunctionInfo() + { + FunctionName = Function.Negative, + RequiredParameters = 1, + OptionalParameters = 0, + ParameterChecker = (info, types) => + { + EnsureParameterCount(info, types.Count()); + EnsureNumericType(info, types.First()); + } + } + }, + { "not", new FunctionInfo() + { + FunctionName = Function.Not, + RequiredParameters = 1, + OptionalParameters = 0, + ParameterChecker = (info, types) => + { + EnsureParameterCount(info, types.Count()); + EnsureBooleanType(info, types.First()); + } + } + }, + { "tofloat", new FunctionInfo() + { + FunctionName = Function.ToFloat, + RequiredParameters = 1, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "tostring", new FunctionInfo() + { + FunctionName = Function.ToString, + RequiredParameters = 1, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "toboolean", new FunctionInfo() + { + FunctionName = Function.ToBoolean, + RequiredParameters = 1, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "tointeger", new FunctionInfo() + { + FunctionName = Function.ToInteger, + RequiredParameters = 1, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "tolong", new FunctionInfo() + { + FunctionName = Function.ToLong, + RequiredParameters = 1, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "todouble", new FunctionInfo() + { + FunctionName = Function.ToDouble, + RequiredParameters = 1, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "stringstartswith", new FunctionInfo() + { + FunctionName = Function.StringStartsWith, + RequiredParameters = 2, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "stringendswith", new FunctionInfo() + { + FunctionName = Function.StringEndsWith, + RequiredParameters = 2, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "stringcontains", new FunctionInfo() + { + FunctionName = Function.StringContains, + RequiredParameters = 2, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "isnull", new FunctionInfo() + { + FunctionName = Function.IsNull, + RequiredParameters = 1, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "isnotnull", new FunctionInfo() + { + FunctionName = Function.IsNotNull, + RequiredParameters = 1, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "left", new FunctionInfo() + { + FunctionName = Function.StringLeft, + RequiredParameters = 2, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "right", new FunctionInfo() + { + FunctionName = Function.StringRight, + RequiredParameters = 2, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "trim", new FunctionInfo() + { + FunctionName = Function.StringTrim, + RequiredParameters = 1, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "ltrim", new FunctionInfo() + { + FunctionName = Function.StringLTrim, + RequiredParameters = 1, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "rtrim", new FunctionInfo() + { + FunctionName = Function.StringRTrim, + RequiredParameters = 1, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "toupper", new FunctionInfo() + { + FunctionName = Function.StringToUpper, + RequiredParameters = 1, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "tolower", new FunctionInfo() + { + FunctionName = Function.StringToLower, + RequiredParameters = 1, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + { "size", new FunctionInfo() + { + FunctionName = Function.StringSize, + RequiredParameters = 1, + OptionalParameters = 0, + ParameterChecker = EnsureParameterCountChecker + } + }, + }; + + /// + /// Helper to check if a given function is supported or not + /// + /// + /// throws not supported exception if a function is not supported + /// Return function info object, or if no match, return null + public static FunctionInfo TryGetFunctionInfo(string functionName) + { + string lowerCaseFunctionName = functionName.ToLower(); + FunctionInfo funcInfo = null; + + if (_funcInfoMap.TryGetValue(functionName?.ToLower(), out funcInfo)) + { + return funcInfo; + } + + return null; + } + + public static FunctionInfo GetFunctionInfo(Function functionNameEnum) + { + return _funcInfoMap.Values.FirstOrDefault(fi => fi.FunctionName == functionNameEnum); + } + + } +} diff --git a/src/openCypherParser/Grammar/Cypher.interp b/src/openCypherParser/Grammar/Cypher.interp new file mode 100644 index 0000000..c15cf14 --- /dev/null +++ b/src/openCypherParser/Grammar/Cypher.interp @@ -0,0 +1,361 @@ +token literal names: +null +';' +',' +'=' +'+=' +'-' +'*' +'(' +')' +'[' +']' +':' +'|' +'..' +'+' +'/' +'%' +'^' +'<>' +'<' +'>' +'<=' +'>=' +'.' +'{' +'}' +'$' +'⟨' +'〈' +'﹤' +'<' +'⟩' +'〉' +'ï¹¥' +'>' +'­' +'â€�' +'‑' +'‒' +'–' +'â€�' +'―' +'−' +'﹘' +'ï¹£' +'ï¼�' +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +'0' +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null + +token symbolic names: +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +UNION +ALL +OPTIONAL +MATCH +UNWIND +AS +MERGE +ON +CREATE +SET +DETACH +DELETE +REMOVE +CALL +YIELD +WITH +DISTINCT +RETURN +ORDER +BY +L_SKIP +LIMIT +ASCENDING +ASC +DESCENDING +DESC +WHERE +OR +XOR +AND +NOT +IN +STARTS +ENDS +CONTAINS +IS +NULL +COUNT +FILTER +EXTRACT +ANY +NONE +SINGLE +TRUE +FALSE +EXISTS +CASE +ELSE +END +WHEN +THEN +StringLiteral +EscapedChar +HexInteger +DecimalInteger +OctalInteger +HexLetter +HexDigit +Digit +NonZeroDigit +NonZeroOctDigit +OctDigit +ZeroDigit +ExponentDecimalReal +RegularDecimalReal +CONSTRAINT +DO +FOR +REQUIRE +UNIQUE +MANDATORY +SCALAR +OF +ADD +DROP +UnescapedSymbolicName +IdentifierStart +IdentifierPart +EscapedSymbolicName +SP +WHITESPACE +Comment + +rule names: +oC_Cypher +oC_Statement +oC_Query +oC_RegularQuery +oC_Union +oC_SingleQuery +oC_SinglePartQuery +oC_MultiPartQuery +oC_UpdatingClause +oC_ReadingClause +oC_Match +oC_Unwind +oC_Merge +oC_MergeAction +oC_Create +oC_Set +oC_SetItem +oC_Delete +oC_Remove +oC_RemoveItem +oC_InQueryCall +oC_StandaloneCall +oC_YieldItems +oC_YieldItem +oC_With +oC_Return +oC_ReturnBody +oC_ReturnItems +oC_ReturnItem +oC_Order +oC_Skip +oC_Limit +oC_SortItem +oC_Where +oC_Pattern +oC_PatternPart +oC_AnonymousPatternPart +oC_PatternElement +oC_NodePattern +oC_PatternElementChain +oC_RelationshipPattern +oC_RelationshipDetail +oC_Properties +oC_RelationshipTypes +oC_NodeLabels +oC_NodeLabel +oC_RangeLiteral +oC_LabelName +oC_RelTypeName +oC_Expression +oC_OrExpression +oC_XorExpression +oC_AndExpression +oC_NotExpression +oC_ComparisonExpression +oC_AddOrSubtractExpression +oC_MultiplyDivideModuloExpression +oC_PowerOfExpression +oC_UnaryAddOrSubtractExpression +oC_StringListNullOperatorExpression +oC_PropertyOrLabelsExpression +oC_Atom +oC_Literal +oC_BooleanLiteral +oC_ListLiteral +oC_PartialComparisonExpression +oC_ParenthesizedExpression +oC_RelationshipsPattern +oC_FilterExpression +oC_IdInColl +oC_FunctionInvocation +oC_FunctionName +oC_ExplicitProcedureInvocation +oC_ImplicitProcedureInvocation +oC_ProcedureResultField +oC_ProcedureName +oC_Namespace +oC_ListComprehension +oC_PatternComprehension +oC_PropertyLookup +oC_CaseExpression +oC_CaseAlternatives +oC_Variable +oC_NumberLiteral +oC_MapLiteral +oC_Parameter +oC_PropertyExpression +oC_PropertyKeyName +oC_IntegerLiteral +oC_DoubleLiteral +oC_SchemaName +oC_ReservedWord +oC_SymbolicName +oC_LeftArrowHead +oC_RightArrowHead +oC_Dash + + +atn: +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 129, 1559, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 4, 61, 9, 61, 4, 62, 9, 62, 4, 63, 9, 63, 4, 64, 9, 64, 4, 65, 9, 65, 4, 66, 9, 66, 4, 67, 9, 67, 4, 68, 9, 68, 4, 69, 9, 69, 4, 70, 9, 70, 4, 71, 9, 71, 4, 72, 9, 72, 4, 73, 9, 73, 4, 74, 9, 74, 4, 75, 9, 75, 4, 76, 9, 76, 4, 77, 9, 77, 4, 78, 9, 78, 4, 79, 9, 79, 4, 80, 9, 80, 4, 81, 9, 81, 4, 82, 9, 82, 4, 83, 9, 83, 4, 84, 9, 84, 4, 85, 9, 85, 4, 86, 9, 86, 4, 87, 9, 87, 4, 88, 9, 88, 4, 89, 9, 89, 4, 90, 9, 90, 4, 91, 9, 91, 4, 92, 9, 92, 4, 93, 9, 93, 4, 94, 9, 94, 4, 95, 9, 95, 4, 96, 9, 96, 4, 97, 9, 97, 3, 2, 5, 2, 196, 10, 2, 3, 2, 3, 2, 5, 2, 200, 10, 2, 3, 2, 5, 2, 203, 10, 2, 3, 2, 5, 2, 206, 10, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 5, 4, 214, 10, 4, 3, 5, 3, 5, 5, 5, 218, 10, 5, 3, 5, 7, 5, 221, 10, 5, 12, 5, 14, 5, 224, 11, 5, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 230, 10, 6, 3, 6, 3, 6, 3, 6, 5, 6, 235, 10, 6, 3, 6, 5, 6, 238, 10, 6, 3, 7, 3, 7, 5, 7, 242, 10, 7, 3, 8, 3, 8, 5, 8, 246, 10, 8, 7, 8, 248, 10, 8, 12, 8, 14, 8, 251, 11, 8, 3, 8, 3, 8, 3, 8, 5, 8, 256, 10, 8, 7, 8, 258, 10, 8, 12, 8, 14, 8, 261, 11, 8, 3, 8, 3, 8, 5, 8, 265, 10, 8, 3, 8, 7, 8, 268, 10, 8, 12, 8, 14, 8, 271, 11, 8, 3, 8, 5, 8, 274, 10, 8, 3, 8, 5, 8, 277, 10, 8, 5, 8, 279, 10, 8, 3, 9, 3, 9, 5, 9, 283, 10, 9, 7, 9, 285, 10, 9, 12, 9, 14, 9, 288, 11, 9, 3, 9, 3, 9, 5, 9, 292, 10, 9, 7, 9, 294, 10, 9, 12, 9, 14, 9, 297, 11, 9, 3, 9, 3, 9, 5, 9, 301, 10, 9, 6, 9, 303, 10, 9, 13, 9, 14, 9, 304, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 5, 10, 314, 10, 10, 3, 11, 3, 11, 3, 11, 5, 11, 319, 10, 11, 3, 12, 3, 12, 5, 12, 323, 10, 12, 3, 12, 3, 12, 5, 12, 327, 10, 12, 3, 12, 3, 12, 5, 12, 331, 10, 12, 3, 12, 5, 12, 334, 10, 12, 3, 13, 3, 13, 5, 13, 338, 10, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 5, 14, 348, 10, 14, 3, 14, 3, 14, 3, 14, 7, 14, 353, 10, 14, 12, 14, 14, 14, 356, 11, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 5, 15, 368, 10, 15, 3, 16, 3, 16, 5, 16, 372, 10, 16, 3, 16, 3, 16, 3, 17, 3, 17, 5, 17, 378, 10, 17, 3, 17, 3, 17, 3, 17, 7, 17, 383, 10, 17, 12, 17, 14, 17, 386, 11, 17, 3, 18, 3, 18, 5, 18, 390, 10, 18, 3, 18, 3, 18, 5, 18, 394, 10, 18, 3, 18, 3, 18, 3, 18, 3, 18, 5, 18, 400, 10, 18, 3, 18, 3, 18, 5, 18, 404, 10, 18, 3, 18, 3, 18, 3, 18, 3, 18, 5, 18, 410, 10, 18, 3, 18, 3, 18, 5, 18, 414, 10, 18, 3, 18, 3, 18, 3, 18, 3, 18, 5, 18, 420, 10, 18, 3, 18, 3, 18, 5, 18, 424, 10, 18, 3, 19, 3, 19, 5, 19, 428, 10, 19, 3, 19, 3, 19, 5, 19, 432, 10, 19, 3, 19, 3, 19, 5, 19, 436, 10, 19, 3, 19, 3, 19, 5, 19, 440, 10, 19, 3, 19, 7, 19, 443, 10, 19, 12, 19, 14, 19, 446, 11, 19, 3, 20, 3, 20, 3, 20, 3, 20, 5, 20, 452, 10, 20, 3, 20, 3, 20, 5, 20, 456, 10, 20, 3, 20, 7, 20, 459, 10, 20, 12, 20, 14, 20, 462, 11, 20, 3, 21, 3, 21, 3, 21, 3, 21, 5, 21, 468, 10, 21, 3, 22, 3, 22, 3, 22, 3, 22, 5, 22, 474, 10, 22, 3, 22, 3, 22, 3, 22, 5, 22, 479, 10, 22, 3, 23, 3, 23, 3, 23, 3, 23, 5, 23, 485, 10, 23, 3, 23, 3, 23, 3, 23, 3, 23, 5, 23, 491, 10, 23, 3, 24, 3, 24, 5, 24, 495, 10, 24, 3, 24, 3, 24, 5, 24, 499, 10, 24, 3, 24, 7, 24, 502, 10, 24, 12, 24, 14, 24, 505, 11, 24, 3, 24, 5, 24, 508, 10, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 5, 25, 515, 10, 25, 3, 25, 3, 25, 3, 26, 3, 26, 5, 26, 521, 10, 26, 3, 26, 5, 26, 524, 10, 26, 3, 26, 3, 26, 3, 26, 5, 26, 529, 10, 26, 3, 26, 5, 26, 532, 10, 26, 3, 27, 3, 27, 5, 27, 536, 10, 27, 3, 27, 5, 27, 539, 10, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 5, 28, 547, 10, 28, 3, 28, 3, 28, 5, 28, 551, 10, 28, 3, 28, 3, 28, 5, 28, 555, 10, 28, 3, 29, 3, 29, 5, 29, 559, 10, 29, 3, 29, 3, 29, 5, 29, 563, 10, 29, 3, 29, 7, 29, 566, 10, 29, 12, 29, 14, 29, 569, 11, 29, 3, 29, 3, 29, 5, 29, 573, 10, 29, 3, 29, 3, 29, 5, 29, 577, 10, 29, 3, 29, 7, 29, 580, 10, 29, 12, 29, 14, 29, 583, 11, 29, 5, 29, 585, 10, 29, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 5, 30, 594, 10, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 5, 31, 603, 10, 31, 3, 31, 7, 31, 606, 10, 31, 12, 31, 14, 31, 609, 11, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 5, 34, 621, 10, 34, 3, 34, 5, 34, 624, 10, 34, 3, 35, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 5, 36, 632, 10, 36, 3, 36, 3, 36, 5, 36, 636, 10, 36, 3, 36, 7, 36, 639, 10, 36, 12, 36, 14, 36, 642, 11, 36, 3, 37, 3, 37, 5, 37, 646, 10, 37, 3, 37, 3, 37, 5, 37, 650, 10, 37, 3, 37, 3, 37, 3, 37, 5, 37, 655, 10, 37, 3, 38, 3, 38, 3, 39, 3, 39, 5, 39, 661, 10, 39, 3, 39, 7, 39, 664, 10, 39, 12, 39, 14, 39, 667, 11, 39, 3, 39, 3, 39, 3, 39, 3, 39, 5, 39, 673, 10, 39, 3, 40, 3, 40, 5, 40, 677, 10, 40, 3, 40, 3, 40, 5, 40, 681, 10, 40, 5, 40, 683, 10, 40, 3, 40, 3, 40, 5, 40, 687, 10, 40, 5, 40, 689, 10, 40, 3, 40, 3, 40, 5, 40, 693, 10, 40, 5, 40, 695, 10, 40, 3, 40, 3, 40, 3, 41, 3, 41, 5, 41, 701, 10, 41, 3, 41, 3, 41, 3, 42, 3, 42, 5, 42, 707, 10, 42, 3, 42, 3, 42, 5, 42, 711, 10, 42, 3, 42, 5, 42, 714, 10, 42, 3, 42, 5, 42, 717, 10, 42, 3, 42, 3, 42, 5, 42, 721, 10, 42, 3, 42, 3, 42, 3, 42, 3, 42, 5, 42, 727, 10, 42, 3, 42, 3, 42, 5, 42, 731, 10, 42, 3, 42, 5, 42, 734, 10, 42, 3, 42, 5, 42, 737, 10, 42, 3, 42, 3, 42, 3, 42, 3, 42, 5, 42, 743, 10, 42, 3, 42, 5, 42, 746, 10, 42, 3, 42, 5, 42, 749, 10, 42, 3, 42, 3, 42, 5, 42, 753, 10, 42, 3, 42, 3, 42, 3, 42, 3, 42, 5, 42, 759, 10, 42, 3, 42, 5, 42, 762, 10, 42, 3, 42, 5, 42, 765, 10, 42, 3, 42, 3, 42, 5, 42, 769, 10, 42, 3, 43, 3, 43, 5, 43, 773, 10, 43, 3, 43, 3, 43, 5, 43, 777, 10, 43, 5, 43, 779, 10, 43, 3, 43, 3, 43, 5, 43, 783, 10, 43, 5, 43, 785, 10, 43, 3, 43, 5, 43, 788, 10, 43, 3, 43, 3, 43, 5, 43, 792, 10, 43, 5, 43, 794, 10, 43, 3, 43, 3, 43, 3, 44, 3, 44, 5, 44, 800, 10, 44, 3, 45, 3, 45, 5, 45, 804, 10, 45, 3, 45, 3, 45, 5, 45, 808, 10, 45, 3, 45, 3, 45, 5, 45, 812, 10, 45, 3, 45, 5, 45, 815, 10, 45, 3, 45, 7, 45, 818, 10, 45, 12, 45, 14, 45, 821, 11, 45, 3, 46, 3, 46, 5, 46, 825, 10, 46, 3, 46, 7, 46, 828, 10, 46, 12, 46, 14, 46, 831, 11, 46, 3, 47, 3, 47, 5, 47, 835, 10, 47, 3, 47, 3, 47, 3, 48, 3, 48, 5, 48, 841, 10, 48, 3, 48, 3, 48, 5, 48, 845, 10, 48, 5, 48, 847, 10, 48, 3, 48, 3, 48, 5, 48, 851, 10, 48, 3, 48, 3, 48, 5, 48, 855, 10, 48, 5, 48, 857, 10, 48, 5, 48, 859, 10, 48, 3, 49, 3, 49, 3, 50, 3, 50, 3, 51, 3, 51, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 7, 52, 872, 10, 52, 12, 52, 14, 52, 875, 11, 52, 3, 53, 3, 53, 3, 53, 3, 53, 3, 53, 7, 53, 882, 10, 53, 12, 53, 14, 53, 885, 11, 53, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 7, 54, 892, 10, 54, 12, 54, 14, 54, 895, 11, 54, 3, 55, 3, 55, 5, 55, 899, 10, 55, 7, 55, 901, 10, 55, 12, 55, 14, 55, 904, 11, 55, 3, 55, 3, 55, 3, 56, 3, 56, 5, 56, 910, 10, 56, 3, 56, 7, 56, 913, 10, 56, 12, 56, 14, 56, 916, 11, 56, 3, 57, 3, 57, 5, 57, 920, 10, 57, 3, 57, 3, 57, 5, 57, 924, 10, 57, 3, 57, 3, 57, 5, 57, 928, 10, 57, 3, 57, 3, 57, 5, 57, 932, 10, 57, 3, 57, 7, 57, 935, 10, 57, 12, 57, 14, 57, 938, 11, 57, 3, 58, 3, 58, 5, 58, 942, 10, 58, 3, 58, 3, 58, 5, 58, 946, 10, 58, 3, 58, 3, 58, 5, 58, 950, 10, 58, 3, 58, 3, 58, 5, 58, 954, 10, 58, 3, 58, 3, 58, 5, 58, 958, 10, 58, 3, 58, 3, 58, 5, 58, 962, 10, 58, 3, 58, 7, 58, 965, 10, 58, 12, 58, 14, 58, 968, 11, 58, 3, 59, 3, 59, 5, 59, 972, 10, 59, 3, 59, 3, 59, 5, 59, 976, 10, 59, 3, 59, 7, 59, 979, 10, 59, 12, 59, 14, 59, 982, 11, 59, 3, 60, 3, 60, 5, 60, 986, 10, 60, 7, 60, 988, 10, 60, 12, 60, 14, 60, 991, 11, 60, 3, 60, 3, 60, 3, 61, 3, 61, 5, 61, 997, 10, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 5, 61, 1004, 10, 61, 3, 61, 3, 61, 5, 61, 1008, 10, 61, 3, 61, 3, 61, 5, 61, 1012, 10, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 5, 61, 1027, 10, 61, 3, 61, 5, 61, 1030, 10, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 7, 61, 1043, 10, 61, 12, 61, 14, 61, 1046, 11, 61, 3, 62, 3, 62, 5, 62, 1050, 10, 62, 3, 62, 7, 62, 1053, 10, 62, 12, 62, 14, 62, 1056, 11, 62, 3, 62, 5, 62, 1059, 10, 62, 3, 62, 5, 62, 1062, 10, 62, 3, 63, 3, 63, 3, 63, 3, 63, 3, 63, 5, 63, 1069, 10, 63, 3, 63, 3, 63, 5, 63, 1073, 10, 63, 3, 63, 3, 63, 5, 63, 1077, 10, 63, 3, 63, 3, 63, 3, 63, 3, 63, 3, 63, 5, 63, 1084, 10, 63, 3, 63, 3, 63, 5, 63, 1088, 10, 63, 3, 63, 3, 63, 5, 63, 1092, 10, 63, 3, 63, 3, 63, 3, 63, 3, 63, 5, 63, 1098, 10, 63, 3, 63, 3, 63, 5, 63, 1102, 10, 63, 3, 63, 3, 63, 5, 63, 1106, 10, 63, 3, 63, 5, 63, 1109, 10, 63, 3, 63, 3, 63, 5, 63, 1113, 10, 63, 3, 63, 3, 63, 3, 63, 3, 63, 5, 63, 1119, 10, 63, 3, 63, 3, 63, 5, 63, 1123, 10, 63, 3, 63, 3, 63, 5, 63, 1127, 10, 63, 3, 63, 3, 63, 3, 63, 3, 63, 5, 63, 1133, 10, 63, 3, 63, 3, 63, 5, 63, 1137, 10, 63, 3, 63, 3, 63, 5, 63, 1141, 10, 63, 3, 63, 3, 63, 3, 63, 3, 63, 5, 63, 1147, 10, 63, 3, 63, 3, 63, 5, 63, 1151, 10, 63, 3, 63, 3, 63, 5, 63, 1155, 10, 63, 3, 63, 3, 63, 3, 63, 3, 63, 5, 63, 1161, 10, 63, 3, 63, 3, 63, 5, 63, 1165, 10, 63, 3, 63, 3, 63, 5, 63, 1169, 10, 63, 3, 63, 3, 63, 3, 63, 3, 63, 3, 63, 3, 63, 5, 63, 1177, 10, 63, 3, 64, 3, 64, 3, 64, 3, 64, 3, 64, 3, 64, 5, 64, 1185, 10, 64, 3, 65, 3, 65, 3, 66, 3, 66, 5, 66, 1191, 10, 66, 3, 66, 3, 66, 5, 66, 1195, 10, 66, 3, 66, 3, 66, 5, 66, 1199, 10, 66, 3, 66, 3, 66, 5, 66, 1203, 10, 66, 7, 66, 1205, 10, 66, 12, 66, 14, 66, 1208, 11, 66, 5, 66, 1210, 10, 66, 3, 66, 3, 66, 3, 67, 3, 67, 5, 67, 1216, 10, 67, 3, 67, 3, 67, 3, 67, 5, 67, 1221, 10, 67, 3, 67, 3, 67, 3, 67, 5, 67, 1226, 10, 67, 3, 67, 3, 67, 3, 67, 5, 67, 1231, 10, 67, 3, 67, 3, 67, 3, 67, 5, 67, 1236, 10, 67, 3, 67, 3, 67, 3, 67, 5, 67, 1241, 10, 67, 3, 67, 5, 67, 1244, 10, 67, 3, 68, 3, 68, 5, 68, 1248, 10, 68, 3, 68, 3, 68, 5, 68, 1252, 10, 68, 3, 68, 3, 68, 3, 69, 3, 69, 5, 69, 1258, 10, 69, 3, 69, 6, 69, 1261, 10, 69, 13, 69, 14, 69, 1262, 3, 70, 3, 70, 5, 70, 1267, 10, 70, 3, 70, 5, 70, 1270, 10, 70, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 72, 3, 72, 5, 72, 1280, 10, 72, 3, 72, 3, 72, 5, 72, 1284, 10, 72, 3, 72, 3, 72, 5, 72, 1288, 10, 72, 5, 72, 1290, 10, 72, 3, 72, 3, 72, 5, 72, 1294, 10, 72, 3, 72, 3, 72, 5, 72, 1298, 10, 72, 3, 72, 3, 72, 5, 72, 1302, 10, 72, 7, 72, 1304, 10, 72, 12, 72, 14, 72, 1307, 11, 72, 5, 72, 1309, 10, 72, 3, 72, 3, 72, 3, 73, 3, 73, 5, 73, 1315, 10, 73, 3, 74, 3, 74, 5, 74, 1319, 10, 74, 3, 74, 3, 74, 5, 74, 1323, 10, 74, 3, 74, 3, 74, 5, 74, 1327, 10, 74, 3, 74, 3, 74, 5, 74, 1331, 10, 74, 3, 74, 3, 74, 5, 74, 1335, 10, 74, 7, 74, 1337, 10, 74, 12, 74, 14, 74, 1340, 11, 74, 5, 74, 1342, 10, 74, 3, 74, 3, 74, 3, 75, 3, 75, 3, 76, 3, 76, 3, 77, 3, 77, 3, 77, 3, 78, 3, 78, 3, 78, 7, 78, 1356, 10, 78, 12, 78, 14, 78, 1359, 11, 78, 3, 79, 3, 79, 5, 79, 1363, 10, 79, 3, 79, 3, 79, 5, 79, 1367, 10, 79, 3, 79, 3, 79, 5, 79, 1371, 10, 79, 3, 79, 5, 79, 1374, 10, 79, 3, 79, 5, 79, 1377, 10, 79, 3, 79, 3, 79, 3, 80, 3, 80, 5, 80, 1383, 10, 80, 3, 80, 3, 80, 5, 80, 1387, 10, 80, 3, 80, 3, 80, 5, 80, 1391, 10, 80, 5, 80, 1393, 10, 80, 3, 80, 3, 80, 5, 80, 1397, 10, 80, 3, 80, 3, 80, 5, 80, 1401, 10, 80, 3, 80, 3, 80, 5, 80, 1405, 10, 80, 5, 80, 1407, 10, 80, 3, 80, 3, 80, 5, 80, 1411, 10, 80, 3, 80, 3, 80, 5, 80, 1415, 10, 80, 3, 80, 3, 80, 3, 81, 3, 81, 5, 81, 1421, 10, 81, 3, 81, 3, 81, 3, 82, 3, 82, 5, 82, 1427, 10, 82, 3, 82, 6, 82, 1430, 10, 82, 13, 82, 14, 82, 1431, 3, 82, 3, 82, 5, 82, 1436, 10, 82, 3, 82, 3, 82, 5, 82, 1440, 10, 82, 3, 82, 6, 82, 1443, 10, 82, 13, 82, 14, 82, 1444, 5, 82, 1447, 10, 82, 3, 82, 5, 82, 1450, 10, 82, 3, 82, 3, 82, 5, 82, 1454, 10, 82, 3, 82, 5, 82, 1457, 10, 82, 3, 82, 5, 82, 1460, 10, 82, 3, 82, 3, 82, 3, 83, 3, 83, 5, 83, 1466, 10, 83, 3, 83, 3, 83, 5, 83, 1470, 10, 83, 3, 83, 3, 83, 5, 83, 1474, 10, 83, 3, 83, 3, 83, 3, 84, 3, 84, 3, 85, 3, 85, 5, 85, 1482, 10, 85, 3, 86, 3, 86, 5, 86, 1486, 10, 86, 3, 86, 3, 86, 5, 86, 1490, 10, 86, 3, 86, 3, 86, 5, 86, 1494, 10, 86, 3, 86, 3, 86, 5, 86, 1498, 10, 86, 3, 86, 3, 86, 5, 86, 1502, 10, 86, 3, 86, 3, 86, 5, 86, 1506, 10, 86, 3, 86, 3, 86, 5, 86, 1510, 10, 86, 3, 86, 3, 86, 5, 86, 1514, 10, 86, 7, 86, 1516, 10, 86, 12, 86, 14, 86, 1519, 11, 86, 5, 86, 1521, 10, 86, 3, 86, 3, 86, 3, 87, 3, 87, 3, 87, 5, 87, 1528, 10, 87, 3, 88, 3, 88, 5, 88, 1532, 10, 88, 3, 88, 6, 88, 1535, 10, 88, 13, 88, 14, 88, 1536, 3, 89, 3, 89, 3, 90, 3, 90, 3, 91, 3, 91, 3, 92, 3, 92, 5, 92, 1547, 10, 92, 3, 93, 3, 93, 3, 94, 3, 94, 3, 95, 3, 95, 3, 96, 3, 96, 3, 97, 3, 97, 3, 97, 2, 2, 98, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 2, 12, 3, 2, 70, 73, 4, 2, 7, 7, 16, 16, 3, 2, 91, 92, 3, 2, 101, 103, 3, 2, 111, 112, 6, 2, 48, 60, 63, 84, 91, 98, 113, 122, 6, 2, 85, 90, 104, 104, 123, 123, 126, 126, 4, 2, 21, 21, 29, 32, 4, 2, 22, 22, 33, 36, 4, 2, 7, 7, 37, 47, 2, 1786, 2, 195, 3, 2, 2, 2, 4, 209, 3, 2, 2, 2, 6, 213, 3, 2, 2, 2, 8, 215, 3, 2, 2, 2, 10, 237, 3, 2, 2, 2, 12, 241, 3, 2, 2, 2, 14, 278, 3, 2, 2, 2, 16, 302, 3, 2, 2, 2, 18, 313, 3, 2, 2, 2, 20, 318, 3, 2, 2, 2, 22, 322, 3, 2, 2, 2, 24, 335, 3, 2, 2, 2, 26, 345, 3, 2, 2, 2, 28, 367, 3, 2, 2, 2, 30, 369, 3, 2, 2, 2, 32, 375, 3, 2, 2, 2, 34, 423, 3, 2, 2, 2, 36, 427, 3, 2, 2, 2, 38, 447, 3, 2, 2, 2, 40, 467, 3, 2, 2, 2, 42, 469, 3, 2, 2, 2, 44, 480, 3, 2, 2, 2, 46, 507, 3, 2, 2, 2, 48, 514, 3, 2, 2, 2, 50, 518, 3, 2, 2, 2, 52, 533, 3, 2, 2, 2, 54, 543, 3, 2, 2, 2, 56, 584, 3, 2, 2, 2, 58, 593, 3, 2, 2, 2, 60, 595, 3, 2, 2, 2, 62, 610, 3, 2, 2, 2, 64, 614, 3, 2, 2, 2, 66, 618, 3, 2, 2, 2, 68, 625, 3, 2, 2, 2, 70, 629, 3, 2, 2, 2, 72, 654, 3, 2, 2, 2, 74, 656, 3, 2, 2, 2, 76, 672, 3, 2, 2, 2, 78, 674, 3, 2, 2, 2, 80, 698, 3, 2, 2, 2, 82, 768, 3, 2, 2, 2, 84, 770, 3, 2, 2, 2, 86, 799, 3, 2, 2, 2, 88, 801, 3, 2, 2, 2, 90, 822, 3, 2, 2, 2, 92, 832, 3, 2, 2, 2, 94, 838, 3, 2, 2, 2, 96, 860, 3, 2, 2, 2, 98, 862, 3, 2, 2, 2, 100, 864, 3, 2, 2, 2, 102, 866, 3, 2, 2, 2, 104, 876, 3, 2, 2, 2, 106, 886, 3, 2, 2, 2, 108, 902, 3, 2, 2, 2, 110, 907, 3, 2, 2, 2, 112, 917, 3, 2, 2, 2, 114, 939, 3, 2, 2, 2, 116, 969, 3, 2, 2, 2, 118, 989, 3, 2, 2, 2, 120, 994, 3, 2, 2, 2, 122, 1047, 3, 2, 2, 2, 124, 1176, 3, 2, 2, 2, 126, 1184, 3, 2, 2, 2, 128, 1186, 3, 2, 2, 2, 130, 1188, 3, 2, 2, 2, 132, 1243, 3, 2, 2, 2, 134, 1245, 3, 2, 2, 2, 136, 1255, 3, 2, 2, 2, 138, 1264, 3, 2, 2, 2, 140, 1271, 3, 2, 2, 2, 142, 1277, 3, 2, 2, 2, 144, 1314, 3, 2, 2, 2, 146, 1316, 3, 2, 2, 2, 148, 1345, 3, 2, 2, 2, 150, 1347, 3, 2, 2, 2, 152, 1349, 3, 2, 2, 2, 154, 1357, 3, 2, 2, 2, 156, 1360, 3, 2, 2, 2, 158, 1380, 3, 2, 2, 2, 160, 1418, 3, 2, 2, 2, 162, 1446, 3, 2, 2, 2, 164, 1463, 3, 2, 2, 2, 166, 1477, 3, 2, 2, 2, 168, 1481, 3, 2, 2, 2, 170, 1483, 3, 2, 2, 2, 172, 1524, 3, 2, 2, 2, 174, 1529, 3, 2, 2, 2, 176, 1538, 3, 2, 2, 2, 178, 1540, 3, 2, 2, 2, 180, 1542, 3, 2, 2, 2, 182, 1546, 3, 2, 2, 2, 184, 1548, 3, 2, 2, 2, 186, 1550, 3, 2, 2, 2, 188, 1552, 3, 2, 2, 2, 190, 1554, 3, 2, 2, 2, 192, 1556, 3, 2, 2, 2, 194, 196, 7, 127, 2, 2, 195, 194, 3, 2, 2, 2, 195, 196, 3, 2, 2, 2, 196, 197, 3, 2, 2, 2, 197, 202, 5, 4, 3, 2, 198, 200, 7, 127, 2, 2, 199, 198, 3, 2, 2, 2, 199, 200, 3, 2, 2, 2, 200, 201, 3, 2, 2, 2, 201, 203, 7, 3, 2, 2, 202, 199, 3, 2, 2, 2, 202, 203, 3, 2, 2, 2, 203, 205, 3, 2, 2, 2, 204, 206, 7, 127, 2, 2, 205, 204, 3, 2, 2, 2, 205, 206, 3, 2, 2, 2, 206, 207, 3, 2, 2, 2, 207, 208, 7, 2, 2, 3, 208, 3, 3, 2, 2, 2, 209, 210, 5, 6, 4, 2, 210, 5, 3, 2, 2, 2, 211, 214, 5, 8, 5, 2, 212, 214, 5, 44, 23, 2, 213, 211, 3, 2, 2, 2, 213, 212, 3, 2, 2, 2, 214, 7, 3, 2, 2, 2, 215, 222, 5, 12, 7, 2, 216, 218, 7, 127, 2, 2, 217, 216, 3, 2, 2, 2, 217, 218, 3, 2, 2, 2, 218, 219, 3, 2, 2, 2, 219, 221, 5, 10, 6, 2, 220, 217, 3, 2, 2, 2, 221, 224, 3, 2, 2, 2, 222, 220, 3, 2, 2, 2, 222, 223, 3, 2, 2, 2, 223, 9, 3, 2, 2, 2, 224, 222, 3, 2, 2, 2, 225, 226, 7, 48, 2, 2, 226, 227, 7, 127, 2, 2, 227, 229, 7, 49, 2, 2, 228, 230, 7, 127, 2, 2, 229, 228, 3, 2, 2, 2, 229, 230, 3, 2, 2, 2, 230, 231, 3, 2, 2, 2, 231, 238, 5, 12, 7, 2, 232, 234, 7, 48, 2, 2, 233, 235, 7, 127, 2, 2, 234, 233, 3, 2, 2, 2, 234, 235, 3, 2, 2, 2, 235, 236, 3, 2, 2, 2, 236, 238, 5, 12, 7, 2, 237, 225, 3, 2, 2, 2, 237, 232, 3, 2, 2, 2, 238, 11, 3, 2, 2, 2, 239, 242, 5, 14, 8, 2, 240, 242, 5, 16, 9, 2, 241, 239, 3, 2, 2, 2, 241, 240, 3, 2, 2, 2, 242, 13, 3, 2, 2, 2, 243, 245, 5, 20, 11, 2, 244, 246, 7, 127, 2, 2, 245, 244, 3, 2, 2, 2, 245, 246, 3, 2, 2, 2, 246, 248, 3, 2, 2, 2, 247, 243, 3, 2, 2, 2, 248, 251, 3, 2, 2, 2, 249, 247, 3, 2, 2, 2, 249, 250, 3, 2, 2, 2, 250, 252, 3, 2, 2, 2, 251, 249, 3, 2, 2, 2, 252, 279, 5, 52, 27, 2, 253, 255, 5, 20, 11, 2, 254, 256, 7, 127, 2, 2, 255, 254, 3, 2, 2, 2, 255, 256, 3, 2, 2, 2, 256, 258, 3, 2, 2, 2, 257, 253, 3, 2, 2, 2, 258, 261, 3, 2, 2, 2, 259, 257, 3, 2, 2, 2, 259, 260, 3, 2, 2, 2, 260, 262, 3, 2, 2, 2, 261, 259, 3, 2, 2, 2, 262, 269, 5, 18, 10, 2, 263, 265, 7, 127, 2, 2, 264, 263, 3, 2, 2, 2, 264, 265, 3, 2, 2, 2, 265, 266, 3, 2, 2, 2, 266, 268, 5, 18, 10, 2, 267, 264, 3, 2, 2, 2, 268, 271, 3, 2, 2, 2, 269, 267, 3, 2, 2, 2, 269, 270, 3, 2, 2, 2, 270, 276, 3, 2, 2, 2, 271, 269, 3, 2, 2, 2, 272, 274, 7, 127, 2, 2, 273, 272, 3, 2, 2, 2, 273, 274, 3, 2, 2, 2, 274, 275, 3, 2, 2, 2, 275, 277, 5, 52, 27, 2, 276, 273, 3, 2, 2, 2, 276, 277, 3, 2, 2, 2, 277, 279, 3, 2, 2, 2, 278, 249, 3, 2, 2, 2, 278, 259, 3, 2, 2, 2, 279, 15, 3, 2, 2, 2, 280, 282, 5, 20, 11, 2, 281, 283, 7, 127, 2, 2, 282, 281, 3, 2, 2, 2, 282, 283, 3, 2, 2, 2, 283, 285, 3, 2, 2, 2, 284, 280, 3, 2, 2, 2, 285, 288, 3, 2, 2, 2, 286, 284, 3, 2, 2, 2, 286, 287, 3, 2, 2, 2, 287, 295, 3, 2, 2, 2, 288, 286, 3, 2, 2, 2, 289, 291, 5, 18, 10, 2, 290, 292, 7, 127, 2, 2, 291, 290, 3, 2, 2, 2, 291, 292, 3, 2, 2, 2, 292, 294, 3, 2, 2, 2, 293, 289, 3, 2, 2, 2, 294, 297, 3, 2, 2, 2, 295, 293, 3, 2, 2, 2, 295, 296, 3, 2, 2, 2, 296, 298, 3, 2, 2, 2, 297, 295, 3, 2, 2, 2, 298, 300, 5, 50, 26, 2, 299, 301, 7, 127, 2, 2, 300, 299, 3, 2, 2, 2, 300, 301, 3, 2, 2, 2, 301, 303, 3, 2, 2, 2, 302, 286, 3, 2, 2, 2, 303, 304, 3, 2, 2, 2, 304, 302, 3, 2, 2, 2, 304, 305, 3, 2, 2, 2, 305, 306, 3, 2, 2, 2, 306, 307, 5, 14, 8, 2, 307, 17, 3, 2, 2, 2, 308, 314, 5, 30, 16, 2, 309, 314, 5, 26, 14, 2, 310, 314, 5, 36, 19, 2, 311, 314, 5, 32, 17, 2, 312, 314, 5, 38, 20, 2, 313, 308, 3, 2, 2, 2, 313, 309, 3, 2, 2, 2, 313, 310, 3, 2, 2, 2, 313, 311, 3, 2, 2, 2, 313, 312, 3, 2, 2, 2, 314, 19, 3, 2, 2, 2, 315, 319, 5, 22, 12, 2, 316, 319, 5, 24, 13, 2, 317, 319, 5, 42, 22, 2, 318, 315, 3, 2, 2, 2, 318, 316, 3, 2, 2, 2, 318, 317, 3, 2, 2, 2, 319, 21, 3, 2, 2, 2, 320, 321, 7, 50, 2, 2, 321, 323, 7, 127, 2, 2, 322, 320, 3, 2, 2, 2, 322, 323, 3, 2, 2, 2, 323, 324, 3, 2, 2, 2, 324, 326, 7, 51, 2, 2, 325, 327, 7, 127, 2, 2, 326, 325, 3, 2, 2, 2, 326, 327, 3, 2, 2, 2, 327, 328, 3, 2, 2, 2, 328, 333, 5, 70, 36, 2, 329, 331, 7, 127, 2, 2, 330, 329, 3, 2, 2, 2, 330, 331, 3, 2, 2, 2, 331, 332, 3, 2, 2, 2, 332, 334, 5, 68, 35, 2, 333, 330, 3, 2, 2, 2, 333, 334, 3, 2, 2, 2, 334, 23, 3, 2, 2, 2, 335, 337, 7, 52, 2, 2, 336, 338, 7, 127, 2, 2, 337, 336, 3, 2, 2, 2, 337, 338, 3, 2, 2, 2, 338, 339, 3, 2, 2, 2, 339, 340, 5, 100, 51, 2, 340, 341, 7, 127, 2, 2, 341, 342, 7, 53, 2, 2, 342, 343, 7, 127, 2, 2, 343, 344, 5, 166, 84, 2, 344, 25, 3, 2, 2, 2, 345, 347, 7, 54, 2, 2, 346, 348, 7, 127, 2, 2, 347, 346, 3, 2, 2, 2, 347, 348, 3, 2, 2, 2, 348, 349, 3, 2, 2, 2, 349, 354, 5, 72, 37, 2, 350, 351, 7, 127, 2, 2, 351, 353, 5, 28, 15, 2, 352, 350, 3, 2, 2, 2, 353, 356, 3, 2, 2, 2, 354, 352, 3, 2, 2, 2, 354, 355, 3, 2, 2, 2, 355, 27, 3, 2, 2, 2, 356, 354, 3, 2, 2, 2, 357, 358, 7, 55, 2, 2, 358, 359, 7, 127, 2, 2, 359, 360, 7, 51, 2, 2, 360, 361, 7, 127, 2, 2, 361, 368, 5, 32, 17, 2, 362, 363, 7, 55, 2, 2, 363, 364, 7, 127, 2, 2, 364, 365, 7, 56, 2, 2, 365, 366, 7, 127, 2, 2, 366, 368, 5, 32, 17, 2, 367, 357, 3, 2, 2, 2, 367, 362, 3, 2, 2, 2, 368, 29, 3, 2, 2, 2, 369, 371, 7, 56, 2, 2, 370, 372, 7, 127, 2, 2, 371, 370, 3, 2, 2, 2, 371, 372, 3, 2, 2, 2, 372, 373, 3, 2, 2, 2, 373, 374, 5, 70, 36, 2, 374, 31, 3, 2, 2, 2, 375, 377, 7, 57, 2, 2, 376, 378, 7, 127, 2, 2, 377, 376, 3, 2, 2, 2, 377, 378, 3, 2, 2, 2, 378, 379, 3, 2, 2, 2, 379, 384, 5, 34, 18, 2, 380, 381, 7, 4, 2, 2, 381, 383, 5, 34, 18, 2, 382, 380, 3, 2, 2, 2, 383, 386, 3, 2, 2, 2, 384, 382, 3, 2, 2, 2, 384, 385, 3, 2, 2, 2, 385, 33, 3, 2, 2, 2, 386, 384, 3, 2, 2, 2, 387, 389, 5, 174, 88, 2, 388, 390, 7, 127, 2, 2, 389, 388, 3, 2, 2, 2, 389, 390, 3, 2, 2, 2, 390, 391, 3, 2, 2, 2, 391, 393, 7, 5, 2, 2, 392, 394, 7, 127, 2, 2, 393, 392, 3, 2, 2, 2, 393, 394, 3, 2, 2, 2, 394, 395, 3, 2, 2, 2, 395, 396, 5, 100, 51, 2, 396, 424, 3, 2, 2, 2, 397, 399, 5, 166, 84, 2, 398, 400, 7, 127, 2, 2, 399, 398, 3, 2, 2, 2, 399, 400, 3, 2, 2, 2, 400, 401, 3, 2, 2, 2, 401, 403, 7, 5, 2, 2, 402, 404, 7, 127, 2, 2, 403, 402, 3, 2, 2, 2, 403, 404, 3, 2, 2, 2, 404, 405, 3, 2, 2, 2, 405, 406, 5, 100, 51, 2, 406, 424, 3, 2, 2, 2, 407, 409, 5, 166, 84, 2, 408, 410, 7, 127, 2, 2, 409, 408, 3, 2, 2, 2, 409, 410, 3, 2, 2, 2, 410, 411, 3, 2, 2, 2, 411, 413, 7, 6, 2, 2, 412, 414, 7, 127, 2, 2, 413, 412, 3, 2, 2, 2, 413, 414, 3, 2, 2, 2, 414, 415, 3, 2, 2, 2, 415, 416, 5, 100, 51, 2, 416, 424, 3, 2, 2, 2, 417, 419, 5, 166, 84, 2, 418, 420, 7, 127, 2, 2, 419, 418, 3, 2, 2, 2, 419, 420, 3, 2, 2, 2, 420, 421, 3, 2, 2, 2, 421, 422, 5, 90, 46, 2, 422, 424, 3, 2, 2, 2, 423, 387, 3, 2, 2, 2, 423, 397, 3, 2, 2, 2, 423, 407, 3, 2, 2, 2, 423, 417, 3, 2, 2, 2, 424, 35, 3, 2, 2, 2, 425, 426, 7, 58, 2, 2, 426, 428, 7, 127, 2, 2, 427, 425, 3, 2, 2, 2, 427, 428, 3, 2, 2, 2, 428, 429, 3, 2, 2, 2, 429, 431, 7, 59, 2, 2, 430, 432, 7, 127, 2, 2, 431, 430, 3, 2, 2, 2, 431, 432, 3, 2, 2, 2, 432, 433, 3, 2, 2, 2, 433, 444, 5, 100, 51, 2, 434, 436, 7, 127, 2, 2, 435, 434, 3, 2, 2, 2, 435, 436, 3, 2, 2, 2, 436, 437, 3, 2, 2, 2, 437, 439, 7, 4, 2, 2, 438, 440, 7, 127, 2, 2, 439, 438, 3, 2, 2, 2, 439, 440, 3, 2, 2, 2, 440, 441, 3, 2, 2, 2, 441, 443, 5, 100, 51, 2, 442, 435, 3, 2, 2, 2, 443, 446, 3, 2, 2, 2, 444, 442, 3, 2, 2, 2, 444, 445, 3, 2, 2, 2, 445, 37, 3, 2, 2, 2, 446, 444, 3, 2, 2, 2, 447, 448, 7, 60, 2, 2, 448, 449, 7, 127, 2, 2, 449, 460, 5, 40, 21, 2, 450, 452, 7, 127, 2, 2, 451, 450, 3, 2, 2, 2, 451, 452, 3, 2, 2, 2, 452, 453, 3, 2, 2, 2, 453, 455, 7, 4, 2, 2, 454, 456, 7, 127, 2, 2, 455, 454, 3, 2, 2, 2, 455, 456, 3, 2, 2, 2, 456, 457, 3, 2, 2, 2, 457, 459, 5, 40, 21, 2, 458, 451, 3, 2, 2, 2, 459, 462, 3, 2, 2, 2, 460, 458, 3, 2, 2, 2, 460, 461, 3, 2, 2, 2, 461, 39, 3, 2, 2, 2, 462, 460, 3, 2, 2, 2, 463, 464, 5, 166, 84, 2, 464, 465, 5, 90, 46, 2, 465, 468, 3, 2, 2, 2, 466, 468, 5, 174, 88, 2, 467, 463, 3, 2, 2, 2, 467, 466, 3, 2, 2, 2, 468, 41, 3, 2, 2, 2, 469, 470, 7, 61, 2, 2, 470, 471, 7, 127, 2, 2, 471, 478, 5, 146, 74, 2, 472, 474, 7, 127, 2, 2, 473, 472, 3, 2, 2, 2, 473, 474, 3, 2, 2, 2, 474, 475, 3, 2, 2, 2, 475, 476, 7, 62, 2, 2, 476, 477, 7, 127, 2, 2, 477, 479, 5, 46, 24, 2, 478, 473, 3, 2, 2, 2, 478, 479, 3, 2, 2, 2, 479, 43, 3, 2, 2, 2, 480, 481, 7, 61, 2, 2, 481, 484, 7, 127, 2, 2, 482, 485, 5, 146, 74, 2, 483, 485, 5, 148, 75, 2, 484, 482, 3, 2, 2, 2, 484, 483, 3, 2, 2, 2, 485, 490, 3, 2, 2, 2, 486, 487, 7, 127, 2, 2, 487, 488, 7, 62, 2, 2, 488, 489, 7, 127, 2, 2, 489, 491, 5, 46, 24, 2, 490, 486, 3, 2, 2, 2, 490, 491, 3, 2, 2, 2, 491, 45, 3, 2, 2, 2, 492, 503, 5, 48, 25, 2, 493, 495, 7, 127, 2, 2, 494, 493, 3, 2, 2, 2, 494, 495, 3, 2, 2, 2, 495, 496, 3, 2, 2, 2, 496, 498, 7, 4, 2, 2, 497, 499, 7, 127, 2, 2, 498, 497, 3, 2, 2, 2, 498, 499, 3, 2, 2, 2, 499, 500, 3, 2, 2, 2, 500, 502, 5, 48, 25, 2, 501, 494, 3, 2, 2, 2, 502, 505, 3, 2, 2, 2, 503, 501, 3, 2, 2, 2, 503, 504, 3, 2, 2, 2, 504, 508, 3, 2, 2, 2, 505, 503, 3, 2, 2, 2, 506, 508, 7, 7, 2, 2, 507, 492, 3, 2, 2, 2, 507, 506, 3, 2, 2, 2, 508, 47, 3, 2, 2, 2, 509, 510, 5, 150, 76, 2, 510, 511, 7, 127, 2, 2, 511, 512, 7, 53, 2, 2, 512, 513, 7, 127, 2, 2, 513, 515, 3, 2, 2, 2, 514, 509, 3, 2, 2, 2, 514, 515, 3, 2, 2, 2, 515, 516, 3, 2, 2, 2, 516, 517, 5, 166, 84, 2, 517, 49, 3, 2, 2, 2, 518, 523, 7, 63, 2, 2, 519, 521, 7, 127, 2, 2, 520, 519, 3, 2, 2, 2, 520, 521, 3, 2, 2, 2, 521, 522, 3, 2, 2, 2, 522, 524, 7, 64, 2, 2, 523, 520, 3, 2, 2, 2, 523, 524, 3, 2, 2, 2, 524, 525, 3, 2, 2, 2, 525, 526, 7, 127, 2, 2, 526, 531, 5, 54, 28, 2, 527, 529, 7, 127, 2, 2, 528, 527, 3, 2, 2, 2, 528, 529, 3, 2, 2, 2, 529, 530, 3, 2, 2, 2, 530, 532, 5, 68, 35, 2, 531, 528, 3, 2, 2, 2, 531, 532, 3, 2, 2, 2, 532, 51, 3, 2, 2, 2, 533, 538, 7, 65, 2, 2, 534, 536, 7, 127, 2, 2, 535, 534, 3, 2, 2, 2, 535, 536, 3, 2, 2, 2, 536, 537, 3, 2, 2, 2, 537, 539, 7, 64, 2, 2, 538, 535, 3, 2, 2, 2, 538, 539, 3, 2, 2, 2, 539, 540, 3, 2, 2, 2, 540, 541, 7, 127, 2, 2, 541, 542, 5, 54, 28, 2, 542, 53, 3, 2, 2, 2, 543, 546, 5, 56, 29, 2, 544, 545, 7, 127, 2, 2, 545, 547, 5, 60, 31, 2, 546, 544, 3, 2, 2, 2, 546, 547, 3, 2, 2, 2, 547, 550, 3, 2, 2, 2, 548, 549, 7, 127, 2, 2, 549, 551, 5, 62, 32, 2, 550, 548, 3, 2, 2, 2, 550, 551, 3, 2, 2, 2, 551, 554, 3, 2, 2, 2, 552, 553, 7, 127, 2, 2, 553, 555, 5, 64, 33, 2, 554, 552, 3, 2, 2, 2, 554, 555, 3, 2, 2, 2, 555, 55, 3, 2, 2, 2, 556, 567, 7, 8, 2, 2, 557, 559, 7, 127, 2, 2, 558, 557, 3, 2, 2, 2, 558, 559, 3, 2, 2, 2, 559, 560, 3, 2, 2, 2, 560, 562, 7, 4, 2, 2, 561, 563, 7, 127, 2, 2, 562, 561, 3, 2, 2, 2, 562, 563, 3, 2, 2, 2, 563, 564, 3, 2, 2, 2, 564, 566, 5, 58, 30, 2, 565, 558, 3, 2, 2, 2, 566, 569, 3, 2, 2, 2, 567, 565, 3, 2, 2, 2, 567, 568, 3, 2, 2, 2, 568, 585, 3, 2, 2, 2, 569, 567, 3, 2, 2, 2, 570, 581, 5, 58, 30, 2, 571, 573, 7, 127, 2, 2, 572, 571, 3, 2, 2, 2, 572, 573, 3, 2, 2, 2, 573, 574, 3, 2, 2, 2, 574, 576, 7, 4, 2, 2, 575, 577, 7, 127, 2, 2, 576, 575, 3, 2, 2, 2, 576, 577, 3, 2, 2, 2, 577, 578, 3, 2, 2, 2, 578, 580, 5, 58, 30, 2, 579, 572, 3, 2, 2, 2, 580, 583, 3, 2, 2, 2, 581, 579, 3, 2, 2, 2, 581, 582, 3, 2, 2, 2, 582, 585, 3, 2, 2, 2, 583, 581, 3, 2, 2, 2, 584, 556, 3, 2, 2, 2, 584, 570, 3, 2, 2, 2, 585, 57, 3, 2, 2, 2, 586, 587, 5, 100, 51, 2, 587, 588, 7, 127, 2, 2, 588, 589, 7, 53, 2, 2, 589, 590, 7, 127, 2, 2, 590, 591, 5, 166, 84, 2, 591, 594, 3, 2, 2, 2, 592, 594, 5, 100, 51, 2, 593, 586, 3, 2, 2, 2, 593, 592, 3, 2, 2, 2, 594, 59, 3, 2, 2, 2, 595, 596, 7, 66, 2, 2, 596, 597, 7, 127, 2, 2, 597, 598, 7, 67, 2, 2, 598, 599, 7, 127, 2, 2, 599, 607, 5, 66, 34, 2, 600, 602, 7, 4, 2, 2, 601, 603, 7, 127, 2, 2, 602, 601, 3, 2, 2, 2, 602, 603, 3, 2, 2, 2, 603, 604, 3, 2, 2, 2, 604, 606, 5, 66, 34, 2, 605, 600, 3, 2, 2, 2, 606, 609, 3, 2, 2, 2, 607, 605, 3, 2, 2, 2, 607, 608, 3, 2, 2, 2, 608, 61, 3, 2, 2, 2, 609, 607, 3, 2, 2, 2, 610, 611, 7, 68, 2, 2, 611, 612, 7, 127, 2, 2, 612, 613, 5, 100, 51, 2, 613, 63, 3, 2, 2, 2, 614, 615, 7, 69, 2, 2, 615, 616, 7, 127, 2, 2, 616, 617, 5, 100, 51, 2, 617, 65, 3, 2, 2, 2, 618, 623, 5, 100, 51, 2, 619, 621, 7, 127, 2, 2, 620, 619, 3, 2, 2, 2, 620, 621, 3, 2, 2, 2, 621, 622, 3, 2, 2, 2, 622, 624, 9, 2, 2, 2, 623, 620, 3, 2, 2, 2, 623, 624, 3, 2, 2, 2, 624, 67, 3, 2, 2, 2, 625, 626, 7, 74, 2, 2, 626, 627, 7, 127, 2, 2, 627, 628, 5, 100, 51, 2, 628, 69, 3, 2, 2, 2, 629, 640, 5, 72, 37, 2, 630, 632, 7, 127, 2, 2, 631, 630, 3, 2, 2, 2, 631, 632, 3, 2, 2, 2, 632, 633, 3, 2, 2, 2, 633, 635, 7, 4, 2, 2, 634, 636, 7, 127, 2, 2, 635, 634, 3, 2, 2, 2, 635, 636, 3, 2, 2, 2, 636, 637, 3, 2, 2, 2, 637, 639, 5, 72, 37, 2, 638, 631, 3, 2, 2, 2, 639, 642, 3, 2, 2, 2, 640, 638, 3, 2, 2, 2, 640, 641, 3, 2, 2, 2, 641, 71, 3, 2, 2, 2, 642, 640, 3, 2, 2, 2, 643, 645, 5, 166, 84, 2, 644, 646, 7, 127, 2, 2, 645, 644, 3, 2, 2, 2, 645, 646, 3, 2, 2, 2, 646, 647, 3, 2, 2, 2, 647, 649, 7, 5, 2, 2, 648, 650, 7, 127, 2, 2, 649, 648, 3, 2, 2, 2, 649, 650, 3, 2, 2, 2, 650, 651, 3, 2, 2, 2, 651, 652, 5, 74, 38, 2, 652, 655, 3, 2, 2, 2, 653, 655, 5, 74, 38, 2, 654, 643, 3, 2, 2, 2, 654, 653, 3, 2, 2, 2, 655, 73, 3, 2, 2, 2, 656, 657, 5, 76, 39, 2, 657, 75, 3, 2, 2, 2, 658, 665, 5, 78, 40, 2, 659, 661, 7, 127, 2, 2, 660, 659, 3, 2, 2, 2, 660, 661, 3, 2, 2, 2, 661, 662, 3, 2, 2, 2, 662, 664, 5, 80, 41, 2, 663, 660, 3, 2, 2, 2, 664, 667, 3, 2, 2, 2, 665, 663, 3, 2, 2, 2, 665, 666, 3, 2, 2, 2, 666, 673, 3, 2, 2, 2, 667, 665, 3, 2, 2, 2, 668, 669, 7, 9, 2, 2, 669, 670, 5, 76, 39, 2, 670, 671, 7, 10, 2, 2, 671, 673, 3, 2, 2, 2, 672, 658, 3, 2, 2, 2, 672, 668, 3, 2, 2, 2, 673, 77, 3, 2, 2, 2, 674, 676, 7, 9, 2, 2, 675, 677, 7, 127, 2, 2, 676, 675, 3, 2, 2, 2, 676, 677, 3, 2, 2, 2, 677, 682, 3, 2, 2, 2, 678, 680, 5, 166, 84, 2, 679, 681, 7, 127, 2, 2, 680, 679, 3, 2, 2, 2, 680, 681, 3, 2, 2, 2, 681, 683, 3, 2, 2, 2, 682, 678, 3, 2, 2, 2, 682, 683, 3, 2, 2, 2, 683, 688, 3, 2, 2, 2, 684, 686, 5, 90, 46, 2, 685, 687, 7, 127, 2, 2, 686, 685, 3, 2, 2, 2, 686, 687, 3, 2, 2, 2, 687, 689, 3, 2, 2, 2, 688, 684, 3, 2, 2, 2, 688, 689, 3, 2, 2, 2, 689, 694, 3, 2, 2, 2, 690, 692, 5, 86, 44, 2, 691, 693, 7, 127, 2, 2, 692, 691, 3, 2, 2, 2, 692, 693, 3, 2, 2, 2, 693, 695, 3, 2, 2, 2, 694, 690, 3, 2, 2, 2, 694, 695, 3, 2, 2, 2, 695, 696, 3, 2, 2, 2, 696, 697, 7, 10, 2, 2, 697, 79, 3, 2, 2, 2, 698, 700, 5, 82, 42, 2, 699, 701, 7, 127, 2, 2, 700, 699, 3, 2, 2, 2, 700, 701, 3, 2, 2, 2, 701, 702, 3, 2, 2, 2, 702, 703, 5, 78, 40, 2, 703, 81, 3, 2, 2, 2, 704, 706, 5, 188, 95, 2, 705, 707, 7, 127, 2, 2, 706, 705, 3, 2, 2, 2, 706, 707, 3, 2, 2, 2, 707, 708, 3, 2, 2, 2, 708, 710, 5, 192, 97, 2, 709, 711, 7, 127, 2, 2, 710, 709, 3, 2, 2, 2, 710, 711, 3, 2, 2, 2, 711, 713, 3, 2, 2, 2, 712, 714, 5, 84, 43, 2, 713, 712, 3, 2, 2, 2, 713, 714, 3, 2, 2, 2, 714, 716, 3, 2, 2, 2, 715, 717, 7, 127, 2, 2, 716, 715, 3, 2, 2, 2, 716, 717, 3, 2, 2, 2, 717, 718, 3, 2, 2, 2, 718, 720, 5, 192, 97, 2, 719, 721, 7, 127, 2, 2, 720, 719, 3, 2, 2, 2, 720, 721, 3, 2, 2, 2, 721, 722, 3, 2, 2, 2, 722, 723, 5, 190, 96, 2, 723, 769, 3, 2, 2, 2, 724, 726, 5, 188, 95, 2, 725, 727, 7, 127, 2, 2, 726, 725, 3, 2, 2, 2, 726, 727, 3, 2, 2, 2, 727, 728, 3, 2, 2, 2, 728, 730, 5, 192, 97, 2, 729, 731, 7, 127, 2, 2, 730, 729, 3, 2, 2, 2, 730, 731, 3, 2, 2, 2, 731, 733, 3, 2, 2, 2, 732, 734, 5, 84, 43, 2, 733, 732, 3, 2, 2, 2, 733, 734, 3, 2, 2, 2, 734, 736, 3, 2, 2, 2, 735, 737, 7, 127, 2, 2, 736, 735, 3, 2, 2, 2, 736, 737, 3, 2, 2, 2, 737, 738, 3, 2, 2, 2, 738, 739, 5, 192, 97, 2, 739, 769, 3, 2, 2, 2, 740, 742, 5, 192, 97, 2, 741, 743, 7, 127, 2, 2, 742, 741, 3, 2, 2, 2, 742, 743, 3, 2, 2, 2, 743, 745, 3, 2, 2, 2, 744, 746, 5, 84, 43, 2, 745, 744, 3, 2, 2, 2, 745, 746, 3, 2, 2, 2, 746, 748, 3, 2, 2, 2, 747, 749, 7, 127, 2, 2, 748, 747, 3, 2, 2, 2, 748, 749, 3, 2, 2, 2, 749, 750, 3, 2, 2, 2, 750, 752, 5, 192, 97, 2, 751, 753, 7, 127, 2, 2, 752, 751, 3, 2, 2, 2, 752, 753, 3, 2, 2, 2, 753, 754, 3, 2, 2, 2, 754, 755, 5, 190, 96, 2, 755, 769, 3, 2, 2, 2, 756, 758, 5, 192, 97, 2, 757, 759, 7, 127, 2, 2, 758, 757, 3, 2, 2, 2, 758, 759, 3, 2, 2, 2, 759, 761, 3, 2, 2, 2, 760, 762, 5, 84, 43, 2, 761, 760, 3, 2, 2, 2, 761, 762, 3, 2, 2, 2, 762, 764, 3, 2, 2, 2, 763, 765, 7, 127, 2, 2, 764, 763, 3, 2, 2, 2, 764, 765, 3, 2, 2, 2, 765, 766, 3, 2, 2, 2, 766, 767, 5, 192, 97, 2, 767, 769, 3, 2, 2, 2, 768, 704, 3, 2, 2, 2, 768, 724, 3, 2, 2, 2, 768, 740, 3, 2, 2, 2, 768, 756, 3, 2, 2, 2, 769, 83, 3, 2, 2, 2, 770, 772, 7, 11, 2, 2, 771, 773, 7, 127, 2, 2, 772, 771, 3, 2, 2, 2, 772, 773, 3, 2, 2, 2, 773, 778, 3, 2, 2, 2, 774, 776, 5, 166, 84, 2, 775, 777, 7, 127, 2, 2, 776, 775, 3, 2, 2, 2, 776, 777, 3, 2, 2, 2, 777, 779, 3, 2, 2, 2, 778, 774, 3, 2, 2, 2, 778, 779, 3, 2, 2, 2, 779, 784, 3, 2, 2, 2, 780, 782, 5, 88, 45, 2, 781, 783, 7, 127, 2, 2, 782, 781, 3, 2, 2, 2, 782, 783, 3, 2, 2, 2, 783, 785, 3, 2, 2, 2, 784, 780, 3, 2, 2, 2, 784, 785, 3, 2, 2, 2, 785, 787, 3, 2, 2, 2, 786, 788, 5, 94, 48, 2, 787, 786, 3, 2, 2, 2, 787, 788, 3, 2, 2, 2, 788, 793, 3, 2, 2, 2, 789, 791, 5, 86, 44, 2, 790, 792, 7, 127, 2, 2, 791, 790, 3, 2, 2, 2, 791, 792, 3, 2, 2, 2, 792, 794, 3, 2, 2, 2, 793, 789, 3, 2, 2, 2, 793, 794, 3, 2, 2, 2, 794, 795, 3, 2, 2, 2, 795, 796, 7, 12, 2, 2, 796, 85, 3, 2, 2, 2, 797, 800, 5, 170, 86, 2, 798, 800, 5, 172, 87, 2, 799, 797, 3, 2, 2, 2, 799, 798, 3, 2, 2, 2, 800, 87, 3, 2, 2, 2, 801, 803, 7, 13, 2, 2, 802, 804, 7, 127, 2, 2, 803, 802, 3, 2, 2, 2, 803, 804, 3, 2, 2, 2, 804, 805, 3, 2, 2, 2, 805, 819, 5, 98, 50, 2, 806, 808, 7, 127, 2, 2, 807, 806, 3, 2, 2, 2, 807, 808, 3, 2, 2, 2, 808, 809, 3, 2, 2, 2, 809, 811, 7, 14, 2, 2, 810, 812, 7, 13, 2, 2, 811, 810, 3, 2, 2, 2, 811, 812, 3, 2, 2, 2, 812, 814, 3, 2, 2, 2, 813, 815, 7, 127, 2, 2, 814, 813, 3, 2, 2, 2, 814, 815, 3, 2, 2, 2, 815, 816, 3, 2, 2, 2, 816, 818, 5, 98, 50, 2, 817, 807, 3, 2, 2, 2, 818, 821, 3, 2, 2, 2, 819, 817, 3, 2, 2, 2, 819, 820, 3, 2, 2, 2, 820, 89, 3, 2, 2, 2, 821, 819, 3, 2, 2, 2, 822, 829, 5, 92, 47, 2, 823, 825, 7, 127, 2, 2, 824, 823, 3, 2, 2, 2, 824, 825, 3, 2, 2, 2, 825, 826, 3, 2, 2, 2, 826, 828, 5, 92, 47, 2, 827, 824, 3, 2, 2, 2, 828, 831, 3, 2, 2, 2, 829, 827, 3, 2, 2, 2, 829, 830, 3, 2, 2, 2, 830, 91, 3, 2, 2, 2, 831, 829, 3, 2, 2, 2, 832, 834, 7, 13, 2, 2, 833, 835, 7, 127, 2, 2, 834, 833, 3, 2, 2, 2, 834, 835, 3, 2, 2, 2, 835, 836, 3, 2, 2, 2, 836, 837, 5, 96, 49, 2, 837, 93, 3, 2, 2, 2, 838, 840, 7, 8, 2, 2, 839, 841, 7, 127, 2, 2, 840, 839, 3, 2, 2, 2, 840, 841, 3, 2, 2, 2, 841, 846, 3, 2, 2, 2, 842, 844, 5, 178, 90, 2, 843, 845, 7, 127, 2, 2, 844, 843, 3, 2, 2, 2, 844, 845, 3, 2, 2, 2, 845, 847, 3, 2, 2, 2, 846, 842, 3, 2, 2, 2, 846, 847, 3, 2, 2, 2, 847, 858, 3, 2, 2, 2, 848, 850, 7, 15, 2, 2, 849, 851, 7, 127, 2, 2, 850, 849, 3, 2, 2, 2, 850, 851, 3, 2, 2, 2, 851, 856, 3, 2, 2, 2, 852, 854, 5, 178, 90, 2, 853, 855, 7, 127, 2, 2, 854, 853, 3, 2, 2, 2, 854, 855, 3, 2, 2, 2, 855, 857, 3, 2, 2, 2, 856, 852, 3, 2, 2, 2, 856, 857, 3, 2, 2, 2, 857, 859, 3, 2, 2, 2, 858, 848, 3, 2, 2, 2, 858, 859, 3, 2, 2, 2, 859, 95, 3, 2, 2, 2, 860, 861, 5, 182, 92, 2, 861, 97, 3, 2, 2, 2, 862, 863, 5, 182, 92, 2, 863, 99, 3, 2, 2, 2, 864, 865, 5, 102, 52, 2, 865, 101, 3, 2, 2, 2, 866, 873, 5, 104, 53, 2, 867, 868, 7, 127, 2, 2, 868, 869, 7, 75, 2, 2, 869, 870, 7, 127, 2, 2, 870, 872, 5, 104, 53, 2, 871, 867, 3, 2, 2, 2, 872, 875, 3, 2, 2, 2, 873, 871, 3, 2, 2, 2, 873, 874, 3, 2, 2, 2, 874, 103, 3, 2, 2, 2, 875, 873, 3, 2, 2, 2, 876, 883, 5, 106, 54, 2, 877, 878, 7, 127, 2, 2, 878, 879, 7, 76, 2, 2, 879, 880, 7, 127, 2, 2, 880, 882, 5, 106, 54, 2, 881, 877, 3, 2, 2, 2, 882, 885, 3, 2, 2, 2, 883, 881, 3, 2, 2, 2, 883, 884, 3, 2, 2, 2, 884, 105, 3, 2, 2, 2, 885, 883, 3, 2, 2, 2, 886, 893, 5, 108, 55, 2, 887, 888, 7, 127, 2, 2, 888, 889, 7, 77, 2, 2, 889, 890, 7, 127, 2, 2, 890, 892, 5, 108, 55, 2, 891, 887, 3, 2, 2, 2, 892, 895, 3, 2, 2, 2, 893, 891, 3, 2, 2, 2, 893, 894, 3, 2, 2, 2, 894, 107, 3, 2, 2, 2, 895, 893, 3, 2, 2, 2, 896, 898, 7, 78, 2, 2, 897, 899, 7, 127, 2, 2, 898, 897, 3, 2, 2, 2, 898, 899, 3, 2, 2, 2, 899, 901, 3, 2, 2, 2, 900, 896, 3, 2, 2, 2, 901, 904, 3, 2, 2, 2, 902, 900, 3, 2, 2, 2, 902, 903, 3, 2, 2, 2, 903, 905, 3, 2, 2, 2, 904, 902, 3, 2, 2, 2, 905, 906, 5, 110, 56, 2, 906, 109, 3, 2, 2, 2, 907, 914, 5, 112, 57, 2, 908, 910, 7, 127, 2, 2, 909, 908, 3, 2, 2, 2, 909, 910, 3, 2, 2, 2, 910, 911, 3, 2, 2, 2, 911, 913, 5, 132, 67, 2, 912, 909, 3, 2, 2, 2, 913, 916, 3, 2, 2, 2, 914, 912, 3, 2, 2, 2, 914, 915, 3, 2, 2, 2, 915, 111, 3, 2, 2, 2, 916, 914, 3, 2, 2, 2, 917, 936, 5, 114, 58, 2, 918, 920, 7, 127, 2, 2, 919, 918, 3, 2, 2, 2, 919, 920, 3, 2, 2, 2, 920, 921, 3, 2, 2, 2, 921, 923, 7, 16, 2, 2, 922, 924, 7, 127, 2, 2, 923, 922, 3, 2, 2, 2, 923, 924, 3, 2, 2, 2, 924, 925, 3, 2, 2, 2, 925, 935, 5, 114, 58, 2, 926, 928, 7, 127, 2, 2, 927, 926, 3, 2, 2, 2, 927, 928, 3, 2, 2, 2, 928, 929, 3, 2, 2, 2, 929, 931, 7, 7, 2, 2, 930, 932, 7, 127, 2, 2, 931, 930, 3, 2, 2, 2, 931, 932, 3, 2, 2, 2, 932, 933, 3, 2, 2, 2, 933, 935, 5, 114, 58, 2, 934, 919, 3, 2, 2, 2, 934, 927, 3, 2, 2, 2, 935, 938, 3, 2, 2, 2, 936, 934, 3, 2, 2, 2, 936, 937, 3, 2, 2, 2, 937, 113, 3, 2, 2, 2, 938, 936, 3, 2, 2, 2, 939, 966, 5, 116, 59, 2, 940, 942, 7, 127, 2, 2, 941, 940, 3, 2, 2, 2, 941, 942, 3, 2, 2, 2, 942, 943, 3, 2, 2, 2, 943, 945, 7, 8, 2, 2, 944, 946, 7, 127, 2, 2, 945, 944, 3, 2, 2, 2, 945, 946, 3, 2, 2, 2, 946, 947, 3, 2, 2, 2, 947, 965, 5, 116, 59, 2, 948, 950, 7, 127, 2, 2, 949, 948, 3, 2, 2, 2, 949, 950, 3, 2, 2, 2, 950, 951, 3, 2, 2, 2, 951, 953, 7, 17, 2, 2, 952, 954, 7, 127, 2, 2, 953, 952, 3, 2, 2, 2, 953, 954, 3, 2, 2, 2, 954, 955, 3, 2, 2, 2, 955, 965, 5, 116, 59, 2, 956, 958, 7, 127, 2, 2, 957, 956, 3, 2, 2, 2, 957, 958, 3, 2, 2, 2, 958, 959, 3, 2, 2, 2, 959, 961, 7, 18, 2, 2, 960, 962, 7, 127, 2, 2, 961, 960, 3, 2, 2, 2, 961, 962, 3, 2, 2, 2, 962, 963, 3, 2, 2, 2, 963, 965, 5, 116, 59, 2, 964, 941, 3, 2, 2, 2, 964, 949, 3, 2, 2, 2, 964, 957, 3, 2, 2, 2, 965, 968, 3, 2, 2, 2, 966, 964, 3, 2, 2, 2, 966, 967, 3, 2, 2, 2, 967, 115, 3, 2, 2, 2, 968, 966, 3, 2, 2, 2, 969, 980, 5, 118, 60, 2, 970, 972, 7, 127, 2, 2, 971, 970, 3, 2, 2, 2, 971, 972, 3, 2, 2, 2, 972, 973, 3, 2, 2, 2, 973, 975, 7, 19, 2, 2, 974, 976, 7, 127, 2, 2, 975, 974, 3, 2, 2, 2, 975, 976, 3, 2, 2, 2, 976, 977, 3, 2, 2, 2, 977, 979, 5, 118, 60, 2, 978, 971, 3, 2, 2, 2, 979, 982, 3, 2, 2, 2, 980, 978, 3, 2, 2, 2, 980, 981, 3, 2, 2, 2, 981, 117, 3, 2, 2, 2, 982, 980, 3, 2, 2, 2, 983, 985, 9, 3, 2, 2, 984, 986, 7, 127, 2, 2, 985, 984, 3, 2, 2, 2, 985, 986, 3, 2, 2, 2, 986, 988, 3, 2, 2, 2, 987, 983, 3, 2, 2, 2, 988, 991, 3, 2, 2, 2, 989, 987, 3, 2, 2, 2, 989, 990, 3, 2, 2, 2, 990, 992, 3, 2, 2, 2, 991, 989, 3, 2, 2, 2, 992, 993, 5, 120, 61, 2, 993, 119, 3, 2, 2, 2, 994, 1044, 5, 122, 62, 2, 995, 997, 7, 127, 2, 2, 996, 995, 3, 2, 2, 2, 996, 997, 3, 2, 2, 2, 997, 998, 3, 2, 2, 2, 998, 999, 7, 11, 2, 2, 999, 1000, 5, 100, 51, 2, 1000, 1001, 7, 12, 2, 2, 1001, 1043, 3, 2, 2, 2, 1002, 1004, 7, 127, 2, 2, 1003, 1002, 3, 2, 2, 2, 1003, 1004, 3, 2, 2, 2, 1004, 1005, 3, 2, 2, 2, 1005, 1007, 7, 11, 2, 2, 1006, 1008, 5, 100, 51, 2, 1007, 1006, 3, 2, 2, 2, 1007, 1008, 3, 2, 2, 2, 1008, 1009, 3, 2, 2, 2, 1009, 1011, 7, 15, 2, 2, 1010, 1012, 5, 100, 51, 2, 1011, 1010, 3, 2, 2, 2, 1011, 1012, 3, 2, 2, 2, 1012, 1013, 3, 2, 2, 2, 1013, 1043, 7, 12, 2, 2, 1014, 1015, 7, 127, 2, 2, 1015, 1027, 7, 79, 2, 2, 1016, 1017, 7, 127, 2, 2, 1017, 1018, 7, 80, 2, 2, 1018, 1019, 7, 127, 2, 2, 1019, 1027, 7, 63, 2, 2, 1020, 1021, 7, 127, 2, 2, 1021, 1022, 7, 81, 2, 2, 1022, 1023, 7, 127, 2, 2, 1023, 1027, 7, 63, 2, 2, 1024, 1025, 7, 127, 2, 2, 1025, 1027, 7, 82, 2, 2, 1026, 1014, 3, 2, 2, 2, 1026, 1016, 3, 2, 2, 2, 1026, 1020, 3, 2, 2, 2, 1026, 1024, 3, 2, 2, 2, 1027, 1029, 3, 2, 2, 2, 1028, 1030, 7, 127, 2, 2, 1029, 1028, 3, 2, 2, 2, 1029, 1030, 3, 2, 2, 2, 1030, 1031, 3, 2, 2, 2, 1031, 1043, 5, 122, 62, 2, 1032, 1033, 7, 127, 2, 2, 1033, 1034, 7, 83, 2, 2, 1034, 1035, 7, 127, 2, 2, 1035, 1043, 7, 84, 2, 2, 1036, 1037, 7, 127, 2, 2, 1037, 1038, 7, 83, 2, 2, 1038, 1039, 7, 127, 2, 2, 1039, 1040, 7, 78, 2, 2, 1040, 1041, 7, 127, 2, 2, 1041, 1043, 7, 84, 2, 2, 1042, 996, 3, 2, 2, 2, 1042, 1003, 3, 2, 2, 2, 1042, 1026, 3, 2, 2, 2, 1042, 1032, 3, 2, 2, 2, 1042, 1036, 3, 2, 2, 2, 1043, 1046, 3, 2, 2, 2, 1044, 1042, 3, 2, 2, 2, 1044, 1045, 3, 2, 2, 2, 1045, 121, 3, 2, 2, 2, 1046, 1044, 3, 2, 2, 2, 1047, 1054, 5, 124, 63, 2, 1048, 1050, 7, 127, 2, 2, 1049, 1048, 3, 2, 2, 2, 1049, 1050, 3, 2, 2, 2, 1050, 1051, 3, 2, 2, 2, 1051, 1053, 5, 160, 81, 2, 1052, 1049, 3, 2, 2, 2, 1053, 1056, 3, 2, 2, 2, 1054, 1052, 3, 2, 2, 2, 1054, 1055, 3, 2, 2, 2, 1055, 1061, 3, 2, 2, 2, 1056, 1054, 3, 2, 2, 2, 1057, 1059, 7, 127, 2, 2, 1058, 1057, 3, 2, 2, 2, 1058, 1059, 3, 2, 2, 2, 1059, 1060, 3, 2, 2, 2, 1060, 1062, 5, 90, 46, 2, 1061, 1058, 3, 2, 2, 2, 1061, 1062, 3, 2, 2, 2, 1062, 123, 3, 2, 2, 2, 1063, 1177, 5, 126, 64, 2, 1064, 1177, 5, 172, 87, 2, 1065, 1177, 5, 162, 82, 2, 1066, 1068, 7, 85, 2, 2, 1067, 1069, 7, 127, 2, 2, 1068, 1067, 3, 2, 2, 2, 1068, 1069, 3, 2, 2, 2, 1069, 1070, 3, 2, 2, 2, 1070, 1072, 7, 9, 2, 2, 1071, 1073, 7, 127, 2, 2, 1072, 1071, 3, 2, 2, 2, 1072, 1073, 3, 2, 2, 2, 1073, 1074, 3, 2, 2, 2, 1074, 1076, 7, 8, 2, 2, 1075, 1077, 7, 127, 2, 2, 1076, 1075, 3, 2, 2, 2, 1076, 1077, 3, 2, 2, 2, 1077, 1078, 3, 2, 2, 2, 1078, 1177, 7, 10, 2, 2, 1079, 1177, 5, 156, 79, 2, 1080, 1177, 5, 158, 80, 2, 1081, 1083, 7, 86, 2, 2, 1082, 1084, 7, 127, 2, 2, 1083, 1082, 3, 2, 2, 2, 1083, 1084, 3, 2, 2, 2, 1084, 1085, 3, 2, 2, 2, 1085, 1087, 7, 9, 2, 2, 1086, 1088, 7, 127, 2, 2, 1087, 1086, 3, 2, 2, 2, 1087, 1088, 3, 2, 2, 2, 1088, 1089, 3, 2, 2, 2, 1089, 1091, 5, 138, 70, 2, 1090, 1092, 7, 127, 2, 2, 1091, 1090, 3, 2, 2, 2, 1091, 1092, 3, 2, 2, 2, 1092, 1093, 3, 2, 2, 2, 1093, 1094, 7, 10, 2, 2, 1094, 1177, 3, 2, 2, 2, 1095, 1097, 7, 87, 2, 2, 1096, 1098, 7, 127, 2, 2, 1097, 1096, 3, 2, 2, 2, 1097, 1098, 3, 2, 2, 2, 1098, 1099, 3, 2, 2, 2, 1099, 1101, 7, 9, 2, 2, 1100, 1102, 7, 127, 2, 2, 1101, 1100, 3, 2, 2, 2, 1101, 1102, 3, 2, 2, 2, 1102, 1103, 3, 2, 2, 2, 1103, 1105, 5, 138, 70, 2, 1104, 1106, 7, 127, 2, 2, 1105, 1104, 3, 2, 2, 2, 1105, 1106, 3, 2, 2, 2, 1106, 1112, 3, 2, 2, 2, 1107, 1109, 7, 127, 2, 2, 1108, 1107, 3, 2, 2, 2, 1108, 1109, 3, 2, 2, 2, 1109, 1110, 3, 2, 2, 2, 1110, 1111, 7, 14, 2, 2, 1111, 1113, 5, 100, 51, 2, 1112, 1108, 3, 2, 2, 2, 1112, 1113, 3, 2, 2, 2, 1113, 1114, 3, 2, 2, 2, 1114, 1115, 7, 10, 2, 2, 1115, 1177, 3, 2, 2, 2, 1116, 1118, 7, 49, 2, 2, 1117, 1119, 7, 127, 2, 2, 1118, 1117, 3, 2, 2, 2, 1118, 1119, 3, 2, 2, 2, 1119, 1120, 3, 2, 2, 2, 1120, 1122, 7, 9, 2, 2, 1121, 1123, 7, 127, 2, 2, 1122, 1121, 3, 2, 2, 2, 1122, 1123, 3, 2, 2, 2, 1123, 1124, 3, 2, 2, 2, 1124, 1126, 5, 138, 70, 2, 1125, 1127, 7, 127, 2, 2, 1126, 1125, 3, 2, 2, 2, 1126, 1127, 3, 2, 2, 2, 1127, 1128, 3, 2, 2, 2, 1128, 1129, 7, 10, 2, 2, 1129, 1177, 3, 2, 2, 2, 1130, 1132, 7, 88, 2, 2, 1131, 1133, 7, 127, 2, 2, 1132, 1131, 3, 2, 2, 2, 1132, 1133, 3, 2, 2, 2, 1133, 1134, 3, 2, 2, 2, 1134, 1136, 7, 9, 2, 2, 1135, 1137, 7, 127, 2, 2, 1136, 1135, 3, 2, 2, 2, 1136, 1137, 3, 2, 2, 2, 1137, 1138, 3, 2, 2, 2, 1138, 1140, 5, 138, 70, 2, 1139, 1141, 7, 127, 2, 2, 1140, 1139, 3, 2, 2, 2, 1140, 1141, 3, 2, 2, 2, 1141, 1142, 3, 2, 2, 2, 1142, 1143, 7, 10, 2, 2, 1143, 1177, 3, 2, 2, 2, 1144, 1146, 7, 89, 2, 2, 1145, 1147, 7, 127, 2, 2, 1146, 1145, 3, 2, 2, 2, 1146, 1147, 3, 2, 2, 2, 1147, 1148, 3, 2, 2, 2, 1148, 1150, 7, 9, 2, 2, 1149, 1151, 7, 127, 2, 2, 1150, 1149, 3, 2, 2, 2, 1150, 1151, 3, 2, 2, 2, 1151, 1152, 3, 2, 2, 2, 1152, 1154, 5, 138, 70, 2, 1153, 1155, 7, 127, 2, 2, 1154, 1153, 3, 2, 2, 2, 1154, 1155, 3, 2, 2, 2, 1155, 1156, 3, 2, 2, 2, 1156, 1157, 7, 10, 2, 2, 1157, 1177, 3, 2, 2, 2, 1158, 1160, 7, 90, 2, 2, 1159, 1161, 7, 127, 2, 2, 1160, 1159, 3, 2, 2, 2, 1160, 1161, 3, 2, 2, 2, 1161, 1162, 3, 2, 2, 2, 1162, 1164, 7, 9, 2, 2, 1163, 1165, 7, 127, 2, 2, 1164, 1163, 3, 2, 2, 2, 1164, 1165, 3, 2, 2, 2, 1165, 1166, 3, 2, 2, 2, 1166, 1168, 5, 138, 70, 2, 1167, 1169, 7, 127, 2, 2, 1168, 1167, 3, 2, 2, 2, 1168, 1169, 3, 2, 2, 2, 1169, 1170, 3, 2, 2, 2, 1170, 1171, 7, 10, 2, 2, 1171, 1177, 3, 2, 2, 2, 1172, 1177, 5, 136, 69, 2, 1173, 1177, 5, 134, 68, 2, 1174, 1177, 5, 142, 72, 2, 1175, 1177, 5, 166, 84, 2, 1176, 1063, 3, 2, 2, 2, 1176, 1064, 3, 2, 2, 2, 1176, 1065, 3, 2, 2, 2, 1176, 1066, 3, 2, 2, 2, 1176, 1079, 3, 2, 2, 2, 1176, 1080, 3, 2, 2, 2, 1176, 1081, 3, 2, 2, 2, 1176, 1095, 3, 2, 2, 2, 1176, 1116, 3, 2, 2, 2, 1176, 1130, 3, 2, 2, 2, 1176, 1144, 3, 2, 2, 2, 1176, 1158, 3, 2, 2, 2, 1176, 1172, 3, 2, 2, 2, 1176, 1173, 3, 2, 2, 2, 1176, 1174, 3, 2, 2, 2, 1176, 1175, 3, 2, 2, 2, 1177, 125, 3, 2, 2, 2, 1178, 1185, 5, 168, 85, 2, 1179, 1185, 7, 99, 2, 2, 1180, 1185, 5, 128, 65, 2, 1181, 1185, 7, 84, 2, 2, 1182, 1185, 5, 170, 86, 2, 1183, 1185, 5, 130, 66, 2, 1184, 1178, 3, 2, 2, 2, 1184, 1179, 3, 2, 2, 2, 1184, 1180, 3, 2, 2, 2, 1184, 1181, 3, 2, 2, 2, 1184, 1182, 3, 2, 2, 2, 1184, 1183, 3, 2, 2, 2, 1185, 127, 3, 2, 2, 2, 1186, 1187, 9, 4, 2, 2, 1187, 129, 3, 2, 2, 2, 1188, 1190, 7, 11, 2, 2, 1189, 1191, 7, 127, 2, 2, 1190, 1189, 3, 2, 2, 2, 1190, 1191, 3, 2, 2, 2, 1191, 1209, 3, 2, 2, 2, 1192, 1194, 5, 100, 51, 2, 1193, 1195, 7, 127, 2, 2, 1194, 1193, 3, 2, 2, 2, 1194, 1195, 3, 2, 2, 2, 1195, 1206, 3, 2, 2, 2, 1196, 1198, 7, 4, 2, 2, 1197, 1199, 7, 127, 2, 2, 1198, 1197, 3, 2, 2, 2, 1198, 1199, 3, 2, 2, 2, 1199, 1200, 3, 2, 2, 2, 1200, 1202, 5, 100, 51, 2, 1201, 1203, 7, 127, 2, 2, 1202, 1201, 3, 2, 2, 2, 1202, 1203, 3, 2, 2, 2, 1203, 1205, 3, 2, 2, 2, 1204, 1196, 3, 2, 2, 2, 1205, 1208, 3, 2, 2, 2, 1206, 1204, 3, 2, 2, 2, 1206, 1207, 3, 2, 2, 2, 1207, 1210, 3, 2, 2, 2, 1208, 1206, 3, 2, 2, 2, 1209, 1192, 3, 2, 2, 2, 1209, 1210, 3, 2, 2, 2, 1210, 1211, 3, 2, 2, 2, 1211, 1212, 7, 12, 2, 2, 1212, 131, 3, 2, 2, 2, 1213, 1215, 7, 5, 2, 2, 1214, 1216, 7, 127, 2, 2, 1215, 1214, 3, 2, 2, 2, 1215, 1216, 3, 2, 2, 2, 1216, 1217, 3, 2, 2, 2, 1217, 1244, 5, 112, 57, 2, 1218, 1220, 7, 20, 2, 2, 1219, 1221, 7, 127, 2, 2, 1220, 1219, 3, 2, 2, 2, 1220, 1221, 3, 2, 2, 2, 1221, 1222, 3, 2, 2, 2, 1222, 1244, 5, 112, 57, 2, 1223, 1225, 7, 21, 2, 2, 1224, 1226, 7, 127, 2, 2, 1225, 1224, 3, 2, 2, 2, 1225, 1226, 3, 2, 2, 2, 1226, 1227, 3, 2, 2, 2, 1227, 1244, 5, 112, 57, 2, 1228, 1230, 7, 22, 2, 2, 1229, 1231, 7, 127, 2, 2, 1230, 1229, 3, 2, 2, 2, 1230, 1231, 3, 2, 2, 2, 1231, 1232, 3, 2, 2, 2, 1232, 1244, 5, 112, 57, 2, 1233, 1235, 7, 23, 2, 2, 1234, 1236, 7, 127, 2, 2, 1235, 1234, 3, 2, 2, 2, 1235, 1236, 3, 2, 2, 2, 1236, 1237, 3, 2, 2, 2, 1237, 1244, 5, 112, 57, 2, 1238, 1240, 7, 24, 2, 2, 1239, 1241, 7, 127, 2, 2, 1240, 1239, 3, 2, 2, 2, 1240, 1241, 3, 2, 2, 2, 1241, 1242, 3, 2, 2, 2, 1242, 1244, 5, 112, 57, 2, 1243, 1213, 3, 2, 2, 2, 1243, 1218, 3, 2, 2, 2, 1243, 1223, 3, 2, 2, 2, 1243, 1228, 3, 2, 2, 2, 1243, 1233, 3, 2, 2, 2, 1243, 1238, 3, 2, 2, 2, 1244, 133, 3, 2, 2, 2, 1245, 1247, 7, 9, 2, 2, 1246, 1248, 7, 127, 2, 2, 1247, 1246, 3, 2, 2, 2, 1247, 1248, 3, 2, 2, 2, 1248, 1249, 3, 2, 2, 2, 1249, 1251, 5, 100, 51, 2, 1250, 1252, 7, 127, 2, 2, 1251, 1250, 3, 2, 2, 2, 1251, 1252, 3, 2, 2, 2, 1252, 1253, 3, 2, 2, 2, 1253, 1254, 7, 10, 2, 2, 1254, 135, 3, 2, 2, 2, 1255, 1260, 5, 78, 40, 2, 1256, 1258, 7, 127, 2, 2, 1257, 1256, 3, 2, 2, 2, 1257, 1258, 3, 2, 2, 2, 1258, 1259, 3, 2, 2, 2, 1259, 1261, 5, 80, 41, 2, 1260, 1257, 3, 2, 2, 2, 1261, 1262, 3, 2, 2, 2, 1262, 1260, 3, 2, 2, 2, 1262, 1263, 3, 2, 2, 2, 1263, 137, 3, 2, 2, 2, 1264, 1269, 5, 140, 71, 2, 1265, 1267, 7, 127, 2, 2, 1266, 1265, 3, 2, 2, 2, 1266, 1267, 3, 2, 2, 2, 1267, 1268, 3, 2, 2, 2, 1268, 1270, 5, 68, 35, 2, 1269, 1266, 3, 2, 2, 2, 1269, 1270, 3, 2, 2, 2, 1270, 139, 3, 2, 2, 2, 1271, 1272, 5, 166, 84, 2, 1272, 1273, 7, 127, 2, 2, 1273, 1274, 7, 79, 2, 2, 1274, 1275, 7, 127, 2, 2, 1275, 1276, 5, 100, 51, 2, 1276, 141, 3, 2, 2, 2, 1277, 1279, 5, 144, 73, 2, 1278, 1280, 7, 127, 2, 2, 1279, 1278, 3, 2, 2, 2, 1279, 1280, 3, 2, 2, 2, 1280, 1281, 3, 2, 2, 2, 1281, 1283, 7, 9, 2, 2, 1282, 1284, 7, 127, 2, 2, 1283, 1282, 3, 2, 2, 2, 1283, 1284, 3, 2, 2, 2, 1284, 1289, 3, 2, 2, 2, 1285, 1287, 7, 64, 2, 2, 1286, 1288, 7, 127, 2, 2, 1287, 1286, 3, 2, 2, 2, 1287, 1288, 3, 2, 2, 2, 1288, 1290, 3, 2, 2, 2, 1289, 1285, 3, 2, 2, 2, 1289, 1290, 3, 2, 2, 2, 1290, 1308, 3, 2, 2, 2, 1291, 1293, 5, 100, 51, 2, 1292, 1294, 7, 127, 2, 2, 1293, 1292, 3, 2, 2, 2, 1293, 1294, 3, 2, 2, 2, 1294, 1305, 3, 2, 2, 2, 1295, 1297, 7, 4, 2, 2, 1296, 1298, 7, 127, 2, 2, 1297, 1296, 3, 2, 2, 2, 1297, 1298, 3, 2, 2, 2, 1298, 1299, 3, 2, 2, 2, 1299, 1301, 5, 100, 51, 2, 1300, 1302, 7, 127, 2, 2, 1301, 1300, 3, 2, 2, 2, 1301, 1302, 3, 2, 2, 2, 1302, 1304, 3, 2, 2, 2, 1303, 1295, 3, 2, 2, 2, 1304, 1307, 3, 2, 2, 2, 1305, 1303, 3, 2, 2, 2, 1305, 1306, 3, 2, 2, 2, 1306, 1309, 3, 2, 2, 2, 1307, 1305, 3, 2, 2, 2, 1308, 1291, 3, 2, 2, 2, 1308, 1309, 3, 2, 2, 2, 1309, 1310, 3, 2, 2, 2, 1310, 1311, 7, 10, 2, 2, 1311, 143, 3, 2, 2, 2, 1312, 1315, 5, 186, 94, 2, 1313, 1315, 7, 93, 2, 2, 1314, 1312, 3, 2, 2, 2, 1314, 1313, 3, 2, 2, 2, 1315, 145, 3, 2, 2, 2, 1316, 1318, 5, 152, 77, 2, 1317, 1319, 7, 127, 2, 2, 1318, 1317, 3, 2, 2, 2, 1318, 1319, 3, 2, 2, 2, 1319, 1320, 3, 2, 2, 2, 1320, 1322, 7, 9, 2, 2, 1321, 1323, 7, 127, 2, 2, 1322, 1321, 3, 2, 2, 2, 1322, 1323, 3, 2, 2, 2, 1323, 1341, 3, 2, 2, 2, 1324, 1326, 5, 100, 51, 2, 1325, 1327, 7, 127, 2, 2, 1326, 1325, 3, 2, 2, 2, 1326, 1327, 3, 2, 2, 2, 1327, 1338, 3, 2, 2, 2, 1328, 1330, 7, 4, 2, 2, 1329, 1331, 7, 127, 2, 2, 1330, 1329, 3, 2, 2, 2, 1330, 1331, 3, 2, 2, 2, 1331, 1332, 3, 2, 2, 2, 1332, 1334, 5, 100, 51, 2, 1333, 1335, 7, 127, 2, 2, 1334, 1333, 3, 2, 2, 2, 1334, 1335, 3, 2, 2, 2, 1335, 1337, 3, 2, 2, 2, 1336, 1328, 3, 2, 2, 2, 1337, 1340, 3, 2, 2, 2, 1338, 1336, 3, 2, 2, 2, 1338, 1339, 3, 2, 2, 2, 1339, 1342, 3, 2, 2, 2, 1340, 1338, 3, 2, 2, 2, 1341, 1324, 3, 2, 2, 2, 1341, 1342, 3, 2, 2, 2, 1342, 1343, 3, 2, 2, 2, 1343, 1344, 7, 10, 2, 2, 1344, 147, 3, 2, 2, 2, 1345, 1346, 5, 152, 77, 2, 1346, 149, 3, 2, 2, 2, 1347, 1348, 5, 186, 94, 2, 1348, 151, 3, 2, 2, 2, 1349, 1350, 5, 154, 78, 2, 1350, 1351, 5, 186, 94, 2, 1351, 153, 3, 2, 2, 2, 1352, 1353, 5, 186, 94, 2, 1353, 1354, 7, 25, 2, 2, 1354, 1356, 3, 2, 2, 2, 1355, 1352, 3, 2, 2, 2, 1356, 1359, 3, 2, 2, 2, 1357, 1355, 3, 2, 2, 2, 1357, 1358, 3, 2, 2, 2, 1358, 155, 3, 2, 2, 2, 1359, 1357, 3, 2, 2, 2, 1360, 1362, 7, 11, 2, 2, 1361, 1363, 7, 127, 2, 2, 1362, 1361, 3, 2, 2, 2, 1362, 1363, 3, 2, 2, 2, 1363, 1364, 3, 2, 2, 2, 1364, 1373, 5, 138, 70, 2, 1365, 1367, 7, 127, 2, 2, 1366, 1365, 3, 2, 2, 2, 1366, 1367, 3, 2, 2, 2, 1367, 1368, 3, 2, 2, 2, 1368, 1370, 7, 14, 2, 2, 1369, 1371, 7, 127, 2, 2, 1370, 1369, 3, 2, 2, 2, 1370, 1371, 3, 2, 2, 2, 1371, 1372, 3, 2, 2, 2, 1372, 1374, 5, 100, 51, 2, 1373, 1366, 3, 2, 2, 2, 1373, 1374, 3, 2, 2, 2, 1374, 1376, 3, 2, 2, 2, 1375, 1377, 7, 127, 2, 2, 1376, 1375, 3, 2, 2, 2, 1376, 1377, 3, 2, 2, 2, 1377, 1378, 3, 2, 2, 2, 1378, 1379, 7, 12, 2, 2, 1379, 157, 3, 2, 2, 2, 1380, 1382, 7, 11, 2, 2, 1381, 1383, 7, 127, 2, 2, 1382, 1381, 3, 2, 2, 2, 1382, 1383, 3, 2, 2, 2, 1383, 1392, 3, 2, 2, 2, 1384, 1386, 5, 166, 84, 2, 1385, 1387, 7, 127, 2, 2, 1386, 1385, 3, 2, 2, 2, 1386, 1387, 3, 2, 2, 2, 1387, 1388, 3, 2, 2, 2, 1388, 1390, 7, 5, 2, 2, 1389, 1391, 7, 127, 2, 2, 1390, 1389, 3, 2, 2, 2, 1390, 1391, 3, 2, 2, 2, 1391, 1393, 3, 2, 2, 2, 1392, 1384, 3, 2, 2, 2, 1392, 1393, 3, 2, 2, 2, 1393, 1394, 3, 2, 2, 2, 1394, 1396, 5, 136, 69, 2, 1395, 1397, 7, 127, 2, 2, 1396, 1395, 3, 2, 2, 2, 1396, 1397, 3, 2, 2, 2, 1397, 1406, 3, 2, 2, 2, 1398, 1400, 7, 74, 2, 2, 1399, 1401, 7, 127, 2, 2, 1400, 1399, 3, 2, 2, 2, 1400, 1401, 3, 2, 2, 2, 1401, 1402, 3, 2, 2, 2, 1402, 1404, 5, 100, 51, 2, 1403, 1405, 7, 127, 2, 2, 1404, 1403, 3, 2, 2, 2, 1404, 1405, 3, 2, 2, 2, 1405, 1407, 3, 2, 2, 2, 1406, 1398, 3, 2, 2, 2, 1406, 1407, 3, 2, 2, 2, 1407, 1408, 3, 2, 2, 2, 1408, 1410, 7, 14, 2, 2, 1409, 1411, 7, 127, 2, 2, 1410, 1409, 3, 2, 2, 2, 1410, 1411, 3, 2, 2, 2, 1411, 1412, 3, 2, 2, 2, 1412, 1414, 5, 100, 51, 2, 1413, 1415, 7, 127, 2, 2, 1414, 1413, 3, 2, 2, 2, 1414, 1415, 3, 2, 2, 2, 1415, 1416, 3, 2, 2, 2, 1416, 1417, 7, 12, 2, 2, 1417, 159, 3, 2, 2, 2, 1418, 1420, 7, 25, 2, 2, 1419, 1421, 7, 127, 2, 2, 1420, 1419, 3, 2, 2, 2, 1420, 1421, 3, 2, 2, 2, 1421, 1422, 3, 2, 2, 2, 1422, 1423, 5, 176, 89, 2, 1423, 161, 3, 2, 2, 2, 1424, 1429, 7, 94, 2, 2, 1425, 1427, 7, 127, 2, 2, 1426, 1425, 3, 2, 2, 2, 1426, 1427, 3, 2, 2, 2, 1427, 1428, 3, 2, 2, 2, 1428, 1430, 5, 164, 83, 2, 1429, 1426, 3, 2, 2, 2, 1430, 1431, 3, 2, 2, 2, 1431, 1429, 3, 2, 2, 2, 1431, 1432, 3, 2, 2, 2, 1432, 1447, 3, 2, 2, 2, 1433, 1435, 7, 94, 2, 2, 1434, 1436, 7, 127, 2, 2, 1435, 1434, 3, 2, 2, 2, 1435, 1436, 3, 2, 2, 2, 1436, 1437, 3, 2, 2, 2, 1437, 1442, 5, 100, 51, 2, 1438, 1440, 7, 127, 2, 2, 1439, 1438, 3, 2, 2, 2, 1439, 1440, 3, 2, 2, 2, 1440, 1441, 3, 2, 2, 2, 1441, 1443, 5, 164, 83, 2, 1442, 1439, 3, 2, 2, 2, 1443, 1444, 3, 2, 2, 2, 1444, 1442, 3, 2, 2, 2, 1444, 1445, 3, 2, 2, 2, 1445, 1447, 3, 2, 2, 2, 1446, 1424, 3, 2, 2, 2, 1446, 1433, 3, 2, 2, 2, 1447, 1456, 3, 2, 2, 2, 1448, 1450, 7, 127, 2, 2, 1449, 1448, 3, 2, 2, 2, 1449, 1450, 3, 2, 2, 2, 1450, 1451, 3, 2, 2, 2, 1451, 1453, 7, 95, 2, 2, 1452, 1454, 7, 127, 2, 2, 1453, 1452, 3, 2, 2, 2, 1453, 1454, 3, 2, 2, 2, 1454, 1455, 3, 2, 2, 2, 1455, 1457, 5, 100, 51, 2, 1456, 1449, 3, 2, 2, 2, 1456, 1457, 3, 2, 2, 2, 1457, 1459, 3, 2, 2, 2, 1458, 1460, 7, 127, 2, 2, 1459, 1458, 3, 2, 2, 2, 1459, 1460, 3, 2, 2, 2, 1460, 1461, 3, 2, 2, 2, 1461, 1462, 7, 96, 2, 2, 1462, 163, 3, 2, 2, 2, 1463, 1465, 7, 97, 2, 2, 1464, 1466, 7, 127, 2, 2, 1465, 1464, 3, 2, 2, 2, 1465, 1466, 3, 2, 2, 2, 1466, 1467, 3, 2, 2, 2, 1467, 1469, 5, 100, 51, 2, 1468, 1470, 7, 127, 2, 2, 1469, 1468, 3, 2, 2, 2, 1469, 1470, 3, 2, 2, 2, 1470, 1471, 3, 2, 2, 2, 1471, 1473, 7, 98, 2, 2, 1472, 1474, 7, 127, 2, 2, 1473, 1472, 3, 2, 2, 2, 1473, 1474, 3, 2, 2, 2, 1474, 1475, 3, 2, 2, 2, 1475, 1476, 5, 100, 51, 2, 1476, 165, 3, 2, 2, 2, 1477, 1478, 5, 186, 94, 2, 1478, 167, 3, 2, 2, 2, 1479, 1482, 5, 180, 91, 2, 1480, 1482, 5, 178, 90, 2, 1481, 1479, 3, 2, 2, 2, 1481, 1480, 3, 2, 2, 2, 1482, 169, 3, 2, 2, 2, 1483, 1485, 7, 26, 2, 2, 1484, 1486, 7, 127, 2, 2, 1485, 1484, 3, 2, 2, 2, 1485, 1486, 3, 2, 2, 2, 1486, 1520, 3, 2, 2, 2, 1487, 1489, 5, 176, 89, 2, 1488, 1490, 7, 127, 2, 2, 1489, 1488, 3, 2, 2, 2, 1489, 1490, 3, 2, 2, 2, 1490, 1491, 3, 2, 2, 2, 1491, 1493, 7, 13, 2, 2, 1492, 1494, 7, 127, 2, 2, 1493, 1492, 3, 2, 2, 2, 1493, 1494, 3, 2, 2, 2, 1494, 1495, 3, 2, 2, 2, 1495, 1497, 5, 100, 51, 2, 1496, 1498, 7, 127, 2, 2, 1497, 1496, 3, 2, 2, 2, 1497, 1498, 3, 2, 2, 2, 1498, 1517, 3, 2, 2, 2, 1499, 1501, 7, 4, 2, 2, 1500, 1502, 7, 127, 2, 2, 1501, 1500, 3, 2, 2, 2, 1501, 1502, 3, 2, 2, 2, 1502, 1503, 3, 2, 2, 2, 1503, 1505, 5, 176, 89, 2, 1504, 1506, 7, 127, 2, 2, 1505, 1504, 3, 2, 2, 2, 1505, 1506, 3, 2, 2, 2, 1506, 1507, 3, 2, 2, 2, 1507, 1509, 7, 13, 2, 2, 1508, 1510, 7, 127, 2, 2, 1509, 1508, 3, 2, 2, 2, 1509, 1510, 3, 2, 2, 2, 1510, 1511, 3, 2, 2, 2, 1511, 1513, 5, 100, 51, 2, 1512, 1514, 7, 127, 2, 2, 1513, 1512, 3, 2, 2, 2, 1513, 1514, 3, 2, 2, 2, 1514, 1516, 3, 2, 2, 2, 1515, 1499, 3, 2, 2, 2, 1516, 1519, 3, 2, 2, 2, 1517, 1515, 3, 2, 2, 2, 1517, 1518, 3, 2, 2, 2, 1518, 1521, 3, 2, 2, 2, 1519, 1517, 3, 2, 2, 2, 1520, 1487, 3, 2, 2, 2, 1520, 1521, 3, 2, 2, 2, 1521, 1522, 3, 2, 2, 2, 1522, 1523, 7, 27, 2, 2, 1523, 171, 3, 2, 2, 2, 1524, 1527, 7, 28, 2, 2, 1525, 1528, 5, 186, 94, 2, 1526, 1528, 7, 102, 2, 2, 1527, 1525, 3, 2, 2, 2, 1527, 1526, 3, 2, 2, 2, 1528, 173, 3, 2, 2, 2, 1529, 1534, 5, 124, 63, 2, 1530, 1532, 7, 127, 2, 2, 1531, 1530, 3, 2, 2, 2, 1531, 1532, 3, 2, 2, 2, 1532, 1533, 3, 2, 2, 2, 1533, 1535, 5, 160, 81, 2, 1534, 1531, 3, 2, 2, 2, 1535, 1536, 3, 2, 2, 2, 1536, 1534, 3, 2, 2, 2, 1536, 1537, 3, 2, 2, 2, 1537, 175, 3, 2, 2, 2, 1538, 1539, 5, 182, 92, 2, 1539, 177, 3, 2, 2, 2, 1540, 1541, 9, 5, 2, 2, 1541, 179, 3, 2, 2, 2, 1542, 1543, 9, 6, 2, 2, 1543, 181, 3, 2, 2, 2, 1544, 1547, 5, 186, 94, 2, 1545, 1547, 5, 184, 93, 2, 1546, 1544, 3, 2, 2, 2, 1546, 1545, 3, 2, 2, 2, 1547, 183, 3, 2, 2, 2, 1548, 1549, 9, 7, 2, 2, 1549, 185, 3, 2, 2, 2, 1550, 1551, 9, 8, 2, 2, 1551, 187, 3, 2, 2, 2, 1552, 1553, 9, 9, 2, 2, 1553, 189, 3, 2, 2, 2, 1554, 1555, 9, 10, 2, 2, 1555, 191, 3, 2, 2, 2, 1556, 1557, 9, 11, 2, 2, 1557, 193, 3, 2, 2, 2, 290, 195, 199, 202, 205, 213, 217, 222, 229, 234, 237, 241, 245, 249, 255, 259, 264, 269, 273, 276, 278, 282, 286, 291, 295, 300, 304, 313, 318, 322, 326, 330, 333, 337, 347, 354, 367, 371, 377, 384, 389, 393, 399, 403, 409, 413, 419, 423, 427, 431, 435, 439, 444, 451, 455, 460, 467, 473, 478, 484, 490, 494, 498, 503, 507, 514, 520, 523, 528, 531, 535, 538, 546, 550, 554, 558, 562, 567, 572, 576, 581, 584, 593, 602, 607, 620, 623, 631, 635, 640, 645, 649, 654, 660, 665, 672, 676, 680, 682, 686, 688, 692, 694, 700, 706, 710, 713, 716, 720, 726, 730, 733, 736, 742, 745, 748, 752, 758, 761, 764, 768, 772, 776, 778, 782, 784, 787, 791, 793, 799, 803, 807, 811, 814, 819, 824, 829, 834, 840, 844, 846, 850, 854, 856, 858, 873, 883, 893, 898, 902, 909, 914, 919, 923, 927, 931, 934, 936, 941, 945, 949, 953, 957, 961, 964, 966, 971, 975, 980, 985, 989, 996, 1003, 1007, 1011, 1026, 1029, 1042, 1044, 1049, 1054, 1058, 1061, 1068, 1072, 1076, 1083, 1087, 1091, 1097, 1101, 1105, 1108, 1112, 1118, 1122, 1126, 1132, 1136, 1140, 1146, 1150, 1154, 1160, 1164, 1168, 1176, 1184, 1190, 1194, 1198, 1202, 1206, 1209, 1215, 1220, 1225, 1230, 1235, 1240, 1243, 1247, 1251, 1257, 1262, 1266, 1269, 1279, 1283, 1287, 1289, 1293, 1297, 1301, 1305, 1308, 1314, 1318, 1322, 1326, 1330, 1334, 1338, 1341, 1357, 1362, 1366, 1370, 1373, 1376, 1382, 1386, 1390, 1392, 1396, 1400, 1404, 1406, 1410, 1414, 1420, 1426, 1431, 1435, 1439, 1444, 1446, 1449, 1453, 1456, 1459, 1465, 1469, 1473, 1481, 1485, 1489, 1493, 1497, 1501, 1505, 1509, 1513, 1517, 1520, 1527, 1531, 1536, 1546] \ No newline at end of file diff --git a/src/openCypherParser/Grammar/Cypher.tokens b/src/openCypherParser/Grammar/Cypher.tokens new file mode 100644 index 0000000..45df26f --- /dev/null +++ b/src/openCypherParser/Grammar/Cypher.tokens @@ -0,0 +1,173 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +T__10=11 +T__11=12 +T__12=13 +T__13=14 +T__14=15 +T__15=16 +T__16=17 +T__17=18 +T__18=19 +T__19=20 +T__20=21 +T__21=22 +T__22=23 +T__23=24 +T__24=25 +T__25=26 +T__26=27 +T__27=28 +T__28=29 +T__29=30 +T__30=31 +T__31=32 +T__32=33 +T__33=34 +T__34=35 +T__35=36 +T__36=37 +T__37=38 +T__38=39 +T__39=40 +T__40=41 +T__41=42 +T__42=43 +T__43=44 +T__44=45 +UNION=46 +ALL=47 +OPTIONAL=48 +MATCH=49 +UNWIND=50 +AS=51 +MERGE=52 +ON=53 +CREATE=54 +SET=55 +DETACH=56 +DELETE=57 +REMOVE=58 +CALL=59 +YIELD=60 +WITH=61 +DISTINCT=62 +RETURN=63 +ORDER=64 +BY=65 +L_SKIP=66 +LIMIT=67 +ASCENDING=68 +ASC=69 +DESCENDING=70 +DESC=71 +WHERE=72 +OR=73 +XOR=74 +AND=75 +NOT=76 +IN=77 +STARTS=78 +ENDS=79 +CONTAINS=80 +IS=81 +NULL=82 +COUNT=83 +FILTER=84 +EXTRACT=85 +ANY=86 +NONE=87 +SINGLE=88 +TRUE=89 +FALSE=90 +EXISTS=91 +CASE=92 +ELSE=93 +END=94 +WHEN=95 +THEN=96 +StringLiteral=97 +EscapedChar=98 +HexInteger=99 +DecimalInteger=100 +OctalInteger=101 +HexLetter=102 +HexDigit=103 +Digit=104 +NonZeroDigit=105 +NonZeroOctDigit=106 +OctDigit=107 +ZeroDigit=108 +ExponentDecimalReal=109 +RegularDecimalReal=110 +CONSTRAINT=111 +DO=112 +FOR=113 +REQUIRE=114 +UNIQUE=115 +MANDATORY=116 +SCALAR=117 +OF=118 +ADD=119 +DROP=120 +UnescapedSymbolicName=121 +IdentifierStart=122 +IdentifierPart=123 +EscapedSymbolicName=124 +SP=125 +WHITESPACE=126 +Comment=127 +';'=1 +','=2 +'='=3 +'+='=4 +'-'=5 +'*'=6 +'('=7 +')'=8 +'['=9 +']'=10 +':'=11 +'|'=12 +'..'=13 +'+'=14 +'/'=15 +'%'=16 +'^'=17 +'<>'=18 +'<'=19 +'>'=20 +'<='=21 +'>='=22 +'.'=23 +'{'=24 +'}'=25 +'$'=26 +'⟨'=27 +'〈'=28 +'﹤'=29 +'<'=30 +'⟩'=31 +'〉'=32 +'ï¹¥'=33 +'>'=34 +'­'=35 +'â€�'=36 +'‑'=37 +'‒'=38 +'–'=39 +'â€�'=40 +'―'=41 +'−'=42 +'﹘'=43 +'ï¹£'=44 +'ï¼�'=45 +'0'=108 diff --git a/src/openCypherParser/Grammar/CypherBaseVisitor.cs b/src/openCypherParser/Grammar/CypherBaseVisitor.cs new file mode 100644 index 0000000..bc7a11f --- /dev/null +++ b/src/openCypherParser/Grammar/CypherBaseVisitor.cs @@ -0,0 +1,998 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// ANTLR Version: 4.7.2 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +// Generated from Cypher.g4 by ANTLR 4.7.2 + +// Unreachable code detected +#pragma warning disable 0162 +// The variable '...' is assigned but its value is never used +#pragma warning disable 0219 +// Missing XML comment for publicly visible type or member '...' +#pragma warning disable 1591 +// Ambiguous reference in cref attribute +#pragma warning disable 419 + +namespace openCypherTranspiler.openCypherParser.ANTLR { +using Antlr4.Runtime.Misc; +using Antlr4.Runtime.Tree; +using IToken = Antlr4.Runtime.IToken; +using ParserRuleContext = Antlr4.Runtime.ParserRuleContext; + +/// +/// This class provides an empty implementation of , +/// which can be extended to create a visitor which only needs to handle a subset +/// of the available methods. +/// +/// The return type of the visit operation. +[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.7.2")] +[System.CLSCompliant(false)] +public partial class CypherBaseVisitor : AbstractParseTreeVisitor, ICypherVisitor { + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Cypher([NotNull] CypherParser.OC_CypherContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Statement([NotNull] CypherParser.OC_StatementContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Query([NotNull] CypherParser.OC_QueryContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_RegularQuery([NotNull] CypherParser.OC_RegularQueryContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Union([NotNull] CypherParser.OC_UnionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_SingleQuery([NotNull] CypherParser.OC_SingleQueryContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_SinglePartQuery([NotNull] CypherParser.OC_SinglePartQueryContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_MultiPartQuery([NotNull] CypherParser.OC_MultiPartQueryContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_UpdatingClause([NotNull] CypherParser.OC_UpdatingClauseContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_ReadingClause([NotNull] CypherParser.OC_ReadingClauseContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Match([NotNull] CypherParser.OC_MatchContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Unwind([NotNull] CypherParser.OC_UnwindContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Merge([NotNull] CypherParser.OC_MergeContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_MergeAction([NotNull] CypherParser.OC_MergeActionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Create([NotNull] CypherParser.OC_CreateContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Set([NotNull] CypherParser.OC_SetContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_SetItem([NotNull] CypherParser.OC_SetItemContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Delete([NotNull] CypherParser.OC_DeleteContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Remove([NotNull] CypherParser.OC_RemoveContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_RemoveItem([NotNull] CypherParser.OC_RemoveItemContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_InQueryCall([NotNull] CypherParser.OC_InQueryCallContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_StandaloneCall([NotNull] CypherParser.OC_StandaloneCallContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_YieldItems([NotNull] CypherParser.OC_YieldItemsContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_YieldItem([NotNull] CypherParser.OC_YieldItemContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_With([NotNull] CypherParser.OC_WithContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Return([NotNull] CypherParser.OC_ReturnContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_ReturnBody([NotNull] CypherParser.OC_ReturnBodyContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_ReturnItems([NotNull] CypherParser.OC_ReturnItemsContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_ReturnItem([NotNull] CypherParser.OC_ReturnItemContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Order([NotNull] CypherParser.OC_OrderContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Skip([NotNull] CypherParser.OC_SkipContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Limit([NotNull] CypherParser.OC_LimitContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_SortItem([NotNull] CypherParser.OC_SortItemContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Where([NotNull] CypherParser.OC_WhereContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Pattern([NotNull] CypherParser.OC_PatternContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_PatternPart([NotNull] CypherParser.OC_PatternPartContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_AnonymousPatternPart([NotNull] CypherParser.OC_AnonymousPatternPartContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_PatternElement([NotNull] CypherParser.OC_PatternElementContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_NodePattern([NotNull] CypherParser.OC_NodePatternContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_PatternElementChain([NotNull] CypherParser.OC_PatternElementChainContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_RelationshipPattern([NotNull] CypherParser.OC_RelationshipPatternContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_RelationshipDetail([NotNull] CypherParser.OC_RelationshipDetailContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Properties([NotNull] CypherParser.OC_PropertiesContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_RelationshipTypes([NotNull] CypherParser.OC_RelationshipTypesContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_NodeLabels([NotNull] CypherParser.OC_NodeLabelsContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_NodeLabel([NotNull] CypherParser.OC_NodeLabelContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_RangeLiteral([NotNull] CypherParser.OC_RangeLiteralContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_LabelName([NotNull] CypherParser.OC_LabelNameContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_RelTypeName([NotNull] CypherParser.OC_RelTypeNameContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Expression([NotNull] CypherParser.OC_ExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_OrExpression([NotNull] CypherParser.OC_OrExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_XorExpression([NotNull] CypherParser.OC_XorExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_AndExpression([NotNull] CypherParser.OC_AndExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_NotExpression([NotNull] CypherParser.OC_NotExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_ComparisonExpression([NotNull] CypherParser.OC_ComparisonExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_AddOrSubtractExpression([NotNull] CypherParser.OC_AddOrSubtractExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_MultiplyDivideModuloExpression([NotNull] CypherParser.OC_MultiplyDivideModuloExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_PowerOfExpression([NotNull] CypherParser.OC_PowerOfExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_UnaryAddOrSubtractExpression([NotNull] CypherParser.OC_UnaryAddOrSubtractExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_StringListNullOperatorExpression([NotNull] CypherParser.OC_StringListNullOperatorExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_PropertyOrLabelsExpression([NotNull] CypherParser.OC_PropertyOrLabelsExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Atom([NotNull] CypherParser.OC_AtomContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Literal([NotNull] CypherParser.OC_LiteralContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_BooleanLiteral([NotNull] CypherParser.OC_BooleanLiteralContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_ListLiteral([NotNull] CypherParser.OC_ListLiteralContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_PartialComparisonExpression([NotNull] CypherParser.OC_PartialComparisonExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_ParenthesizedExpression([NotNull] CypherParser.OC_ParenthesizedExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_RelationshipsPattern([NotNull] CypherParser.OC_RelationshipsPatternContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_FilterExpression([NotNull] CypherParser.OC_FilterExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_IdInColl([NotNull] CypherParser.OC_IdInCollContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_FunctionInvocation([NotNull] CypherParser.OC_FunctionInvocationContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_FunctionName([NotNull] CypherParser.OC_FunctionNameContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_ExplicitProcedureInvocation([NotNull] CypherParser.OC_ExplicitProcedureInvocationContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_ImplicitProcedureInvocation([NotNull] CypherParser.OC_ImplicitProcedureInvocationContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_ProcedureResultField([NotNull] CypherParser.OC_ProcedureResultFieldContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_ProcedureName([NotNull] CypherParser.OC_ProcedureNameContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Namespace([NotNull] CypherParser.OC_NamespaceContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_ListComprehension([NotNull] CypherParser.OC_ListComprehensionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_PatternComprehension([NotNull] CypherParser.OC_PatternComprehensionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_PropertyLookup([NotNull] CypherParser.OC_PropertyLookupContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_CaseExpression([NotNull] CypherParser.OC_CaseExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_CaseAlternatives([NotNull] CypherParser.OC_CaseAlternativesContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Variable([NotNull] CypherParser.OC_VariableContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_NumberLiteral([NotNull] CypherParser.OC_NumberLiteralContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_MapLiteral([NotNull] CypherParser.OC_MapLiteralContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Parameter([NotNull] CypherParser.OC_ParameterContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_PropertyExpression([NotNull] CypherParser.OC_PropertyExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_PropertyKeyName([NotNull] CypherParser.OC_PropertyKeyNameContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_IntegerLiteral([NotNull] CypherParser.OC_IntegerLiteralContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_DoubleLiteral([NotNull] CypherParser.OC_DoubleLiteralContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_SchemaName([NotNull] CypherParser.OC_SchemaNameContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_ReservedWord([NotNull] CypherParser.OC_ReservedWordContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_SymbolicName([NotNull] CypherParser.OC_SymbolicNameContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_LeftArrowHead([NotNull] CypherParser.OC_LeftArrowHeadContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_RightArrowHead([NotNull] CypherParser.OC_RightArrowHeadContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitOC_Dash([NotNull] CypherParser.OC_DashContext context) { return VisitChildren(context); } +} +} // namespace openCypherTranspiler.openCypherParser.ANTLR diff --git a/src/openCypherParser/Grammar/CypherLexer.cs b/src/openCypherParser/Grammar/CypherLexer.cs new file mode 100644 index 0000000..dcd77b5 --- /dev/null +++ b/src/openCypherParser/Grammar/CypherLexer.cs @@ -0,0 +1,1460 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// ANTLR Version: 4.7.2 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +// Generated from Cypher.g4 by ANTLR 4.7.2 + +// Unreachable code detected +#pragma warning disable 0162 +// The variable '...' is assigned but its value is never used +#pragma warning disable 0219 +// Missing XML comment for publicly visible type or member '...' +#pragma warning disable 1591 +// Ambiguous reference in cref attribute +#pragma warning disable 419 + +namespace openCypherTranspiler.openCypherParser.ANTLR { +using System; +using System.IO; +using System.Text; +using Antlr4.Runtime; +using Antlr4.Runtime.Atn; +using Antlr4.Runtime.Misc; +using DFA = Antlr4.Runtime.Dfa.DFA; + +[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.7.2")] +[System.CLSCompliant(false)] +public partial class CypherLexer : Lexer { + protected static DFA[] decisionToDFA; + protected static PredictionContextCache sharedContextCache = new PredictionContextCache(); + public const int + T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, + T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, + T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, + T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31, + T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38, + T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, T__43=44, T__44=45, + UNION=46, ALL=47, OPTIONAL=48, MATCH=49, UNWIND=50, AS=51, MERGE=52, ON=53, + CREATE=54, SET=55, DETACH=56, DELETE=57, REMOVE=58, CALL=59, YIELD=60, + WITH=61, DISTINCT=62, RETURN=63, ORDER=64, BY=65, L_SKIP=66, LIMIT=67, + ASCENDING=68, ASC=69, DESCENDING=70, DESC=71, WHERE=72, OR=73, XOR=74, + AND=75, NOT=76, IN=77, STARTS=78, ENDS=79, CONTAINS=80, IS=81, NULL=82, + COUNT=83, FILTER=84, EXTRACT=85, ANY=86, NONE=87, SINGLE=88, TRUE=89, + FALSE=90, EXISTS=91, CASE=92, ELSE=93, END=94, WHEN=95, THEN=96, StringLiteral=97, + EscapedChar=98, HexInteger=99, DecimalInteger=100, OctalInteger=101, HexLetter=102, + HexDigit=103, Digit=104, NonZeroDigit=105, NonZeroOctDigit=106, OctDigit=107, + ZeroDigit=108, ExponentDecimalReal=109, RegularDecimalReal=110, CONSTRAINT=111, + DO=112, FOR=113, REQUIRE=114, UNIQUE=115, MANDATORY=116, SCALAR=117, OF=118, + ADD=119, DROP=120, UnescapedSymbolicName=121, IdentifierStart=122, IdentifierPart=123, + EscapedSymbolicName=124, SP=125, WHITESPACE=126, Comment=127; + public static string[] channelNames = { + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" + }; + + public static string[] modeNames = { + "DEFAULT_MODE" + }; + + public static readonly string[] ruleNames = { + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", + "T__17", "T__18", "T__19", "T__20", "T__21", "T__22", "T__23", "T__24", + "T__25", "T__26", "T__27", "T__28", "T__29", "T__30", "T__31", "T__32", + "T__33", "T__34", "T__35", "T__36", "T__37", "T__38", "T__39", "T__40", + "T__41", "T__42", "T__43", "T__44", "UNION", "ALL", "OPTIONAL", "MATCH", + "UNWIND", "AS", "MERGE", "ON", "CREATE", "SET", "DETACH", "DELETE", "REMOVE", + "CALL", "YIELD", "WITH", "DISTINCT", "RETURN", "ORDER", "BY", "L_SKIP", + "LIMIT", "ASCENDING", "ASC", "DESCENDING", "DESC", "WHERE", "OR", "XOR", + "AND", "NOT", "IN", "STARTS", "ENDS", "CONTAINS", "IS", "NULL", "COUNT", + "FILTER", "EXTRACT", "ANY", "NONE", "SINGLE", "TRUE", "FALSE", "EXISTS", + "CASE", "ELSE", "END", "WHEN", "THEN", "StringLiteral", "EscapedChar", + "HexInteger", "DecimalInteger", "OctalInteger", "HexLetter", "HexDigit", + "Digit", "NonZeroDigit", "NonZeroOctDigit", "OctDigit", "ZeroDigit", "ExponentDecimalReal", + "RegularDecimalReal", "CONSTRAINT", "DO", "FOR", "REQUIRE", "UNIQUE", + "MANDATORY", "SCALAR", "OF", "ADD", "DROP", "UnescapedSymbolicName", "IdentifierStart", + "IdentifierPart", "EscapedSymbolicName", "SP", "WHITESPACE", "Comment", + "FF", "EscapedSymbolicName_0", "RS", "ID_Continue", "Comment_1", "StringLiteral_1", + "Comment_3", "Comment_2", "GS", "FS", "CR", "Sc", "SPACE", "Pc", "TAB", + "StringLiteral_0", "LF", "VT", "US", "ID_Start" + }; + + + public CypherLexer(ICharStream input) + : this(input, Console.Out, Console.Error) { } + + public CypherLexer(ICharStream input, TextWriter output, TextWriter errorOutput) + : base(input, output, errorOutput) + { + Interpreter = new LexerATNSimulator(this, _ATN, decisionToDFA, sharedContextCache); + } + + private static readonly string[] _LiteralNames = { + null, "';'", "','", "'='", "'+='", "'-'", "'*'", "'('", "')'", "'['", + "']'", "':'", "'|'", "'..'", "'+'", "'/'", "'%'", "'^'", "'<>'", "'<'", + "'>'", "'<='", "'>='", "'.'", "'{'", "'}'", "'$'", "'\u00C3\u00A2\u00C5\u00B8\u00C2\u00A8'", + "'\u00C3\u00A3\u00E2\u201A\u00AC\u00CB\u2020'", "'\u00C3\u00AF\u00C2\u00B9\u00C2\u00A4'", + "'\u00C3\u00AF\u00C2\u00BC\u00C5\u201C'", "'\u00C3\u00A2\u00C5\u00B8\u00C2\u00A9'", + "'\u00C3\u00A3\u00E2\u201A\u00AC\u00E2\u20AC\u00B0'", "'\u00C3\u00AF\u00C2\u00B9\u00C2\u00A5'", + "'\u00C3\u00AF\u00C2\u00BC\u00C5\u00BE'", "'\u00C3\u201A\u00C2\u00AD'", + "'\u00C3\u00A2\u00E2\u201A\u00AC\u00C2\uFFFD'", "'\u00C3\u00A2\u00E2\u201A\u00AC\u00E2\u20AC\u02DC'", + "'\u00C3\u00A2\u00E2\u201A\u00AC\u00E2\u20AC\u2122'", "'\u00C3\u00A2\u00E2\u201A\u00AC\u00E2\u20AC\u0153'", + "'\u00C3\u00A2\u00E2\u201A\u00AC\u00E2\u20AC\uFFFD'", "'\u00C3\u00A2\u00E2\u201A\u00AC\u00E2\u20AC\u00A2'", + "'\u00C3\u00A2\u00CB\u2020\u00E2\u20AC\u2122'", "'\u00C3\u00AF\u00C2\u00B9\u00CB\u0153'", + "'\u00C3\u00AF\u00C2\u00B9\u00C2\u00A3'", "'\u00C3\u00AF\u00C2\u00BC\u00C2\uFFFD'", + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, "'0'" + }; + private static readonly string[] _SymbolicNames = { + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, "UNION", "ALL", + "OPTIONAL", "MATCH", "UNWIND", "AS", "MERGE", "ON", "CREATE", "SET", "DETACH", + "DELETE", "REMOVE", "CALL", "YIELD", "WITH", "DISTINCT", "RETURN", "ORDER", + "BY", "L_SKIP", "LIMIT", "ASCENDING", "ASC", "DESCENDING", "DESC", "WHERE", + "OR", "XOR", "AND", "NOT", "IN", "STARTS", "ENDS", "CONTAINS", "IS", "NULL", + "COUNT", "FILTER", "EXTRACT", "ANY", "NONE", "SINGLE", "TRUE", "FALSE", + "EXISTS", "CASE", "ELSE", "END", "WHEN", "THEN", "StringLiteral", "EscapedChar", + "HexInteger", "DecimalInteger", "OctalInteger", "HexLetter", "HexDigit", + "Digit", "NonZeroDigit", "NonZeroOctDigit", "OctDigit", "ZeroDigit", "ExponentDecimalReal", + "RegularDecimalReal", "CONSTRAINT", "DO", "FOR", "REQUIRE", "UNIQUE", + "MANDATORY", "SCALAR", "OF", "ADD", "DROP", "UnescapedSymbolicName", "IdentifierStart", + "IdentifierPart", "EscapedSymbolicName", "SP", "WHITESPACE", "Comment" + }; + public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames); + + [NotNull] + public override IVocabulary Vocabulary + { + get + { + return DefaultVocabulary; + } + } + + public override string GrammarFileName { get { return "Cypher.g4"; } } + + public override string[] RuleNames { get { return ruleNames; } } + + public override string[] ChannelNames { get { return channelNames; } } + + public override string[] ModeNames { get { return modeNames; } } + + public override string SerializedAtn { get { return new string(_serializedATN); } } + + static CypherLexer() { + decisionToDFA = new DFA[_ATN.NumberOfDecisions]; + for (int i = 0; i < _ATN.NumberOfDecisions; i++) { + decisionToDFA[i] = new DFA(_ATN.GetDecisionState(i), i); + } + } + private static char[] _serializedATN = { + '\x3', '\x608B', '\xA72A', '\x8133', '\xB9ED', '\x417C', '\x3BE7', '\x7786', + '\x5964', '\x2', '\x81', '\x4D4', '\b', '\x1', '\x4', '\x2', '\t', '\x2', + '\x4', '\x3', '\t', '\x3', '\x4', '\x4', '\t', '\x4', '\x4', '\x5', '\t', + '\x5', '\x4', '\x6', '\t', '\x6', '\x4', '\a', '\t', '\a', '\x4', '\b', + '\t', '\b', '\x4', '\t', '\t', '\t', '\x4', '\n', '\t', '\n', '\x4', '\v', + '\t', '\v', '\x4', '\f', '\t', '\f', '\x4', '\r', '\t', '\r', '\x4', '\xE', + '\t', '\xE', '\x4', '\xF', '\t', '\xF', '\x4', '\x10', '\t', '\x10', '\x4', + '\x11', '\t', '\x11', '\x4', '\x12', '\t', '\x12', '\x4', '\x13', '\t', + '\x13', '\x4', '\x14', '\t', '\x14', '\x4', '\x15', '\t', '\x15', '\x4', + '\x16', '\t', '\x16', '\x4', '\x17', '\t', '\x17', '\x4', '\x18', '\t', + '\x18', '\x4', '\x19', '\t', '\x19', '\x4', '\x1A', '\t', '\x1A', '\x4', + '\x1B', '\t', '\x1B', '\x4', '\x1C', '\t', '\x1C', '\x4', '\x1D', '\t', + '\x1D', '\x4', '\x1E', '\t', '\x1E', '\x4', '\x1F', '\t', '\x1F', '\x4', + ' ', '\t', ' ', '\x4', '!', '\t', '!', '\x4', '\"', '\t', '\"', '\x4', + '#', '\t', '#', '\x4', '$', '\t', '$', '\x4', '%', '\t', '%', '\x4', '&', + '\t', '&', '\x4', '\'', '\t', '\'', '\x4', '(', '\t', '(', '\x4', ')', + '\t', ')', '\x4', '*', '\t', '*', '\x4', '+', '\t', '+', '\x4', ',', '\t', + ',', '\x4', '-', '\t', '-', '\x4', '.', '\t', '.', '\x4', '/', '\t', '/', + '\x4', '\x30', '\t', '\x30', '\x4', '\x31', '\t', '\x31', '\x4', '\x32', + '\t', '\x32', '\x4', '\x33', '\t', '\x33', '\x4', '\x34', '\t', '\x34', + '\x4', '\x35', '\t', '\x35', '\x4', '\x36', '\t', '\x36', '\x4', '\x37', + '\t', '\x37', '\x4', '\x38', '\t', '\x38', '\x4', '\x39', '\t', '\x39', + '\x4', ':', '\t', ':', '\x4', ';', '\t', ';', '\x4', '<', '\t', '<', '\x4', + '=', '\t', '=', '\x4', '>', '\t', '>', '\x4', '?', '\t', '?', '\x4', '@', + '\t', '@', '\x4', '\x41', '\t', '\x41', '\x4', '\x42', '\t', '\x42', '\x4', + '\x43', '\t', '\x43', '\x4', '\x44', '\t', '\x44', '\x4', '\x45', '\t', + '\x45', '\x4', '\x46', '\t', '\x46', '\x4', 'G', '\t', 'G', '\x4', 'H', + '\t', 'H', '\x4', 'I', '\t', 'I', '\x4', 'J', '\t', 'J', '\x4', 'K', '\t', + 'K', '\x4', 'L', '\t', 'L', '\x4', 'M', '\t', 'M', '\x4', 'N', '\t', 'N', + '\x4', 'O', '\t', 'O', '\x4', 'P', '\t', 'P', '\x4', 'Q', '\t', 'Q', '\x4', + 'R', '\t', 'R', '\x4', 'S', '\t', 'S', '\x4', 'T', '\t', 'T', '\x4', 'U', + '\t', 'U', '\x4', 'V', '\t', 'V', '\x4', 'W', '\t', 'W', '\x4', 'X', '\t', + 'X', '\x4', 'Y', '\t', 'Y', '\x4', 'Z', '\t', 'Z', '\x4', '[', '\t', '[', + '\x4', '\\', '\t', '\\', '\x4', ']', '\t', ']', '\x4', '^', '\t', '^', + '\x4', '_', '\t', '_', '\x4', '`', '\t', '`', '\x4', '\x61', '\t', '\x61', + '\x4', '\x62', '\t', '\x62', '\x4', '\x63', '\t', '\x63', '\x4', '\x64', + '\t', '\x64', '\x4', '\x65', '\t', '\x65', '\x4', '\x66', '\t', '\x66', + '\x4', 'g', '\t', 'g', '\x4', 'h', '\t', 'h', '\x4', 'i', '\t', 'i', '\x4', + 'j', '\t', 'j', '\x4', 'k', '\t', 'k', '\x4', 'l', '\t', 'l', '\x4', 'm', + '\t', 'm', '\x4', 'n', '\t', 'n', '\x4', 'o', '\t', 'o', '\x4', 'p', '\t', + 'p', '\x4', 'q', '\t', 'q', '\x4', 'r', '\t', 'r', '\x4', 's', '\t', 's', + '\x4', 't', '\t', 't', '\x4', 'u', '\t', 'u', '\x4', 'v', '\t', 'v', '\x4', + 'w', '\t', 'w', '\x4', 'x', '\t', 'x', '\x4', 'y', '\t', 'y', '\x4', 'z', + '\t', 'z', '\x4', '{', '\t', '{', '\x4', '|', '\t', '|', '\x4', '}', '\t', + '}', '\x4', '~', '\t', '~', '\x4', '\x7F', '\t', '\x7F', '\x4', '\x80', + '\t', '\x80', '\x4', '\x81', '\t', '\x81', '\x4', '\x82', '\t', '\x82', + '\x4', '\x83', '\t', '\x83', '\x4', '\x84', '\t', '\x84', '\x4', '\x85', + '\t', '\x85', '\x4', '\x86', '\t', '\x86', '\x4', '\x87', '\t', '\x87', + '\x4', '\x88', '\t', '\x88', '\x4', '\x89', '\t', '\x89', '\x4', '\x8A', + '\t', '\x8A', '\x4', '\x8B', '\t', '\x8B', '\x4', '\x8C', '\t', '\x8C', + '\x4', '\x8D', '\t', '\x8D', '\x4', '\x8E', '\t', '\x8E', '\x4', '\x8F', + '\t', '\x8F', '\x4', '\x90', '\t', '\x90', '\x4', '\x91', '\t', '\x91', + '\x4', '\x92', '\t', '\x92', '\x4', '\x93', '\t', '\x93', '\x4', '\x94', + '\t', '\x94', '\x3', '\x2', '\x3', '\x2', '\x3', '\x3', '\x3', '\x3', + '\x3', '\x4', '\x3', '\x4', '\x3', '\x5', '\x3', '\x5', '\x3', '\x5', + '\x3', '\x6', '\x3', '\x6', '\x3', '\a', '\x3', '\a', '\x3', '\b', '\x3', + '\b', '\x3', '\t', '\x3', '\t', '\x3', '\n', '\x3', '\n', '\x3', '\v', + '\x3', '\v', '\x3', '\f', '\x3', '\f', '\x3', '\r', '\x3', '\r', '\x3', + '\xE', '\x3', '\xE', '\x3', '\xE', '\x3', '\xF', '\x3', '\xF', '\x3', + '\x10', '\x3', '\x10', '\x3', '\x11', '\x3', '\x11', '\x3', '\x12', '\x3', + '\x12', '\x3', '\x13', '\x3', '\x13', '\x3', '\x13', '\x3', '\x14', '\x3', + '\x14', '\x3', '\x15', '\x3', '\x15', '\x3', '\x16', '\x3', '\x16', '\x3', + '\x16', '\x3', '\x17', '\x3', '\x17', '\x3', '\x17', '\x3', '\x18', '\x3', + '\x18', '\x3', '\x19', '\x3', '\x19', '\x3', '\x1A', '\x3', '\x1A', '\x3', + '\x1B', '\x3', '\x1B', '\x3', '\x1C', '\x3', '\x1C', '\x3', '\x1C', '\x3', + '\x1C', '\x3', '\x1C', '\x3', '\x1C', '\x3', '\x1C', '\x3', '\x1D', '\x3', + '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', + '\x1D', '\x3', '\x1D', '\x3', '\x1E', '\x3', '\x1E', '\x3', '\x1E', '\x3', + '\x1E', '\x3', '\x1E', '\x3', '\x1E', '\x3', '\x1E', '\x3', '\x1F', '\x3', + '\x1F', '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', '\x3', + '\x1F', '\x3', ' ', '\x3', ' ', '\x3', ' ', '\x3', ' ', '\x3', ' ', '\x3', + ' ', '\x3', ' ', '\x3', '!', '\x3', '!', '\x3', '!', '\x3', '!', '\x3', + '!', '\x3', '!', '\x3', '!', '\x3', '!', '\x3', '!', '\x3', '\"', '\x3', + '\"', '\x3', '\"', '\x3', '\"', '\x3', '\"', '\x3', '\"', '\x3', '\"', + '\x3', '#', '\x3', '#', '\x3', '#', '\x3', '#', '\x3', '#', '\x3', '#', + '\x3', '#', '\x3', '$', '\x3', '$', '\x3', '$', '\x3', '$', '\x3', '$', + '\x3', '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', '%', + '\x3', '%', '\x3', '%', '\x3', '&', '\x3', '&', '\x3', '&', '\x3', '&', + '\x3', '&', '\x3', '&', '\x3', '&', '\x3', '&', '\x3', '&', '\x3', '\'', + '\x3', '\'', '\x3', '\'', '\x3', '\'', '\x3', '\'', '\x3', '\'', '\x3', + '\'', '\x3', '\'', '\x3', '\'', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', + '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', + ')', '\x3', ')', '\x3', ')', '\x3', ')', '\x3', ')', '\x3', ')', '\x3', + ')', '\x3', ')', '\x3', ')', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', + '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', + '+', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', + '+', '\x3', '+', '\x3', ',', '\x3', ',', '\x3', ',', '\x3', ',', '\x3', + ',', '\x3', ',', '\x3', ',', '\x3', '-', '\x3', '-', '\x3', '-', '\x3', + '-', '\x3', '-', '\x3', '-', '\x3', '-', '\x3', '.', '\x3', '.', '\x3', + '.', '\x3', '.', '\x3', '.', '\x3', '.', '\x3', '.', '\x3', '/', '\x3', + '/', '\x3', '/', '\x3', '/', '\x3', '/', '\x3', '/', '\x3', '\x30', '\x3', + '\x30', '\x3', '\x30', '\x3', '\x30', '\x3', '\x31', '\x3', '\x31', '\x3', + '\x31', '\x3', '\x31', '\x3', '\x31', '\x3', '\x31', '\x3', '\x31', '\x3', + '\x31', '\x3', '\x31', '\x3', '\x32', '\x3', '\x32', '\x3', '\x32', '\x3', + '\x32', '\x3', '\x32', '\x3', '\x32', '\x3', '\x33', '\x3', '\x33', '\x3', + '\x33', '\x3', '\x33', '\x3', '\x33', '\x3', '\x33', '\x3', '\x33', '\x3', + '\x34', '\x3', '\x34', '\x3', '\x34', '\x3', '\x35', '\x3', '\x35', '\x3', + '\x35', '\x3', '\x35', '\x3', '\x35', '\x3', '\x35', '\x3', '\x36', '\x3', + '\x36', '\x3', '\x36', '\x3', '\x37', '\x3', '\x37', '\x3', '\x37', '\x3', + '\x37', '\x3', '\x37', '\x3', '\x37', '\x3', '\x37', '\x3', '\x38', '\x3', + '\x38', '\x3', '\x38', '\x3', '\x38', '\x3', '\x39', '\x3', '\x39', '\x3', + '\x39', '\x3', '\x39', '\x3', '\x39', '\x3', '\x39', '\x3', '\x39', '\x3', + ':', '\x3', ':', '\x3', ':', '\x3', ':', '\x3', ':', '\x3', ':', '\x3', + ':', '\x3', ';', '\x3', ';', '\x3', ';', '\x3', ';', '\x3', ';', '\x3', + ';', '\x3', ';', '\x3', '<', '\x3', '<', '\x3', '<', '\x3', '<', '\x3', + '<', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', + '=', '\x3', '>', '\x3', '>', '\x3', '>', '\x3', '>', '\x3', '>', '\x3', + '?', '\x3', '?', '\x3', '?', '\x3', '?', '\x3', '?', '\x3', '?', '\x3', + '?', '\x3', '?', '\x3', '?', '\x3', '@', '\x3', '@', '\x3', '@', '\x3', + '@', '\x3', '@', '\x3', '@', '\x3', '@', '\x3', '\x41', '\x3', '\x41', + '\x3', '\x41', '\x3', '\x41', '\x3', '\x41', '\x3', '\x41', '\x3', '\x42', + '\x3', '\x42', '\x3', '\x42', '\x3', '\x43', '\x3', '\x43', '\x3', '\x43', + '\x3', '\x43', '\x3', '\x43', '\x3', '\x44', '\x3', '\x44', '\x3', '\x44', + '\x3', '\x44', '\x3', '\x44', '\x3', '\x44', '\x3', '\x45', '\x3', '\x45', + '\x3', '\x45', '\x3', '\x45', '\x3', '\x45', '\x3', '\x45', '\x3', '\x45', + '\x3', '\x45', '\x3', '\x45', '\x3', '\x45', '\x3', '\x46', '\x3', '\x46', + '\x3', '\x46', '\x3', '\x46', '\x3', 'G', '\x3', 'G', '\x3', 'G', '\x3', + 'G', '\x3', 'G', '\x3', 'G', '\x3', 'G', '\x3', 'G', '\x3', 'G', '\x3', + 'G', '\x3', 'G', '\x3', 'H', '\x3', 'H', '\x3', 'H', '\x3', 'H', '\x3', + 'H', '\x3', 'I', '\x3', 'I', '\x3', 'I', '\x3', 'I', '\x3', 'I', '\x3', + 'I', '\x3', 'J', '\x3', 'J', '\x3', 'J', '\x3', 'K', '\x3', 'K', '\x3', + 'K', '\x3', 'K', '\x3', 'L', '\x3', 'L', '\x3', 'L', '\x3', 'L', '\x3', + 'M', '\x3', 'M', '\x3', 'M', '\x3', 'M', '\x3', 'N', '\x3', 'N', '\x3', + 'N', '\x3', 'O', '\x3', 'O', '\x3', 'O', '\x3', 'O', '\x3', 'O', '\x3', + 'O', '\x3', 'O', '\x3', 'P', '\x3', 'P', '\x3', 'P', '\x3', 'P', '\x3', + 'P', '\x3', 'Q', '\x3', 'Q', '\x3', 'Q', '\x3', 'Q', '\x3', 'Q', '\x3', + 'Q', '\x3', 'Q', '\x3', 'Q', '\x3', 'Q', '\x3', 'R', '\x3', 'R', '\x3', + 'R', '\x3', 'S', '\x3', 'S', '\x3', 'S', '\x3', 'S', '\x3', 'S', '\x3', + 'T', '\x3', 'T', '\x3', 'T', '\x3', 'T', '\x3', 'T', '\x3', 'T', '\x3', + 'U', '\x3', 'U', '\x3', 'U', '\x3', 'U', '\x3', 'U', '\x3', 'U', '\x3', + 'U', '\x3', 'V', '\x3', 'V', '\x3', 'V', '\x3', 'V', '\x3', 'V', '\x3', + 'V', '\x3', 'V', '\x3', 'V', '\x3', 'W', '\x3', 'W', '\x3', 'W', '\x3', + 'W', '\x3', 'X', '\x3', 'X', '\x3', 'X', '\x3', 'X', '\x3', 'X', '\x3', + 'Y', '\x3', 'Y', '\x3', 'Y', '\x3', 'Y', '\x3', 'Y', '\x3', 'Y', '\x3', + 'Y', '\x3', 'Z', '\x3', 'Z', '\x3', 'Z', '\x3', 'Z', '\x3', 'Z', '\x3', + '[', '\x3', '[', '\x3', '[', '\x3', '[', '\x3', '[', '\x3', '[', '\x3', + '\\', '\x3', '\\', '\x3', '\\', '\x3', '\\', '\x3', '\\', '\x3', '\\', + '\x3', '\\', '\x3', ']', '\x3', ']', '\x3', ']', '\x3', ']', '\x3', ']', + '\x3', '^', '\x3', '^', '\x3', '^', '\x3', '^', '\x3', '^', '\x3', '_', + '\x3', '_', '\x3', '_', '\x3', '_', '\x3', '`', '\x3', '`', '\x3', '`', + '\x3', '`', '\x3', '`', '\x3', '\x61', '\x3', '\x61', '\x3', '\x61', '\x3', + '\x61', '\x3', '\x61', '\x3', '\x62', '\x3', '\x62', '\x3', '\x62', '\a', + '\x62', '\x31A', '\n', '\x62', '\f', '\x62', '\xE', '\x62', '\x31D', '\v', + '\x62', '\x3', '\x62', '\x3', '\x62', '\x3', '\x62', '\x3', '\x62', '\a', + '\x62', '\x323', '\n', '\x62', '\f', '\x62', '\xE', '\x62', '\x326', '\v', + '\x62', '\x3', '\x62', '\x5', '\x62', '\x329', '\n', '\x62', '\x3', '\x63', + '\x3', '\x63', '\x3', '\x63', '\x3', '\x63', '\x3', '\x63', '\x3', '\x63', + '\x3', '\x63', '\x3', '\x63', '\x3', '\x63', '\x3', '\x63', '\x3', '\x63', + '\x3', '\x63', '\x3', '\x63', '\x3', '\x63', '\x3', '\x63', '\x3', '\x63', + '\x3', '\x63', '\x3', '\x63', '\x5', '\x63', '\x33D', '\n', '\x63', '\x3', + '\x64', '\x3', '\x64', '\x3', '\x64', '\x3', '\x64', '\x6', '\x64', '\x343', + '\n', '\x64', '\r', '\x64', '\xE', '\x64', '\x344', '\x3', '\x65', '\x3', + '\x65', '\x3', '\x65', '\a', '\x65', '\x34A', '\n', '\x65', '\f', '\x65', + '\xE', '\x65', '\x34D', '\v', '\x65', '\x5', '\x65', '\x34F', '\n', '\x65', + '\x3', '\x66', '\x3', '\x66', '\x6', '\x66', '\x353', '\n', '\x66', '\r', + '\x66', '\xE', '\x66', '\x354', '\x3', 'g', '\x5', 'g', '\x358', '\n', + 'g', '\x3', 'h', '\x3', 'h', '\x5', 'h', '\x35C', '\n', 'h', '\x3', 'i', + '\x3', 'i', '\x5', 'i', '\x360', '\n', 'i', '\x3', 'j', '\x3', 'j', '\x5', + 'j', '\x364', '\n', 'j', '\x3', 'k', '\x3', 'k', '\x3', 'l', '\x3', 'l', + '\x5', 'l', '\x36A', '\n', 'l', '\x3', 'm', '\x3', 'm', '\x3', 'n', '\x6', + 'n', '\x36F', '\n', 'n', '\r', 'n', '\xE', 'n', '\x370', '\x3', 'n', '\x6', + 'n', '\x374', '\n', 'n', '\r', 'n', '\xE', 'n', '\x375', '\x3', 'n', '\x3', + 'n', '\x6', 'n', '\x37A', '\n', 'n', '\r', 'n', '\xE', 'n', '\x37B', '\x3', + 'n', '\x3', 'n', '\x6', 'n', '\x380', '\n', 'n', '\r', 'n', '\xE', 'n', + '\x381', '\x5', 'n', '\x384', '\n', 'n', '\x3', 'n', '\x5', 'n', '\x387', + '\n', 'n', '\x3', 'n', '\x5', 'n', '\x38A', '\n', 'n', '\x3', 'n', '\x6', + 'n', '\x38D', '\n', 'n', '\r', 'n', '\xE', 'n', '\x38E', '\x3', 'o', '\a', + 'o', '\x392', '\n', 'o', '\f', 'o', '\xE', 'o', '\x395', '\v', 'o', '\x3', + 'o', '\x3', 'o', '\x6', 'o', '\x399', '\n', 'o', '\r', 'o', '\xE', 'o', + '\x39A', '\x3', 'p', '\x3', 'p', '\x3', 'p', '\x3', 'p', '\x3', 'p', '\x3', + 'p', '\x3', 'p', '\x3', 'p', '\x3', 'p', '\x3', 'p', '\x3', 'p', '\x3', + 'q', '\x3', 'q', '\x3', 'q', '\x3', 'r', '\x3', 'r', '\x3', 'r', '\x3', + 'r', '\x3', 's', '\x3', 's', '\x3', 's', '\x3', 's', '\x3', 's', '\x3', + 's', '\x3', 's', '\x3', 's', '\x3', 't', '\x3', 't', '\x3', 't', '\x3', + 't', '\x3', 't', '\x3', 't', '\x3', 't', '\x3', 'u', '\x3', 'u', '\x3', + 'u', '\x3', 'u', '\x3', 'u', '\x3', 'u', '\x3', 'u', '\x3', 'u', '\x3', + 'u', '\x3', 'u', '\x3', 'v', '\x3', 'v', '\x3', 'v', '\x3', 'v', '\x3', + 'v', '\x3', 'v', '\x3', 'v', '\x3', 'w', '\x3', 'w', '\x3', 'w', '\x3', + 'x', '\x3', 'x', '\x3', 'x', '\x3', 'x', '\x3', 'y', '\x3', 'y', '\x3', + 'y', '\x3', 'y', '\x3', 'y', '\x3', 'z', '\x3', 'z', '\a', 'z', '\x3DD', + '\n', 'z', '\f', 'z', '\xE', 'z', '\x3E0', '\v', 'z', '\x3', '{', '\x3', + '{', '\x5', '{', '\x3E4', '\n', '{', '\x3', '|', '\x3', '|', '\x5', '|', + '\x3E8', '\n', '|', '\x3', '}', '\x3', '}', '\a', '}', '\x3EC', '\n', + '}', '\f', '}', '\xE', '}', '\x3EF', '\v', '}', '\x3', '}', '\x6', '}', + '\x3F2', '\n', '}', '\r', '}', '\xE', '}', '\x3F3', '\x3', '~', '\x6', + '~', '\x3F7', '\n', '~', '\r', '~', '\xE', '~', '\x3F8', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', + '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x3', '\x7F', '\x5', '\x7F', + '\x48C', '\n', '\x7F', '\x3', '\x80', '\x3', '\x80', '\x3', '\x80', '\x3', + '\x80', '\x3', '\x80', '\x3', '\x80', '\a', '\x80', '\x494', '\n', '\x80', + '\f', '\x80', '\xE', '\x80', '\x497', '\v', '\x80', '\x3', '\x80', '\x3', + '\x80', '\x3', '\x80', '\x3', '\x80', '\x3', '\x80', '\x3', '\x80', '\a', + '\x80', '\x49F', '\n', '\x80', '\f', '\x80', '\xE', '\x80', '\x4A2', '\v', + '\x80', '\x3', '\x80', '\x5', '\x80', '\x4A5', '\n', '\x80', '\x3', '\x80', + '\x3', '\x80', '\x5', '\x80', '\x4A9', '\n', '\x80', '\x5', '\x80', '\x4AB', + '\n', '\x80', '\x3', '\x81', '\x3', '\x81', '\x3', '\x82', '\x3', '\x82', + '\x3', '\x83', '\x3', '\x83', '\x3', '\x84', '\x3', '\x84', '\x3', '\x85', + '\x3', '\x85', '\x3', '\x86', '\x3', '\x86', '\x3', '\x87', '\x3', '\x87', + '\x3', '\x88', '\x3', '\x88', '\x3', '\x89', '\x3', '\x89', '\x3', '\x8A', + '\x3', '\x8A', '\x3', '\x8B', '\x3', '\x8B', '\x3', '\x8C', '\x3', '\x8C', + '\x3', '\x8D', '\x3', '\x8D', '\x3', '\x8E', '\x3', '\x8E', '\x3', '\x8F', + '\x3', '\x8F', '\x3', '\x90', '\x3', '\x90', '\x3', '\x91', '\x3', '\x91', + '\x3', '\x92', '\x3', '\x92', '\x3', '\x93', '\x3', '\x93', '\x3', '\x94', + '\x3', '\x94', '\x2', '\x2', '\x95', '\x3', '\x3', '\x5', '\x4', '\a', + '\x5', '\t', '\x6', '\v', '\a', '\r', '\b', '\xF', '\t', '\x11', '\n', + '\x13', '\v', '\x15', '\f', '\x17', '\r', '\x19', '\xE', '\x1B', '\xF', + '\x1D', '\x10', '\x1F', '\x11', '!', '\x12', '#', '\x13', '%', '\x14', + '\'', '\x15', ')', '\x16', '+', '\x17', '-', '\x18', '/', '\x19', '\x31', + '\x1A', '\x33', '\x1B', '\x35', '\x1C', '\x37', '\x1D', '\x39', '\x1E', + ';', '\x1F', '=', ' ', '?', '!', '\x41', '\"', '\x43', '#', '\x45', '$', + 'G', '%', 'I', '&', 'K', '\'', 'M', '(', 'O', ')', 'Q', '*', 'S', '+', + 'U', ',', 'W', '-', 'Y', '.', '[', '/', ']', '\x30', '_', '\x31', '\x61', + '\x32', '\x63', '\x33', '\x65', '\x34', 'g', '\x35', 'i', '\x36', 'k', + '\x37', 'm', '\x38', 'o', '\x39', 'q', ':', 's', ';', 'u', '<', 'w', '=', + 'y', '>', '{', '?', '}', '@', '\x7F', '\x41', '\x81', '\x42', '\x83', + '\x43', '\x85', '\x44', '\x87', '\x45', '\x89', '\x46', '\x8B', 'G', '\x8D', + 'H', '\x8F', 'I', '\x91', 'J', '\x93', 'K', '\x95', 'L', '\x97', 'M', + '\x99', 'N', '\x9B', 'O', '\x9D', 'P', '\x9F', 'Q', '\xA1', 'R', '\xA3', + 'S', '\xA5', 'T', '\xA7', 'U', '\xA9', 'V', '\xAB', 'W', '\xAD', 'X', + '\xAF', 'Y', '\xB1', 'Z', '\xB3', '[', '\xB5', '\\', '\xB7', ']', '\xB9', + '^', '\xBB', '_', '\xBD', '`', '\xBF', '\x61', '\xC1', '\x62', '\xC3', + '\x63', '\xC5', '\x64', '\xC7', '\x65', '\xC9', '\x66', '\xCB', 'g', '\xCD', + 'h', '\xCF', 'i', '\xD1', 'j', '\xD3', 'k', '\xD5', 'l', '\xD7', 'm', + '\xD9', 'n', '\xDB', 'o', '\xDD', 'p', '\xDF', 'q', '\xE1', 'r', '\xE3', + 's', '\xE5', 't', '\xE7', 'u', '\xE9', 'v', '\xEB', 'w', '\xED', 'x', + '\xEF', 'y', '\xF1', 'z', '\xF3', '{', '\xF5', '|', '\xF7', '}', '\xF9', + '~', '\xFB', '\x7F', '\xFD', '\x80', '\xFF', '\x81', '\x101', '\x2', '\x103', + '\x2', '\x105', '\x2', '\x107', '\x2', '\x109', '\x2', '\x10B', '\x2', + '\x10D', '\x2', '\x10F', '\x2', '\x111', '\x2', '\x113', '\x2', '\x115', + '\x2', '\x117', '\x2', '\x119', '\x2', '\x11B', '\x2', '\x11D', '\x2', + '\x11F', '\x2', '\x121', '\x2', '\x123', '\x2', '\x125', '\x2', '\x127', + '\x2', '\x3', '\x2', '\x30', '\x4', '\x2', 'W', 'W', 'w', 'w', '\x4', + '\x2', 'P', 'P', 'p', 'p', '\x4', '\x2', 'K', 'K', 'k', 'k', '\x4', '\x2', + 'Q', 'Q', 'q', 'q', '\x4', '\x2', '\x43', '\x43', '\x63', '\x63', '\x4', + '\x2', 'N', 'N', 'n', 'n', '\x4', '\x2', 'R', 'R', 'r', 'r', '\x4', '\x2', + 'V', 'V', 'v', 'v', '\x4', '\x2', 'O', 'O', 'o', 'o', '\x4', '\x2', '\x45', + '\x45', '\x65', '\x65', '\x4', '\x2', 'J', 'J', 'j', 'j', '\x4', '\x2', + 'Y', 'Y', 'y', 'y', '\x4', '\x2', '\x46', '\x46', '\x66', '\x66', '\x4', + '\x2', 'U', 'U', 'u', 'u', '\x4', '\x2', 'G', 'G', 'g', 'g', '\x4', '\x2', + 'T', 'T', 't', 't', '\x4', '\x2', 'I', 'I', 'i', 'i', '\x4', '\x2', 'X', + 'X', 'x', 'x', '\x4', '\x2', '[', '[', '{', '{', '\x4', '\x2', '\x44', + '\x44', '\x64', '\x64', '\x4', '\x2', 'M', 'M', 'm', 'm', '\x4', '\x2', + 'Z', 'Z', 'z', 'z', '\x4', '\x2', 'H', 'H', 'h', 'h', '\xF', '\x2', '$', + '$', ')', ')', '\x44', '\x44', 'H', 'H', 'P', 'P', 'T', 'T', 'V', 'V', + '^', '^', '\x64', '\x64', 'h', 'h', 'p', 'p', 't', 't', 'v', 'v', '\x4', + '\x2', '\x43', 'H', '\x63', 'h', '\x4', '\x2', 'S', 'S', 's', 's', '\x3', + '\x2', '\xE', '\xE', '\x4', '\x2', '\x2', '\x61', '\x63', '\x1', '\x3', + '\x2', ' ', ' ', '\x1AF', '\x2', '\x32', ';', '\x43', '\\', '\x61', '\x61', + '\x63', '|', '\xAC', '\xAC', '\xB7', '\xB7', '\xB9', '\xB9', '\xBC', '\xBC', + '\xC2', '\xD8', '\xDA', '\xF8', '\xFA', '\x2C3', '\x2C8', '\x2D3', '\x2E2', + '\x2E6', '\x2EE', '\x2EE', '\x2F0', '\x2F0', '\x302', '\x376', '\x378', + '\x379', '\x37C', '\x37F', '\x388', '\x38C', '\x38E', '\x38E', '\x390', + '\x3A3', '\x3A5', '\x3F7', '\x3F9', '\x483', '\x485', '\x489', '\x48C', + '\x529', '\x533', '\x558', '\x55B', '\x55B', '\x563', '\x589', '\x593', + '\x5BF', '\x5C1', '\x5C1', '\x5C3', '\x5C4', '\x5C6', '\x5C7', '\x5C9', + '\x5C9', '\x5D2', '\x5EC', '\x5F2', '\x5F4', '\x612', '\x61C', '\x622', + '\x66B', '\x670', '\x6D5', '\x6D7', '\x6DE', '\x6E1', '\x6EA', '\x6EC', + '\x6FE', '\x701', '\x701', '\x712', '\x74C', '\x74F', '\x7B3', '\x7C2', + '\x7F7', '\x7FC', '\x7FC', '\x802', '\x82F', '\x842', '\x85D', '\x8A2', + '\x8A2', '\x8A4', '\x8AE', '\x8E6', '\x900', '\x902', '\x965', '\x968', + '\x971', '\x973', '\x979', '\x97B', '\x981', '\x983', '\x985', '\x987', + '\x98E', '\x991', '\x992', '\x995', '\x9AA', '\x9AC', '\x9B2', '\x9B4', + '\x9B4', '\x9B8', '\x9BB', '\x9BE', '\x9C6', '\x9C9', '\x9CA', '\x9CD', + '\x9D0', '\x9D9', '\x9D9', '\x9DE', '\x9DF', '\x9E1', '\x9E5', '\x9E8', + '\x9F3', '\xA03', '\xA05', '\xA07', '\xA0C', '\xA11', '\xA12', '\xA15', + '\xA2A', '\xA2C', '\xA32', '\xA34', '\xA35', '\xA37', '\xA38', '\xA3A', + '\xA3B', '\xA3E', '\xA3E', '\xA40', '\xA44', '\xA49', '\xA4A', '\xA4D', + '\xA4F', '\xA53', '\xA53', '\xA5B', '\xA5E', '\xA60', '\xA60', '\xA68', + '\xA77', '\xA83', '\xA85', '\xA87', '\xA8F', '\xA91', '\xA93', '\xA95', + '\xAAA', '\xAAC', '\xAB2', '\xAB4', '\xAB5', '\xAB7', '\xABB', '\xABE', + '\xAC7', '\xAC9', '\xACB', '\xACD', '\xACF', '\xAD2', '\xAD2', '\xAE2', + '\xAE5', '\xAE8', '\xAF1', '\xB03', '\xB05', '\xB07', '\xB0E', '\xB11', + '\xB12', '\xB15', '\xB2A', '\xB2C', '\xB32', '\xB34', '\xB35', '\xB37', + '\xB3B', '\xB3E', '\xB46', '\xB49', '\xB4A', '\xB4D', '\xB4F', '\xB58', + '\xB59', '\xB5E', '\xB5F', '\xB61', '\xB65', '\xB68', '\xB71', '\xB73', + '\xB73', '\xB84', '\xB85', '\xB87', '\xB8C', '\xB90', '\xB92', '\xB94', + '\xB97', '\xB9B', '\xB9C', '\xB9E', '\xB9E', '\xBA0', '\xBA1', '\xBA5', + '\xBA6', '\xBAA', '\xBAC', '\xBB0', '\xBBB', '\xBC0', '\xBC4', '\xBC8', + '\xBCA', '\xBCC', '\xBCF', '\xBD2', '\xBD2', '\xBD9', '\xBD9', '\xBE8', + '\xBF1', '\xC03', '\xC05', '\xC07', '\xC0E', '\xC10', '\xC12', '\xC14', + '\xC2A', '\xC2C', '\xC35', '\xC37', '\xC3B', '\xC3F', '\xC46', '\xC48', + '\xC4A', '\xC4C', '\xC4F', '\xC57', '\xC58', '\xC5A', '\xC5B', '\xC62', + '\xC65', '\xC68', '\xC71', '\xC84', '\xC85', '\xC87', '\xC8E', '\xC90', + '\xC92', '\xC94', '\xCAA', '\xCAC', '\xCB5', '\xCB7', '\xCBB', '\xCBE', + '\xCC6', '\xCC8', '\xCCA', '\xCCC', '\xCCF', '\xCD7', '\xCD8', '\xCE0', + '\xCE0', '\xCE2', '\xCE5', '\xCE8', '\xCF1', '\xCF3', '\xCF4', '\xD04', + '\xD05', '\xD07', '\xD0E', '\xD10', '\xD12', '\xD14', '\xD3C', '\xD3F', + '\xD46', '\xD48', '\xD4A', '\xD4C', '\xD50', '\xD59', '\xD59', '\xD62', + '\xD65', '\xD68', '\xD71', '\xD7C', '\xD81', '\xD84', '\xD85', '\xD87', + '\xD98', '\xD9C', '\xDB3', '\xDB5', '\xDBD', '\xDBF', '\xDBF', '\xDC2', + '\xDC8', '\xDCC', '\xDCC', '\xDD1', '\xDD6', '\xDD8', '\xDD8', '\xDDA', + '\xDE1', '\xDF4', '\xDF5', '\xE03', '\xE3C', '\xE42', '\xE50', '\xE52', + '\xE5B', '\xE83', '\xE84', '\xE86', '\xE86', '\xE89', '\xE8A', '\xE8C', + '\xE8C', '\xE8F', '\xE8F', '\xE96', '\xE99', '\xE9B', '\xEA1', '\xEA3', + '\xEA5', '\xEA7', '\xEA7', '\xEA9', '\xEA9', '\xEAC', '\xEAD', '\xEAF', + '\xEBB', '\xEBD', '\xEBF', '\xEC2', '\xEC6', '\xEC8', '\xEC8', '\xECA', + '\xECF', '\xED2', '\xEDB', '\xEDE', '\xEE1', '\xF02', '\xF02', '\xF1A', + '\xF1B', '\xF22', '\xF2B', '\xF37', '\xF37', '\xF39', '\xF39', '\xF3B', + '\xF3B', '\xF40', '\xF49', '\xF4B', '\xF6E', '\xF73', '\xF86', '\xF88', + '\xF99', '\xF9B', '\xFBE', '\xFC8', '\xFC8', '\x1002', '\x104B', '\x1052', + '\x109F', '\x10A2', '\x10C7', '\x10C9', '\x10C9', '\x10CF', '\x10CF', + '\x10D2', '\x10FC', '\x10FE', '\x124A', '\x124C', '\x124F', '\x1252', + '\x1258', '\x125A', '\x125A', '\x125C', '\x125F', '\x1262', '\x128A', + '\x128C', '\x128F', '\x1292', '\x12B2', '\x12B4', '\x12B7', '\x12BA', + '\x12C0', '\x12C2', '\x12C2', '\x12C4', '\x12C7', '\x12CA', '\x12D8', + '\x12DA', '\x1312', '\x1314', '\x1317', '\x131A', '\x135C', '\x135F', + '\x1361', '\x136B', '\x1373', '\x1382', '\x1391', '\x13A2', '\x13F6', + '\x1403', '\x166E', '\x1671', '\x1681', '\x1683', '\x169C', '\x16A2', + '\x16EC', '\x16F0', '\x16F2', '\x1702', '\x170E', '\x1710', '\x1716', + '\x1722', '\x1736', '\x1742', '\x1755', '\x1762', '\x176E', '\x1770', + '\x1772', '\x1774', '\x1775', '\x1782', '\x17D5', '\x17D9', '\x17D9', + '\x17DE', '\x17DF', '\x17E2', '\x17EB', '\x180D', '\x180F', '\x1812', + '\x181B', '\x1822', '\x1879', '\x1882', '\x18AC', '\x18B2', '\x18F7', + '\x1902', '\x191E', '\x1922', '\x192D', '\x1932', '\x193D', '\x1948', + '\x196F', '\x1972', '\x1976', '\x1982', '\x19AD', '\x19B2', '\x19CB', + '\x19D2', '\x19DC', '\x1A02', '\x1A1D', '\x1A22', '\x1A60', '\x1A62', + '\x1A7E', '\x1A81', '\x1A8B', '\x1A92', '\x1A9B', '\x1AA9', '\x1AA9', + '\x1B02', '\x1B4D', '\x1B52', '\x1B5B', '\x1B6D', '\x1B75', '\x1B82', + '\x1BF5', '\x1C02', '\x1C39', '\x1C42', '\x1C4B', '\x1C4F', '\x1C7F', + '\x1CD2', '\x1CD4', '\x1CD6', '\x1CF8', '\x1D02', '\x1DE8', '\x1DFE', + '\x1F17', '\x1F1A', '\x1F1F', '\x1F22', '\x1F47', '\x1F4A', '\x1F4F', + '\x1F52', '\x1F59', '\x1F5B', '\x1F5B', '\x1F5D', '\x1F5D', '\x1F5F', + '\x1F5F', '\x1F61', '\x1F7F', '\x1F82', '\x1FB6', '\x1FB8', '\x1FBE', + '\x1FC0', '\x1FC0', '\x1FC4', '\x1FC6', '\x1FC8', '\x1FCE', '\x1FD2', + '\x1FD5', '\x1FD8', '\x1FDD', '\x1FE2', '\x1FEE', '\x1FF4', '\x1FF6', + '\x1FF8', '\x1FFE', '\x2041', '\x2042', '\x2056', '\x2056', '\x2073', + '\x2073', '\x2081', '\x2081', '\x2092', '\x209E', '\x20D2', '\x20DE', + '\x20E3', '\x20E3', '\x20E7', '\x20F2', '\x2104', '\x2104', '\x2109', + '\x2109', '\x210C', '\x2115', '\x2117', '\x2117', '\x211A', '\x211F', + '\x2126', '\x2126', '\x2128', '\x2128', '\x212A', '\x212A', '\x212C', + '\x213B', '\x213E', '\x2141', '\x2147', '\x214B', '\x2150', '\x2150', + '\x2162', '\x218A', '\x2C02', '\x2C30', '\x2C32', '\x2C60', '\x2C62', + '\x2CE6', '\x2CED', '\x2CF5', '\x2D02', '\x2D27', '\x2D29', '\x2D29', + '\x2D2F', '\x2D2F', '\x2D32', '\x2D69', '\x2D71', '\x2D71', '\x2D81', + '\x2D98', '\x2DA2', '\x2DA8', '\x2DAA', '\x2DB0', '\x2DB2', '\x2DB8', + '\x2DBA', '\x2DC0', '\x2DC2', '\x2DC8', '\x2DCA', '\x2DD0', '\x2DD2', + '\x2DD8', '\x2DDA', '\x2DE0', '\x2DE2', '\x2E01', '\x3007', '\x3009', + '\x3023', '\x3031', '\x3033', '\x3037', '\x303A', '\x303E', '\x3043', + '\x3098', '\x309B', '\x30A1', '\x30A3', '\x30FC', '\x30FE', '\x3101', + '\x3107', '\x312F', '\x3133', '\x3190', '\x31A2', '\x31BC', '\x31F2', + '\x3201', '\x3402', '\x4DB7', '\x4E02', '\x9FCE', '\xA002', '\xA48E', + '\xA4D2', '\xA4FF', '\xA502', '\xA60E', '\xA612', '\xA62D', '\xA642', + '\xA671', '\xA676', '\xA67F', '\xA681', '\xA699', '\xA6A1', '\xA6F3', + '\xA719', '\xA721', '\xA724', '\xA78A', '\xA78D', '\xA790', '\xA792', + '\xA795', '\xA7A2', '\xA7AC', '\xA7FA', '\xA829', '\xA842', '\xA875', + '\xA882', '\xA8C6', '\xA8D2', '\xA8DB', '\xA8E2', '\xA8F9', '\xA8FD', + '\xA8FD', '\xA902', '\xA92F', '\xA932', '\xA955', '\xA962', '\xA97E', + '\xA982', '\xA9C2', '\xA9D1', '\xA9DB', '\xAA02', '\xAA38', '\xAA42', + '\xAA4F', '\xAA52', '\xAA5B', '\xAA62', '\xAA78', '\xAA7C', '\xAA7D', + '\xAA82', '\xAAC4', '\xAADD', '\xAADF', '\xAAE2', '\xAAF1', '\xAAF4', + '\xAAF8', '\xAB03', '\xAB08', '\xAB0B', '\xAB10', '\xAB13', '\xAB18', + '\xAB22', '\xAB28', '\xAB2A', '\xAB30', '\xABC2', '\xABEC', '\xABEE', + '\xABEF', '\xABF2', '\xABFB', '\xAC02', '\xD7A5', '\xD7B2', '\xD7C8', + '\xD7CD', '\xD7FD', '\xF902', '\xFA6F', '\xFA72', '\xFADB', '\xFB02', + '\xFB08', '\xFB15', '\xFB19', '\xFB1F', '\xFB2A', '\xFB2C', '\xFB38', + '\xFB3A', '\xFB3E', '\xFB40', '\xFB40', '\xFB42', '\xFB43', '\xFB45', + '\xFB46', '\xFB48', '\xFBB3', '\xFBD5', '\xFD3F', '\xFD52', '\xFD91', + '\xFD94', '\xFDC9', '\xFDF2', '\xFDFD', '\xFE02', '\xFE11', '\xFE22', + '\xFE28', '\xFE35', '\xFE36', '\xFE4F', '\xFE51', '\xFE72', '\xFE76', + '\xFE78', '\xFEFE', '\xFF12', '\xFF1B', '\xFF23', '\xFF3C', '\xFF41', + '\xFF41', '\xFF43', '\xFF5C', '\xFF68', '\xFFC0', '\xFFC4', '\xFFC9', + '\xFFCC', '\xFFD1', '\xFFD4', '\xFFD9', '\xFFDC', '\xFFDE', '\x4', '\x2', + '\x2', '+', '-', '\x1', '\x5', '\x2', '\x2', '(', '*', ']', '_', '\x1', + '\x5', '\x2', '\x2', '\v', '\r', '\xE', '\x10', '\x1', '\x4', '\x2', '\x2', + '\x30', '\x32', '\x1', '\x3', '\x2', '\x1F', '\x1F', '\x3', '\x2', '\x1E', + '\x1E', '\x3', '\x2', '\xF', '\xF', '\x13', '\x2', '&', '&', '\xA4', '\xA7', + '\x591', '\x591', '\x60D', '\x60D', '\x9F4', '\x9F5', '\x9FD', '\x9FD', + '\xAF3', '\xAF3', '\xBFB', '\xBFB', '\xE41', '\xE41', '\x17DD', '\x17DD', + '\x20A2', '\x20BC', '\xA83A', '\xA83A', '\xFDFE', '\xFDFE', '\xFE6B', + '\xFE6B', '\xFF06', '\xFF06', '\xFFE2', '\xFFE3', '\xFFE7', '\xFFE8', + '\x3', '\x2', '\"', '\"', '\b', '\x2', '\x61', '\x61', '\x2041', '\x2042', + '\x2056', '\x2056', '\xFE35', '\xFE36', '\xFE4F', '\xFE51', '\xFF41', + '\xFF41', '\x3', '\x2', '\v', '\v', '\x5', '\x2', '\x2', '#', '%', ']', + '_', '\x1', '\x3', '\x2', '\f', '\f', '\x3', '\x2', '\r', '\r', '\x3', + '\x2', '!', '!', '\x174', '\x2', '\x43', '\\', '\x63', '|', '\xAC', '\xAC', + '\xB7', '\xB7', '\xBC', '\xBC', '\xC2', '\xD8', '\xDA', '\xF8', '\xFA', + '\x2C3', '\x2C8', '\x2D3', '\x2E2', '\x2E6', '\x2EE', '\x2EE', '\x2F0', + '\x2F0', '\x372', '\x376', '\x378', '\x379', '\x37C', '\x37F', '\x388', + '\x388', '\x38A', '\x38C', '\x38E', '\x38E', '\x390', '\x3A3', '\x3A5', + '\x3F7', '\x3F9', '\x483', '\x48C', '\x529', '\x533', '\x558', '\x55B', + '\x55B', '\x563', '\x589', '\x5D2', '\x5EC', '\x5F2', '\x5F4', '\x622', + '\x64C', '\x670', '\x671', '\x673', '\x6D5', '\x6D7', '\x6D7', '\x6E7', + '\x6E8', '\x6F0', '\x6F1', '\x6FC', '\x6FE', '\x701', '\x701', '\x712', + '\x712', '\x714', '\x731', '\x74F', '\x7A7', '\x7B3', '\x7B3', '\x7CC', + '\x7EC', '\x7F6', '\x7F7', '\x7FC', '\x7FC', '\x802', '\x817', '\x81C', + '\x81C', '\x826', '\x826', '\x82A', '\x82A', '\x842', '\x85A', '\x8A2', + '\x8A2', '\x8A4', '\x8AE', '\x906', '\x93B', '\x93F', '\x93F', '\x952', + '\x952', '\x95A', '\x963', '\x973', '\x979', '\x97B', '\x981', '\x987', + '\x98E', '\x991', '\x992', '\x995', '\x9AA', '\x9AC', '\x9B2', '\x9B4', + '\x9B4', '\x9B8', '\x9BB', '\x9BF', '\x9BF', '\x9D0', '\x9D0', '\x9DE', + '\x9DF', '\x9E1', '\x9E3', '\x9F2', '\x9F3', '\xA07', '\xA0C', '\xA11', + '\xA12', '\xA15', '\xA2A', '\xA2C', '\xA32', '\xA34', '\xA35', '\xA37', + '\xA38', '\xA3A', '\xA3B', '\xA5B', '\xA5E', '\xA60', '\xA60', '\xA74', + '\xA76', '\xA87', '\xA8F', '\xA91', '\xA93', '\xA95', '\xAAA', '\xAAC', + '\xAB2', '\xAB4', '\xAB5', '\xAB7', '\xABB', '\xABF', '\xABF', '\xAD2', + '\xAD2', '\xAE2', '\xAE3', '\xB07', '\xB0E', '\xB11', '\xB12', '\xB15', + '\xB2A', '\xB2C', '\xB32', '\xB34', '\xB35', '\xB37', '\xB3B', '\xB3F', + '\xB3F', '\xB5E', '\xB5F', '\xB61', '\xB63', '\xB73', '\xB73', '\xB85', + '\xB85', '\xB87', '\xB8C', '\xB90', '\xB92', '\xB94', '\xB97', '\xB9B', + '\xB9C', '\xB9E', '\xB9E', '\xBA0', '\xBA1', '\xBA5', '\xBA6', '\xBAA', + '\xBAC', '\xBB0', '\xBBB', '\xBD2', '\xBD2', '\xC07', '\xC0E', '\xC10', + '\xC12', '\xC14', '\xC2A', '\xC2C', '\xC35', '\xC37', '\xC3B', '\xC3F', + '\xC3F', '\xC5A', '\xC5B', '\xC62', '\xC63', '\xC87', '\xC8E', '\xC90', + '\xC92', '\xC94', '\xCAA', '\xCAC', '\xCB5', '\xCB7', '\xCBB', '\xCBF', + '\xCBF', '\xCE0', '\xCE0', '\xCE2', '\xCE3', '\xCF3', '\xCF4', '\xD07', + '\xD0E', '\xD10', '\xD12', '\xD14', '\xD3C', '\xD3F', '\xD3F', '\xD50', + '\xD50', '\xD62', '\xD63', '\xD7C', '\xD81', '\xD87', '\xD98', '\xD9C', + '\xDB3', '\xDB5', '\xDBD', '\xDBF', '\xDBF', '\xDC2', '\xDC8', '\xE03', + '\xE32', '\xE34', '\xE35', '\xE42', '\xE48', '\xE83', '\xE84', '\xE86', + '\xE86', '\xE89', '\xE8A', '\xE8C', '\xE8C', '\xE8F', '\xE8F', '\xE96', + '\xE99', '\xE9B', '\xEA1', '\xEA3', '\xEA5', '\xEA7', '\xEA7', '\xEA9', + '\xEA9', '\xEAC', '\xEAD', '\xEAF', '\xEB2', '\xEB4', '\xEB5', '\xEBF', + '\xEBF', '\xEC2', '\xEC6', '\xEC8', '\xEC8', '\xEDE', '\xEE1', '\xF02', + '\xF02', '\xF42', '\xF49', '\xF4B', '\xF6E', '\xF8A', '\xF8E', '\x1002', + '\x102C', '\x1041', '\x1041', '\x1052', '\x1057', '\x105C', '\x105F', + '\x1063', '\x1063', '\x1067', '\x1068', '\x1070', '\x1072', '\x1077', + '\x1083', '\x1090', '\x1090', '\x10A2', '\x10C7', '\x10C9', '\x10C9', + '\x10CF', '\x10CF', '\x10D2', '\x10FC', '\x10FE', '\x124A', '\x124C', + '\x124F', '\x1252', '\x1258', '\x125A', '\x125A', '\x125C', '\x125F', + '\x1262', '\x128A', '\x128C', '\x128F', '\x1292', '\x12B2', '\x12B4', + '\x12B7', '\x12BA', '\x12C0', '\x12C2', '\x12C2', '\x12C4', '\x12C7', + '\x12CA', '\x12D8', '\x12DA', '\x1312', '\x1314', '\x1317', '\x131A', + '\x135C', '\x1382', '\x1391', '\x13A2', '\x13F6', '\x1403', '\x166E', + '\x1671', '\x1681', '\x1683', '\x169C', '\x16A2', '\x16EC', '\x16F0', + '\x16F2', '\x1702', '\x170E', '\x1710', '\x1713', '\x1722', '\x1733', + '\x1742', '\x1753', '\x1762', '\x176E', '\x1770', '\x1772', '\x1782', + '\x17B5', '\x17D9', '\x17D9', '\x17DE', '\x17DE', '\x1822', '\x1879', + '\x1882', '\x18AA', '\x18AC', '\x18AC', '\x18B2', '\x18F7', '\x1902', + '\x191E', '\x1952', '\x196F', '\x1972', '\x1976', '\x1982', '\x19AD', + '\x19C3', '\x19C9', '\x1A02', '\x1A18', '\x1A22', '\x1A56', '\x1AA9', + '\x1AA9', '\x1B07', '\x1B35', '\x1B47', '\x1B4D', '\x1B85', '\x1BA2', + '\x1BB0', '\x1BB1', '\x1BBC', '\x1BE7', '\x1C02', '\x1C25', '\x1C4F', + '\x1C51', '\x1C5C', '\x1C7F', '\x1CEB', '\x1CEE', '\x1CF0', '\x1CF3', + '\x1CF7', '\x1CF8', '\x1D02', '\x1DC1', '\x1E02', '\x1F17', '\x1F1A', + '\x1F1F', '\x1F22', '\x1F47', '\x1F4A', '\x1F4F', '\x1F52', '\x1F59', + '\x1F5B', '\x1F5B', '\x1F5D', '\x1F5D', '\x1F5F', '\x1F5F', '\x1F61', + '\x1F7F', '\x1F82', '\x1FB6', '\x1FB8', '\x1FBE', '\x1FC0', '\x1FC0', + '\x1FC4', '\x1FC6', '\x1FC8', '\x1FCE', '\x1FD2', '\x1FD5', '\x1FD8', + '\x1FDD', '\x1FE2', '\x1FEE', '\x1FF4', '\x1FF6', '\x1FF8', '\x1FFE', + '\x2073', '\x2073', '\x2081', '\x2081', '\x2092', '\x209E', '\x2104', + '\x2104', '\x2109', '\x2109', '\x210C', '\x2115', '\x2117', '\x2117', + '\x211A', '\x211F', '\x2126', '\x2126', '\x2128', '\x2128', '\x212A', + '\x212A', '\x212C', '\x213B', '\x213E', '\x2141', '\x2147', '\x214B', + '\x2150', '\x2150', '\x2162', '\x218A', '\x2C02', '\x2C30', '\x2C32', + '\x2C60', '\x2C62', '\x2CE6', '\x2CED', '\x2CF0', '\x2CF4', '\x2CF5', + '\x2D02', '\x2D27', '\x2D29', '\x2D29', '\x2D2F', '\x2D2F', '\x2D32', + '\x2D69', '\x2D71', '\x2D71', '\x2D82', '\x2D98', '\x2DA2', '\x2DA8', + '\x2DAA', '\x2DB0', '\x2DB2', '\x2DB8', '\x2DBA', '\x2DC0', '\x2DC2', + '\x2DC8', '\x2DCA', '\x2DD0', '\x2DD2', '\x2DD8', '\x2DDA', '\x2DE0', + '\x3007', '\x3009', '\x3023', '\x302B', '\x3033', '\x3037', '\x303A', + '\x303E', '\x3043', '\x3098', '\x309D', '\x30A1', '\x30A3', '\x30FC', + '\x30FE', '\x3101', '\x3107', '\x312F', '\x3133', '\x3190', '\x31A2', + '\x31BC', '\x31F2', '\x3201', '\x3402', '\x4DB7', '\x4E02', '\x9FCE', + '\xA002', '\xA48E', '\xA4D2', '\xA4FF', '\xA502', '\xA60E', '\xA612', + '\xA621', '\xA62C', '\xA62D', '\xA642', '\xA670', '\xA681', '\xA699', + '\xA6A2', '\xA6F1', '\xA719', '\xA721', '\xA724', '\xA78A', '\xA78D', + '\xA790', '\xA792', '\xA795', '\xA7A2', '\xA7AC', '\xA7FA', '\xA803', + '\xA805', '\xA807', '\xA809', '\xA80C', '\xA80E', '\xA824', '\xA842', + '\xA875', '\xA884', '\xA8B5', '\xA8F4', '\xA8F9', '\xA8FD', '\xA8FD', + '\xA90C', '\xA927', '\xA932', '\xA948', '\xA962', '\xA97E', '\xA986', + '\xA9B4', '\xA9D1', '\xA9D1', '\xAA02', '\xAA2A', '\xAA42', '\xAA44', + '\xAA46', '\xAA4D', '\xAA62', '\xAA78', '\xAA7C', '\xAA7C', '\xAA82', + '\xAAB1', '\xAAB3', '\xAAB3', '\xAAB7', '\xAAB8', '\xAABB', '\xAABF', + '\xAAC2', '\xAAC2', '\xAAC4', '\xAAC4', '\xAADD', '\xAADF', '\xAAE2', + '\xAAEC', '\xAAF4', '\xAAF6', '\xAB03', '\xAB08', '\xAB0B', '\xAB10', + '\xAB13', '\xAB18', '\xAB22', '\xAB28', '\xAB2A', '\xAB30', '\xABC2', + '\xABE4', '\xAC02', '\xD7A5', '\xD7B2', '\xD7C8', '\xD7CD', '\xD7FD', + '\xF902', '\xFA6F', '\xFA72', '\xFADB', '\xFB02', '\xFB08', '\xFB15', + '\xFB19', '\xFB1F', '\xFB1F', '\xFB21', '\xFB2A', '\xFB2C', '\xFB38', + '\xFB3A', '\xFB3E', '\xFB40', '\xFB40', '\xFB42', '\xFB43', '\xFB45', + '\xFB46', '\xFB48', '\xFBB3', '\xFBD5', '\xFD3F', '\xFD52', '\xFD91', + '\xFD94', '\xFDC9', '\xFDF2', '\xFDFD', '\xFE72', '\xFE76', '\xFE78', + '\xFEFE', '\xFF23', '\xFF3C', '\xFF43', '\xFF5C', '\xFF68', '\xFFC0', + '\xFFC4', '\xFFC9', '\xFFCC', '\xFFD1', '\xFFD4', '\xFFD9', '\xFFDC', + '\xFFDE', '\x2', '\x501', '\x2', '\x3', '\x3', '\x2', '\x2', '\x2', '\x2', + '\x5', '\x3', '\x2', '\x2', '\x2', '\x2', '\a', '\x3', '\x2', '\x2', '\x2', + '\x2', '\t', '\x3', '\x2', '\x2', '\x2', '\x2', '\v', '\x3', '\x2', '\x2', + '\x2', '\x2', '\r', '\x3', '\x2', '\x2', '\x2', '\x2', '\xF', '\x3', '\x2', + '\x2', '\x2', '\x2', '\x11', '\x3', '\x2', '\x2', '\x2', '\x2', '\x13', + '\x3', '\x2', '\x2', '\x2', '\x2', '\x15', '\x3', '\x2', '\x2', '\x2', + '\x2', '\x17', '\x3', '\x2', '\x2', '\x2', '\x2', '\x19', '\x3', '\x2', + '\x2', '\x2', '\x2', '\x1B', '\x3', '\x2', '\x2', '\x2', '\x2', '\x1D', + '\x3', '\x2', '\x2', '\x2', '\x2', '\x1F', '\x3', '\x2', '\x2', '\x2', + '\x2', '!', '\x3', '\x2', '\x2', '\x2', '\x2', '#', '\x3', '\x2', '\x2', + '\x2', '\x2', '%', '\x3', '\x2', '\x2', '\x2', '\x2', '\'', '\x3', '\x2', + '\x2', '\x2', '\x2', ')', '\x3', '\x2', '\x2', '\x2', '\x2', '+', '\x3', + '\x2', '\x2', '\x2', '\x2', '-', '\x3', '\x2', '\x2', '\x2', '\x2', '/', + '\x3', '\x2', '\x2', '\x2', '\x2', '\x31', '\x3', '\x2', '\x2', '\x2', + '\x2', '\x33', '\x3', '\x2', '\x2', '\x2', '\x2', '\x35', '\x3', '\x2', + '\x2', '\x2', '\x2', '\x37', '\x3', '\x2', '\x2', '\x2', '\x2', '\x39', + '\x3', '\x2', '\x2', '\x2', '\x2', ';', '\x3', '\x2', '\x2', '\x2', '\x2', + '=', '\x3', '\x2', '\x2', '\x2', '\x2', '?', '\x3', '\x2', '\x2', '\x2', + '\x2', '\x41', '\x3', '\x2', '\x2', '\x2', '\x2', '\x43', '\x3', '\x2', + '\x2', '\x2', '\x2', '\x45', '\x3', '\x2', '\x2', '\x2', '\x2', 'G', '\x3', + '\x2', '\x2', '\x2', '\x2', 'I', '\x3', '\x2', '\x2', '\x2', '\x2', 'K', + '\x3', '\x2', '\x2', '\x2', '\x2', 'M', '\x3', '\x2', '\x2', '\x2', '\x2', + 'O', '\x3', '\x2', '\x2', '\x2', '\x2', 'Q', '\x3', '\x2', '\x2', '\x2', + '\x2', 'S', '\x3', '\x2', '\x2', '\x2', '\x2', 'U', '\x3', '\x2', '\x2', + '\x2', '\x2', 'W', '\x3', '\x2', '\x2', '\x2', '\x2', 'Y', '\x3', '\x2', + '\x2', '\x2', '\x2', '[', '\x3', '\x2', '\x2', '\x2', '\x2', ']', '\x3', + '\x2', '\x2', '\x2', '\x2', '_', '\x3', '\x2', '\x2', '\x2', '\x2', '\x61', + '\x3', '\x2', '\x2', '\x2', '\x2', '\x63', '\x3', '\x2', '\x2', '\x2', + '\x2', '\x65', '\x3', '\x2', '\x2', '\x2', '\x2', 'g', '\x3', '\x2', '\x2', + '\x2', '\x2', 'i', '\x3', '\x2', '\x2', '\x2', '\x2', 'k', '\x3', '\x2', + '\x2', '\x2', '\x2', 'm', '\x3', '\x2', '\x2', '\x2', '\x2', 'o', '\x3', + '\x2', '\x2', '\x2', '\x2', 'q', '\x3', '\x2', '\x2', '\x2', '\x2', 's', + '\x3', '\x2', '\x2', '\x2', '\x2', 'u', '\x3', '\x2', '\x2', '\x2', '\x2', + 'w', '\x3', '\x2', '\x2', '\x2', '\x2', 'y', '\x3', '\x2', '\x2', '\x2', + '\x2', '{', '\x3', '\x2', '\x2', '\x2', '\x2', '}', '\x3', '\x2', '\x2', + '\x2', '\x2', '\x7F', '\x3', '\x2', '\x2', '\x2', '\x2', '\x81', '\x3', + '\x2', '\x2', '\x2', '\x2', '\x83', '\x3', '\x2', '\x2', '\x2', '\x2', + '\x85', '\x3', '\x2', '\x2', '\x2', '\x2', '\x87', '\x3', '\x2', '\x2', + '\x2', '\x2', '\x89', '\x3', '\x2', '\x2', '\x2', '\x2', '\x8B', '\x3', + '\x2', '\x2', '\x2', '\x2', '\x8D', '\x3', '\x2', '\x2', '\x2', '\x2', + '\x8F', '\x3', '\x2', '\x2', '\x2', '\x2', '\x91', '\x3', '\x2', '\x2', + '\x2', '\x2', '\x93', '\x3', '\x2', '\x2', '\x2', '\x2', '\x95', '\x3', + '\x2', '\x2', '\x2', '\x2', '\x97', '\x3', '\x2', '\x2', '\x2', '\x2', + '\x99', '\x3', '\x2', '\x2', '\x2', '\x2', '\x9B', '\x3', '\x2', '\x2', + '\x2', '\x2', '\x9D', '\x3', '\x2', '\x2', '\x2', '\x2', '\x9F', '\x3', + '\x2', '\x2', '\x2', '\x2', '\xA1', '\x3', '\x2', '\x2', '\x2', '\x2', + '\xA3', '\x3', '\x2', '\x2', '\x2', '\x2', '\xA5', '\x3', '\x2', '\x2', + '\x2', '\x2', '\xA7', '\x3', '\x2', '\x2', '\x2', '\x2', '\xA9', '\x3', + '\x2', '\x2', '\x2', '\x2', '\xAB', '\x3', '\x2', '\x2', '\x2', '\x2', + '\xAD', '\x3', '\x2', '\x2', '\x2', '\x2', '\xAF', '\x3', '\x2', '\x2', + '\x2', '\x2', '\xB1', '\x3', '\x2', '\x2', '\x2', '\x2', '\xB3', '\x3', + '\x2', '\x2', '\x2', '\x2', '\xB5', '\x3', '\x2', '\x2', '\x2', '\x2', + '\xB7', '\x3', '\x2', '\x2', '\x2', '\x2', '\xB9', '\x3', '\x2', '\x2', + '\x2', '\x2', '\xBB', '\x3', '\x2', '\x2', '\x2', '\x2', '\xBD', '\x3', + '\x2', '\x2', '\x2', '\x2', '\xBF', '\x3', '\x2', '\x2', '\x2', '\x2', + '\xC1', '\x3', '\x2', '\x2', '\x2', '\x2', '\xC3', '\x3', '\x2', '\x2', + '\x2', '\x2', '\xC5', '\x3', '\x2', '\x2', '\x2', '\x2', '\xC7', '\x3', + '\x2', '\x2', '\x2', '\x2', '\xC9', '\x3', '\x2', '\x2', '\x2', '\x2', + '\xCB', '\x3', '\x2', '\x2', '\x2', '\x2', '\xCD', '\x3', '\x2', '\x2', + '\x2', '\x2', '\xCF', '\x3', '\x2', '\x2', '\x2', '\x2', '\xD1', '\x3', + '\x2', '\x2', '\x2', '\x2', '\xD3', '\x3', '\x2', '\x2', '\x2', '\x2', + '\xD5', '\x3', '\x2', '\x2', '\x2', '\x2', '\xD7', '\x3', '\x2', '\x2', + '\x2', '\x2', '\xD9', '\x3', '\x2', '\x2', '\x2', '\x2', '\xDB', '\x3', + '\x2', '\x2', '\x2', '\x2', '\xDD', '\x3', '\x2', '\x2', '\x2', '\x2', + '\xDF', '\x3', '\x2', '\x2', '\x2', '\x2', '\xE1', '\x3', '\x2', '\x2', + '\x2', '\x2', '\xE3', '\x3', '\x2', '\x2', '\x2', '\x2', '\xE5', '\x3', + '\x2', '\x2', '\x2', '\x2', '\xE7', '\x3', '\x2', '\x2', '\x2', '\x2', + '\xE9', '\x3', '\x2', '\x2', '\x2', '\x2', '\xEB', '\x3', '\x2', '\x2', + '\x2', '\x2', '\xED', '\x3', '\x2', '\x2', '\x2', '\x2', '\xEF', '\x3', + '\x2', '\x2', '\x2', '\x2', '\xF1', '\x3', '\x2', '\x2', '\x2', '\x2', + '\xF3', '\x3', '\x2', '\x2', '\x2', '\x2', '\xF5', '\x3', '\x2', '\x2', + '\x2', '\x2', '\xF7', '\x3', '\x2', '\x2', '\x2', '\x2', '\xF9', '\x3', + '\x2', '\x2', '\x2', '\x2', '\xFB', '\x3', '\x2', '\x2', '\x2', '\x2', + '\xFD', '\x3', '\x2', '\x2', '\x2', '\x2', '\xFF', '\x3', '\x2', '\x2', + '\x2', '\x3', '\x129', '\x3', '\x2', '\x2', '\x2', '\x5', '\x12B', '\x3', + '\x2', '\x2', '\x2', '\a', '\x12D', '\x3', '\x2', '\x2', '\x2', '\t', + '\x12F', '\x3', '\x2', '\x2', '\x2', '\v', '\x132', '\x3', '\x2', '\x2', + '\x2', '\r', '\x134', '\x3', '\x2', '\x2', '\x2', '\xF', '\x136', '\x3', + '\x2', '\x2', '\x2', '\x11', '\x138', '\x3', '\x2', '\x2', '\x2', '\x13', + '\x13A', '\x3', '\x2', '\x2', '\x2', '\x15', '\x13C', '\x3', '\x2', '\x2', + '\x2', '\x17', '\x13E', '\x3', '\x2', '\x2', '\x2', '\x19', '\x140', '\x3', + '\x2', '\x2', '\x2', '\x1B', '\x142', '\x3', '\x2', '\x2', '\x2', '\x1D', + '\x145', '\x3', '\x2', '\x2', '\x2', '\x1F', '\x147', '\x3', '\x2', '\x2', + '\x2', '!', '\x149', '\x3', '\x2', '\x2', '\x2', '#', '\x14B', '\x3', + '\x2', '\x2', '\x2', '%', '\x14D', '\x3', '\x2', '\x2', '\x2', '\'', '\x150', + '\x3', '\x2', '\x2', '\x2', ')', '\x152', '\x3', '\x2', '\x2', '\x2', + '+', '\x154', '\x3', '\x2', '\x2', '\x2', '-', '\x157', '\x3', '\x2', + '\x2', '\x2', '/', '\x15A', '\x3', '\x2', '\x2', '\x2', '\x31', '\x15C', + '\x3', '\x2', '\x2', '\x2', '\x33', '\x15E', '\x3', '\x2', '\x2', '\x2', + '\x35', '\x160', '\x3', '\x2', '\x2', '\x2', '\x37', '\x162', '\x3', '\x2', + '\x2', '\x2', '\x39', '\x169', '\x3', '\x2', '\x2', '\x2', ';', '\x171', + '\x3', '\x2', '\x2', '\x2', '=', '\x178', '\x3', '\x2', '\x2', '\x2', + '?', '\x17F', '\x3', '\x2', '\x2', '\x2', '\x41', '\x186', '\x3', '\x2', + '\x2', '\x2', '\x43', '\x18F', '\x3', '\x2', '\x2', '\x2', '\x45', '\x196', + '\x3', '\x2', '\x2', '\x2', 'G', '\x19D', '\x3', '\x2', '\x2', '\x2', + 'I', '\x1A2', '\x3', '\x2', '\x2', '\x2', 'K', '\x1AA', '\x3', '\x2', + '\x2', '\x2', 'M', '\x1B3', '\x3', '\x2', '\x2', '\x2', 'O', '\x1BC', + '\x3', '\x2', '\x2', '\x2', 'Q', '\x1C5', '\x3', '\x2', '\x2', '\x2', + 'S', '\x1CE', '\x3', '\x2', '\x2', '\x2', 'U', '\x1D7', '\x3', '\x2', + '\x2', '\x2', 'W', '\x1DF', '\x3', '\x2', '\x2', '\x2', 'Y', '\x1E6', + '\x3', '\x2', '\x2', '\x2', '[', '\x1ED', '\x3', '\x2', '\x2', '\x2', + ']', '\x1F4', '\x3', '\x2', '\x2', '\x2', '_', '\x1FA', '\x3', '\x2', + '\x2', '\x2', '\x61', '\x1FE', '\x3', '\x2', '\x2', '\x2', '\x63', '\x207', + '\x3', '\x2', '\x2', '\x2', '\x65', '\x20D', '\x3', '\x2', '\x2', '\x2', + 'g', '\x214', '\x3', '\x2', '\x2', '\x2', 'i', '\x217', '\x3', '\x2', + '\x2', '\x2', 'k', '\x21D', '\x3', '\x2', '\x2', '\x2', 'm', '\x220', + '\x3', '\x2', '\x2', '\x2', 'o', '\x227', '\x3', '\x2', '\x2', '\x2', + 'q', '\x22B', '\x3', '\x2', '\x2', '\x2', 's', '\x232', '\x3', '\x2', + '\x2', '\x2', 'u', '\x239', '\x3', '\x2', '\x2', '\x2', 'w', '\x240', + '\x3', '\x2', '\x2', '\x2', 'y', '\x245', '\x3', '\x2', '\x2', '\x2', + '{', '\x24B', '\x3', '\x2', '\x2', '\x2', '}', '\x250', '\x3', '\x2', + '\x2', '\x2', '\x7F', '\x259', '\x3', '\x2', '\x2', '\x2', '\x81', '\x260', + '\x3', '\x2', '\x2', '\x2', '\x83', '\x266', '\x3', '\x2', '\x2', '\x2', + '\x85', '\x269', '\x3', '\x2', '\x2', '\x2', '\x87', '\x26E', '\x3', '\x2', + '\x2', '\x2', '\x89', '\x274', '\x3', '\x2', '\x2', '\x2', '\x8B', '\x27E', + '\x3', '\x2', '\x2', '\x2', '\x8D', '\x282', '\x3', '\x2', '\x2', '\x2', + '\x8F', '\x28D', '\x3', '\x2', '\x2', '\x2', '\x91', '\x292', '\x3', '\x2', + '\x2', '\x2', '\x93', '\x298', '\x3', '\x2', '\x2', '\x2', '\x95', '\x29B', + '\x3', '\x2', '\x2', '\x2', '\x97', '\x29F', '\x3', '\x2', '\x2', '\x2', + '\x99', '\x2A3', '\x3', '\x2', '\x2', '\x2', '\x9B', '\x2A7', '\x3', '\x2', + '\x2', '\x2', '\x9D', '\x2AA', '\x3', '\x2', '\x2', '\x2', '\x9F', '\x2B1', + '\x3', '\x2', '\x2', '\x2', '\xA1', '\x2B6', '\x3', '\x2', '\x2', '\x2', + '\xA3', '\x2BF', '\x3', '\x2', '\x2', '\x2', '\xA5', '\x2C2', '\x3', '\x2', + '\x2', '\x2', '\xA7', '\x2C7', '\x3', '\x2', '\x2', '\x2', '\xA9', '\x2CD', + '\x3', '\x2', '\x2', '\x2', '\xAB', '\x2D4', '\x3', '\x2', '\x2', '\x2', + '\xAD', '\x2DC', '\x3', '\x2', '\x2', '\x2', '\xAF', '\x2E0', '\x3', '\x2', + '\x2', '\x2', '\xB1', '\x2E5', '\x3', '\x2', '\x2', '\x2', '\xB3', '\x2EC', + '\x3', '\x2', '\x2', '\x2', '\xB5', '\x2F1', '\x3', '\x2', '\x2', '\x2', + '\xB7', '\x2F7', '\x3', '\x2', '\x2', '\x2', '\xB9', '\x2FE', '\x3', '\x2', + '\x2', '\x2', '\xBB', '\x303', '\x3', '\x2', '\x2', '\x2', '\xBD', '\x308', + '\x3', '\x2', '\x2', '\x2', '\xBF', '\x30C', '\x3', '\x2', '\x2', '\x2', + '\xC1', '\x311', '\x3', '\x2', '\x2', '\x2', '\xC3', '\x328', '\x3', '\x2', + '\x2', '\x2', '\xC5', '\x32A', '\x3', '\x2', '\x2', '\x2', '\xC7', '\x33E', + '\x3', '\x2', '\x2', '\x2', '\xC9', '\x34E', '\x3', '\x2', '\x2', '\x2', + '\xCB', '\x350', '\x3', '\x2', '\x2', '\x2', '\xCD', '\x357', '\x3', '\x2', + '\x2', '\x2', '\xCF', '\x35B', '\x3', '\x2', '\x2', '\x2', '\xD1', '\x35F', + '\x3', '\x2', '\x2', '\x2', '\xD3', '\x363', '\x3', '\x2', '\x2', '\x2', + '\xD5', '\x365', '\x3', '\x2', '\x2', '\x2', '\xD7', '\x369', '\x3', '\x2', + '\x2', '\x2', '\xD9', '\x36B', '\x3', '\x2', '\x2', '\x2', '\xDB', '\x383', + '\x3', '\x2', '\x2', '\x2', '\xDD', '\x393', '\x3', '\x2', '\x2', '\x2', + '\xDF', '\x39C', '\x3', '\x2', '\x2', '\x2', '\xE1', '\x3A7', '\x3', '\x2', + '\x2', '\x2', '\xE3', '\x3AA', '\x3', '\x2', '\x2', '\x2', '\xE5', '\x3AE', + '\x3', '\x2', '\x2', '\x2', '\xE7', '\x3B6', '\x3', '\x2', '\x2', '\x2', + '\xE9', '\x3BD', '\x3', '\x2', '\x2', '\x2', '\xEB', '\x3C7', '\x3', '\x2', + '\x2', '\x2', '\xED', '\x3CE', '\x3', '\x2', '\x2', '\x2', '\xEF', '\x3D1', + '\x3', '\x2', '\x2', '\x2', '\xF1', '\x3D5', '\x3', '\x2', '\x2', '\x2', + '\xF3', '\x3DA', '\x3', '\x2', '\x2', '\x2', '\xF5', '\x3E3', '\x3', '\x2', + '\x2', '\x2', '\xF7', '\x3E7', '\x3', '\x2', '\x2', '\x2', '\xF9', '\x3F1', + '\x3', '\x2', '\x2', '\x2', '\xFB', '\x3F6', '\x3', '\x2', '\x2', '\x2', + '\xFD', '\x48B', '\x3', '\x2', '\x2', '\x2', '\xFF', '\x4AA', '\x3', '\x2', + '\x2', '\x2', '\x101', '\x4AC', '\x3', '\x2', '\x2', '\x2', '\x103', '\x4AE', + '\x3', '\x2', '\x2', '\x2', '\x105', '\x4B0', '\x3', '\x2', '\x2', '\x2', + '\x107', '\x4B2', '\x3', '\x2', '\x2', '\x2', '\x109', '\x4B4', '\x3', + '\x2', '\x2', '\x2', '\x10B', '\x4B6', '\x3', '\x2', '\x2', '\x2', '\x10D', + '\x4B8', '\x3', '\x2', '\x2', '\x2', '\x10F', '\x4BA', '\x3', '\x2', '\x2', + '\x2', '\x111', '\x4BC', '\x3', '\x2', '\x2', '\x2', '\x113', '\x4BE', + '\x3', '\x2', '\x2', '\x2', '\x115', '\x4C0', '\x3', '\x2', '\x2', '\x2', + '\x117', '\x4C2', '\x3', '\x2', '\x2', '\x2', '\x119', '\x4C4', '\x3', + '\x2', '\x2', '\x2', '\x11B', '\x4C6', '\x3', '\x2', '\x2', '\x2', '\x11D', + '\x4C8', '\x3', '\x2', '\x2', '\x2', '\x11F', '\x4CA', '\x3', '\x2', '\x2', + '\x2', '\x121', '\x4CC', '\x3', '\x2', '\x2', '\x2', '\x123', '\x4CE', + '\x3', '\x2', '\x2', '\x2', '\x125', '\x4D0', '\x3', '\x2', '\x2', '\x2', + '\x127', '\x4D2', '\x3', '\x2', '\x2', '\x2', '\x129', '\x12A', '\a', + '=', '\x2', '\x2', '\x12A', '\x4', '\x3', '\x2', '\x2', '\x2', '\x12B', + '\x12C', '\a', '.', '\x2', '\x2', '\x12C', '\x6', '\x3', '\x2', '\x2', + '\x2', '\x12D', '\x12E', '\a', '?', '\x2', '\x2', '\x12E', '\b', '\x3', + '\x2', '\x2', '\x2', '\x12F', '\x130', '\a', '-', '\x2', '\x2', '\x130', + '\x131', '\a', '?', '\x2', '\x2', '\x131', '\n', '\x3', '\x2', '\x2', + '\x2', '\x132', '\x133', '\a', '/', '\x2', '\x2', '\x133', '\f', '\x3', + '\x2', '\x2', '\x2', '\x134', '\x135', '\a', ',', '\x2', '\x2', '\x135', + '\xE', '\x3', '\x2', '\x2', '\x2', '\x136', '\x137', '\a', '*', '\x2', + '\x2', '\x137', '\x10', '\x3', '\x2', '\x2', '\x2', '\x138', '\x139', + '\a', '+', '\x2', '\x2', '\x139', '\x12', '\x3', '\x2', '\x2', '\x2', + '\x13A', '\x13B', '\a', ']', '\x2', '\x2', '\x13B', '\x14', '\x3', '\x2', + '\x2', '\x2', '\x13C', '\x13D', '\a', '_', '\x2', '\x2', '\x13D', '\x16', + '\x3', '\x2', '\x2', '\x2', '\x13E', '\x13F', '\a', '<', '\x2', '\x2', + '\x13F', '\x18', '\x3', '\x2', '\x2', '\x2', '\x140', '\x141', '\a', '~', + '\x2', '\x2', '\x141', '\x1A', '\x3', '\x2', '\x2', '\x2', '\x142', '\x143', + '\a', '\x30', '\x2', '\x2', '\x143', '\x144', '\a', '\x30', '\x2', '\x2', + '\x144', '\x1C', '\x3', '\x2', '\x2', '\x2', '\x145', '\x146', '\a', '-', + '\x2', '\x2', '\x146', '\x1E', '\x3', '\x2', '\x2', '\x2', '\x147', '\x148', + '\a', '\x31', '\x2', '\x2', '\x148', ' ', '\x3', '\x2', '\x2', '\x2', + '\x149', '\x14A', '\a', '\'', '\x2', '\x2', '\x14A', '\"', '\x3', '\x2', + '\x2', '\x2', '\x14B', '\x14C', '\a', '`', '\x2', '\x2', '\x14C', '$', + '\x3', '\x2', '\x2', '\x2', '\x14D', '\x14E', '\a', '>', '\x2', '\x2', + '\x14E', '\x14F', '\a', '@', '\x2', '\x2', '\x14F', '&', '\x3', '\x2', + '\x2', '\x2', '\x150', '\x151', '\a', '>', '\x2', '\x2', '\x151', '(', + '\x3', '\x2', '\x2', '\x2', '\x152', '\x153', '\a', '@', '\x2', '\x2', + '\x153', '*', '\x3', '\x2', '\x2', '\x2', '\x154', '\x155', '\a', '>', + '\x2', '\x2', '\x155', '\x156', '\a', '?', '\x2', '\x2', '\x156', ',', + '\x3', '\x2', '\x2', '\x2', '\x157', '\x158', '\a', '@', '\x2', '\x2', + '\x158', '\x159', '\a', '?', '\x2', '\x2', '\x159', '.', '\x3', '\x2', + '\x2', '\x2', '\x15A', '\x15B', '\a', '\x30', '\x2', '\x2', '\x15B', '\x30', + '\x3', '\x2', '\x2', '\x2', '\x15C', '\x15D', '\a', '}', '\x2', '\x2', + '\x15D', '\x32', '\x3', '\x2', '\x2', '\x2', '\x15E', '\x15F', '\a', '\x7F', + '\x2', '\x2', '\x15F', '\x34', '\x3', '\x2', '\x2', '\x2', '\x160', '\x161', + '\a', '&', '\x2', '\x2', '\x161', '\x36', '\x3', '\x2', '\x2', '\x2', + '\x162', '\x163', '\a', '\xC5', '\x2', '\x2', '\x163', '\x164', '\a', + '\xA4', '\x2', '\x2', '\x164', '\x165', '\a', '\xC7', '\x2', '\x2', '\x165', + '\x166', '\a', '\xBA', '\x2', '\x2', '\x166', '\x167', '\a', '\xC4', '\x2', + '\x2', '\x167', '\x168', '\a', '\xAA', '\x2', '\x2', '\x168', '\x38', + '\x3', '\x2', '\x2', '\x2', '\x169', '\x16A', '\a', '\xC5', '\x2', '\x2', + '\x16A', '\x16B', '\a', '\xA5', '\x2', '\x2', '\x16B', '\x16C', '\a', + '\xE4', '\x2', '\x2', '\x16C', '\x16D', '\a', '\x201C', '\x2', '\x2', + '\x16D', '\x16E', '\a', '\xAE', '\x2', '\x2', '\x16E', '\x16F', '\a', + '\xCD', '\x2', '\x2', '\x16F', '\x170', '\a', '\x2022', '\x2', '\x2', + '\x170', ':', '\x3', '\x2', '\x2', '\x2', '\x171', '\x172', '\a', '\xC5', + '\x2', '\x2', '\x172', '\x173', '\a', '\xB1', '\x2', '\x2', '\x173', '\x174', + '\a', '\xC4', '\x2', '\x2', '\x174', '\x175', '\a', '\xBB', '\x2', '\x2', + '\x175', '\x176', '\a', '\xC4', '\x2', '\x2', '\x176', '\x177', '\a', + '\xA6', '\x2', '\x2', '\x177', '<', '\x3', '\x2', '\x2', '\x2', '\x178', + '\x179', '\a', '\xC5', '\x2', '\x2', '\x179', '\x17A', '\a', '\xB1', '\x2', + '\x2', '\x17A', '\x17B', '\a', '\xC4', '\x2', '\x2', '\x17B', '\x17C', + '\a', '\xBE', '\x2', '\x2', '\x17C', '\x17D', '\a', '\xC7', '\x2', '\x2', + '\x17D', '\x17E', '\a', '\x201E', '\x2', '\x2', '\x17E', '>', '\x3', '\x2', + '\x2', '\x2', '\x17F', '\x180', '\a', '\xC5', '\x2', '\x2', '\x180', '\x181', + '\a', '\xA4', '\x2', '\x2', '\x181', '\x182', '\a', '\xC7', '\x2', '\x2', + '\x182', '\x183', '\a', '\xBA', '\x2', '\x2', '\x183', '\x184', '\a', + '\xC4', '\x2', '\x2', '\x184', '\x185', '\a', '\xAB', '\x2', '\x2', '\x185', + '@', '\x3', '\x2', '\x2', '\x2', '\x186', '\x187', '\a', '\xC5', '\x2', + '\x2', '\x187', '\x188', '\a', '\xA5', '\x2', '\x2', '\x188', '\x189', + '\a', '\xE4', '\x2', '\x2', '\x189', '\x18A', '\a', '\x201C', '\x2', '\x2', + '\x18A', '\x18B', '\a', '\xAE', '\x2', '\x2', '\x18B', '\x18C', '\a', + '\xE4', '\x2', '\x2', '\x18C', '\x18D', '\a', '\x20AE', '\x2', '\x2', + '\x18D', '\x18E', '\a', '\xB2', '\x2', '\x2', '\x18E', '\x42', '\x3', + '\x2', '\x2', '\x2', '\x18F', '\x190', '\a', '\xC5', '\x2', '\x2', '\x190', + '\x191', '\a', '\xB1', '\x2', '\x2', '\x191', '\x192', '\a', '\xC4', '\x2', + '\x2', '\x192', '\x193', '\a', '\xBB', '\x2', '\x2', '\x193', '\x194', + '\a', '\xC4', '\x2', '\x2', '\x194', '\x195', '\a', '\xA7', '\x2', '\x2', + '\x195', '\x44', '\x3', '\x2', '\x2', '\x2', '\x196', '\x197', '\a', '\xC5', + '\x2', '\x2', '\x197', '\x198', '\a', '\xB1', '\x2', '\x2', '\x198', '\x199', + '\a', '\xC4', '\x2', '\x2', '\x199', '\x19A', '\a', '\xBE', '\x2', '\x2', + '\x19A', '\x19B', '\a', '\xC7', '\x2', '\x2', '\x19B', '\x19C', '\a', + '\xC0', '\x2', '\x2', '\x19C', '\x46', '\x3', '\x2', '\x2', '\x2', '\x19D', + '\x19E', '\a', '\xC5', '\x2', '\x2', '\x19E', '\x19F', '\a', '\x201C', + '\x2', '\x2', '\x19F', '\x1A0', '\a', '\xC4', '\x2', '\x2', '\x1A0', '\x1A1', + '\a', '\xAF', '\x2', '\x2', '\x1A1', 'H', '\x3', '\x2', '\x2', '\x2', + '\x1A2', '\x1A3', '\a', '\xC5', '\x2', '\x2', '\x1A3', '\x1A4', '\a', + '\xA4', '\x2', '\x2', '\x1A4', '\x1A5', '\a', '\xE4', '\x2', '\x2', '\x1A5', + '\x1A6', '\a', '\x201C', '\x2', '\x2', '\x1A6', '\x1A7', '\a', '\xAE', + '\x2', '\x2', '\x1A7', '\x1A8', '\a', '\xC4', '\x2', '\x2', '\x1A8', '\x1A9', + '\a', '\xFFFF', '\x2', '\x2', '\x1A9', 'J', '\x3', '\x2', '\x2', '\x2', + '\x1AA', '\x1AB', '\a', '\xC5', '\x2', '\x2', '\x1AB', '\x1AC', '\a', + '\xA4', '\x2', '\x2', '\x1AC', '\x1AD', '\a', '\xE4', '\x2', '\x2', '\x1AD', + '\x1AE', '\a', '\x201C', '\x2', '\x2', '\x1AE', '\x1AF', '\a', '\xAE', + '\x2', '\x2', '\x1AF', '\x1B0', '\a', '\xE4', '\x2', '\x2', '\x1B0', '\x1B1', + '\a', '\x20AE', '\x2', '\x2', '\x1B1', '\x1B2', '\a', '\x2DE', '\x2', + '\x2', '\x1B2', 'L', '\x3', '\x2', '\x2', '\x2', '\x1B3', '\x1B4', '\a', + '\xC5', '\x2', '\x2', '\x1B4', '\x1B5', '\a', '\xA4', '\x2', '\x2', '\x1B5', + '\x1B6', '\a', '\xE4', '\x2', '\x2', '\x1B6', '\x1B7', '\a', '\x201C', + '\x2', '\x2', '\x1B7', '\x1B8', '\a', '\xAE', '\x2', '\x2', '\x1B8', '\x1B9', + '\a', '\xE4', '\x2', '\x2', '\x1B9', '\x1BA', '\a', '\x20AE', '\x2', '\x2', + '\x1BA', '\x1BB', '\a', '\x2124', '\x2', '\x2', '\x1BB', 'N', '\x3', '\x2', + '\x2', '\x2', '\x1BC', '\x1BD', '\a', '\xC5', '\x2', '\x2', '\x1BD', '\x1BE', + '\a', '\xA4', '\x2', '\x2', '\x1BE', '\x1BF', '\a', '\xE4', '\x2', '\x2', + '\x1BF', '\x1C0', '\a', '\x201C', '\x2', '\x2', '\x1C0', '\x1C1', '\a', + '\xAE', '\x2', '\x2', '\x1C1', '\x1C2', '\a', '\xE4', '\x2', '\x2', '\x1C2', + '\x1C3', '\a', '\x20AE', '\x2', '\x2', '\x1C3', '\x1C4', '\a', '\x155', + '\x2', '\x2', '\x1C4', 'P', '\x3', '\x2', '\x2', '\x2', '\x1C5', '\x1C6', + '\a', '\xC5', '\x2', '\x2', '\x1C6', '\x1C7', '\a', '\xA4', '\x2', '\x2', + '\x1C7', '\x1C8', '\a', '\xE4', '\x2', '\x2', '\x1C8', '\x1C9', '\a', + '\x201C', '\x2', '\x2', '\x1C9', '\x1CA', '\a', '\xAE', '\x2', '\x2', + '\x1CA', '\x1CB', '\a', '\xE4', '\x2', '\x2', '\x1CB', '\x1CC', '\a', + '\x20AE', '\x2', '\x2', '\x1CC', '\x1CD', '\a', '\xFFFF', '\x2', '\x2', + '\x1CD', 'R', '\x3', '\x2', '\x2', '\x2', '\x1CE', '\x1CF', '\a', '\xC5', + '\x2', '\x2', '\x1CF', '\x1D0', '\a', '\xA4', '\x2', '\x2', '\x1D0', '\x1D1', + '\a', '\xE4', '\x2', '\x2', '\x1D1', '\x1D2', '\a', '\x201C', '\x2', '\x2', + '\x1D2', '\x1D3', '\a', '\xAE', '\x2', '\x2', '\x1D3', '\x1D4', '\a', + '\xE4', '\x2', '\x2', '\x1D4', '\x1D5', '\a', '\x20AE', '\x2', '\x2', + '\x1D5', '\x1D6', '\a', '\xA4', '\x2', '\x2', '\x1D6', 'T', '\x3', '\x2', + '\x2', '\x2', '\x1D7', '\x1D8', '\a', '\xC5', '\x2', '\x2', '\x1D8', '\x1D9', + '\a', '\xA4', '\x2', '\x2', '\x1D9', '\x1DA', '\a', '\xCD', '\x2', '\x2', + '\x1DA', '\x1DB', '\a', '\x2022', '\x2', '\x2', '\x1DB', '\x1DC', '\a', + '\xE4', '\x2', '\x2', '\x1DC', '\x1DD', '\a', '\x20AE', '\x2', '\x2', + '\x1DD', '\x1DE', '\a', '\x2124', '\x2', '\x2', '\x1DE', 'V', '\x3', '\x2', + '\x2', '\x2', '\x1DF', '\x1E0', '\a', '\xC5', '\x2', '\x2', '\x1E0', '\x1E1', + '\a', '\xB1', '\x2', '\x2', '\x1E1', '\x1E2', '\a', '\xC4', '\x2', '\x2', + '\x1E2', '\x1E3', '\a', '\xBB', '\x2', '\x2', '\x1E3', '\x1E4', '\a', + '\xCD', '\x2', '\x2', '\x1E4', '\x1E5', '\a', '\x155', '\x2', '\x2', '\x1E5', + 'X', '\x3', '\x2', '\x2', '\x2', '\x1E6', '\x1E7', '\a', '\xC5', '\x2', + '\x2', '\x1E7', '\x1E8', '\a', '\xB1', '\x2', '\x2', '\x1E8', '\x1E9', + '\a', '\xC4', '\x2', '\x2', '\x1E9', '\x1EA', '\a', '\xBB', '\x2', '\x2', + '\x1EA', '\x1EB', '\a', '\xC4', '\x2', '\x2', '\x1EB', '\x1EC', '\a', + '\xA5', '\x2', '\x2', '\x1EC', 'Z', '\x3', '\x2', '\x2', '\x2', '\x1ED', + '\x1EE', '\a', '\xC5', '\x2', '\x2', '\x1EE', '\x1EF', '\a', '\xB1', '\x2', + '\x2', '\x1EF', '\x1F0', '\a', '\xC4', '\x2', '\x2', '\x1F0', '\x1F1', + '\a', '\xBE', '\x2', '\x2', '\x1F1', '\x1F2', '\a', '\xC4', '\x2', '\x2', + '\x1F2', '\x1F3', '\a', '\xFFFF', '\x2', '\x2', '\x1F3', '\\', '\x3', + '\x2', '\x2', '\x2', '\x1F4', '\x1F5', '\t', '\x2', '\x2', '\x2', '\x1F5', + '\x1F6', '\t', '\x3', '\x2', '\x2', '\x1F6', '\x1F7', '\t', '\x4', '\x2', + '\x2', '\x1F7', '\x1F8', '\t', '\x5', '\x2', '\x2', '\x1F8', '\x1F9', + '\t', '\x3', '\x2', '\x2', '\x1F9', '^', '\x3', '\x2', '\x2', '\x2', '\x1FA', + '\x1FB', '\t', '\x6', '\x2', '\x2', '\x1FB', '\x1FC', '\t', '\a', '\x2', + '\x2', '\x1FC', '\x1FD', '\t', '\a', '\x2', '\x2', '\x1FD', '`', '\x3', + '\x2', '\x2', '\x2', '\x1FE', '\x1FF', '\t', '\x5', '\x2', '\x2', '\x1FF', + '\x200', '\t', '\b', '\x2', '\x2', '\x200', '\x201', '\t', '\t', '\x2', + '\x2', '\x201', '\x202', '\t', '\x4', '\x2', '\x2', '\x202', '\x203', + '\t', '\x5', '\x2', '\x2', '\x203', '\x204', '\t', '\x3', '\x2', '\x2', + '\x204', '\x205', '\t', '\x6', '\x2', '\x2', '\x205', '\x206', '\t', '\a', + '\x2', '\x2', '\x206', '\x62', '\x3', '\x2', '\x2', '\x2', '\x207', '\x208', + '\t', '\n', '\x2', '\x2', '\x208', '\x209', '\t', '\x6', '\x2', '\x2', + '\x209', '\x20A', '\t', '\t', '\x2', '\x2', '\x20A', '\x20B', '\t', '\v', + '\x2', '\x2', '\x20B', '\x20C', '\t', '\f', '\x2', '\x2', '\x20C', '\x64', + '\x3', '\x2', '\x2', '\x2', '\x20D', '\x20E', '\t', '\x2', '\x2', '\x2', + '\x20E', '\x20F', '\t', '\x3', '\x2', '\x2', '\x20F', '\x210', '\t', '\r', + '\x2', '\x2', '\x210', '\x211', '\t', '\x4', '\x2', '\x2', '\x211', '\x212', + '\t', '\x3', '\x2', '\x2', '\x212', '\x213', '\t', '\xE', '\x2', '\x2', + '\x213', '\x66', '\x3', '\x2', '\x2', '\x2', '\x214', '\x215', '\t', '\x6', + '\x2', '\x2', '\x215', '\x216', '\t', '\xF', '\x2', '\x2', '\x216', 'h', + '\x3', '\x2', '\x2', '\x2', '\x217', '\x218', '\t', '\n', '\x2', '\x2', + '\x218', '\x219', '\t', '\x10', '\x2', '\x2', '\x219', '\x21A', '\t', + '\x11', '\x2', '\x2', '\x21A', '\x21B', '\t', '\x12', '\x2', '\x2', '\x21B', + '\x21C', '\t', '\x10', '\x2', '\x2', '\x21C', 'j', '\x3', '\x2', '\x2', + '\x2', '\x21D', '\x21E', '\t', '\x5', '\x2', '\x2', '\x21E', '\x21F', + '\t', '\x3', '\x2', '\x2', '\x21F', 'l', '\x3', '\x2', '\x2', '\x2', '\x220', + '\x221', '\t', '\v', '\x2', '\x2', '\x221', '\x222', '\t', '\x11', '\x2', + '\x2', '\x222', '\x223', '\t', '\x10', '\x2', '\x2', '\x223', '\x224', + '\t', '\x6', '\x2', '\x2', '\x224', '\x225', '\t', '\t', '\x2', '\x2', + '\x225', '\x226', '\t', '\x10', '\x2', '\x2', '\x226', 'n', '\x3', '\x2', + '\x2', '\x2', '\x227', '\x228', '\t', '\xF', '\x2', '\x2', '\x228', '\x229', + '\t', '\x10', '\x2', '\x2', '\x229', '\x22A', '\t', '\t', '\x2', '\x2', + '\x22A', 'p', '\x3', '\x2', '\x2', '\x2', '\x22B', '\x22C', '\t', '\xE', + '\x2', '\x2', '\x22C', '\x22D', '\t', '\x10', '\x2', '\x2', '\x22D', '\x22E', + '\t', '\t', '\x2', '\x2', '\x22E', '\x22F', '\t', '\x6', '\x2', '\x2', + '\x22F', '\x230', '\t', '\v', '\x2', '\x2', '\x230', '\x231', '\t', '\f', + '\x2', '\x2', '\x231', 'r', '\x3', '\x2', '\x2', '\x2', '\x232', '\x233', + '\t', '\xE', '\x2', '\x2', '\x233', '\x234', '\t', '\x10', '\x2', '\x2', + '\x234', '\x235', '\t', '\a', '\x2', '\x2', '\x235', '\x236', '\t', '\x10', + '\x2', '\x2', '\x236', '\x237', '\t', '\t', '\x2', '\x2', '\x237', '\x238', + '\t', '\x10', '\x2', '\x2', '\x238', 't', '\x3', '\x2', '\x2', '\x2', + '\x239', '\x23A', '\t', '\x11', '\x2', '\x2', '\x23A', '\x23B', '\t', + '\x10', '\x2', '\x2', '\x23B', '\x23C', '\t', '\n', '\x2', '\x2', '\x23C', + '\x23D', '\t', '\x5', '\x2', '\x2', '\x23D', '\x23E', '\t', '\x13', '\x2', + '\x2', '\x23E', '\x23F', '\t', '\x10', '\x2', '\x2', '\x23F', 'v', '\x3', + '\x2', '\x2', '\x2', '\x240', '\x241', '\t', '\v', '\x2', '\x2', '\x241', + '\x242', '\t', '\x6', '\x2', '\x2', '\x242', '\x243', '\t', '\a', '\x2', + '\x2', '\x243', '\x244', '\t', '\a', '\x2', '\x2', '\x244', 'x', '\x3', + '\x2', '\x2', '\x2', '\x245', '\x246', '\t', '\x14', '\x2', '\x2', '\x246', + '\x247', '\t', '\x4', '\x2', '\x2', '\x247', '\x248', '\t', '\x10', '\x2', + '\x2', '\x248', '\x249', '\t', '\a', '\x2', '\x2', '\x249', '\x24A', '\t', + '\xE', '\x2', '\x2', '\x24A', 'z', '\x3', '\x2', '\x2', '\x2', '\x24B', + '\x24C', '\t', '\r', '\x2', '\x2', '\x24C', '\x24D', '\t', '\x4', '\x2', + '\x2', '\x24D', '\x24E', '\t', '\t', '\x2', '\x2', '\x24E', '\x24F', '\t', + '\f', '\x2', '\x2', '\x24F', '|', '\x3', '\x2', '\x2', '\x2', '\x250', + '\x251', '\t', '\xE', '\x2', '\x2', '\x251', '\x252', '\t', '\x4', '\x2', + '\x2', '\x252', '\x253', '\t', '\xF', '\x2', '\x2', '\x253', '\x254', + '\t', '\t', '\x2', '\x2', '\x254', '\x255', '\t', '\x4', '\x2', '\x2', + '\x255', '\x256', '\t', '\x3', '\x2', '\x2', '\x256', '\x257', '\t', '\v', + '\x2', '\x2', '\x257', '\x258', '\t', '\t', '\x2', '\x2', '\x258', '~', + '\x3', '\x2', '\x2', '\x2', '\x259', '\x25A', '\t', '\x11', '\x2', '\x2', + '\x25A', '\x25B', '\t', '\x10', '\x2', '\x2', '\x25B', '\x25C', '\t', + '\t', '\x2', '\x2', '\x25C', '\x25D', '\t', '\x2', '\x2', '\x2', '\x25D', + '\x25E', '\t', '\x11', '\x2', '\x2', '\x25E', '\x25F', '\t', '\x3', '\x2', + '\x2', '\x25F', '\x80', '\x3', '\x2', '\x2', '\x2', '\x260', '\x261', + '\t', '\x5', '\x2', '\x2', '\x261', '\x262', '\t', '\x11', '\x2', '\x2', + '\x262', '\x263', '\t', '\xE', '\x2', '\x2', '\x263', '\x264', '\t', '\x10', + '\x2', '\x2', '\x264', '\x265', '\t', '\x11', '\x2', '\x2', '\x265', '\x82', + '\x3', '\x2', '\x2', '\x2', '\x266', '\x267', '\t', '\x15', '\x2', '\x2', + '\x267', '\x268', '\t', '\x14', '\x2', '\x2', '\x268', '\x84', '\x3', + '\x2', '\x2', '\x2', '\x269', '\x26A', '\t', '\xF', '\x2', '\x2', '\x26A', + '\x26B', '\t', '\x16', '\x2', '\x2', '\x26B', '\x26C', '\t', '\x4', '\x2', + '\x2', '\x26C', '\x26D', '\t', '\b', '\x2', '\x2', '\x26D', '\x86', '\x3', + '\x2', '\x2', '\x2', '\x26E', '\x26F', '\t', '\a', '\x2', '\x2', '\x26F', + '\x270', '\t', '\x4', '\x2', '\x2', '\x270', '\x271', '\t', '\n', '\x2', + '\x2', '\x271', '\x272', '\t', '\x4', '\x2', '\x2', '\x272', '\x273', + '\t', '\t', '\x2', '\x2', '\x273', '\x88', '\x3', '\x2', '\x2', '\x2', + '\x274', '\x275', '\t', '\x6', '\x2', '\x2', '\x275', '\x276', '\t', '\xF', + '\x2', '\x2', '\x276', '\x277', '\t', '\v', '\x2', '\x2', '\x277', '\x278', + '\t', '\x10', '\x2', '\x2', '\x278', '\x279', '\t', '\x3', '\x2', '\x2', + '\x279', '\x27A', '\t', '\xE', '\x2', '\x2', '\x27A', '\x27B', '\t', '\x4', + '\x2', '\x2', '\x27B', '\x27C', '\t', '\x3', '\x2', '\x2', '\x27C', '\x27D', + '\t', '\x12', '\x2', '\x2', '\x27D', '\x8A', '\x3', '\x2', '\x2', '\x2', + '\x27E', '\x27F', '\t', '\x6', '\x2', '\x2', '\x27F', '\x280', '\t', '\xF', + '\x2', '\x2', '\x280', '\x281', '\t', '\v', '\x2', '\x2', '\x281', '\x8C', + '\x3', '\x2', '\x2', '\x2', '\x282', '\x283', '\t', '\xE', '\x2', '\x2', + '\x283', '\x284', '\t', '\x10', '\x2', '\x2', '\x284', '\x285', '\t', + '\xF', '\x2', '\x2', '\x285', '\x286', '\t', '\v', '\x2', '\x2', '\x286', + '\x287', '\t', '\x10', '\x2', '\x2', '\x287', '\x288', '\t', '\x3', '\x2', + '\x2', '\x288', '\x289', '\t', '\xE', '\x2', '\x2', '\x289', '\x28A', + '\t', '\x4', '\x2', '\x2', '\x28A', '\x28B', '\t', '\x3', '\x2', '\x2', + '\x28B', '\x28C', '\t', '\x12', '\x2', '\x2', '\x28C', '\x8E', '\x3', + '\x2', '\x2', '\x2', '\x28D', '\x28E', '\t', '\xE', '\x2', '\x2', '\x28E', + '\x28F', '\t', '\x10', '\x2', '\x2', '\x28F', '\x290', '\t', '\xF', '\x2', + '\x2', '\x290', '\x291', '\t', '\v', '\x2', '\x2', '\x291', '\x90', '\x3', + '\x2', '\x2', '\x2', '\x292', '\x293', '\t', '\r', '\x2', '\x2', '\x293', + '\x294', '\t', '\f', '\x2', '\x2', '\x294', '\x295', '\t', '\x10', '\x2', + '\x2', '\x295', '\x296', '\t', '\x11', '\x2', '\x2', '\x296', '\x297', + '\t', '\x10', '\x2', '\x2', '\x297', '\x92', '\x3', '\x2', '\x2', '\x2', + '\x298', '\x299', '\t', '\x5', '\x2', '\x2', '\x299', '\x29A', '\t', '\x11', + '\x2', '\x2', '\x29A', '\x94', '\x3', '\x2', '\x2', '\x2', '\x29B', '\x29C', + '\t', '\x17', '\x2', '\x2', '\x29C', '\x29D', '\t', '\x5', '\x2', '\x2', + '\x29D', '\x29E', '\t', '\x11', '\x2', '\x2', '\x29E', '\x96', '\x3', + '\x2', '\x2', '\x2', '\x29F', '\x2A0', '\t', '\x6', '\x2', '\x2', '\x2A0', + '\x2A1', '\t', '\x3', '\x2', '\x2', '\x2A1', '\x2A2', '\t', '\xE', '\x2', + '\x2', '\x2A2', '\x98', '\x3', '\x2', '\x2', '\x2', '\x2A3', '\x2A4', + '\t', '\x3', '\x2', '\x2', '\x2A4', '\x2A5', '\t', '\x5', '\x2', '\x2', + '\x2A5', '\x2A6', '\t', '\t', '\x2', '\x2', '\x2A6', '\x9A', '\x3', '\x2', + '\x2', '\x2', '\x2A7', '\x2A8', '\t', '\x4', '\x2', '\x2', '\x2A8', '\x2A9', + '\t', '\x3', '\x2', '\x2', '\x2A9', '\x9C', '\x3', '\x2', '\x2', '\x2', + '\x2AA', '\x2AB', '\t', '\xF', '\x2', '\x2', '\x2AB', '\x2AC', '\t', '\t', + '\x2', '\x2', '\x2AC', '\x2AD', '\t', '\x6', '\x2', '\x2', '\x2AD', '\x2AE', + '\t', '\x11', '\x2', '\x2', '\x2AE', '\x2AF', '\t', '\t', '\x2', '\x2', + '\x2AF', '\x2B0', '\t', '\xF', '\x2', '\x2', '\x2B0', '\x9E', '\x3', '\x2', + '\x2', '\x2', '\x2B1', '\x2B2', '\t', '\x10', '\x2', '\x2', '\x2B2', '\x2B3', + '\t', '\x3', '\x2', '\x2', '\x2B3', '\x2B4', '\t', '\xE', '\x2', '\x2', + '\x2B4', '\x2B5', '\t', '\xF', '\x2', '\x2', '\x2B5', '\xA0', '\x3', '\x2', + '\x2', '\x2', '\x2B6', '\x2B7', '\t', '\v', '\x2', '\x2', '\x2B7', '\x2B8', + '\t', '\x5', '\x2', '\x2', '\x2B8', '\x2B9', '\t', '\x3', '\x2', '\x2', + '\x2B9', '\x2BA', '\t', '\t', '\x2', '\x2', '\x2BA', '\x2BB', '\t', '\x6', + '\x2', '\x2', '\x2BB', '\x2BC', '\t', '\x4', '\x2', '\x2', '\x2BC', '\x2BD', + '\t', '\x3', '\x2', '\x2', '\x2BD', '\x2BE', '\t', '\xF', '\x2', '\x2', + '\x2BE', '\xA2', '\x3', '\x2', '\x2', '\x2', '\x2BF', '\x2C0', '\t', '\x4', + '\x2', '\x2', '\x2C0', '\x2C1', '\t', '\xF', '\x2', '\x2', '\x2C1', '\xA4', + '\x3', '\x2', '\x2', '\x2', '\x2C2', '\x2C3', '\t', '\x3', '\x2', '\x2', + '\x2C3', '\x2C4', '\t', '\x2', '\x2', '\x2', '\x2C4', '\x2C5', '\t', '\a', + '\x2', '\x2', '\x2C5', '\x2C6', '\t', '\a', '\x2', '\x2', '\x2C6', '\xA6', + '\x3', '\x2', '\x2', '\x2', '\x2C7', '\x2C8', '\t', '\v', '\x2', '\x2', + '\x2C8', '\x2C9', '\t', '\x5', '\x2', '\x2', '\x2C9', '\x2CA', '\t', '\x2', + '\x2', '\x2', '\x2CA', '\x2CB', '\t', '\x3', '\x2', '\x2', '\x2CB', '\x2CC', + '\t', '\t', '\x2', '\x2', '\x2CC', '\xA8', '\x3', '\x2', '\x2', '\x2', + '\x2CD', '\x2CE', '\t', '\x18', '\x2', '\x2', '\x2CE', '\x2CF', '\t', + '\x4', '\x2', '\x2', '\x2CF', '\x2D0', '\t', '\a', '\x2', '\x2', '\x2D0', + '\x2D1', '\t', '\t', '\x2', '\x2', '\x2D1', '\x2D2', '\t', '\x10', '\x2', + '\x2', '\x2D2', '\x2D3', '\t', '\x11', '\x2', '\x2', '\x2D3', '\xAA', + '\x3', '\x2', '\x2', '\x2', '\x2D4', '\x2D5', '\t', '\x10', '\x2', '\x2', + '\x2D5', '\x2D6', '\t', '\x17', '\x2', '\x2', '\x2D6', '\x2D7', '\t', + '\t', '\x2', '\x2', '\x2D7', '\x2D8', '\t', '\x11', '\x2', '\x2', '\x2D8', + '\x2D9', '\t', '\x6', '\x2', '\x2', '\x2D9', '\x2DA', '\t', '\v', '\x2', + '\x2', '\x2DA', '\x2DB', '\t', '\t', '\x2', '\x2', '\x2DB', '\xAC', '\x3', + '\x2', '\x2', '\x2', '\x2DC', '\x2DD', '\t', '\x6', '\x2', '\x2', '\x2DD', + '\x2DE', '\t', '\x3', '\x2', '\x2', '\x2DE', '\x2DF', '\t', '\x14', '\x2', + '\x2', '\x2DF', '\xAE', '\x3', '\x2', '\x2', '\x2', '\x2E0', '\x2E1', + '\t', '\x3', '\x2', '\x2', '\x2E1', '\x2E2', '\t', '\x5', '\x2', '\x2', + '\x2E2', '\x2E3', '\t', '\x3', '\x2', '\x2', '\x2E3', '\x2E4', '\t', '\x10', + '\x2', '\x2', '\x2E4', '\xB0', '\x3', '\x2', '\x2', '\x2', '\x2E5', '\x2E6', + '\t', '\xF', '\x2', '\x2', '\x2E6', '\x2E7', '\t', '\x4', '\x2', '\x2', + '\x2E7', '\x2E8', '\t', '\x3', '\x2', '\x2', '\x2E8', '\x2E9', '\t', '\x12', + '\x2', '\x2', '\x2E9', '\x2EA', '\t', '\a', '\x2', '\x2', '\x2EA', '\x2EB', + '\t', '\x10', '\x2', '\x2', '\x2EB', '\xB2', '\x3', '\x2', '\x2', '\x2', + '\x2EC', '\x2ED', '\t', '\t', '\x2', '\x2', '\x2ED', '\x2EE', '\t', '\x11', + '\x2', '\x2', '\x2EE', '\x2EF', '\t', '\x2', '\x2', '\x2', '\x2EF', '\x2F0', + '\t', '\x10', '\x2', '\x2', '\x2F0', '\xB4', '\x3', '\x2', '\x2', '\x2', + '\x2F1', '\x2F2', '\t', '\x18', '\x2', '\x2', '\x2F2', '\x2F3', '\t', + '\x6', '\x2', '\x2', '\x2F3', '\x2F4', '\t', '\a', '\x2', '\x2', '\x2F4', + '\x2F5', '\t', '\xF', '\x2', '\x2', '\x2F5', '\x2F6', '\t', '\x10', '\x2', + '\x2', '\x2F6', '\xB6', '\x3', '\x2', '\x2', '\x2', '\x2F7', '\x2F8', + '\t', '\x10', '\x2', '\x2', '\x2F8', '\x2F9', '\t', '\x17', '\x2', '\x2', + '\x2F9', '\x2FA', '\t', '\x4', '\x2', '\x2', '\x2FA', '\x2FB', '\t', '\xF', + '\x2', '\x2', '\x2FB', '\x2FC', '\t', '\t', '\x2', '\x2', '\x2FC', '\x2FD', + '\t', '\xF', '\x2', '\x2', '\x2FD', '\xB8', '\x3', '\x2', '\x2', '\x2', + '\x2FE', '\x2FF', '\t', '\v', '\x2', '\x2', '\x2FF', '\x300', '\t', '\x6', + '\x2', '\x2', '\x300', '\x301', '\t', '\xF', '\x2', '\x2', '\x301', '\x302', + '\t', '\x10', '\x2', '\x2', '\x302', '\xBA', '\x3', '\x2', '\x2', '\x2', + '\x303', '\x304', '\t', '\x10', '\x2', '\x2', '\x304', '\x305', '\t', + '\a', '\x2', '\x2', '\x305', '\x306', '\t', '\xF', '\x2', '\x2', '\x306', + '\x307', '\t', '\x10', '\x2', '\x2', '\x307', '\xBC', '\x3', '\x2', '\x2', + '\x2', '\x308', '\x309', '\t', '\x10', '\x2', '\x2', '\x309', '\x30A', + '\t', '\x3', '\x2', '\x2', '\x30A', '\x30B', '\t', '\xE', '\x2', '\x2', + '\x30B', '\xBE', '\x3', '\x2', '\x2', '\x2', '\x30C', '\x30D', '\t', '\r', + '\x2', '\x2', '\x30D', '\x30E', '\t', '\f', '\x2', '\x2', '\x30E', '\x30F', + '\t', '\x10', '\x2', '\x2', '\x30F', '\x310', '\t', '\x3', '\x2', '\x2', + '\x310', '\xC0', '\x3', '\x2', '\x2', '\x2', '\x311', '\x312', '\t', '\t', + '\x2', '\x2', '\x312', '\x313', '\t', '\f', '\x2', '\x2', '\x313', '\x314', + '\t', '\x10', '\x2', '\x2', '\x314', '\x315', '\t', '\x3', '\x2', '\x2', + '\x315', '\xC2', '\x3', '\x2', '\x2', '\x2', '\x316', '\x31B', '\a', '$', + '\x2', '\x2', '\x317', '\x31A', '\x5', '\x11F', '\x90', '\x2', '\x318', + '\x31A', '\x5', '\xC5', '\x63', '\x2', '\x319', '\x317', '\x3', '\x2', + '\x2', '\x2', '\x319', '\x318', '\x3', '\x2', '\x2', '\x2', '\x31A', '\x31D', + '\x3', '\x2', '\x2', '\x2', '\x31B', '\x319', '\x3', '\x2', '\x2', '\x2', + '\x31B', '\x31C', '\x3', '\x2', '\x2', '\x2', '\x31C', '\x31E', '\x3', + '\x2', '\x2', '\x2', '\x31D', '\x31B', '\x3', '\x2', '\x2', '\x2', '\x31E', + '\x329', '\a', '$', '\x2', '\x2', '\x31F', '\x324', '\a', ')', '\x2', + '\x2', '\x320', '\x323', '\x5', '\x10B', '\x86', '\x2', '\x321', '\x323', + '\x5', '\xC5', '\x63', '\x2', '\x322', '\x320', '\x3', '\x2', '\x2', '\x2', + '\x322', '\x321', '\x3', '\x2', '\x2', '\x2', '\x323', '\x326', '\x3', + '\x2', '\x2', '\x2', '\x324', '\x322', '\x3', '\x2', '\x2', '\x2', '\x324', + '\x325', '\x3', '\x2', '\x2', '\x2', '\x325', '\x327', '\x3', '\x2', '\x2', + '\x2', '\x326', '\x324', '\x3', '\x2', '\x2', '\x2', '\x327', '\x329', + '\a', ')', '\x2', '\x2', '\x328', '\x316', '\x3', '\x2', '\x2', '\x2', + '\x328', '\x31F', '\x3', '\x2', '\x2', '\x2', '\x329', '\xC4', '\x3', + '\x2', '\x2', '\x2', '\x32A', '\x33C', '\a', '^', '\x2', '\x2', '\x32B', + '\x33D', '\t', '\x19', '\x2', '\x2', '\x32C', '\x32D', '\t', '\x2', '\x2', + '\x2', '\x32D', '\x32E', '\x5', '\xCF', 'h', '\x2', '\x32E', '\x32F', + '\x5', '\xCF', 'h', '\x2', '\x32F', '\x330', '\x5', '\xCF', 'h', '\x2', + '\x330', '\x331', '\x5', '\xCF', 'h', '\x2', '\x331', '\x33D', '\x3', + '\x2', '\x2', '\x2', '\x332', '\x333', '\t', '\x2', '\x2', '\x2', '\x333', + '\x334', '\x5', '\xCF', 'h', '\x2', '\x334', '\x335', '\x5', '\xCF', 'h', + '\x2', '\x335', '\x336', '\x5', '\xCF', 'h', '\x2', '\x336', '\x337', + '\x5', '\xCF', 'h', '\x2', '\x337', '\x338', '\x5', '\xCF', 'h', '\x2', + '\x338', '\x339', '\x5', '\xCF', 'h', '\x2', '\x339', '\x33A', '\x5', + '\xCF', 'h', '\x2', '\x33A', '\x33B', '\x5', '\xCF', 'h', '\x2', '\x33B', + '\x33D', '\x3', '\x2', '\x2', '\x2', '\x33C', '\x32B', '\x3', '\x2', '\x2', + '\x2', '\x33C', '\x32C', '\x3', '\x2', '\x2', '\x2', '\x33C', '\x332', + '\x3', '\x2', '\x2', '\x2', '\x33D', '\xC6', '\x3', '\x2', '\x2', '\x2', + '\x33E', '\x33F', '\a', '\x32', '\x2', '\x2', '\x33F', '\x340', '\a', + 'z', '\x2', '\x2', '\x340', '\x342', '\x3', '\x2', '\x2', '\x2', '\x341', + '\x343', '\x5', '\xCF', 'h', '\x2', '\x342', '\x341', '\x3', '\x2', '\x2', + '\x2', '\x343', '\x344', '\x3', '\x2', '\x2', '\x2', '\x344', '\x342', + '\x3', '\x2', '\x2', '\x2', '\x344', '\x345', '\x3', '\x2', '\x2', '\x2', + '\x345', '\xC8', '\x3', '\x2', '\x2', '\x2', '\x346', '\x34F', '\x5', + '\xD9', 'm', '\x2', '\x347', '\x34B', '\x5', '\xD3', 'j', '\x2', '\x348', + '\x34A', '\x5', '\xD1', 'i', '\x2', '\x349', '\x348', '\x3', '\x2', '\x2', + '\x2', '\x34A', '\x34D', '\x3', '\x2', '\x2', '\x2', '\x34B', '\x349', + '\x3', '\x2', '\x2', '\x2', '\x34B', '\x34C', '\x3', '\x2', '\x2', '\x2', + '\x34C', '\x34F', '\x3', '\x2', '\x2', '\x2', '\x34D', '\x34B', '\x3', + '\x2', '\x2', '\x2', '\x34E', '\x346', '\x3', '\x2', '\x2', '\x2', '\x34E', + '\x347', '\x3', '\x2', '\x2', '\x2', '\x34F', '\xCA', '\x3', '\x2', '\x2', + '\x2', '\x350', '\x352', '\x5', '\xD9', 'm', '\x2', '\x351', '\x353', + '\x5', '\xD7', 'l', '\x2', '\x352', '\x351', '\x3', '\x2', '\x2', '\x2', + '\x353', '\x354', '\x3', '\x2', '\x2', '\x2', '\x354', '\x352', '\x3', + '\x2', '\x2', '\x2', '\x354', '\x355', '\x3', '\x2', '\x2', '\x2', '\x355', + '\xCC', '\x3', '\x2', '\x2', '\x2', '\x356', '\x358', '\t', '\x1A', '\x2', + '\x2', '\x357', '\x356', '\x3', '\x2', '\x2', '\x2', '\x358', '\xCE', + '\x3', '\x2', '\x2', '\x2', '\x359', '\x35C', '\x5', '\xD1', 'i', '\x2', + '\x35A', '\x35C', '\x5', '\xCD', 'g', '\x2', '\x35B', '\x359', '\x3', + '\x2', '\x2', '\x2', '\x35B', '\x35A', '\x3', '\x2', '\x2', '\x2', '\x35C', + '\xD0', '\x3', '\x2', '\x2', '\x2', '\x35D', '\x360', '\x5', '\xD9', 'm', + '\x2', '\x35E', '\x360', '\x5', '\xD3', 'j', '\x2', '\x35F', '\x35D', + '\x3', '\x2', '\x2', '\x2', '\x35F', '\x35E', '\x3', '\x2', '\x2', '\x2', + '\x360', '\xD2', '\x3', '\x2', '\x2', '\x2', '\x361', '\x364', '\x5', + '\xD5', 'k', '\x2', '\x362', '\x364', '\x4', ':', ';', '\x2', '\x363', + '\x361', '\x3', '\x2', '\x2', '\x2', '\x363', '\x362', '\x3', '\x2', '\x2', + '\x2', '\x364', '\xD4', '\x3', '\x2', '\x2', '\x2', '\x365', '\x366', + '\x4', '\x33', '\x39', '\x2', '\x366', '\xD6', '\x3', '\x2', '\x2', '\x2', + '\x367', '\x36A', '\x5', '\xD9', 'm', '\x2', '\x368', '\x36A', '\x5', + '\xD5', 'k', '\x2', '\x369', '\x367', '\x3', '\x2', '\x2', '\x2', '\x369', + '\x368', '\x3', '\x2', '\x2', '\x2', '\x36A', '\xD8', '\x3', '\x2', '\x2', + '\x2', '\x36B', '\x36C', '\a', '\x32', '\x2', '\x2', '\x36C', '\xDA', + '\x3', '\x2', '\x2', '\x2', '\x36D', '\x36F', '\x5', '\xD1', 'i', '\x2', + '\x36E', '\x36D', '\x3', '\x2', '\x2', '\x2', '\x36F', '\x370', '\x3', + '\x2', '\x2', '\x2', '\x370', '\x36E', '\x3', '\x2', '\x2', '\x2', '\x370', + '\x371', '\x3', '\x2', '\x2', '\x2', '\x371', '\x384', '\x3', '\x2', '\x2', + '\x2', '\x372', '\x374', '\x5', '\xD1', 'i', '\x2', '\x373', '\x372', + '\x3', '\x2', '\x2', '\x2', '\x374', '\x375', '\x3', '\x2', '\x2', '\x2', + '\x375', '\x373', '\x3', '\x2', '\x2', '\x2', '\x375', '\x376', '\x3', + '\x2', '\x2', '\x2', '\x376', '\x377', '\x3', '\x2', '\x2', '\x2', '\x377', + '\x379', '\a', '\x30', '\x2', '\x2', '\x378', '\x37A', '\x5', '\xD1', + 'i', '\x2', '\x379', '\x378', '\x3', '\x2', '\x2', '\x2', '\x37A', '\x37B', + '\x3', '\x2', '\x2', '\x2', '\x37B', '\x379', '\x3', '\x2', '\x2', '\x2', + '\x37B', '\x37C', '\x3', '\x2', '\x2', '\x2', '\x37C', '\x384', '\x3', + '\x2', '\x2', '\x2', '\x37D', '\x37F', '\a', '\x30', '\x2', '\x2', '\x37E', + '\x380', '\x5', '\xD1', 'i', '\x2', '\x37F', '\x37E', '\x3', '\x2', '\x2', + '\x2', '\x380', '\x381', '\x3', '\x2', '\x2', '\x2', '\x381', '\x37F', + '\x3', '\x2', '\x2', '\x2', '\x381', '\x382', '\x3', '\x2', '\x2', '\x2', + '\x382', '\x384', '\x3', '\x2', '\x2', '\x2', '\x383', '\x36E', '\x3', + '\x2', '\x2', '\x2', '\x383', '\x373', '\x3', '\x2', '\x2', '\x2', '\x383', + '\x37D', '\x3', '\x2', '\x2', '\x2', '\x384', '\x386', '\x3', '\x2', '\x2', + '\x2', '\x385', '\x387', '\t', '\x10', '\x2', '\x2', '\x386', '\x385', + '\x3', '\x2', '\x2', '\x2', '\x387', '\x389', '\x3', '\x2', '\x2', '\x2', + '\x388', '\x38A', '\a', '/', '\x2', '\x2', '\x389', '\x388', '\x3', '\x2', + '\x2', '\x2', '\x389', '\x38A', '\x3', '\x2', '\x2', '\x2', '\x38A', '\x38C', + '\x3', '\x2', '\x2', '\x2', '\x38B', '\x38D', '\x5', '\xD1', 'i', '\x2', + '\x38C', '\x38B', '\x3', '\x2', '\x2', '\x2', '\x38D', '\x38E', '\x3', + '\x2', '\x2', '\x2', '\x38E', '\x38C', '\x3', '\x2', '\x2', '\x2', '\x38E', + '\x38F', '\x3', '\x2', '\x2', '\x2', '\x38F', '\xDC', '\x3', '\x2', '\x2', + '\x2', '\x390', '\x392', '\x5', '\xD1', 'i', '\x2', '\x391', '\x390', + '\x3', '\x2', '\x2', '\x2', '\x392', '\x395', '\x3', '\x2', '\x2', '\x2', + '\x393', '\x391', '\x3', '\x2', '\x2', '\x2', '\x393', '\x394', '\x3', + '\x2', '\x2', '\x2', '\x394', '\x396', '\x3', '\x2', '\x2', '\x2', '\x395', + '\x393', '\x3', '\x2', '\x2', '\x2', '\x396', '\x398', '\a', '\x30', '\x2', + '\x2', '\x397', '\x399', '\x5', '\xD1', 'i', '\x2', '\x398', '\x397', + '\x3', '\x2', '\x2', '\x2', '\x399', '\x39A', '\x3', '\x2', '\x2', '\x2', + '\x39A', '\x398', '\x3', '\x2', '\x2', '\x2', '\x39A', '\x39B', '\x3', + '\x2', '\x2', '\x2', '\x39B', '\xDE', '\x3', '\x2', '\x2', '\x2', '\x39C', + '\x39D', '\t', '\v', '\x2', '\x2', '\x39D', '\x39E', '\t', '\x5', '\x2', + '\x2', '\x39E', '\x39F', '\t', '\x3', '\x2', '\x2', '\x39F', '\x3A0', + '\t', '\xF', '\x2', '\x2', '\x3A0', '\x3A1', '\t', '\t', '\x2', '\x2', + '\x3A1', '\x3A2', '\t', '\x11', '\x2', '\x2', '\x3A2', '\x3A3', '\t', + '\x6', '\x2', '\x2', '\x3A3', '\x3A4', '\t', '\x4', '\x2', '\x2', '\x3A4', + '\x3A5', '\t', '\x3', '\x2', '\x2', '\x3A5', '\x3A6', '\t', '\t', '\x2', + '\x2', '\x3A6', '\xE0', '\x3', '\x2', '\x2', '\x2', '\x3A7', '\x3A8', + '\t', '\xE', '\x2', '\x2', '\x3A8', '\x3A9', '\t', '\x5', '\x2', '\x2', + '\x3A9', '\xE2', '\x3', '\x2', '\x2', '\x2', '\x3AA', '\x3AB', '\t', '\x18', + '\x2', '\x2', '\x3AB', '\x3AC', '\t', '\x5', '\x2', '\x2', '\x3AC', '\x3AD', + '\t', '\x11', '\x2', '\x2', '\x3AD', '\xE4', '\x3', '\x2', '\x2', '\x2', + '\x3AE', '\x3AF', '\t', '\x11', '\x2', '\x2', '\x3AF', '\x3B0', '\t', + '\x10', '\x2', '\x2', '\x3B0', '\x3B1', '\t', '\x1B', '\x2', '\x2', '\x3B1', + '\x3B2', '\t', '\x2', '\x2', '\x2', '\x3B2', '\x3B3', '\t', '\x4', '\x2', + '\x2', '\x3B3', '\x3B4', '\t', '\x11', '\x2', '\x2', '\x3B4', '\x3B5', + '\t', '\x10', '\x2', '\x2', '\x3B5', '\xE6', '\x3', '\x2', '\x2', '\x2', + '\x3B6', '\x3B7', '\t', '\x2', '\x2', '\x2', '\x3B7', '\x3B8', '\t', '\x3', + '\x2', '\x2', '\x3B8', '\x3B9', '\t', '\x4', '\x2', '\x2', '\x3B9', '\x3BA', + '\t', '\x1B', '\x2', '\x2', '\x3BA', '\x3BB', '\t', '\x2', '\x2', '\x2', + '\x3BB', '\x3BC', '\t', '\x10', '\x2', '\x2', '\x3BC', '\xE8', '\x3', + '\x2', '\x2', '\x2', '\x3BD', '\x3BE', '\t', '\n', '\x2', '\x2', '\x3BE', + '\x3BF', '\t', '\x6', '\x2', '\x2', '\x3BF', '\x3C0', '\t', '\x3', '\x2', + '\x2', '\x3C0', '\x3C1', '\t', '\xE', '\x2', '\x2', '\x3C1', '\x3C2', + '\t', '\x6', '\x2', '\x2', '\x3C2', '\x3C3', '\t', '\t', '\x2', '\x2', + '\x3C3', '\x3C4', '\t', '\x5', '\x2', '\x2', '\x3C4', '\x3C5', '\t', '\x11', + '\x2', '\x2', '\x3C5', '\x3C6', '\t', '\x14', '\x2', '\x2', '\x3C6', '\xEA', + '\x3', '\x2', '\x2', '\x2', '\x3C7', '\x3C8', '\t', '\xF', '\x2', '\x2', + '\x3C8', '\x3C9', '\t', '\v', '\x2', '\x2', '\x3C9', '\x3CA', '\t', '\x6', + '\x2', '\x2', '\x3CA', '\x3CB', '\t', '\a', '\x2', '\x2', '\x3CB', '\x3CC', + '\t', '\x6', '\x2', '\x2', '\x3CC', '\x3CD', '\t', '\x11', '\x2', '\x2', + '\x3CD', '\xEC', '\x3', '\x2', '\x2', '\x2', '\x3CE', '\x3CF', '\t', '\x5', + '\x2', '\x2', '\x3CF', '\x3D0', '\t', '\x18', '\x2', '\x2', '\x3D0', '\xEE', + '\x3', '\x2', '\x2', '\x2', '\x3D1', '\x3D2', '\t', '\x6', '\x2', '\x2', + '\x3D2', '\x3D3', '\t', '\xE', '\x2', '\x2', '\x3D3', '\x3D4', '\t', '\xE', + '\x2', '\x2', '\x3D4', '\xF0', '\x3', '\x2', '\x2', '\x2', '\x3D5', '\x3D6', + '\t', '\xE', '\x2', '\x2', '\x3D6', '\x3D7', '\t', '\x11', '\x2', '\x2', + '\x3D7', '\x3D8', '\t', '\x5', '\x2', '\x2', '\x3D8', '\x3D9', '\t', '\b', + '\x2', '\x2', '\x3D9', '\xF2', '\x3', '\x2', '\x2', '\x2', '\x3DA', '\x3DE', + '\x5', '\xF5', '{', '\x2', '\x3DB', '\x3DD', '\x5', '\xF7', '|', '\x2', + '\x3DC', '\x3DB', '\x3', '\x2', '\x2', '\x2', '\x3DD', '\x3E0', '\x3', + '\x2', '\x2', '\x2', '\x3DE', '\x3DC', '\x3', '\x2', '\x2', '\x2', '\x3DE', + '\x3DF', '\x3', '\x2', '\x2', '\x2', '\x3DF', '\xF4', '\x3', '\x2', '\x2', + '\x2', '\x3E0', '\x3DE', '\x3', '\x2', '\x2', '\x2', '\x3E1', '\x3E4', + '\x5', '\x127', '\x94', '\x2', '\x3E2', '\x3E4', '\x5', '\x11B', '\x8E', + '\x2', '\x3E3', '\x3E1', '\x3', '\x2', '\x2', '\x2', '\x3E3', '\x3E2', + '\x3', '\x2', '\x2', '\x2', '\x3E4', '\xF6', '\x3', '\x2', '\x2', '\x2', + '\x3E5', '\x3E8', '\x5', '\x107', '\x84', '\x2', '\x3E6', '\x3E8', '\x5', + '\x117', '\x8C', '\x2', '\x3E7', '\x3E5', '\x3', '\x2', '\x2', '\x2', + '\x3E7', '\x3E6', '\x3', '\x2', '\x2', '\x2', '\x3E8', '\xF8', '\x3', + '\x2', '\x2', '\x2', '\x3E9', '\x3ED', '\a', '\x62', '\x2', '\x2', '\x3EA', + '\x3EC', '\x5', '\x103', '\x82', '\x2', '\x3EB', '\x3EA', '\x3', '\x2', + '\x2', '\x2', '\x3EC', '\x3EF', '\x3', '\x2', '\x2', '\x2', '\x3ED', '\x3EB', + '\x3', '\x2', '\x2', '\x2', '\x3ED', '\x3EE', '\x3', '\x2', '\x2', '\x2', + '\x3EE', '\x3F0', '\x3', '\x2', '\x2', '\x2', '\x3EF', '\x3ED', '\x3', + '\x2', '\x2', '\x2', '\x3F0', '\x3F2', '\a', '\x62', '\x2', '\x2', '\x3F1', + '\x3E9', '\x3', '\x2', '\x2', '\x2', '\x3F2', '\x3F3', '\x3', '\x2', '\x2', + '\x2', '\x3F3', '\x3F1', '\x3', '\x2', '\x2', '\x2', '\x3F3', '\x3F4', + '\x3', '\x2', '\x2', '\x2', '\x3F4', '\xFA', '\x3', '\x2', '\x2', '\x2', + '\x3F5', '\x3F7', '\x5', '\xFD', '\x7F', '\x2', '\x3F6', '\x3F5', '\x3', + '\x2', '\x2', '\x2', '\x3F7', '\x3F8', '\x3', '\x2', '\x2', '\x2', '\x3F8', + '\x3F6', '\x3', '\x2', '\x2', '\x2', '\x3F8', '\x3F9', '\x3', '\x2', '\x2', + '\x2', '\x3F9', '\xFC', '\x3', '\x2', '\x2', '\x2', '\x3FA', '\x48C', + '\x5', '\x119', '\x8D', '\x2', '\x3FB', '\x48C', '\x5', '\x11D', '\x8F', + '\x2', '\x3FC', '\x48C', '\x5', '\x121', '\x91', '\x2', '\x3FD', '\x48C', + '\x5', '\x123', '\x92', '\x2', '\x3FE', '\x48C', '\x5', '\x101', '\x81', + '\x2', '\x3FF', '\x48C', '\x5', '\x115', '\x8B', '\x2', '\x400', '\x48C', + '\x5', '\x113', '\x8A', '\x2', '\x401', '\x48C', '\x5', '\x111', '\x89', + '\x2', '\x402', '\x48C', '\x5', '\x105', '\x83', '\x2', '\x403', '\x48C', + '\x5', '\x125', '\x93', '\x2', '\x404', '\x405', '\a', '\xC5', '\x2', + '\x2', '\x405', '\x406', '\a', '\xA3', '\x2', '\x2', '\x406', '\x407', + '\a', '\xC7', '\x2', '\x2', '\x407', '\x408', '\a', '\xA3', '\x2', '\x2', + '\x408', '\x409', '\a', '\xE4', '\x2', '\x2', '\x409', '\x40A', '\a', + '\x201C', '\x2', '\x2', '\x40A', '\x48C', '\a', '\xAE', '\x2', '\x2', + '\x40B', '\x40C', '\a', '\xC5', '\x2', '\x2', '\x40C', '\x40D', '\a', + '\xA3', '\x2', '\x2', '\x40D', '\x40E', '\a', '\"', '\x2', '\x2', '\x40E', + '\x40F', '\a', '\xC7', '\x2', '\x2', '\x40F', '\x48C', '\a', '\xBF', '\x2', + '\x2', '\x410', '\x411', '\a', '\xC5', '\x2', '\x2', '\x411', '\x412', + '\a', '\xA4', '\x2', '\x2', '\x412', '\x413', '\a', '\xE4', '\x2', '\x2', + '\x413', '\x414', '\a', '\x201C', '\x2', '\x2', '\x414', '\x415', '\a', + '\xAE', '\x2', '\x2', '\x415', '\x416', '\a', '\xE4', '\x2', '\x2', '\x416', + '\x417', '\a', '\x201C', '\x2', '\x2', '\x417', '\x48C', '\a', '\xAE', + '\x2', '\x2', '\x418', '\x419', '\a', '\xC5', '\x2', '\x2', '\x419', '\x41A', + '\a', '\xA4', '\x2', '\x2', '\x41A', '\x41B', '\a', '\xE4', '\x2', '\x2', + '\x41B', '\x41C', '\a', '\x201C', '\x2', '\x2', '\x41C', '\x41D', '\a', + '\xAE', '\x2', '\x2', '\x41D', '\x41E', '\a', '\xC4', '\x2', '\x2', '\x41E', + '\x48C', '\a', '\xFFFF', '\x2', '\x2', '\x41F', '\x420', '\a', '\xC5', + '\x2', '\x2', '\x420', '\x421', '\a', '\xA4', '\x2', '\x2', '\x421', '\x422', + '\a', '\xE4', '\x2', '\x2', '\x422', '\x423', '\a', '\x201C', '\x2', '\x2', + '\x423', '\x424', '\a', '\xAE', '\x2', '\x2', '\x424', '\x425', '\a', + '\xE4', '\x2', '\x2', '\x425', '\x426', '\a', '\x20AE', '\x2', '\x2', + '\x426', '\x48C', '\a', '\x163', '\x2', '\x2', '\x427', '\x428', '\a', + '\xC5', '\x2', '\x2', '\x428', '\x429', '\a', '\xA4', '\x2', '\x2', '\x429', + '\x42A', '\a', '\xE4', '\x2', '\x2', '\x42A', '\x42B', '\a', '\x201C', + '\x2', '\x2', '\x42B', '\x42C', '\a', '\xAE', '\x2', '\x2', '\x42C', '\x42D', + '\a', '\xC8', '\x2', '\x2', '\x42D', '\x48C', '\a', '\x201B', '\x2', '\x2', + '\x42E', '\x42F', '\a', '\xC5', '\x2', '\x2', '\x42F', '\x430', '\a', + '\xA4', '\x2', '\x2', '\x430', '\x431', '\a', '\xE4', '\x2', '\x2', '\x431', + '\x432', '\a', '\x201C', '\x2', '\x2', '\x432', '\x433', '\a', '\xAE', + '\x2', '\x2', '\x433', '\x434', '\a', '\xE4', '\x2', '\x2', '\x434', '\x435', + '\a', '\x20AE', '\x2', '\x2', '\x435', '\x48C', '\a', '\x180', '\x2', + '\x2', '\x436', '\x437', '\a', '\xC5', '\x2', '\x2', '\x437', '\x438', + '\a', '\xA4', '\x2', '\x2', '\x438', '\x439', '\a', '\xE4', '\x2', '\x2', + '\x439', '\x43A', '\a', '\x201C', '\x2', '\x2', '\x43A', '\x43B', '\a', + '\xAE', '\x2', '\x2', '\x43B', '\x43C', '\a', '\xE4', '\x2', '\x2', '\x43C', + '\x43D', '\a', '\x20AE', '\x2', '\x2', '\x43D', '\x48C', '\a', '\xA8', + '\x2', '\x2', '\x43E', '\x43F', '\a', '\xC5', '\x2', '\x2', '\x43F', '\x440', + '\a', '\xA4', '\x2', '\x2', '\x440', '\x441', '\a', '\xE4', '\x2', '\x2', + '\x441', '\x442', '\a', '\x201C', '\x2', '\x2', '\x442', '\x443', '\a', + '\xAE', '\x2', '\x2', '\x443', '\x444', '\a', '\xE4', '\x2', '\x2', '\x444', + '\x445', '\a', '\x20AE', '\x2', '\x2', '\x445', '\x48C', '\a', '\xA2', + '\x2', '\x2', '\x446', '\x447', '\a', '\xC5', '\x2', '\x2', '\x447', '\x448', + '\a', '\xA4', '\x2', '\x2', '\x448', '\x449', '\a', '\xE4', '\x2', '\x2', + '\x449', '\x44A', '\a', '\x201C', '\x2', '\x2', '\x44A', '\x44B', '\a', + '\xAE', '\x2', '\x2', '\x44B', '\x44C', '\a', '\xCD', '\x2', '\x2', '\x44C', + '\x48C', '\a', '\x2022', '\x2', '\x2', '\x44D', '\x44E', '\a', '\xC5', + '\x2', '\x2', '\x44E', '\x44F', '\a', '\xA4', '\x2', '\x2', '\x44F', '\x450', + '\a', '\xE4', '\x2', '\x2', '\x450', '\x451', '\a', '\x201C', '\x2', '\x2', + '\x451', '\x452', '\a', '\xAE', '\x2', '\x2', '\x452', '\x453', '\a', + '\xE4', '\x2', '\x2', '\x453', '\x454', '\a', '\x20AE', '\x2', '\x2', + '\x454', '\x48C', '\a', '\xB2', '\x2', '\x2', '\x455', '\x456', '\a', + '\xC5', '\x2', '\x2', '\x456', '\x457', '\a', '\xA4', '\x2', '\x2', '\x457', + '\x458', '\a', '\xE4', '\x2', '\x2', '\x458', '\x459', '\a', '\x201C', + '\x2', '\x2', '\x459', '\x45A', '\a', '\xAE', '\x2', '\x2', '\x45A', '\x45B', + '\a', '\xC7', '\x2', '\x2', '\x45B', '\x48C', '\a', '\xA2', '\x2', '\x2', + '\x45C', '\x45D', '\a', '\xC5', '\x2', '\x2', '\x45D', '\x45E', '\a', + '\xA4', '\x2', '\x2', '\x45E', '\x45F', '\a', '\xE4', '\x2', '\x2', '\x45F', + '\x460', '\a', '\x201C', '\x2', '\x2', '\x460', '\x461', '\a', '\xAE', + '\x2', '\x2', '\x461', '\x462', '\a', '\xC4', '\x2', '\x2', '\x462', '\x48C', + '\a', '\xAA', '\x2', '\x2', '\x463', '\x464', '\a', '\xC5', '\x2', '\x2', + '\x464', '\x465', '\a', '\xA4', '\x2', '\x2', '\x465', '\x466', '\a', + '\xE4', '\x2', '\x2', '\x466', '\x467', '\a', '\x201C', '\x2', '\x2', + '\x467', '\x468', '\a', '\xAE', '\x2', '\x2', '\x468', '\x469', '\a', + '\xC4', '\x2', '\x2', '\x469', '\x48C', '\a', '\xAB', '\x2', '\x2', '\x46A', + '\x46B', '\a', '\xC5', '\x2', '\x2', '\x46B', '\x46C', '\a', '\xA4', '\x2', + '\x2', '\x46C', '\x46D', '\a', '\xC4', '\x2', '\x2', '\x46D', '\x46E', + '\a', '\xFFFF', '\x2', '\x2', '\x46E', '\x46F', '\a', '\xC7', '\x2', '\x2', + '\x46F', '\x48C', '\a', '\xBA', '\x2', '\x2', '\x470', '\x471', '\a', + '\xC5', '\x2', '\x2', '\x471', '\x472', '\a', '\xA5', '\x2', '\x2', '\x472', + '\x473', '\a', '\xE4', '\x2', '\x2', '\x473', '\x474', '\a', '\x201C', + '\x2', '\x2', '\x474', '\x475', '\a', '\xAE', '\x2', '\x2', '\x475', '\x476', + '\a', '\xE4', '\x2', '\x2', '\x476', '\x477', '\a', '\x201C', '\x2', '\x2', + '\x477', '\x48C', '\a', '\xAE', '\x2', '\x2', '\x478', '\x479', '\a', + '\xC5', '\x2', '\x2', '\x479', '\x47A', '\a', '\x201C', '\x2', '\x2', + '\x47A', '\x48C', '\a', '\"', '\x2', '\x2', '\x47B', '\x47C', '\a', '\xC5', + '\x2', '\x2', '\x47C', '\x47D', '\a', '\xA4', '\x2', '\x2', '\x47D', '\x47E', + '\a', '\xE4', '\x2', '\x2', '\x47E', '\x47F', '\a', '\x201C', '\x2', '\x2', + '\x47F', '\x480', '\a', '\xAE', '\x2', '\x2', '\x480', '\x481', '\a', + '\xE4', '\x2', '\x2', '\x481', '\x482', '\a', '\x20AE', '\x2', '\x2', + '\x482', '\x48C', '\a', '\xA3', '\x2', '\x2', '\x483', '\x484', '\a', + '\xC5', '\x2', '\x2', '\x484', '\x485', '\a', '\xA4', '\x2', '\x2', '\x485', + '\x486', '\a', '\xE4', '\x2', '\x2', '\x486', '\x487', '\a', '\x201C', + '\x2', '\x2', '\x487', '\x488', '\a', '\xAE', '\x2', '\x2', '\x488', '\x489', + '\a', '\xC4', '\x2', '\x2', '\x489', '\x48C', '\a', '\xB1', '\x2', '\x2', + '\x48A', '\x48C', '\x5', '\xFF', '\x80', '\x2', '\x48B', '\x3FA', '\x3', + '\x2', '\x2', '\x2', '\x48B', '\x3FB', '\x3', '\x2', '\x2', '\x2', '\x48B', + '\x3FC', '\x3', '\x2', '\x2', '\x2', '\x48B', '\x3FD', '\x3', '\x2', '\x2', + '\x2', '\x48B', '\x3FE', '\x3', '\x2', '\x2', '\x2', '\x48B', '\x3FF', + '\x3', '\x2', '\x2', '\x2', '\x48B', '\x400', '\x3', '\x2', '\x2', '\x2', + '\x48B', '\x401', '\x3', '\x2', '\x2', '\x2', '\x48B', '\x402', '\x3', + '\x2', '\x2', '\x2', '\x48B', '\x403', '\x3', '\x2', '\x2', '\x2', '\x48B', + '\x404', '\x3', '\x2', '\x2', '\x2', '\x48B', '\x40B', '\x3', '\x2', '\x2', + '\x2', '\x48B', '\x410', '\x3', '\x2', '\x2', '\x2', '\x48B', '\x418', + '\x3', '\x2', '\x2', '\x2', '\x48B', '\x41F', '\x3', '\x2', '\x2', '\x2', + '\x48B', '\x427', '\x3', '\x2', '\x2', '\x2', '\x48B', '\x42E', '\x3', + '\x2', '\x2', '\x2', '\x48B', '\x436', '\x3', '\x2', '\x2', '\x2', '\x48B', + '\x43E', '\x3', '\x2', '\x2', '\x2', '\x48B', '\x446', '\x3', '\x2', '\x2', + '\x2', '\x48B', '\x44D', '\x3', '\x2', '\x2', '\x2', '\x48B', '\x455', + '\x3', '\x2', '\x2', '\x2', '\x48B', '\x45C', '\x3', '\x2', '\x2', '\x2', + '\x48B', '\x463', '\x3', '\x2', '\x2', '\x2', '\x48B', '\x46A', '\x3', + '\x2', '\x2', '\x2', '\x48B', '\x470', '\x3', '\x2', '\x2', '\x2', '\x48B', + '\x478', '\x3', '\x2', '\x2', '\x2', '\x48B', '\x47B', '\x3', '\x2', '\x2', + '\x2', '\x48B', '\x483', '\x3', '\x2', '\x2', '\x2', '\x48B', '\x48A', + '\x3', '\x2', '\x2', '\x2', '\x48C', '\xFE', '\x3', '\x2', '\x2', '\x2', + '\x48D', '\x48E', '\a', '\x31', '\x2', '\x2', '\x48E', '\x48F', '\a', + ',', '\x2', '\x2', '\x48F', '\x495', '\x3', '\x2', '\x2', '\x2', '\x490', + '\x494', '\x5', '\x109', '\x85', '\x2', '\x491', '\x492', '\a', ',', '\x2', + '\x2', '\x492', '\x494', '\x5', '\x10F', '\x88', '\x2', '\x493', '\x490', + '\x3', '\x2', '\x2', '\x2', '\x493', '\x491', '\x3', '\x2', '\x2', '\x2', + '\x494', '\x497', '\x3', '\x2', '\x2', '\x2', '\x495', '\x493', '\x3', + '\x2', '\x2', '\x2', '\x495', '\x496', '\x3', '\x2', '\x2', '\x2', '\x496', + '\x498', '\x3', '\x2', '\x2', '\x2', '\x497', '\x495', '\x3', '\x2', '\x2', + '\x2', '\x498', '\x499', '\a', ',', '\x2', '\x2', '\x499', '\x4AB', '\a', + '\x31', '\x2', '\x2', '\x49A', '\x49B', '\a', '\x31', '\x2', '\x2', '\x49B', + '\x49C', '\a', '\x31', '\x2', '\x2', '\x49C', '\x4A0', '\x3', '\x2', '\x2', + '\x2', '\x49D', '\x49F', '\x5', '\x10D', '\x87', '\x2', '\x49E', '\x49D', + '\x3', '\x2', '\x2', '\x2', '\x49F', '\x4A2', '\x3', '\x2', '\x2', '\x2', + '\x4A0', '\x49E', '\x3', '\x2', '\x2', '\x2', '\x4A0', '\x4A1', '\x3', + '\x2', '\x2', '\x2', '\x4A1', '\x4A4', '\x3', '\x2', '\x2', '\x2', '\x4A2', + '\x4A0', '\x3', '\x2', '\x2', '\x2', '\x4A3', '\x4A5', '\x5', '\x115', + '\x8B', '\x2', '\x4A4', '\x4A3', '\x3', '\x2', '\x2', '\x2', '\x4A4', + '\x4A5', '\x3', '\x2', '\x2', '\x2', '\x4A5', '\x4A8', '\x3', '\x2', '\x2', + '\x2', '\x4A6', '\x4A9', '\x5', '\x121', '\x91', '\x2', '\x4A7', '\x4A9', + '\a', '\x2', '\x2', '\x3', '\x4A8', '\x4A6', '\x3', '\x2', '\x2', '\x2', + '\x4A8', '\x4A7', '\x3', '\x2', '\x2', '\x2', '\x4A9', '\x4AB', '\x3', + '\x2', '\x2', '\x2', '\x4AA', '\x48D', '\x3', '\x2', '\x2', '\x2', '\x4AA', + '\x49A', '\x3', '\x2', '\x2', '\x2', '\x4AB', '\x100', '\x3', '\x2', '\x2', + '\x2', '\x4AC', '\x4AD', '\t', '\x1C', '\x2', '\x2', '\x4AD', '\x102', + '\x3', '\x2', '\x2', '\x2', '\x4AE', '\x4AF', '\t', '\x1D', '\x2', '\x2', + '\x4AF', '\x104', '\x3', '\x2', '\x2', '\x2', '\x4B0', '\x4B1', '\t', + '\x1E', '\x2', '\x2', '\x4B1', '\x106', '\x3', '\x2', '\x2', '\x2', '\x4B2', + '\x4B3', '\t', '\x1F', '\x2', '\x2', '\x4B3', '\x108', '\x3', '\x2', '\x2', + '\x2', '\x4B4', '\x4B5', '\t', ' ', '\x2', '\x2', '\x4B5', '\x10A', '\x3', + '\x2', '\x2', '\x2', '\x4B6', '\x4B7', '\t', '!', '\x2', '\x2', '\x4B7', + '\x10C', '\x3', '\x2', '\x2', '\x2', '\x4B8', '\x4B9', '\t', '\"', '\x2', + '\x2', '\x4B9', '\x10E', '\x3', '\x2', '\x2', '\x2', '\x4BA', '\x4BB', + '\t', '#', '\x2', '\x2', '\x4BB', '\x110', '\x3', '\x2', '\x2', '\x2', + '\x4BC', '\x4BD', '\t', '$', '\x2', '\x2', '\x4BD', '\x112', '\x3', '\x2', + '\x2', '\x2', '\x4BE', '\x4BF', '\t', '%', '\x2', '\x2', '\x4BF', '\x114', + '\x3', '\x2', '\x2', '\x2', '\x4C0', '\x4C1', '\t', '&', '\x2', '\x2', + '\x4C1', '\x116', '\x3', '\x2', '\x2', '\x2', '\x4C2', '\x4C3', '\t', + '\'', '\x2', '\x2', '\x4C3', '\x118', '\x3', '\x2', '\x2', '\x2', '\x4C4', + '\x4C5', '\t', '(', '\x2', '\x2', '\x4C5', '\x11A', '\x3', '\x2', '\x2', + '\x2', '\x4C6', '\x4C7', '\t', ')', '\x2', '\x2', '\x4C7', '\x11C', '\x3', + '\x2', '\x2', '\x2', '\x4C8', '\x4C9', '\t', '*', '\x2', '\x2', '\x4C9', + '\x11E', '\x3', '\x2', '\x2', '\x2', '\x4CA', '\x4CB', '\t', '+', '\x2', + '\x2', '\x4CB', '\x120', '\x3', '\x2', '\x2', '\x2', '\x4CC', '\x4CD', + '\t', ',', '\x2', '\x2', '\x4CD', '\x122', '\x3', '\x2', '\x2', '\x2', + '\x4CE', '\x4CF', '\t', '-', '\x2', '\x2', '\x4CF', '\x124', '\x3', '\x2', + '\x2', '\x2', '\x4D0', '\x4D1', '\t', '.', '\x2', '\x2', '\x4D1', '\x126', + '\x3', '\x2', '\x2', '\x2', '\x4D2', '\x4D3', '\t', '/', '\x2', '\x2', + '\x4D3', '\x128', '\x3', '\x2', '\x2', '\x2', ')', '\x2', '\x319', '\x31B', + '\x322', '\x324', '\x328', '\x33C', '\x344', '\x34B', '\x34E', '\x354', + '\x357', '\x35B', '\x35F', '\x363', '\x369', '\x370', '\x375', '\x37B', + '\x381', '\x383', '\x386', '\x389', '\x38E', '\x393', '\x39A', '\x3DE', + '\x3E3', '\x3E7', '\x3ED', '\x3F3', '\x3F8', '\x48B', '\x493', '\x495', + '\x4A0', '\x4A4', '\x4A8', '\x4AA', '\x2', + }; + + public static readonly ATN _ATN = + new ATNDeserializer().Deserialize(_serializedATN); + + +} +} // namespace openCypherTranspiler.openCypherParser.ANTLR diff --git a/src/openCypherParser/Grammar/CypherLexer.interp b/src/openCypherParser/Grammar/CypherLexer.interp new file mode 100644 index 0000000..552433d --- /dev/null +++ b/src/openCypherParser/Grammar/CypherLexer.interp @@ -0,0 +1,418 @@ +token literal names: +null +';' +',' +'=' +'+=' +'-' +'*' +'(' +')' +'[' +']' +':' +'|' +'..' +'+' +'/' +'%' +'^' +'<>' +'<' +'>' +'<=' +'>=' +'.' +'{' +'}' +'$' +'⟨' +'〈' +'﹤' +'<' +'⟩' +'〉' +'ï¹¥' +'>' +'­' +'â€�' +'‑' +'‒' +'–' +'â€�' +'―' +'−' +'﹘' +'ï¹£' +'ï¼�' +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +'0' +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null + +token symbolic names: +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +null +UNION +ALL +OPTIONAL +MATCH +UNWIND +AS +MERGE +ON +CREATE +SET +DETACH +DELETE +REMOVE +CALL +YIELD +WITH +DISTINCT +RETURN +ORDER +BY +L_SKIP +LIMIT +ASCENDING +ASC +DESCENDING +DESC +WHERE +OR +XOR +AND +NOT +IN +STARTS +ENDS +CONTAINS +IS +NULL +COUNT +FILTER +EXTRACT +ANY +NONE +SINGLE +TRUE +FALSE +EXISTS +CASE +ELSE +END +WHEN +THEN +StringLiteral +EscapedChar +HexInteger +DecimalInteger +OctalInteger +HexLetter +HexDigit +Digit +NonZeroDigit +NonZeroOctDigit +OctDigit +ZeroDigit +ExponentDecimalReal +RegularDecimalReal +CONSTRAINT +DO +FOR +REQUIRE +UNIQUE +MANDATORY +SCALAR +OF +ADD +DROP +UnescapedSymbolicName +IdentifierStart +IdentifierPart +EscapedSymbolicName +SP +WHITESPACE +Comment + +rule names: +T__0 +T__1 +T__2 +T__3 +T__4 +T__5 +T__6 +T__7 +T__8 +T__9 +T__10 +T__11 +T__12 +T__13 +T__14 +T__15 +T__16 +T__17 +T__18 +T__19 +T__20 +T__21 +T__22 +T__23 +T__24 +T__25 +T__26 +T__27 +T__28 +T__29 +T__30 +T__31 +T__32 +T__33 +T__34 +T__35 +T__36 +T__37 +T__38 +T__39 +T__40 +T__41 +T__42 +T__43 +T__44 +UNION +ALL +OPTIONAL +MATCH +UNWIND +AS +MERGE +ON +CREATE +SET +DETACH +DELETE +REMOVE +CALL +YIELD +WITH +DISTINCT +RETURN +ORDER +BY +L_SKIP +LIMIT +ASCENDING +ASC +DESCENDING +DESC +WHERE +OR +XOR +AND +NOT +IN +STARTS +ENDS +CONTAINS +IS +NULL +COUNT +FILTER +EXTRACT +ANY +NONE +SINGLE +TRUE +FALSE +EXISTS +CASE +ELSE +END +WHEN +THEN +StringLiteral +EscapedChar +HexInteger +DecimalInteger +OctalInteger +HexLetter +HexDigit +Digit +NonZeroDigit +NonZeroOctDigit +OctDigit +ZeroDigit +ExponentDecimalReal +RegularDecimalReal +CONSTRAINT +DO +FOR +REQUIRE +UNIQUE +MANDATORY +SCALAR +OF +ADD +DROP +UnescapedSymbolicName +IdentifierStart +IdentifierPart +EscapedSymbolicName +SP +WHITESPACE +Comment +FF +EscapedSymbolicName_0 +RS +ID_Continue +Comment_1 +StringLiteral_1 +Comment_3 +Comment_2 +GS +FS +CR +Sc +SPACE +Pc +TAB +StringLiteral_0 +LF +VT +US +ID_Start + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 129, 1236, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 4, 61, 9, 61, 4, 62, 9, 62, 4, 63, 9, 63, 4, 64, 9, 64, 4, 65, 9, 65, 4, 66, 9, 66, 4, 67, 9, 67, 4, 68, 9, 68, 4, 69, 9, 69, 4, 70, 9, 70, 4, 71, 9, 71, 4, 72, 9, 72, 4, 73, 9, 73, 4, 74, 9, 74, 4, 75, 9, 75, 4, 76, 9, 76, 4, 77, 9, 77, 4, 78, 9, 78, 4, 79, 9, 79, 4, 80, 9, 80, 4, 81, 9, 81, 4, 82, 9, 82, 4, 83, 9, 83, 4, 84, 9, 84, 4, 85, 9, 85, 4, 86, 9, 86, 4, 87, 9, 87, 4, 88, 9, 88, 4, 89, 9, 89, 4, 90, 9, 90, 4, 91, 9, 91, 4, 92, 9, 92, 4, 93, 9, 93, 4, 94, 9, 94, 4, 95, 9, 95, 4, 96, 9, 96, 4, 97, 9, 97, 4, 98, 9, 98, 4, 99, 9, 99, 4, 100, 9, 100, 4, 101, 9, 101, 4, 102, 9, 102, 4, 103, 9, 103, 4, 104, 9, 104, 4, 105, 9, 105, 4, 106, 9, 106, 4, 107, 9, 107, 4, 108, 9, 108, 4, 109, 9, 109, 4, 110, 9, 110, 4, 111, 9, 111, 4, 112, 9, 112, 4, 113, 9, 113, 4, 114, 9, 114, 4, 115, 9, 115, 4, 116, 9, 116, 4, 117, 9, 117, 4, 118, 9, 118, 4, 119, 9, 119, 4, 120, 9, 120, 4, 121, 9, 121, 4, 122, 9, 122, 4, 123, 9, 123, 4, 124, 9, 124, 4, 125, 9, 125, 4, 126, 9, 126, 4, 127, 9, 127, 4, 128, 9, 128, 4, 129, 9, 129, 4, 130, 9, 130, 4, 131, 9, 131, 4, 132, 9, 132, 4, 133, 9, 133, 4, 134, 9, 134, 4, 135, 9, 135, 4, 136, 9, 136, 4, 137, 9, 137, 4, 138, 9, 138, 4, 139, 9, 139, 4, 140, 9, 140, 4, 141, 9, 141, 4, 142, 9, 142, 4, 143, 9, 143, 4, 144, 9, 144, 4, 145, 9, 145, 4, 146, 9, 146, 4, 147, 9, 147, 4, 148, 9, 148, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 41, 3, 41, 3, 41, 3, 41, 3, 41, 3, 41, 3, 41, 3, 41, 3, 41, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 47, 3, 47, 3, 47, 3, 47, 3, 47, 3, 47, 3, 48, 3, 48, 3, 48, 3, 48, 3, 49, 3, 49, 3, 49, 3, 49, 3, 49, 3, 49, 3, 49, 3, 49, 3, 49, 3, 50, 3, 50, 3, 50, 3, 50, 3, 50, 3, 50, 3, 51, 3, 51, 3, 51, 3, 51, 3, 51, 3, 51, 3, 51, 3, 52, 3, 52, 3, 52, 3, 53, 3, 53, 3, 53, 3, 53, 3, 53, 3, 53, 3, 54, 3, 54, 3, 54, 3, 55, 3, 55, 3, 55, 3, 55, 3, 55, 3, 55, 3, 55, 3, 56, 3, 56, 3, 56, 3, 56, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 60, 3, 60, 3, 60, 3, 60, 3, 60, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 62, 3, 62, 3, 62, 3, 62, 3, 62, 3, 63, 3, 63, 3, 63, 3, 63, 3, 63, 3, 63, 3, 63, 3, 63, 3, 63, 3, 64, 3, 64, 3, 64, 3, 64, 3, 64, 3, 64, 3, 64, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 3, 66, 3, 66, 3, 66, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 70, 3, 70, 3, 70, 3, 70, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 72, 3, 72, 3, 72, 3, 72, 3, 72, 3, 73, 3, 73, 3, 73, 3, 73, 3, 73, 3, 73, 3, 74, 3, 74, 3, 74, 3, 75, 3, 75, 3, 75, 3, 75, 3, 76, 3, 76, 3, 76, 3, 76, 3, 77, 3, 77, 3, 77, 3, 77, 3, 78, 3, 78, 3, 78, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 82, 3, 82, 3, 82, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 84, 3, 84, 3, 84, 3, 84, 3, 84, 3, 84, 3, 85, 3, 85, 3, 85, 3, 85, 3, 85, 3, 85, 3, 85, 3, 86, 3, 86, 3, 86, 3, 86, 3, 86, 3, 86, 3, 86, 3, 86, 3, 87, 3, 87, 3, 87, 3, 87, 3, 88, 3, 88, 3, 88, 3, 88, 3, 88, 3, 89, 3, 89, 3, 89, 3, 89, 3, 89, 3, 89, 3, 89, 3, 90, 3, 90, 3, 90, 3, 90, 3, 90, 3, 91, 3, 91, 3, 91, 3, 91, 3, 91, 3, 91, 3, 92, 3, 92, 3, 92, 3, 92, 3, 92, 3, 92, 3, 92, 3, 93, 3, 93, 3, 93, 3, 93, 3, 93, 3, 94, 3, 94, 3, 94, 3, 94, 3, 94, 3, 95, 3, 95, 3, 95, 3, 95, 3, 96, 3, 96, 3, 96, 3, 96, 3, 96, 3, 97, 3, 97, 3, 97, 3, 97, 3, 97, 3, 98, 3, 98, 3, 98, 7, 98, 794, 10, 98, 12, 98, 14, 98, 797, 11, 98, 3, 98, 3, 98, 3, 98, 3, 98, 7, 98, 803, 10, 98, 12, 98, 14, 98, 806, 11, 98, 3, 98, 5, 98, 809, 10, 98, 3, 99, 3, 99, 3, 99, 3, 99, 3, 99, 3, 99, 3, 99, 3, 99, 3, 99, 3, 99, 3, 99, 3, 99, 3, 99, 3, 99, 3, 99, 3, 99, 3, 99, 3, 99, 5, 99, 829, 10, 99, 3, 100, 3, 100, 3, 100, 3, 100, 6, 100, 835, 10, 100, 13, 100, 14, 100, 836, 3, 101, 3, 101, 3, 101, 7, 101, 842, 10, 101, 12, 101, 14, 101, 845, 11, 101, 5, 101, 847, 10, 101, 3, 102, 3, 102, 6, 102, 851, 10, 102, 13, 102, 14, 102, 852, 3, 103, 5, 103, 856, 10, 103, 3, 104, 3, 104, 5, 104, 860, 10, 104, 3, 105, 3, 105, 5, 105, 864, 10, 105, 3, 106, 3, 106, 5, 106, 868, 10, 106, 3, 107, 3, 107, 3, 108, 3, 108, 5, 108, 874, 10, 108, 3, 109, 3, 109, 3, 110, 6, 110, 879, 10, 110, 13, 110, 14, 110, 880, 3, 110, 6, 110, 884, 10, 110, 13, 110, 14, 110, 885, 3, 110, 3, 110, 6, 110, 890, 10, 110, 13, 110, 14, 110, 891, 3, 110, 3, 110, 6, 110, 896, 10, 110, 13, 110, 14, 110, 897, 5, 110, 900, 10, 110, 3, 110, 5, 110, 903, 10, 110, 3, 110, 5, 110, 906, 10, 110, 3, 110, 6, 110, 909, 10, 110, 13, 110, 14, 110, 910, 3, 111, 7, 111, 914, 10, 111, 12, 111, 14, 111, 917, 11, 111, 3, 111, 3, 111, 6, 111, 921, 10, 111, 13, 111, 14, 111, 922, 3, 112, 3, 112, 3, 112, 3, 112, 3, 112, 3, 112, 3, 112, 3, 112, 3, 112, 3, 112, 3, 112, 3, 113, 3, 113, 3, 113, 3, 114, 3, 114, 3, 114, 3, 114, 3, 115, 3, 115, 3, 115, 3, 115, 3, 115, 3, 115, 3, 115, 3, 115, 3, 116, 3, 116, 3, 116, 3, 116, 3, 116, 3, 116, 3, 116, 3, 117, 3, 117, 3, 117, 3, 117, 3, 117, 3, 117, 3, 117, 3, 117, 3, 117, 3, 117, 3, 118, 3, 118, 3, 118, 3, 118, 3, 118, 3, 118, 3, 118, 3, 119, 3, 119, 3, 119, 3, 120, 3, 120, 3, 120, 3, 120, 3, 121, 3, 121, 3, 121, 3, 121, 3, 121, 3, 122, 3, 122, 7, 122, 989, 10, 122, 12, 122, 14, 122, 992, 11, 122, 3, 123, 3, 123, 5, 123, 996, 10, 123, 3, 124, 3, 124, 5, 124, 1000, 10, 124, 3, 125, 3, 125, 7, 125, 1004, 10, 125, 12, 125, 14, 125, 1007, 11, 125, 3, 125, 6, 125, 1010, 10, 125, 13, 125, 14, 125, 1011, 3, 126, 6, 126, 1015, 10, 126, 13, 126, 14, 126, 1016, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 5, 127, 1164, 10, 127, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 7, 128, 1172, 10, 128, 12, 128, 14, 128, 1175, 11, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 7, 128, 1183, 10, 128, 12, 128, 14, 128, 1186, 11, 128, 3, 128, 5, 128, 1189, 10, 128, 3, 128, 3, 128, 5, 128, 1193, 10, 128, 5, 128, 1195, 10, 128, 3, 129, 3, 129, 3, 130, 3, 130, 3, 131, 3, 131, 3, 132, 3, 132, 3, 133, 3, 133, 3, 134, 3, 134, 3, 135, 3, 135, 3, 136, 3, 136, 3, 137, 3, 137, 3, 138, 3, 138, 3, 139, 3, 139, 3, 140, 3, 140, 3, 141, 3, 141, 3, 142, 3, 142, 3, 143, 3, 143, 3, 144, 3, 144, 3, 145, 3, 145, 3, 146, 3, 146, 3, 147, 3, 147, 3, 148, 3, 148, 2, 2, 149, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26, 51, 27, 53, 28, 55, 29, 57, 30, 59, 31, 61, 32, 63, 33, 65, 34, 67, 35, 69, 36, 71, 37, 73, 38, 75, 39, 77, 40, 79, 41, 81, 42, 83, 43, 85, 44, 87, 45, 89, 46, 91, 47, 93, 48, 95, 49, 97, 50, 99, 51, 101, 52, 103, 53, 105, 54, 107, 55, 109, 56, 111, 57, 113, 58, 115, 59, 117, 60, 119, 61, 121, 62, 123, 63, 125, 64, 127, 65, 129, 66, 131, 67, 133, 68, 135, 69, 137, 70, 139, 71, 141, 72, 143, 73, 145, 74, 147, 75, 149, 76, 151, 77, 153, 78, 155, 79, 157, 80, 159, 81, 161, 82, 163, 83, 165, 84, 167, 85, 169, 86, 171, 87, 173, 88, 175, 89, 177, 90, 179, 91, 181, 92, 183, 93, 185, 94, 187, 95, 189, 96, 191, 97, 193, 98, 195, 99, 197, 100, 199, 101, 201, 102, 203, 103, 205, 104, 207, 105, 209, 106, 211, 107, 213, 108, 215, 109, 217, 110, 219, 111, 221, 112, 223, 113, 225, 114, 227, 115, 229, 116, 231, 117, 233, 118, 235, 119, 237, 120, 239, 121, 241, 122, 243, 123, 245, 124, 247, 125, 249, 126, 251, 127, 253, 128, 255, 129, 257, 2, 259, 2, 261, 2, 263, 2, 265, 2, 267, 2, 269, 2, 271, 2, 273, 2, 275, 2, 277, 2, 279, 2, 281, 2, 283, 2, 285, 2, 287, 2, 289, 2, 291, 2, 293, 2, 295, 2, 3, 2, 48, 4, 2, 87, 87, 119, 119, 4, 2, 80, 80, 112, 112, 4, 2, 75, 75, 107, 107, 4, 2, 81, 81, 113, 113, 4, 2, 67, 67, 99, 99, 4, 2, 78, 78, 110, 110, 4, 2, 82, 82, 114, 114, 4, 2, 86, 86, 118, 118, 4, 2, 79, 79, 111, 111, 4, 2, 69, 69, 101, 101, 4, 2, 74, 74, 106, 106, 4, 2, 89, 89, 121, 121, 4, 2, 70, 70, 102, 102, 4, 2, 85, 85, 117, 117, 4, 2, 71, 71, 103, 103, 4, 2, 84, 84, 116, 116, 4, 2, 73, 73, 105, 105, 4, 2, 88, 88, 120, 120, 4, 2, 91, 91, 123, 123, 4, 2, 68, 68, 100, 100, 4, 2, 77, 77, 109, 109, 4, 2, 90, 90, 122, 122, 4, 2, 72, 72, 104, 104, 15, 2, 36, 36, 41, 41, 68, 68, 72, 72, 80, 80, 84, 84, 86, 86, 94, 94, 100, 100, 104, 104, 112, 112, 116, 116, 118, 118, 4, 2, 67, 72, 99, 104, 4, 2, 83, 83, 115, 115, 3, 2, 14, 14, 4, 2, 2, 97, 99, 1, 3, 2, 32, 32, 431, 2, 50, 59, 67, 92, 97, 97, 99, 124, 172, 172, 183, 183, 185, 185, 188, 188, 194, 216, 218, 248, 250, 707, 712, 723, 738, 742, 750, 750, 752, 752, 770, 886, 888, 889, 892, 895, 904, 908, 910, 910, 912, 931, 933, 1015, 1017, 1155, 1157, 1161, 1164, 1321, 1331, 1368, 1371, 1371, 1379, 1417, 1427, 1471, 1473, 1473, 1475, 1476, 1478, 1479, 1481, 1481, 1490, 1516, 1522, 1524, 1554, 1564, 1570, 1643, 1648, 1749, 1751, 1758, 1761, 1770, 1772, 1790, 1793, 1793, 1810, 1868, 1871, 1971, 1986, 2039, 2044, 2044, 2050, 2095, 2114, 2141, 2210, 2210, 2212, 2222, 2278, 2304, 2306, 2405, 2408, 2417, 2419, 2425, 2427, 2433, 2435, 2437, 2439, 2446, 2449, 2450, 2453, 2474, 2476, 2482, 2484, 2484, 2488, 2491, 2494, 2502, 2505, 2506, 2509, 2512, 2521, 2521, 2526, 2527, 2529, 2533, 2536, 2547, 2563, 2565, 2567, 2572, 2577, 2578, 2581, 2602, 2604, 2610, 2612, 2613, 2615, 2616, 2618, 2619, 2622, 2622, 2624, 2628, 2633, 2634, 2637, 2639, 2643, 2643, 2651, 2654, 2656, 2656, 2664, 2679, 2691, 2693, 2695, 2703, 2705, 2707, 2709, 2730, 2732, 2738, 2740, 2741, 2743, 2747, 2750, 2759, 2761, 2763, 2765, 2767, 2770, 2770, 2786, 2789, 2792, 2801, 2819, 2821, 2823, 2830, 2833, 2834, 2837, 2858, 2860, 2866, 2868, 2869, 2871, 2875, 2878, 2886, 2889, 2890, 2893, 2895, 2904, 2905, 2910, 2911, 2913, 2917, 2920, 2929, 2931, 2931, 2948, 2949, 2951, 2956, 2960, 2962, 2964, 2967, 2971, 2972, 2974, 2974, 2976, 2977, 2981, 2982, 2986, 2988, 2992, 3003, 3008, 3012, 3016, 3018, 3020, 3023, 3026, 3026, 3033, 3033, 3048, 3057, 3075, 3077, 3079, 3086, 3088, 3090, 3092, 3114, 3116, 3125, 3127, 3131, 3135, 3142, 3144, 3146, 3148, 3151, 3159, 3160, 3162, 3163, 3170, 3173, 3176, 3185, 3204, 3205, 3207, 3214, 3216, 3218, 3220, 3242, 3244, 3253, 3255, 3259, 3262, 3270, 3272, 3274, 3276, 3279, 3287, 3288, 3296, 3296, 3298, 3301, 3304, 3313, 3315, 3316, 3332, 3333, 3335, 3342, 3344, 3346, 3348, 3388, 3391, 3398, 3400, 3402, 3404, 3408, 3417, 3417, 3426, 3429, 3432, 3441, 3452, 3457, 3460, 3461, 3463, 3480, 3484, 3507, 3509, 3517, 3519, 3519, 3522, 3528, 3532, 3532, 3537, 3542, 3544, 3544, 3546, 3553, 3572, 3573, 3587, 3644, 3650, 3664, 3666, 3675, 3715, 3716, 3718, 3718, 3721, 3722, 3724, 3724, 3727, 3727, 3734, 3737, 3739, 3745, 3747, 3749, 3751, 3751, 3753, 3753, 3756, 3757, 3759, 3771, 3773, 3775, 3778, 3782, 3784, 3784, 3786, 3791, 3794, 3803, 3806, 3809, 3842, 3842, 3866, 3867, 3874, 3883, 3895, 3895, 3897, 3897, 3899, 3899, 3904, 3913, 3915, 3950, 3955, 3974, 3976, 3993, 3995, 4030, 4040, 4040, 4098, 4171, 4178, 4255, 4258, 4295, 4297, 4297, 4303, 4303, 4306, 4348, 4350, 4682, 4684, 4687, 4690, 4696, 4698, 4698, 4700, 4703, 4706, 4746, 4748, 4751, 4754, 4786, 4788, 4791, 4794, 4800, 4802, 4802, 4804, 4807, 4810, 4824, 4826, 4882, 4884, 4887, 4890, 4956, 4959, 4961, 4971, 4979, 4994, 5009, 5026, 5110, 5123, 5742, 5745, 5761, 5763, 5788, 5794, 5868, 5872, 5874, 5890, 5902, 5904, 5910, 5922, 5942, 5954, 5973, 5986, 5998, 6000, 6002, 6004, 6005, 6018, 6101, 6105, 6105, 6110, 6111, 6114, 6123, 6157, 6159, 6162, 6171, 6178, 6265, 6274, 6316, 6322, 6391, 6402, 6430, 6434, 6445, 6450, 6461, 6472, 6511, 6514, 6518, 6530, 6573, 6578, 6603, 6610, 6620, 6658, 6685, 6690, 6752, 6754, 6782, 6785, 6795, 6802, 6811, 6825, 6825, 6914, 6989, 6994, 7003, 7021, 7029, 7042, 7157, 7170, 7225, 7234, 7243, 7247, 7295, 7378, 7380, 7382, 7416, 7426, 7656, 7678, 7959, 7962, 7967, 7970, 8007, 8010, 8015, 8018, 8025, 8027, 8027, 8029, 8029, 8031, 8031, 8033, 8063, 8066, 8118, 8120, 8126, 8128, 8128, 8132, 8134, 8136, 8142, 8146, 8149, 8152, 8157, 8162, 8174, 8180, 8182, 8184, 8190, 8257, 8258, 8278, 8278, 8307, 8307, 8321, 8321, 8338, 8350, 8402, 8414, 8419, 8419, 8423, 8434, 8452, 8452, 8457, 8457, 8460, 8469, 8471, 8471, 8474, 8479, 8486, 8486, 8488, 8488, 8490, 8490, 8492, 8507, 8510, 8513, 8519, 8523, 8528, 8528, 8546, 8586, 11266, 11312, 11314, 11360, 11362, 11494, 11501, 11509, 11522, 11559, 11561, 11561, 11567, 11567, 11570, 11625, 11633, 11633, 11649, 11672, 11682, 11688, 11690, 11696, 11698, 11704, 11706, 11712, 11714, 11720, 11722, 11728, 11730, 11736, 11738, 11744, 11746, 11777, 12295, 12297, 12323, 12337, 12339, 12343, 12346, 12350, 12355, 12440, 12443, 12449, 12451, 12540, 12542, 12545, 12551, 12591, 12595, 12688, 12706, 12732, 12786, 12801, 13314, 19895, 19970, 40910, 40962, 42126, 42194, 42239, 42242, 42510, 42514, 42541, 42562, 42609, 42614, 42623, 42625, 42649, 42657, 42739, 42777, 42785, 42788, 42890, 42893, 42896, 42898, 42901, 42914, 42924, 43002, 43049, 43074, 43125, 43138, 43206, 43218, 43227, 43234, 43257, 43261, 43261, 43266, 43311, 43314, 43349, 43362, 43390, 43394, 43458, 43473, 43483, 43522, 43576, 43586, 43599, 43602, 43611, 43618, 43640, 43644, 43645, 43650, 43716, 43741, 43743, 43746, 43761, 43764, 43768, 43779, 43784, 43787, 43792, 43795, 43800, 43810, 43816, 43818, 43824, 43970, 44012, 44014, 44015, 44018, 44027, 44034, 55205, 55218, 55240, 55245, 55293, 63746, 64111, 64114, 64219, 64258, 64264, 64277, 64281, 64287, 64298, 64300, 64312, 64314, 64318, 64320, 64320, 64322, 64323, 64325, 64326, 64328, 64435, 64469, 64831, 64850, 64913, 64916, 64969, 65010, 65021, 65026, 65041, 65058, 65064, 65077, 65078, 65103, 65105, 65138, 65142, 65144, 65278, 65298, 65307, 65315, 65340, 65345, 65345, 65347, 65372, 65384, 65472, 65476, 65481, 65484, 65489, 65492, 65497, 65500, 65502, 4, 2, 2, 43, 45, 1, 5, 2, 2, 40, 42, 93, 95, 1, 5, 2, 2, 11, 13, 14, 16, 1, 4, 2, 2, 48, 50, 1, 3, 2, 31, 31, 3, 2, 30, 30, 3, 2, 15, 15, 19, 2, 38, 38, 164, 167, 1425, 1425, 1549, 1549, 2548, 2549, 2557, 2557, 2803, 2803, 3067, 3067, 3649, 3649, 6109, 6109, 8354, 8380, 43066, 43066, 65022, 65022, 65131, 65131, 65286, 65286, 65506, 65507, 65511, 65512, 3, 2, 34, 34, 8, 2, 97, 97, 8257, 8258, 8278, 8278, 65077, 65078, 65103, 65105, 65345, 65345, 3, 2, 11, 11, 5, 2, 2, 35, 37, 93, 95, 1, 3, 2, 12, 12, 3, 2, 13, 13, 3, 2, 33, 33, 372, 2, 67, 92, 99, 124, 172, 172, 183, 183, 188, 188, 194, 216, 218, 248, 250, 707, 712, 723, 738, 742, 750, 750, 752, 752, 882, 886, 888, 889, 892, 895, 904, 904, 906, 908, 910, 910, 912, 931, 933, 1015, 1017, 1155, 1164, 1321, 1331, 1368, 1371, 1371, 1379, 1417, 1490, 1516, 1522, 1524, 1570, 1612, 1648, 1649, 1651, 1749, 1751, 1751, 1767, 1768, 1776, 1777, 1788, 1790, 1793, 1793, 1810, 1810, 1812, 1841, 1871, 1959, 1971, 1971, 1996, 2028, 2038, 2039, 2044, 2044, 2050, 2071, 2076, 2076, 2086, 2086, 2090, 2090, 2114, 2138, 2210, 2210, 2212, 2222, 2310, 2363, 2367, 2367, 2386, 2386, 2394, 2403, 2419, 2425, 2427, 2433, 2439, 2446, 2449, 2450, 2453, 2474, 2476, 2482, 2484, 2484, 2488, 2491, 2495, 2495, 2512, 2512, 2526, 2527, 2529, 2531, 2546, 2547, 2567, 2572, 2577, 2578, 2581, 2602, 2604, 2610, 2612, 2613, 2615, 2616, 2618, 2619, 2651, 2654, 2656, 2656, 2676, 2678, 2695, 2703, 2705, 2707, 2709, 2730, 2732, 2738, 2740, 2741, 2743, 2747, 2751, 2751, 2770, 2770, 2786, 2787, 2823, 2830, 2833, 2834, 2837, 2858, 2860, 2866, 2868, 2869, 2871, 2875, 2879, 2879, 2910, 2911, 2913, 2915, 2931, 2931, 2949, 2949, 2951, 2956, 2960, 2962, 2964, 2967, 2971, 2972, 2974, 2974, 2976, 2977, 2981, 2982, 2986, 2988, 2992, 3003, 3026, 3026, 3079, 3086, 3088, 3090, 3092, 3114, 3116, 3125, 3127, 3131, 3135, 3135, 3162, 3163, 3170, 3171, 3207, 3214, 3216, 3218, 3220, 3242, 3244, 3253, 3255, 3259, 3263, 3263, 3296, 3296, 3298, 3299, 3315, 3316, 3335, 3342, 3344, 3346, 3348, 3388, 3391, 3391, 3408, 3408, 3426, 3427, 3452, 3457, 3463, 3480, 3484, 3507, 3509, 3517, 3519, 3519, 3522, 3528, 3587, 3634, 3636, 3637, 3650, 3656, 3715, 3716, 3718, 3718, 3721, 3722, 3724, 3724, 3727, 3727, 3734, 3737, 3739, 3745, 3747, 3749, 3751, 3751, 3753, 3753, 3756, 3757, 3759, 3762, 3764, 3765, 3775, 3775, 3778, 3782, 3784, 3784, 3806, 3809, 3842, 3842, 3906, 3913, 3915, 3950, 3978, 3982, 4098, 4140, 4161, 4161, 4178, 4183, 4188, 4191, 4195, 4195, 4199, 4200, 4208, 4210, 4215, 4227, 4240, 4240, 4258, 4295, 4297, 4297, 4303, 4303, 4306, 4348, 4350, 4682, 4684, 4687, 4690, 4696, 4698, 4698, 4700, 4703, 4706, 4746, 4748, 4751, 4754, 4786, 4788, 4791, 4794, 4800, 4802, 4802, 4804, 4807, 4810, 4824, 4826, 4882, 4884, 4887, 4890, 4956, 4994, 5009, 5026, 5110, 5123, 5742, 5745, 5761, 5763, 5788, 5794, 5868, 5872, 5874, 5890, 5902, 5904, 5907, 5922, 5939, 5954, 5971, 5986, 5998, 6000, 6002, 6018, 6069, 6105, 6105, 6110, 6110, 6178, 6265, 6274, 6314, 6316, 6316, 6322, 6391, 6402, 6430, 6482, 6511, 6514, 6518, 6530, 6573, 6595, 6601, 6658, 6680, 6690, 6742, 6825, 6825, 6919, 6965, 6983, 6989, 7045, 7074, 7088, 7089, 7100, 7143, 7170, 7205, 7247, 7249, 7260, 7295, 7403, 7406, 7408, 7411, 7415, 7416, 7426, 7617, 7682, 7959, 7962, 7967, 7970, 8007, 8010, 8015, 8018, 8025, 8027, 8027, 8029, 8029, 8031, 8031, 8033, 8063, 8066, 8118, 8120, 8126, 8128, 8128, 8132, 8134, 8136, 8142, 8146, 8149, 8152, 8157, 8162, 8174, 8180, 8182, 8184, 8190, 8307, 8307, 8321, 8321, 8338, 8350, 8452, 8452, 8457, 8457, 8460, 8469, 8471, 8471, 8474, 8479, 8486, 8486, 8488, 8488, 8490, 8490, 8492, 8507, 8510, 8513, 8519, 8523, 8528, 8528, 8546, 8586, 11266, 11312, 11314, 11360, 11362, 11494, 11501, 11504, 11508, 11509, 11522, 11559, 11561, 11561, 11567, 11567, 11570, 11625, 11633, 11633, 11650, 11672, 11682, 11688, 11690, 11696, 11698, 11704, 11706, 11712, 11714, 11720, 11722, 11728, 11730, 11736, 11738, 11744, 12295, 12297, 12323, 12331, 12339, 12343, 12346, 12350, 12355, 12440, 12445, 12449, 12451, 12540, 12542, 12545, 12551, 12591, 12595, 12688, 12706, 12732, 12786, 12801, 13314, 19895, 19970, 40910, 40962, 42126, 42194, 42239, 42242, 42510, 42514, 42529, 42540, 42541, 42562, 42608, 42625, 42649, 42658, 42737, 42777, 42785, 42788, 42890, 42893, 42896, 42898, 42901, 42914, 42924, 43002, 43011, 43013, 43015, 43017, 43020, 43022, 43044, 43074, 43125, 43140, 43189, 43252, 43257, 43261, 43261, 43276, 43303, 43314, 43336, 43362, 43390, 43398, 43444, 43473, 43473, 43522, 43562, 43586, 43588, 43590, 43597, 43618, 43640, 43644, 43644, 43650, 43697, 43699, 43699, 43703, 43704, 43707, 43711, 43714, 43714, 43716, 43716, 43741, 43743, 43746, 43756, 43764, 43766, 43779, 43784, 43787, 43792, 43795, 43800, 43810, 43816, 43818, 43824, 43970, 44004, 44034, 55205, 55218, 55240, 55245, 55293, 63746, 64111, 64114, 64219, 64258, 64264, 64277, 64281, 64287, 64287, 64289, 64298, 64300, 64312, 64314, 64318, 64320, 64320, 64322, 64323, 64325, 64326, 64328, 64435, 64469, 64831, 64850, 64913, 64916, 64969, 65010, 65021, 65138, 65142, 65144, 65278, 65315, 65340, 65347, 65372, 65384, 65472, 65476, 65481, 65484, 65489, 65492, 65497, 65500, 65502, 2, 1281, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 2, 81, 3, 2, 2, 2, 2, 83, 3, 2, 2, 2, 2, 85, 3, 2, 2, 2, 2, 87, 3, 2, 2, 2, 2, 89, 3, 2, 2, 2, 2, 91, 3, 2, 2, 2, 2, 93, 3, 2, 2, 2, 2, 95, 3, 2, 2, 2, 2, 97, 3, 2, 2, 2, 2, 99, 3, 2, 2, 2, 2, 101, 3, 2, 2, 2, 2, 103, 3, 2, 2, 2, 2, 105, 3, 2, 2, 2, 2, 107, 3, 2, 2, 2, 2, 109, 3, 2, 2, 2, 2, 111, 3, 2, 2, 2, 2, 113, 3, 2, 2, 2, 2, 115, 3, 2, 2, 2, 2, 117, 3, 2, 2, 2, 2, 119, 3, 2, 2, 2, 2, 121, 3, 2, 2, 2, 2, 123, 3, 2, 2, 2, 2, 125, 3, 2, 2, 2, 2, 127, 3, 2, 2, 2, 2, 129, 3, 2, 2, 2, 2, 131, 3, 2, 2, 2, 2, 133, 3, 2, 2, 2, 2, 135, 3, 2, 2, 2, 2, 137, 3, 2, 2, 2, 2, 139, 3, 2, 2, 2, 2, 141, 3, 2, 2, 2, 2, 143, 3, 2, 2, 2, 2, 145, 3, 2, 2, 2, 2, 147, 3, 2, 2, 2, 2, 149, 3, 2, 2, 2, 2, 151, 3, 2, 2, 2, 2, 153, 3, 2, 2, 2, 2, 155, 3, 2, 2, 2, 2, 157, 3, 2, 2, 2, 2, 159, 3, 2, 2, 2, 2, 161, 3, 2, 2, 2, 2, 163, 3, 2, 2, 2, 2, 165, 3, 2, 2, 2, 2, 167, 3, 2, 2, 2, 2, 169, 3, 2, 2, 2, 2, 171, 3, 2, 2, 2, 2, 173, 3, 2, 2, 2, 2, 175, 3, 2, 2, 2, 2, 177, 3, 2, 2, 2, 2, 179, 3, 2, 2, 2, 2, 181, 3, 2, 2, 2, 2, 183, 3, 2, 2, 2, 2, 185, 3, 2, 2, 2, 2, 187, 3, 2, 2, 2, 2, 189, 3, 2, 2, 2, 2, 191, 3, 2, 2, 2, 2, 193, 3, 2, 2, 2, 2, 195, 3, 2, 2, 2, 2, 197, 3, 2, 2, 2, 2, 199, 3, 2, 2, 2, 2, 201, 3, 2, 2, 2, 2, 203, 3, 2, 2, 2, 2, 205, 3, 2, 2, 2, 2, 207, 3, 2, 2, 2, 2, 209, 3, 2, 2, 2, 2, 211, 3, 2, 2, 2, 2, 213, 3, 2, 2, 2, 2, 215, 3, 2, 2, 2, 2, 217, 3, 2, 2, 2, 2, 219, 3, 2, 2, 2, 2, 221, 3, 2, 2, 2, 2, 223, 3, 2, 2, 2, 2, 225, 3, 2, 2, 2, 2, 227, 3, 2, 2, 2, 2, 229, 3, 2, 2, 2, 2, 231, 3, 2, 2, 2, 2, 233, 3, 2, 2, 2, 2, 235, 3, 2, 2, 2, 2, 237, 3, 2, 2, 2, 2, 239, 3, 2, 2, 2, 2, 241, 3, 2, 2, 2, 2, 243, 3, 2, 2, 2, 2, 245, 3, 2, 2, 2, 2, 247, 3, 2, 2, 2, 2, 249, 3, 2, 2, 2, 2, 251, 3, 2, 2, 2, 2, 253, 3, 2, 2, 2, 2, 255, 3, 2, 2, 2, 3, 297, 3, 2, 2, 2, 5, 299, 3, 2, 2, 2, 7, 301, 3, 2, 2, 2, 9, 303, 3, 2, 2, 2, 11, 306, 3, 2, 2, 2, 13, 308, 3, 2, 2, 2, 15, 310, 3, 2, 2, 2, 17, 312, 3, 2, 2, 2, 19, 314, 3, 2, 2, 2, 21, 316, 3, 2, 2, 2, 23, 318, 3, 2, 2, 2, 25, 320, 3, 2, 2, 2, 27, 322, 3, 2, 2, 2, 29, 325, 3, 2, 2, 2, 31, 327, 3, 2, 2, 2, 33, 329, 3, 2, 2, 2, 35, 331, 3, 2, 2, 2, 37, 333, 3, 2, 2, 2, 39, 336, 3, 2, 2, 2, 41, 338, 3, 2, 2, 2, 43, 340, 3, 2, 2, 2, 45, 343, 3, 2, 2, 2, 47, 346, 3, 2, 2, 2, 49, 348, 3, 2, 2, 2, 51, 350, 3, 2, 2, 2, 53, 352, 3, 2, 2, 2, 55, 354, 3, 2, 2, 2, 57, 361, 3, 2, 2, 2, 59, 369, 3, 2, 2, 2, 61, 376, 3, 2, 2, 2, 63, 383, 3, 2, 2, 2, 65, 390, 3, 2, 2, 2, 67, 399, 3, 2, 2, 2, 69, 406, 3, 2, 2, 2, 71, 413, 3, 2, 2, 2, 73, 418, 3, 2, 2, 2, 75, 426, 3, 2, 2, 2, 77, 435, 3, 2, 2, 2, 79, 444, 3, 2, 2, 2, 81, 453, 3, 2, 2, 2, 83, 462, 3, 2, 2, 2, 85, 471, 3, 2, 2, 2, 87, 479, 3, 2, 2, 2, 89, 486, 3, 2, 2, 2, 91, 493, 3, 2, 2, 2, 93, 500, 3, 2, 2, 2, 95, 506, 3, 2, 2, 2, 97, 510, 3, 2, 2, 2, 99, 519, 3, 2, 2, 2, 101, 525, 3, 2, 2, 2, 103, 532, 3, 2, 2, 2, 105, 535, 3, 2, 2, 2, 107, 541, 3, 2, 2, 2, 109, 544, 3, 2, 2, 2, 111, 551, 3, 2, 2, 2, 113, 555, 3, 2, 2, 2, 115, 562, 3, 2, 2, 2, 117, 569, 3, 2, 2, 2, 119, 576, 3, 2, 2, 2, 121, 581, 3, 2, 2, 2, 123, 587, 3, 2, 2, 2, 125, 592, 3, 2, 2, 2, 127, 601, 3, 2, 2, 2, 129, 608, 3, 2, 2, 2, 131, 614, 3, 2, 2, 2, 133, 617, 3, 2, 2, 2, 135, 622, 3, 2, 2, 2, 137, 628, 3, 2, 2, 2, 139, 638, 3, 2, 2, 2, 141, 642, 3, 2, 2, 2, 143, 653, 3, 2, 2, 2, 145, 658, 3, 2, 2, 2, 147, 664, 3, 2, 2, 2, 149, 667, 3, 2, 2, 2, 151, 671, 3, 2, 2, 2, 153, 675, 3, 2, 2, 2, 155, 679, 3, 2, 2, 2, 157, 682, 3, 2, 2, 2, 159, 689, 3, 2, 2, 2, 161, 694, 3, 2, 2, 2, 163, 703, 3, 2, 2, 2, 165, 706, 3, 2, 2, 2, 167, 711, 3, 2, 2, 2, 169, 717, 3, 2, 2, 2, 171, 724, 3, 2, 2, 2, 173, 732, 3, 2, 2, 2, 175, 736, 3, 2, 2, 2, 177, 741, 3, 2, 2, 2, 179, 748, 3, 2, 2, 2, 181, 753, 3, 2, 2, 2, 183, 759, 3, 2, 2, 2, 185, 766, 3, 2, 2, 2, 187, 771, 3, 2, 2, 2, 189, 776, 3, 2, 2, 2, 191, 780, 3, 2, 2, 2, 193, 785, 3, 2, 2, 2, 195, 808, 3, 2, 2, 2, 197, 810, 3, 2, 2, 2, 199, 830, 3, 2, 2, 2, 201, 846, 3, 2, 2, 2, 203, 848, 3, 2, 2, 2, 205, 855, 3, 2, 2, 2, 207, 859, 3, 2, 2, 2, 209, 863, 3, 2, 2, 2, 211, 867, 3, 2, 2, 2, 213, 869, 3, 2, 2, 2, 215, 873, 3, 2, 2, 2, 217, 875, 3, 2, 2, 2, 219, 899, 3, 2, 2, 2, 221, 915, 3, 2, 2, 2, 223, 924, 3, 2, 2, 2, 225, 935, 3, 2, 2, 2, 227, 938, 3, 2, 2, 2, 229, 942, 3, 2, 2, 2, 231, 950, 3, 2, 2, 2, 233, 957, 3, 2, 2, 2, 235, 967, 3, 2, 2, 2, 237, 974, 3, 2, 2, 2, 239, 977, 3, 2, 2, 2, 241, 981, 3, 2, 2, 2, 243, 986, 3, 2, 2, 2, 245, 995, 3, 2, 2, 2, 247, 999, 3, 2, 2, 2, 249, 1009, 3, 2, 2, 2, 251, 1014, 3, 2, 2, 2, 253, 1163, 3, 2, 2, 2, 255, 1194, 3, 2, 2, 2, 257, 1196, 3, 2, 2, 2, 259, 1198, 3, 2, 2, 2, 261, 1200, 3, 2, 2, 2, 263, 1202, 3, 2, 2, 2, 265, 1204, 3, 2, 2, 2, 267, 1206, 3, 2, 2, 2, 269, 1208, 3, 2, 2, 2, 271, 1210, 3, 2, 2, 2, 273, 1212, 3, 2, 2, 2, 275, 1214, 3, 2, 2, 2, 277, 1216, 3, 2, 2, 2, 279, 1218, 3, 2, 2, 2, 281, 1220, 3, 2, 2, 2, 283, 1222, 3, 2, 2, 2, 285, 1224, 3, 2, 2, 2, 287, 1226, 3, 2, 2, 2, 289, 1228, 3, 2, 2, 2, 291, 1230, 3, 2, 2, 2, 293, 1232, 3, 2, 2, 2, 295, 1234, 3, 2, 2, 2, 297, 298, 7, 61, 2, 2, 298, 4, 3, 2, 2, 2, 299, 300, 7, 46, 2, 2, 300, 6, 3, 2, 2, 2, 301, 302, 7, 63, 2, 2, 302, 8, 3, 2, 2, 2, 303, 304, 7, 45, 2, 2, 304, 305, 7, 63, 2, 2, 305, 10, 3, 2, 2, 2, 306, 307, 7, 47, 2, 2, 307, 12, 3, 2, 2, 2, 308, 309, 7, 44, 2, 2, 309, 14, 3, 2, 2, 2, 310, 311, 7, 42, 2, 2, 311, 16, 3, 2, 2, 2, 312, 313, 7, 43, 2, 2, 313, 18, 3, 2, 2, 2, 314, 315, 7, 93, 2, 2, 315, 20, 3, 2, 2, 2, 316, 317, 7, 95, 2, 2, 317, 22, 3, 2, 2, 2, 318, 319, 7, 60, 2, 2, 319, 24, 3, 2, 2, 2, 320, 321, 7, 126, 2, 2, 321, 26, 3, 2, 2, 2, 322, 323, 7, 48, 2, 2, 323, 324, 7, 48, 2, 2, 324, 28, 3, 2, 2, 2, 325, 326, 7, 45, 2, 2, 326, 30, 3, 2, 2, 2, 327, 328, 7, 49, 2, 2, 328, 32, 3, 2, 2, 2, 329, 330, 7, 39, 2, 2, 330, 34, 3, 2, 2, 2, 331, 332, 7, 96, 2, 2, 332, 36, 3, 2, 2, 2, 333, 334, 7, 62, 2, 2, 334, 335, 7, 64, 2, 2, 335, 38, 3, 2, 2, 2, 336, 337, 7, 62, 2, 2, 337, 40, 3, 2, 2, 2, 338, 339, 7, 64, 2, 2, 339, 42, 3, 2, 2, 2, 340, 341, 7, 62, 2, 2, 341, 342, 7, 63, 2, 2, 342, 44, 3, 2, 2, 2, 343, 344, 7, 64, 2, 2, 344, 345, 7, 63, 2, 2, 345, 46, 3, 2, 2, 2, 346, 347, 7, 48, 2, 2, 347, 48, 3, 2, 2, 2, 348, 349, 7, 125, 2, 2, 349, 50, 3, 2, 2, 2, 350, 351, 7, 127, 2, 2, 351, 52, 3, 2, 2, 2, 352, 353, 7, 38, 2, 2, 353, 54, 3, 2, 2, 2, 354, 355, 7, 197, 2, 2, 355, 356, 7, 164, 2, 2, 356, 357, 7, 199, 2, 2, 357, 358, 7, 186, 2, 2, 358, 359, 7, 196, 2, 2, 359, 360, 7, 170, 2, 2, 360, 56, 3, 2, 2, 2, 361, 362, 7, 197, 2, 2, 362, 363, 7, 165, 2, 2, 363, 364, 7, 228, 2, 2, 364, 365, 7, 8220, 2, 2, 365, 366, 7, 174, 2, 2, 366, 367, 7, 205, 2, 2, 367, 368, 7, 8226, 2, 2, 368, 58, 3, 2, 2, 2, 369, 370, 7, 197, 2, 2, 370, 371, 7, 177, 2, 2, 371, 372, 7, 196, 2, 2, 372, 373, 7, 187, 2, 2, 373, 374, 7, 196, 2, 2, 374, 375, 7, 166, 2, 2, 375, 60, 3, 2, 2, 2, 376, 377, 7, 197, 2, 2, 377, 378, 7, 177, 2, 2, 378, 379, 7, 196, 2, 2, 379, 380, 7, 190, 2, 2, 380, 381, 7, 199, 2, 2, 381, 382, 7, 8222, 2, 2, 382, 62, 3, 2, 2, 2, 383, 384, 7, 197, 2, 2, 384, 385, 7, 164, 2, 2, 385, 386, 7, 199, 2, 2, 386, 387, 7, 186, 2, 2, 387, 388, 7, 196, 2, 2, 388, 389, 7, 171, 2, 2, 389, 64, 3, 2, 2, 2, 390, 391, 7, 197, 2, 2, 391, 392, 7, 165, 2, 2, 392, 393, 7, 228, 2, 2, 393, 394, 7, 8220, 2, 2, 394, 395, 7, 174, 2, 2, 395, 396, 7, 228, 2, 2, 396, 397, 7, 8366, 2, 2, 397, 398, 7, 178, 2, 2, 398, 66, 3, 2, 2, 2, 399, 400, 7, 197, 2, 2, 400, 401, 7, 177, 2, 2, 401, 402, 7, 196, 2, 2, 402, 403, 7, 187, 2, 2, 403, 404, 7, 196, 2, 2, 404, 405, 7, 167, 2, 2, 405, 68, 3, 2, 2, 2, 406, 407, 7, 197, 2, 2, 407, 408, 7, 177, 2, 2, 408, 409, 7, 196, 2, 2, 409, 410, 7, 190, 2, 2, 410, 411, 7, 199, 2, 2, 411, 412, 7, 192, 2, 2, 412, 70, 3, 2, 2, 2, 413, 414, 7, 197, 2, 2, 414, 415, 7, 8220, 2, 2, 415, 416, 7, 196, 2, 2, 416, 417, 7, 175, 2, 2, 417, 72, 3, 2, 2, 2, 418, 419, 7, 197, 2, 2, 419, 420, 7, 164, 2, 2, 420, 421, 7, 228, 2, 2, 421, 422, 7, 8220, 2, 2, 422, 423, 7, 174, 2, 2, 423, 424, 7, 196, 2, 2, 424, 425, 7, 65535, 2, 2, 425, 74, 3, 2, 2, 2, 426, 427, 7, 197, 2, 2, 427, 428, 7, 164, 2, 2, 428, 429, 7, 228, 2, 2, 429, 430, 7, 8220, 2, 2, 430, 431, 7, 174, 2, 2, 431, 432, 7, 228, 2, 2, 432, 433, 7, 8366, 2, 2, 433, 434, 7, 734, 2, 2, 434, 76, 3, 2, 2, 2, 435, 436, 7, 197, 2, 2, 436, 437, 7, 164, 2, 2, 437, 438, 7, 228, 2, 2, 438, 439, 7, 8220, 2, 2, 439, 440, 7, 174, 2, 2, 440, 441, 7, 228, 2, 2, 441, 442, 7, 8366, 2, 2, 442, 443, 7, 8484, 2, 2, 443, 78, 3, 2, 2, 2, 444, 445, 7, 197, 2, 2, 445, 446, 7, 164, 2, 2, 446, 447, 7, 228, 2, 2, 447, 448, 7, 8220, 2, 2, 448, 449, 7, 174, 2, 2, 449, 450, 7, 228, 2, 2, 450, 451, 7, 8366, 2, 2, 451, 452, 7, 341, 2, 2, 452, 80, 3, 2, 2, 2, 453, 454, 7, 197, 2, 2, 454, 455, 7, 164, 2, 2, 455, 456, 7, 228, 2, 2, 456, 457, 7, 8220, 2, 2, 457, 458, 7, 174, 2, 2, 458, 459, 7, 228, 2, 2, 459, 460, 7, 8366, 2, 2, 460, 461, 7, 65535, 2, 2, 461, 82, 3, 2, 2, 2, 462, 463, 7, 197, 2, 2, 463, 464, 7, 164, 2, 2, 464, 465, 7, 228, 2, 2, 465, 466, 7, 8220, 2, 2, 466, 467, 7, 174, 2, 2, 467, 468, 7, 228, 2, 2, 468, 469, 7, 8366, 2, 2, 469, 470, 7, 164, 2, 2, 470, 84, 3, 2, 2, 2, 471, 472, 7, 197, 2, 2, 472, 473, 7, 164, 2, 2, 473, 474, 7, 205, 2, 2, 474, 475, 7, 8226, 2, 2, 475, 476, 7, 228, 2, 2, 476, 477, 7, 8366, 2, 2, 477, 478, 7, 8484, 2, 2, 478, 86, 3, 2, 2, 2, 479, 480, 7, 197, 2, 2, 480, 481, 7, 177, 2, 2, 481, 482, 7, 196, 2, 2, 482, 483, 7, 187, 2, 2, 483, 484, 7, 205, 2, 2, 484, 485, 7, 341, 2, 2, 485, 88, 3, 2, 2, 2, 486, 487, 7, 197, 2, 2, 487, 488, 7, 177, 2, 2, 488, 489, 7, 196, 2, 2, 489, 490, 7, 187, 2, 2, 490, 491, 7, 196, 2, 2, 491, 492, 7, 165, 2, 2, 492, 90, 3, 2, 2, 2, 493, 494, 7, 197, 2, 2, 494, 495, 7, 177, 2, 2, 495, 496, 7, 196, 2, 2, 496, 497, 7, 190, 2, 2, 497, 498, 7, 196, 2, 2, 498, 499, 7, 65535, 2, 2, 499, 92, 3, 2, 2, 2, 500, 501, 9, 2, 2, 2, 501, 502, 9, 3, 2, 2, 502, 503, 9, 4, 2, 2, 503, 504, 9, 5, 2, 2, 504, 505, 9, 3, 2, 2, 505, 94, 3, 2, 2, 2, 506, 507, 9, 6, 2, 2, 507, 508, 9, 7, 2, 2, 508, 509, 9, 7, 2, 2, 509, 96, 3, 2, 2, 2, 510, 511, 9, 5, 2, 2, 511, 512, 9, 8, 2, 2, 512, 513, 9, 9, 2, 2, 513, 514, 9, 4, 2, 2, 514, 515, 9, 5, 2, 2, 515, 516, 9, 3, 2, 2, 516, 517, 9, 6, 2, 2, 517, 518, 9, 7, 2, 2, 518, 98, 3, 2, 2, 2, 519, 520, 9, 10, 2, 2, 520, 521, 9, 6, 2, 2, 521, 522, 9, 9, 2, 2, 522, 523, 9, 11, 2, 2, 523, 524, 9, 12, 2, 2, 524, 100, 3, 2, 2, 2, 525, 526, 9, 2, 2, 2, 526, 527, 9, 3, 2, 2, 527, 528, 9, 13, 2, 2, 528, 529, 9, 4, 2, 2, 529, 530, 9, 3, 2, 2, 530, 531, 9, 14, 2, 2, 531, 102, 3, 2, 2, 2, 532, 533, 9, 6, 2, 2, 533, 534, 9, 15, 2, 2, 534, 104, 3, 2, 2, 2, 535, 536, 9, 10, 2, 2, 536, 537, 9, 16, 2, 2, 537, 538, 9, 17, 2, 2, 538, 539, 9, 18, 2, 2, 539, 540, 9, 16, 2, 2, 540, 106, 3, 2, 2, 2, 541, 542, 9, 5, 2, 2, 542, 543, 9, 3, 2, 2, 543, 108, 3, 2, 2, 2, 544, 545, 9, 11, 2, 2, 545, 546, 9, 17, 2, 2, 546, 547, 9, 16, 2, 2, 547, 548, 9, 6, 2, 2, 548, 549, 9, 9, 2, 2, 549, 550, 9, 16, 2, 2, 550, 110, 3, 2, 2, 2, 551, 552, 9, 15, 2, 2, 552, 553, 9, 16, 2, 2, 553, 554, 9, 9, 2, 2, 554, 112, 3, 2, 2, 2, 555, 556, 9, 14, 2, 2, 556, 557, 9, 16, 2, 2, 557, 558, 9, 9, 2, 2, 558, 559, 9, 6, 2, 2, 559, 560, 9, 11, 2, 2, 560, 561, 9, 12, 2, 2, 561, 114, 3, 2, 2, 2, 562, 563, 9, 14, 2, 2, 563, 564, 9, 16, 2, 2, 564, 565, 9, 7, 2, 2, 565, 566, 9, 16, 2, 2, 566, 567, 9, 9, 2, 2, 567, 568, 9, 16, 2, 2, 568, 116, 3, 2, 2, 2, 569, 570, 9, 17, 2, 2, 570, 571, 9, 16, 2, 2, 571, 572, 9, 10, 2, 2, 572, 573, 9, 5, 2, 2, 573, 574, 9, 19, 2, 2, 574, 575, 9, 16, 2, 2, 575, 118, 3, 2, 2, 2, 576, 577, 9, 11, 2, 2, 577, 578, 9, 6, 2, 2, 578, 579, 9, 7, 2, 2, 579, 580, 9, 7, 2, 2, 580, 120, 3, 2, 2, 2, 581, 582, 9, 20, 2, 2, 582, 583, 9, 4, 2, 2, 583, 584, 9, 16, 2, 2, 584, 585, 9, 7, 2, 2, 585, 586, 9, 14, 2, 2, 586, 122, 3, 2, 2, 2, 587, 588, 9, 13, 2, 2, 588, 589, 9, 4, 2, 2, 589, 590, 9, 9, 2, 2, 590, 591, 9, 12, 2, 2, 591, 124, 3, 2, 2, 2, 592, 593, 9, 14, 2, 2, 593, 594, 9, 4, 2, 2, 594, 595, 9, 15, 2, 2, 595, 596, 9, 9, 2, 2, 596, 597, 9, 4, 2, 2, 597, 598, 9, 3, 2, 2, 598, 599, 9, 11, 2, 2, 599, 600, 9, 9, 2, 2, 600, 126, 3, 2, 2, 2, 601, 602, 9, 17, 2, 2, 602, 603, 9, 16, 2, 2, 603, 604, 9, 9, 2, 2, 604, 605, 9, 2, 2, 2, 605, 606, 9, 17, 2, 2, 606, 607, 9, 3, 2, 2, 607, 128, 3, 2, 2, 2, 608, 609, 9, 5, 2, 2, 609, 610, 9, 17, 2, 2, 610, 611, 9, 14, 2, 2, 611, 612, 9, 16, 2, 2, 612, 613, 9, 17, 2, 2, 613, 130, 3, 2, 2, 2, 614, 615, 9, 21, 2, 2, 615, 616, 9, 20, 2, 2, 616, 132, 3, 2, 2, 2, 617, 618, 9, 15, 2, 2, 618, 619, 9, 22, 2, 2, 619, 620, 9, 4, 2, 2, 620, 621, 9, 8, 2, 2, 621, 134, 3, 2, 2, 2, 622, 623, 9, 7, 2, 2, 623, 624, 9, 4, 2, 2, 624, 625, 9, 10, 2, 2, 625, 626, 9, 4, 2, 2, 626, 627, 9, 9, 2, 2, 627, 136, 3, 2, 2, 2, 628, 629, 9, 6, 2, 2, 629, 630, 9, 15, 2, 2, 630, 631, 9, 11, 2, 2, 631, 632, 9, 16, 2, 2, 632, 633, 9, 3, 2, 2, 633, 634, 9, 14, 2, 2, 634, 635, 9, 4, 2, 2, 635, 636, 9, 3, 2, 2, 636, 637, 9, 18, 2, 2, 637, 138, 3, 2, 2, 2, 638, 639, 9, 6, 2, 2, 639, 640, 9, 15, 2, 2, 640, 641, 9, 11, 2, 2, 641, 140, 3, 2, 2, 2, 642, 643, 9, 14, 2, 2, 643, 644, 9, 16, 2, 2, 644, 645, 9, 15, 2, 2, 645, 646, 9, 11, 2, 2, 646, 647, 9, 16, 2, 2, 647, 648, 9, 3, 2, 2, 648, 649, 9, 14, 2, 2, 649, 650, 9, 4, 2, 2, 650, 651, 9, 3, 2, 2, 651, 652, 9, 18, 2, 2, 652, 142, 3, 2, 2, 2, 653, 654, 9, 14, 2, 2, 654, 655, 9, 16, 2, 2, 655, 656, 9, 15, 2, 2, 656, 657, 9, 11, 2, 2, 657, 144, 3, 2, 2, 2, 658, 659, 9, 13, 2, 2, 659, 660, 9, 12, 2, 2, 660, 661, 9, 16, 2, 2, 661, 662, 9, 17, 2, 2, 662, 663, 9, 16, 2, 2, 663, 146, 3, 2, 2, 2, 664, 665, 9, 5, 2, 2, 665, 666, 9, 17, 2, 2, 666, 148, 3, 2, 2, 2, 667, 668, 9, 23, 2, 2, 668, 669, 9, 5, 2, 2, 669, 670, 9, 17, 2, 2, 670, 150, 3, 2, 2, 2, 671, 672, 9, 6, 2, 2, 672, 673, 9, 3, 2, 2, 673, 674, 9, 14, 2, 2, 674, 152, 3, 2, 2, 2, 675, 676, 9, 3, 2, 2, 676, 677, 9, 5, 2, 2, 677, 678, 9, 9, 2, 2, 678, 154, 3, 2, 2, 2, 679, 680, 9, 4, 2, 2, 680, 681, 9, 3, 2, 2, 681, 156, 3, 2, 2, 2, 682, 683, 9, 15, 2, 2, 683, 684, 9, 9, 2, 2, 684, 685, 9, 6, 2, 2, 685, 686, 9, 17, 2, 2, 686, 687, 9, 9, 2, 2, 687, 688, 9, 15, 2, 2, 688, 158, 3, 2, 2, 2, 689, 690, 9, 16, 2, 2, 690, 691, 9, 3, 2, 2, 691, 692, 9, 14, 2, 2, 692, 693, 9, 15, 2, 2, 693, 160, 3, 2, 2, 2, 694, 695, 9, 11, 2, 2, 695, 696, 9, 5, 2, 2, 696, 697, 9, 3, 2, 2, 697, 698, 9, 9, 2, 2, 698, 699, 9, 6, 2, 2, 699, 700, 9, 4, 2, 2, 700, 701, 9, 3, 2, 2, 701, 702, 9, 15, 2, 2, 702, 162, 3, 2, 2, 2, 703, 704, 9, 4, 2, 2, 704, 705, 9, 15, 2, 2, 705, 164, 3, 2, 2, 2, 706, 707, 9, 3, 2, 2, 707, 708, 9, 2, 2, 2, 708, 709, 9, 7, 2, 2, 709, 710, 9, 7, 2, 2, 710, 166, 3, 2, 2, 2, 711, 712, 9, 11, 2, 2, 712, 713, 9, 5, 2, 2, 713, 714, 9, 2, 2, 2, 714, 715, 9, 3, 2, 2, 715, 716, 9, 9, 2, 2, 716, 168, 3, 2, 2, 2, 717, 718, 9, 24, 2, 2, 718, 719, 9, 4, 2, 2, 719, 720, 9, 7, 2, 2, 720, 721, 9, 9, 2, 2, 721, 722, 9, 16, 2, 2, 722, 723, 9, 17, 2, 2, 723, 170, 3, 2, 2, 2, 724, 725, 9, 16, 2, 2, 725, 726, 9, 23, 2, 2, 726, 727, 9, 9, 2, 2, 727, 728, 9, 17, 2, 2, 728, 729, 9, 6, 2, 2, 729, 730, 9, 11, 2, 2, 730, 731, 9, 9, 2, 2, 731, 172, 3, 2, 2, 2, 732, 733, 9, 6, 2, 2, 733, 734, 9, 3, 2, 2, 734, 735, 9, 20, 2, 2, 735, 174, 3, 2, 2, 2, 736, 737, 9, 3, 2, 2, 737, 738, 9, 5, 2, 2, 738, 739, 9, 3, 2, 2, 739, 740, 9, 16, 2, 2, 740, 176, 3, 2, 2, 2, 741, 742, 9, 15, 2, 2, 742, 743, 9, 4, 2, 2, 743, 744, 9, 3, 2, 2, 744, 745, 9, 18, 2, 2, 745, 746, 9, 7, 2, 2, 746, 747, 9, 16, 2, 2, 747, 178, 3, 2, 2, 2, 748, 749, 9, 9, 2, 2, 749, 750, 9, 17, 2, 2, 750, 751, 9, 2, 2, 2, 751, 752, 9, 16, 2, 2, 752, 180, 3, 2, 2, 2, 753, 754, 9, 24, 2, 2, 754, 755, 9, 6, 2, 2, 755, 756, 9, 7, 2, 2, 756, 757, 9, 15, 2, 2, 757, 758, 9, 16, 2, 2, 758, 182, 3, 2, 2, 2, 759, 760, 9, 16, 2, 2, 760, 761, 9, 23, 2, 2, 761, 762, 9, 4, 2, 2, 762, 763, 9, 15, 2, 2, 763, 764, 9, 9, 2, 2, 764, 765, 9, 15, 2, 2, 765, 184, 3, 2, 2, 2, 766, 767, 9, 11, 2, 2, 767, 768, 9, 6, 2, 2, 768, 769, 9, 15, 2, 2, 769, 770, 9, 16, 2, 2, 770, 186, 3, 2, 2, 2, 771, 772, 9, 16, 2, 2, 772, 773, 9, 7, 2, 2, 773, 774, 9, 15, 2, 2, 774, 775, 9, 16, 2, 2, 775, 188, 3, 2, 2, 2, 776, 777, 9, 16, 2, 2, 777, 778, 9, 3, 2, 2, 778, 779, 9, 14, 2, 2, 779, 190, 3, 2, 2, 2, 780, 781, 9, 13, 2, 2, 781, 782, 9, 12, 2, 2, 782, 783, 9, 16, 2, 2, 783, 784, 9, 3, 2, 2, 784, 192, 3, 2, 2, 2, 785, 786, 9, 9, 2, 2, 786, 787, 9, 12, 2, 2, 787, 788, 9, 16, 2, 2, 788, 789, 9, 3, 2, 2, 789, 194, 3, 2, 2, 2, 790, 795, 7, 36, 2, 2, 791, 794, 5, 287, 144, 2, 792, 794, 5, 197, 99, 2, 793, 791, 3, 2, 2, 2, 793, 792, 3, 2, 2, 2, 794, 797, 3, 2, 2, 2, 795, 793, 3, 2, 2, 2, 795, 796, 3, 2, 2, 2, 796, 798, 3, 2, 2, 2, 797, 795, 3, 2, 2, 2, 798, 809, 7, 36, 2, 2, 799, 804, 7, 41, 2, 2, 800, 803, 5, 267, 134, 2, 801, 803, 5, 197, 99, 2, 802, 800, 3, 2, 2, 2, 802, 801, 3, 2, 2, 2, 803, 806, 3, 2, 2, 2, 804, 802, 3, 2, 2, 2, 804, 805, 3, 2, 2, 2, 805, 807, 3, 2, 2, 2, 806, 804, 3, 2, 2, 2, 807, 809, 7, 41, 2, 2, 808, 790, 3, 2, 2, 2, 808, 799, 3, 2, 2, 2, 809, 196, 3, 2, 2, 2, 810, 828, 7, 94, 2, 2, 811, 829, 9, 25, 2, 2, 812, 813, 9, 2, 2, 2, 813, 814, 5, 207, 104, 2, 814, 815, 5, 207, 104, 2, 815, 816, 5, 207, 104, 2, 816, 817, 5, 207, 104, 2, 817, 829, 3, 2, 2, 2, 818, 819, 9, 2, 2, 2, 819, 820, 5, 207, 104, 2, 820, 821, 5, 207, 104, 2, 821, 822, 5, 207, 104, 2, 822, 823, 5, 207, 104, 2, 823, 824, 5, 207, 104, 2, 824, 825, 5, 207, 104, 2, 825, 826, 5, 207, 104, 2, 826, 827, 5, 207, 104, 2, 827, 829, 3, 2, 2, 2, 828, 811, 3, 2, 2, 2, 828, 812, 3, 2, 2, 2, 828, 818, 3, 2, 2, 2, 829, 198, 3, 2, 2, 2, 830, 831, 7, 50, 2, 2, 831, 832, 7, 122, 2, 2, 832, 834, 3, 2, 2, 2, 833, 835, 5, 207, 104, 2, 834, 833, 3, 2, 2, 2, 835, 836, 3, 2, 2, 2, 836, 834, 3, 2, 2, 2, 836, 837, 3, 2, 2, 2, 837, 200, 3, 2, 2, 2, 838, 847, 5, 217, 109, 2, 839, 843, 5, 211, 106, 2, 840, 842, 5, 209, 105, 2, 841, 840, 3, 2, 2, 2, 842, 845, 3, 2, 2, 2, 843, 841, 3, 2, 2, 2, 843, 844, 3, 2, 2, 2, 844, 847, 3, 2, 2, 2, 845, 843, 3, 2, 2, 2, 846, 838, 3, 2, 2, 2, 846, 839, 3, 2, 2, 2, 847, 202, 3, 2, 2, 2, 848, 850, 5, 217, 109, 2, 849, 851, 5, 215, 108, 2, 850, 849, 3, 2, 2, 2, 851, 852, 3, 2, 2, 2, 852, 850, 3, 2, 2, 2, 852, 853, 3, 2, 2, 2, 853, 204, 3, 2, 2, 2, 854, 856, 9, 26, 2, 2, 855, 854, 3, 2, 2, 2, 856, 206, 3, 2, 2, 2, 857, 860, 5, 209, 105, 2, 858, 860, 5, 205, 103, 2, 859, 857, 3, 2, 2, 2, 859, 858, 3, 2, 2, 2, 860, 208, 3, 2, 2, 2, 861, 864, 5, 217, 109, 2, 862, 864, 5, 211, 106, 2, 863, 861, 3, 2, 2, 2, 863, 862, 3, 2, 2, 2, 864, 210, 3, 2, 2, 2, 865, 868, 5, 213, 107, 2, 866, 868, 4, 58, 59, 2, 867, 865, 3, 2, 2, 2, 867, 866, 3, 2, 2, 2, 868, 212, 3, 2, 2, 2, 869, 870, 4, 51, 57, 2, 870, 214, 3, 2, 2, 2, 871, 874, 5, 217, 109, 2, 872, 874, 5, 213, 107, 2, 873, 871, 3, 2, 2, 2, 873, 872, 3, 2, 2, 2, 874, 216, 3, 2, 2, 2, 875, 876, 7, 50, 2, 2, 876, 218, 3, 2, 2, 2, 877, 879, 5, 209, 105, 2, 878, 877, 3, 2, 2, 2, 879, 880, 3, 2, 2, 2, 880, 878, 3, 2, 2, 2, 880, 881, 3, 2, 2, 2, 881, 900, 3, 2, 2, 2, 882, 884, 5, 209, 105, 2, 883, 882, 3, 2, 2, 2, 884, 885, 3, 2, 2, 2, 885, 883, 3, 2, 2, 2, 885, 886, 3, 2, 2, 2, 886, 887, 3, 2, 2, 2, 887, 889, 7, 48, 2, 2, 888, 890, 5, 209, 105, 2, 889, 888, 3, 2, 2, 2, 890, 891, 3, 2, 2, 2, 891, 889, 3, 2, 2, 2, 891, 892, 3, 2, 2, 2, 892, 900, 3, 2, 2, 2, 893, 895, 7, 48, 2, 2, 894, 896, 5, 209, 105, 2, 895, 894, 3, 2, 2, 2, 896, 897, 3, 2, 2, 2, 897, 895, 3, 2, 2, 2, 897, 898, 3, 2, 2, 2, 898, 900, 3, 2, 2, 2, 899, 878, 3, 2, 2, 2, 899, 883, 3, 2, 2, 2, 899, 893, 3, 2, 2, 2, 900, 902, 3, 2, 2, 2, 901, 903, 9, 16, 2, 2, 902, 901, 3, 2, 2, 2, 903, 905, 3, 2, 2, 2, 904, 906, 7, 47, 2, 2, 905, 904, 3, 2, 2, 2, 905, 906, 3, 2, 2, 2, 906, 908, 3, 2, 2, 2, 907, 909, 5, 209, 105, 2, 908, 907, 3, 2, 2, 2, 909, 910, 3, 2, 2, 2, 910, 908, 3, 2, 2, 2, 910, 911, 3, 2, 2, 2, 911, 220, 3, 2, 2, 2, 912, 914, 5, 209, 105, 2, 913, 912, 3, 2, 2, 2, 914, 917, 3, 2, 2, 2, 915, 913, 3, 2, 2, 2, 915, 916, 3, 2, 2, 2, 916, 918, 3, 2, 2, 2, 917, 915, 3, 2, 2, 2, 918, 920, 7, 48, 2, 2, 919, 921, 5, 209, 105, 2, 920, 919, 3, 2, 2, 2, 921, 922, 3, 2, 2, 2, 922, 920, 3, 2, 2, 2, 922, 923, 3, 2, 2, 2, 923, 222, 3, 2, 2, 2, 924, 925, 9, 11, 2, 2, 925, 926, 9, 5, 2, 2, 926, 927, 9, 3, 2, 2, 927, 928, 9, 15, 2, 2, 928, 929, 9, 9, 2, 2, 929, 930, 9, 17, 2, 2, 930, 931, 9, 6, 2, 2, 931, 932, 9, 4, 2, 2, 932, 933, 9, 3, 2, 2, 933, 934, 9, 9, 2, 2, 934, 224, 3, 2, 2, 2, 935, 936, 9, 14, 2, 2, 936, 937, 9, 5, 2, 2, 937, 226, 3, 2, 2, 2, 938, 939, 9, 24, 2, 2, 939, 940, 9, 5, 2, 2, 940, 941, 9, 17, 2, 2, 941, 228, 3, 2, 2, 2, 942, 943, 9, 17, 2, 2, 943, 944, 9, 16, 2, 2, 944, 945, 9, 27, 2, 2, 945, 946, 9, 2, 2, 2, 946, 947, 9, 4, 2, 2, 947, 948, 9, 17, 2, 2, 948, 949, 9, 16, 2, 2, 949, 230, 3, 2, 2, 2, 950, 951, 9, 2, 2, 2, 951, 952, 9, 3, 2, 2, 952, 953, 9, 4, 2, 2, 953, 954, 9, 27, 2, 2, 954, 955, 9, 2, 2, 2, 955, 956, 9, 16, 2, 2, 956, 232, 3, 2, 2, 2, 957, 958, 9, 10, 2, 2, 958, 959, 9, 6, 2, 2, 959, 960, 9, 3, 2, 2, 960, 961, 9, 14, 2, 2, 961, 962, 9, 6, 2, 2, 962, 963, 9, 9, 2, 2, 963, 964, 9, 5, 2, 2, 964, 965, 9, 17, 2, 2, 965, 966, 9, 20, 2, 2, 966, 234, 3, 2, 2, 2, 967, 968, 9, 15, 2, 2, 968, 969, 9, 11, 2, 2, 969, 970, 9, 6, 2, 2, 970, 971, 9, 7, 2, 2, 971, 972, 9, 6, 2, 2, 972, 973, 9, 17, 2, 2, 973, 236, 3, 2, 2, 2, 974, 975, 9, 5, 2, 2, 975, 976, 9, 24, 2, 2, 976, 238, 3, 2, 2, 2, 977, 978, 9, 6, 2, 2, 978, 979, 9, 14, 2, 2, 979, 980, 9, 14, 2, 2, 980, 240, 3, 2, 2, 2, 981, 982, 9, 14, 2, 2, 982, 983, 9, 17, 2, 2, 983, 984, 9, 5, 2, 2, 984, 985, 9, 8, 2, 2, 985, 242, 3, 2, 2, 2, 986, 990, 5, 245, 123, 2, 987, 989, 5, 247, 124, 2, 988, 987, 3, 2, 2, 2, 989, 992, 3, 2, 2, 2, 990, 988, 3, 2, 2, 2, 990, 991, 3, 2, 2, 2, 991, 244, 3, 2, 2, 2, 992, 990, 3, 2, 2, 2, 993, 996, 5, 295, 148, 2, 994, 996, 5, 283, 142, 2, 995, 993, 3, 2, 2, 2, 995, 994, 3, 2, 2, 2, 996, 246, 3, 2, 2, 2, 997, 1000, 5, 263, 132, 2, 998, 1000, 5, 279, 140, 2, 999, 997, 3, 2, 2, 2, 999, 998, 3, 2, 2, 2, 1000, 248, 3, 2, 2, 2, 1001, 1005, 7, 98, 2, 2, 1002, 1004, 5, 259, 130, 2, 1003, 1002, 3, 2, 2, 2, 1004, 1007, 3, 2, 2, 2, 1005, 1003, 3, 2, 2, 2, 1005, 1006, 3, 2, 2, 2, 1006, 1008, 3, 2, 2, 2, 1007, 1005, 3, 2, 2, 2, 1008, 1010, 7, 98, 2, 2, 1009, 1001, 3, 2, 2, 2, 1010, 1011, 3, 2, 2, 2, 1011, 1009, 3, 2, 2, 2, 1011, 1012, 3, 2, 2, 2, 1012, 250, 3, 2, 2, 2, 1013, 1015, 5, 253, 127, 2, 1014, 1013, 3, 2, 2, 2, 1015, 1016, 3, 2, 2, 2, 1016, 1014, 3, 2, 2, 2, 1016, 1017, 3, 2, 2, 2, 1017, 252, 3, 2, 2, 2, 1018, 1164, 5, 281, 141, 2, 1019, 1164, 5, 285, 143, 2, 1020, 1164, 5, 289, 145, 2, 1021, 1164, 5, 291, 146, 2, 1022, 1164, 5, 257, 129, 2, 1023, 1164, 5, 277, 139, 2, 1024, 1164, 5, 275, 138, 2, 1025, 1164, 5, 273, 137, 2, 1026, 1164, 5, 261, 131, 2, 1027, 1164, 5, 293, 147, 2, 1028, 1029, 7, 197, 2, 2, 1029, 1030, 7, 163, 2, 2, 1030, 1031, 7, 199, 2, 2, 1031, 1032, 7, 163, 2, 2, 1032, 1033, 7, 228, 2, 2, 1033, 1034, 7, 8220, 2, 2, 1034, 1164, 7, 174, 2, 2, 1035, 1036, 7, 197, 2, 2, 1036, 1037, 7, 163, 2, 2, 1037, 1038, 7, 34, 2, 2, 1038, 1039, 7, 199, 2, 2, 1039, 1164, 7, 191, 2, 2, 1040, 1041, 7, 197, 2, 2, 1041, 1042, 7, 164, 2, 2, 1042, 1043, 7, 228, 2, 2, 1043, 1044, 7, 8220, 2, 2, 1044, 1045, 7, 174, 2, 2, 1045, 1046, 7, 228, 2, 2, 1046, 1047, 7, 8220, 2, 2, 1047, 1164, 7, 174, 2, 2, 1048, 1049, 7, 197, 2, 2, 1049, 1050, 7, 164, 2, 2, 1050, 1051, 7, 228, 2, 2, 1051, 1052, 7, 8220, 2, 2, 1052, 1053, 7, 174, 2, 2, 1053, 1054, 7, 196, 2, 2, 1054, 1164, 7, 65535, 2, 2, 1055, 1056, 7, 197, 2, 2, 1056, 1057, 7, 164, 2, 2, 1057, 1058, 7, 228, 2, 2, 1058, 1059, 7, 8220, 2, 2, 1059, 1060, 7, 174, 2, 2, 1060, 1061, 7, 228, 2, 2, 1061, 1062, 7, 8366, 2, 2, 1062, 1164, 7, 355, 2, 2, 1063, 1064, 7, 197, 2, 2, 1064, 1065, 7, 164, 2, 2, 1065, 1066, 7, 228, 2, 2, 1066, 1067, 7, 8220, 2, 2, 1067, 1068, 7, 174, 2, 2, 1068, 1069, 7, 200, 2, 2, 1069, 1164, 7, 8219, 2, 2, 1070, 1071, 7, 197, 2, 2, 1071, 1072, 7, 164, 2, 2, 1072, 1073, 7, 228, 2, 2, 1073, 1074, 7, 8220, 2, 2, 1074, 1075, 7, 174, 2, 2, 1075, 1076, 7, 228, 2, 2, 1076, 1077, 7, 8366, 2, 2, 1077, 1164, 7, 384, 2, 2, 1078, 1079, 7, 197, 2, 2, 1079, 1080, 7, 164, 2, 2, 1080, 1081, 7, 228, 2, 2, 1081, 1082, 7, 8220, 2, 2, 1082, 1083, 7, 174, 2, 2, 1083, 1084, 7, 228, 2, 2, 1084, 1085, 7, 8366, 2, 2, 1085, 1164, 7, 168, 2, 2, 1086, 1087, 7, 197, 2, 2, 1087, 1088, 7, 164, 2, 2, 1088, 1089, 7, 228, 2, 2, 1089, 1090, 7, 8220, 2, 2, 1090, 1091, 7, 174, 2, 2, 1091, 1092, 7, 228, 2, 2, 1092, 1093, 7, 8366, 2, 2, 1093, 1164, 7, 162, 2, 2, 1094, 1095, 7, 197, 2, 2, 1095, 1096, 7, 164, 2, 2, 1096, 1097, 7, 228, 2, 2, 1097, 1098, 7, 8220, 2, 2, 1098, 1099, 7, 174, 2, 2, 1099, 1100, 7, 205, 2, 2, 1100, 1164, 7, 8226, 2, 2, 1101, 1102, 7, 197, 2, 2, 1102, 1103, 7, 164, 2, 2, 1103, 1104, 7, 228, 2, 2, 1104, 1105, 7, 8220, 2, 2, 1105, 1106, 7, 174, 2, 2, 1106, 1107, 7, 228, 2, 2, 1107, 1108, 7, 8366, 2, 2, 1108, 1164, 7, 178, 2, 2, 1109, 1110, 7, 197, 2, 2, 1110, 1111, 7, 164, 2, 2, 1111, 1112, 7, 228, 2, 2, 1112, 1113, 7, 8220, 2, 2, 1113, 1114, 7, 174, 2, 2, 1114, 1115, 7, 199, 2, 2, 1115, 1164, 7, 162, 2, 2, 1116, 1117, 7, 197, 2, 2, 1117, 1118, 7, 164, 2, 2, 1118, 1119, 7, 228, 2, 2, 1119, 1120, 7, 8220, 2, 2, 1120, 1121, 7, 174, 2, 2, 1121, 1122, 7, 196, 2, 2, 1122, 1164, 7, 170, 2, 2, 1123, 1124, 7, 197, 2, 2, 1124, 1125, 7, 164, 2, 2, 1125, 1126, 7, 228, 2, 2, 1126, 1127, 7, 8220, 2, 2, 1127, 1128, 7, 174, 2, 2, 1128, 1129, 7, 196, 2, 2, 1129, 1164, 7, 171, 2, 2, 1130, 1131, 7, 197, 2, 2, 1131, 1132, 7, 164, 2, 2, 1132, 1133, 7, 196, 2, 2, 1133, 1134, 7, 65535, 2, 2, 1134, 1135, 7, 199, 2, 2, 1135, 1164, 7, 186, 2, 2, 1136, 1137, 7, 197, 2, 2, 1137, 1138, 7, 165, 2, 2, 1138, 1139, 7, 228, 2, 2, 1139, 1140, 7, 8220, 2, 2, 1140, 1141, 7, 174, 2, 2, 1141, 1142, 7, 228, 2, 2, 1142, 1143, 7, 8220, 2, 2, 1143, 1164, 7, 174, 2, 2, 1144, 1145, 7, 197, 2, 2, 1145, 1146, 7, 8220, 2, 2, 1146, 1164, 7, 34, 2, 2, 1147, 1148, 7, 197, 2, 2, 1148, 1149, 7, 164, 2, 2, 1149, 1150, 7, 228, 2, 2, 1150, 1151, 7, 8220, 2, 2, 1151, 1152, 7, 174, 2, 2, 1152, 1153, 7, 228, 2, 2, 1153, 1154, 7, 8366, 2, 2, 1154, 1164, 7, 163, 2, 2, 1155, 1156, 7, 197, 2, 2, 1156, 1157, 7, 164, 2, 2, 1157, 1158, 7, 228, 2, 2, 1158, 1159, 7, 8220, 2, 2, 1159, 1160, 7, 174, 2, 2, 1160, 1161, 7, 196, 2, 2, 1161, 1164, 7, 177, 2, 2, 1162, 1164, 5, 255, 128, 2, 1163, 1018, 3, 2, 2, 2, 1163, 1019, 3, 2, 2, 2, 1163, 1020, 3, 2, 2, 2, 1163, 1021, 3, 2, 2, 2, 1163, 1022, 3, 2, 2, 2, 1163, 1023, 3, 2, 2, 2, 1163, 1024, 3, 2, 2, 2, 1163, 1025, 3, 2, 2, 2, 1163, 1026, 3, 2, 2, 2, 1163, 1027, 3, 2, 2, 2, 1163, 1028, 3, 2, 2, 2, 1163, 1035, 3, 2, 2, 2, 1163, 1040, 3, 2, 2, 2, 1163, 1048, 3, 2, 2, 2, 1163, 1055, 3, 2, 2, 2, 1163, 1063, 3, 2, 2, 2, 1163, 1070, 3, 2, 2, 2, 1163, 1078, 3, 2, 2, 2, 1163, 1086, 3, 2, 2, 2, 1163, 1094, 3, 2, 2, 2, 1163, 1101, 3, 2, 2, 2, 1163, 1109, 3, 2, 2, 2, 1163, 1116, 3, 2, 2, 2, 1163, 1123, 3, 2, 2, 2, 1163, 1130, 3, 2, 2, 2, 1163, 1136, 3, 2, 2, 2, 1163, 1144, 3, 2, 2, 2, 1163, 1147, 3, 2, 2, 2, 1163, 1155, 3, 2, 2, 2, 1163, 1162, 3, 2, 2, 2, 1164, 254, 3, 2, 2, 2, 1165, 1166, 7, 49, 2, 2, 1166, 1167, 7, 44, 2, 2, 1167, 1173, 3, 2, 2, 2, 1168, 1172, 5, 265, 133, 2, 1169, 1170, 7, 44, 2, 2, 1170, 1172, 5, 271, 136, 2, 1171, 1168, 3, 2, 2, 2, 1171, 1169, 3, 2, 2, 2, 1172, 1175, 3, 2, 2, 2, 1173, 1171, 3, 2, 2, 2, 1173, 1174, 3, 2, 2, 2, 1174, 1176, 3, 2, 2, 2, 1175, 1173, 3, 2, 2, 2, 1176, 1177, 7, 44, 2, 2, 1177, 1195, 7, 49, 2, 2, 1178, 1179, 7, 49, 2, 2, 1179, 1180, 7, 49, 2, 2, 1180, 1184, 3, 2, 2, 2, 1181, 1183, 5, 269, 135, 2, 1182, 1181, 3, 2, 2, 2, 1183, 1186, 3, 2, 2, 2, 1184, 1182, 3, 2, 2, 2, 1184, 1185, 3, 2, 2, 2, 1185, 1188, 3, 2, 2, 2, 1186, 1184, 3, 2, 2, 2, 1187, 1189, 5, 277, 139, 2, 1188, 1187, 3, 2, 2, 2, 1188, 1189, 3, 2, 2, 2, 1189, 1192, 3, 2, 2, 2, 1190, 1193, 5, 289, 145, 2, 1191, 1193, 7, 2, 2, 3, 1192, 1190, 3, 2, 2, 2, 1192, 1191, 3, 2, 2, 2, 1193, 1195, 3, 2, 2, 2, 1194, 1165, 3, 2, 2, 2, 1194, 1178, 3, 2, 2, 2, 1195, 256, 3, 2, 2, 2, 1196, 1197, 9, 28, 2, 2, 1197, 258, 3, 2, 2, 2, 1198, 1199, 9, 29, 2, 2, 1199, 260, 3, 2, 2, 2, 1200, 1201, 9, 30, 2, 2, 1201, 262, 3, 2, 2, 2, 1202, 1203, 9, 31, 2, 2, 1203, 264, 3, 2, 2, 2, 1204, 1205, 9, 32, 2, 2, 1205, 266, 3, 2, 2, 2, 1206, 1207, 9, 33, 2, 2, 1207, 268, 3, 2, 2, 2, 1208, 1209, 9, 34, 2, 2, 1209, 270, 3, 2, 2, 2, 1210, 1211, 9, 35, 2, 2, 1211, 272, 3, 2, 2, 2, 1212, 1213, 9, 36, 2, 2, 1213, 274, 3, 2, 2, 2, 1214, 1215, 9, 37, 2, 2, 1215, 276, 3, 2, 2, 2, 1216, 1217, 9, 38, 2, 2, 1217, 278, 3, 2, 2, 2, 1218, 1219, 9, 39, 2, 2, 1219, 280, 3, 2, 2, 2, 1220, 1221, 9, 40, 2, 2, 1221, 282, 3, 2, 2, 2, 1222, 1223, 9, 41, 2, 2, 1223, 284, 3, 2, 2, 2, 1224, 1225, 9, 42, 2, 2, 1225, 286, 3, 2, 2, 2, 1226, 1227, 9, 43, 2, 2, 1227, 288, 3, 2, 2, 2, 1228, 1229, 9, 44, 2, 2, 1229, 290, 3, 2, 2, 2, 1230, 1231, 9, 45, 2, 2, 1231, 292, 3, 2, 2, 2, 1232, 1233, 9, 46, 2, 2, 1233, 294, 3, 2, 2, 2, 1234, 1235, 9, 47, 2, 2, 1235, 296, 3, 2, 2, 2, 41, 2, 793, 795, 802, 804, 808, 828, 836, 843, 846, 852, 855, 859, 863, 867, 873, 880, 885, 891, 897, 899, 902, 905, 910, 915, 922, 990, 995, 999, 1005, 1011, 1016, 1163, 1171, 1173, 1184, 1188, 1192, 1194, 2] \ No newline at end of file diff --git a/src/openCypherParser/Grammar/CypherLexer.tokens b/src/openCypherParser/Grammar/CypherLexer.tokens new file mode 100644 index 0000000..45df26f --- /dev/null +++ b/src/openCypherParser/Grammar/CypherLexer.tokens @@ -0,0 +1,173 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +T__10=11 +T__11=12 +T__12=13 +T__13=14 +T__14=15 +T__15=16 +T__16=17 +T__17=18 +T__18=19 +T__19=20 +T__20=21 +T__21=22 +T__22=23 +T__23=24 +T__24=25 +T__25=26 +T__26=27 +T__27=28 +T__28=29 +T__29=30 +T__30=31 +T__31=32 +T__32=33 +T__33=34 +T__34=35 +T__35=36 +T__36=37 +T__37=38 +T__38=39 +T__39=40 +T__40=41 +T__41=42 +T__42=43 +T__43=44 +T__44=45 +UNION=46 +ALL=47 +OPTIONAL=48 +MATCH=49 +UNWIND=50 +AS=51 +MERGE=52 +ON=53 +CREATE=54 +SET=55 +DETACH=56 +DELETE=57 +REMOVE=58 +CALL=59 +YIELD=60 +WITH=61 +DISTINCT=62 +RETURN=63 +ORDER=64 +BY=65 +L_SKIP=66 +LIMIT=67 +ASCENDING=68 +ASC=69 +DESCENDING=70 +DESC=71 +WHERE=72 +OR=73 +XOR=74 +AND=75 +NOT=76 +IN=77 +STARTS=78 +ENDS=79 +CONTAINS=80 +IS=81 +NULL=82 +COUNT=83 +FILTER=84 +EXTRACT=85 +ANY=86 +NONE=87 +SINGLE=88 +TRUE=89 +FALSE=90 +EXISTS=91 +CASE=92 +ELSE=93 +END=94 +WHEN=95 +THEN=96 +StringLiteral=97 +EscapedChar=98 +HexInteger=99 +DecimalInteger=100 +OctalInteger=101 +HexLetter=102 +HexDigit=103 +Digit=104 +NonZeroDigit=105 +NonZeroOctDigit=106 +OctDigit=107 +ZeroDigit=108 +ExponentDecimalReal=109 +RegularDecimalReal=110 +CONSTRAINT=111 +DO=112 +FOR=113 +REQUIRE=114 +UNIQUE=115 +MANDATORY=116 +SCALAR=117 +OF=118 +ADD=119 +DROP=120 +UnescapedSymbolicName=121 +IdentifierStart=122 +IdentifierPart=123 +EscapedSymbolicName=124 +SP=125 +WHITESPACE=126 +Comment=127 +';'=1 +','=2 +'='=3 +'+='=4 +'-'=5 +'*'=6 +'('=7 +')'=8 +'['=9 +']'=10 +':'=11 +'|'=12 +'..'=13 +'+'=14 +'/'=15 +'%'=16 +'^'=17 +'<>'=18 +'<'=19 +'>'=20 +'<='=21 +'>='=22 +'.'=23 +'{'=24 +'}'=25 +'$'=26 +'⟨'=27 +'〈'=28 +'﹤'=29 +'<'=30 +'⟩'=31 +'〉'=32 +'ï¹¥'=33 +'>'=34 +'­'=35 +'â€�'=36 +'‑'=37 +'‒'=38 +'–'=39 +'â€�'=40 +'―'=41 +'−'=42 +'﹘'=43 +'ï¹£'=44 +'ï¼�'=45 +'0'=108 diff --git a/src/openCypherParser/Grammar/CypherParser.cs b/src/openCypherParser/Grammar/CypherParser.cs new file mode 100644 index 0000000..35e3259 --- /dev/null +++ b/src/openCypherParser/Grammar/CypherParser.cs @@ -0,0 +1,9681 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// ANTLR Version: 4.7.2 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +// Generated from Cypher.g4 by ANTLR 4.7.2 + +// Unreachable code detected +#pragma warning disable 0162 +// The variable '...' is assigned but its value is never used +#pragma warning disable 0219 +// Missing XML comment for publicly visible type or member '...' +#pragma warning disable 1591 +// Ambiguous reference in cref attribute +#pragma warning disable 419 + +namespace openCypherTranspiler.openCypherParser.ANTLR { +using System; +using System.IO; +using System.Text; +using System.Diagnostics; +using System.Collections.Generic; +using Antlr4.Runtime; +using Antlr4.Runtime.Atn; +using Antlr4.Runtime.Misc; +using Antlr4.Runtime.Tree; +using DFA = Antlr4.Runtime.Dfa.DFA; + +[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.7.2")] +[System.CLSCompliant(false)] +public partial class CypherParser : Parser { + protected static DFA[] decisionToDFA; + protected static PredictionContextCache sharedContextCache = new PredictionContextCache(); + public const int + T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, + T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, + T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, + T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31, + T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38, + T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, T__43=44, T__44=45, + UNION=46, ALL=47, OPTIONAL=48, MATCH=49, UNWIND=50, AS=51, MERGE=52, ON=53, + CREATE=54, SET=55, DETACH=56, DELETE=57, REMOVE=58, CALL=59, YIELD=60, + WITH=61, DISTINCT=62, RETURN=63, ORDER=64, BY=65, L_SKIP=66, LIMIT=67, + ASCENDING=68, ASC=69, DESCENDING=70, DESC=71, WHERE=72, OR=73, XOR=74, + AND=75, NOT=76, IN=77, STARTS=78, ENDS=79, CONTAINS=80, IS=81, NULL=82, + COUNT=83, FILTER=84, EXTRACT=85, ANY=86, NONE=87, SINGLE=88, TRUE=89, + FALSE=90, EXISTS=91, CASE=92, ELSE=93, END=94, WHEN=95, THEN=96, StringLiteral=97, + EscapedChar=98, HexInteger=99, DecimalInteger=100, OctalInteger=101, HexLetter=102, + HexDigit=103, Digit=104, NonZeroDigit=105, NonZeroOctDigit=106, OctDigit=107, + ZeroDigit=108, ExponentDecimalReal=109, RegularDecimalReal=110, CONSTRAINT=111, + DO=112, FOR=113, REQUIRE=114, UNIQUE=115, MANDATORY=116, SCALAR=117, OF=118, + ADD=119, DROP=120, UnescapedSymbolicName=121, IdentifierStart=122, IdentifierPart=123, + EscapedSymbolicName=124, SP=125, WHITESPACE=126, Comment=127; + public const int + RULE_oC_Cypher = 0, RULE_oC_Statement = 1, RULE_oC_Query = 2, RULE_oC_RegularQuery = 3, + RULE_oC_Union = 4, RULE_oC_SingleQuery = 5, RULE_oC_SinglePartQuery = 6, + RULE_oC_MultiPartQuery = 7, RULE_oC_UpdatingClause = 8, RULE_oC_ReadingClause = 9, + RULE_oC_Match = 10, RULE_oC_Unwind = 11, RULE_oC_Merge = 12, RULE_oC_MergeAction = 13, + RULE_oC_Create = 14, RULE_oC_Set = 15, RULE_oC_SetItem = 16, RULE_oC_Delete = 17, + RULE_oC_Remove = 18, RULE_oC_RemoveItem = 19, RULE_oC_InQueryCall = 20, + RULE_oC_StandaloneCall = 21, RULE_oC_YieldItems = 22, RULE_oC_YieldItem = 23, + RULE_oC_With = 24, RULE_oC_Return = 25, RULE_oC_ReturnBody = 26, RULE_oC_ReturnItems = 27, + RULE_oC_ReturnItem = 28, RULE_oC_Order = 29, RULE_oC_Skip = 30, RULE_oC_Limit = 31, + RULE_oC_SortItem = 32, RULE_oC_Where = 33, RULE_oC_Pattern = 34, RULE_oC_PatternPart = 35, + RULE_oC_AnonymousPatternPart = 36, RULE_oC_PatternElement = 37, RULE_oC_NodePattern = 38, + RULE_oC_PatternElementChain = 39, RULE_oC_RelationshipPattern = 40, RULE_oC_RelationshipDetail = 41, + RULE_oC_Properties = 42, RULE_oC_RelationshipTypes = 43, RULE_oC_NodeLabels = 44, + RULE_oC_NodeLabel = 45, RULE_oC_RangeLiteral = 46, RULE_oC_LabelName = 47, + RULE_oC_RelTypeName = 48, RULE_oC_Expression = 49, RULE_oC_OrExpression = 50, + RULE_oC_XorExpression = 51, RULE_oC_AndExpression = 52, RULE_oC_NotExpression = 53, + RULE_oC_ComparisonExpression = 54, RULE_oC_AddOrSubtractExpression = 55, + RULE_oC_MultiplyDivideModuloExpression = 56, RULE_oC_PowerOfExpression = 57, + RULE_oC_UnaryAddOrSubtractExpression = 58, RULE_oC_StringListNullOperatorExpression = 59, + RULE_oC_PropertyOrLabelsExpression = 60, RULE_oC_Atom = 61, RULE_oC_Literal = 62, + RULE_oC_BooleanLiteral = 63, RULE_oC_ListLiteral = 64, RULE_oC_PartialComparisonExpression = 65, + RULE_oC_ParenthesizedExpression = 66, RULE_oC_RelationshipsPattern = 67, + RULE_oC_FilterExpression = 68, RULE_oC_IdInColl = 69, RULE_oC_FunctionInvocation = 70, + RULE_oC_FunctionName = 71, RULE_oC_ExplicitProcedureInvocation = 72, RULE_oC_ImplicitProcedureInvocation = 73, + RULE_oC_ProcedureResultField = 74, RULE_oC_ProcedureName = 75, RULE_oC_Namespace = 76, + RULE_oC_ListComprehension = 77, RULE_oC_PatternComprehension = 78, RULE_oC_PropertyLookup = 79, + RULE_oC_CaseExpression = 80, RULE_oC_CaseAlternatives = 81, RULE_oC_Variable = 82, + RULE_oC_NumberLiteral = 83, RULE_oC_MapLiteral = 84, RULE_oC_Parameter = 85, + RULE_oC_PropertyExpression = 86, RULE_oC_PropertyKeyName = 87, RULE_oC_IntegerLiteral = 88, + RULE_oC_DoubleLiteral = 89, RULE_oC_SchemaName = 90, RULE_oC_ReservedWord = 91, + RULE_oC_SymbolicName = 92, RULE_oC_LeftArrowHead = 93, RULE_oC_RightArrowHead = 94, + RULE_oC_Dash = 95; + public static readonly string[] ruleNames = { + "oC_Cypher", "oC_Statement", "oC_Query", "oC_RegularQuery", "oC_Union", + "oC_SingleQuery", "oC_SinglePartQuery", "oC_MultiPartQuery", "oC_UpdatingClause", + "oC_ReadingClause", "oC_Match", "oC_Unwind", "oC_Merge", "oC_MergeAction", + "oC_Create", "oC_Set", "oC_SetItem", "oC_Delete", "oC_Remove", "oC_RemoveItem", + "oC_InQueryCall", "oC_StandaloneCall", "oC_YieldItems", "oC_YieldItem", + "oC_With", "oC_Return", "oC_ReturnBody", "oC_ReturnItems", "oC_ReturnItem", + "oC_Order", "oC_Skip", "oC_Limit", "oC_SortItem", "oC_Where", "oC_Pattern", + "oC_PatternPart", "oC_AnonymousPatternPart", "oC_PatternElement", "oC_NodePattern", + "oC_PatternElementChain", "oC_RelationshipPattern", "oC_RelationshipDetail", + "oC_Properties", "oC_RelationshipTypes", "oC_NodeLabels", "oC_NodeLabel", + "oC_RangeLiteral", "oC_LabelName", "oC_RelTypeName", "oC_Expression", + "oC_OrExpression", "oC_XorExpression", "oC_AndExpression", "oC_NotExpression", + "oC_ComparisonExpression", "oC_AddOrSubtractExpression", "oC_MultiplyDivideModuloExpression", + "oC_PowerOfExpression", "oC_UnaryAddOrSubtractExpression", "oC_StringListNullOperatorExpression", + "oC_PropertyOrLabelsExpression", "oC_Atom", "oC_Literal", "oC_BooleanLiteral", + "oC_ListLiteral", "oC_PartialComparisonExpression", "oC_ParenthesizedExpression", + "oC_RelationshipsPattern", "oC_FilterExpression", "oC_IdInColl", "oC_FunctionInvocation", + "oC_FunctionName", "oC_ExplicitProcedureInvocation", "oC_ImplicitProcedureInvocation", + "oC_ProcedureResultField", "oC_ProcedureName", "oC_Namespace", "oC_ListComprehension", + "oC_PatternComprehension", "oC_PropertyLookup", "oC_CaseExpression", "oC_CaseAlternatives", + "oC_Variable", "oC_NumberLiteral", "oC_MapLiteral", "oC_Parameter", "oC_PropertyExpression", + "oC_PropertyKeyName", "oC_IntegerLiteral", "oC_DoubleLiteral", "oC_SchemaName", + "oC_ReservedWord", "oC_SymbolicName", "oC_LeftArrowHead", "oC_RightArrowHead", + "oC_Dash" + }; + + private static readonly string[] _LiteralNames = { + null, "';'", "','", "'='", "'+='", "'-'", "'*'", "'('", "')'", "'['", + "']'", "':'", "'|'", "'..'", "'+'", "'/'", "'%'", "'^'", "'<>'", "'<'", + "'>'", "'<='", "'>='", "'.'", "'{'", "'}'", "'$'", "'\u00C3\u00A2\u00C5\u00B8\u00C2\u00A8'", + "'\u00C3\u00A3\u00E2\u201A\u00AC\u00CB\u2020'", "'\u00C3\u00AF\u00C2\u00B9\u00C2\u00A4'", + "'\u00C3\u00AF\u00C2\u00BC\u00C5\u201C'", "'\u00C3\u00A2\u00C5\u00B8\u00C2\u00A9'", + "'\u00C3\u00A3\u00E2\u201A\u00AC\u00E2\u20AC\u00B0'", "'\u00C3\u00AF\u00C2\u00B9\u00C2\u00A5'", + "'\u00C3\u00AF\u00C2\u00BC\u00C5\u00BE'", "'\u00C3\u201A\u00C2\u00AD'", + "'\u00C3\u00A2\u00E2\u201A\u00AC\u00C2\uFFFD'", "'\u00C3\u00A2\u00E2\u201A\u00AC\u00E2\u20AC\u02DC'", + "'\u00C3\u00A2\u00E2\u201A\u00AC\u00E2\u20AC\u2122'", "'\u00C3\u00A2\u00E2\u201A\u00AC\u00E2\u20AC\u0153'", + "'\u00C3\u00A2\u00E2\u201A\u00AC\u00E2\u20AC\uFFFD'", "'\u00C3\u00A2\u00E2\u201A\u00AC\u00E2\u20AC\u00A2'", + "'\u00C3\u00A2\u00CB\u2020\u00E2\u20AC\u2122'", "'\u00C3\u00AF\u00C2\u00B9\u00CB\u0153'", + "'\u00C3\u00AF\u00C2\u00B9\u00C2\u00A3'", "'\u00C3\u00AF\u00C2\u00BC\u00C2\uFFFD'", + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, "'0'" + }; + private static readonly string[] _SymbolicNames = { + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, "UNION", "ALL", + "OPTIONAL", "MATCH", "UNWIND", "AS", "MERGE", "ON", "CREATE", "SET", "DETACH", + "DELETE", "REMOVE", "CALL", "YIELD", "WITH", "DISTINCT", "RETURN", "ORDER", + "BY", "L_SKIP", "LIMIT", "ASCENDING", "ASC", "DESCENDING", "DESC", "WHERE", + "OR", "XOR", "AND", "NOT", "IN", "STARTS", "ENDS", "CONTAINS", "IS", "NULL", + "COUNT", "FILTER", "EXTRACT", "ANY", "NONE", "SINGLE", "TRUE", "FALSE", + "EXISTS", "CASE", "ELSE", "END", "WHEN", "THEN", "StringLiteral", "EscapedChar", + "HexInteger", "DecimalInteger", "OctalInteger", "HexLetter", "HexDigit", + "Digit", "NonZeroDigit", "NonZeroOctDigit", "OctDigit", "ZeroDigit", "ExponentDecimalReal", + "RegularDecimalReal", "CONSTRAINT", "DO", "FOR", "REQUIRE", "UNIQUE", + "MANDATORY", "SCALAR", "OF", "ADD", "DROP", "UnescapedSymbolicName", "IdentifierStart", + "IdentifierPart", "EscapedSymbolicName", "SP", "WHITESPACE", "Comment" + }; + public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames); + + [NotNull] + public override IVocabulary Vocabulary + { + get + { + return DefaultVocabulary; + } + } + + public override string GrammarFileName { get { return "Cypher.g4"; } } + + public override string[] RuleNames { get { return ruleNames; } } + + public override string SerializedAtn { get { return new string(_serializedATN); } } + + static CypherParser() { + decisionToDFA = new DFA[_ATN.NumberOfDecisions]; + for (int i = 0; i < _ATN.NumberOfDecisions; i++) { + decisionToDFA[i] = new DFA(_ATN.GetDecisionState(i), i); + } + } + + public CypherParser(ITokenStream input) : this(input, Console.Out, Console.Error) { } + + public CypherParser(ITokenStream input, TextWriter output, TextWriter errorOutput) + : base(input, output, errorOutput) + { + Interpreter = new ParserATNSimulator(this, _ATN, decisionToDFA, sharedContextCache); + } + + public partial class OC_CypherContext : ParserRuleContext { + public OC_StatementContext oC_Statement() { + return GetRuleContext(0); + } + public ITerminalNode Eof() { return GetToken(CypherParser.Eof, 0); } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_CypherContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Cypher; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Cypher(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_CypherContext oC_Cypher() { + OC_CypherContext _localctx = new OC_CypherContext(Context, State); + EnterRule(_localctx, 0, RULE_oC_Cypher); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 193; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 192; Match(SP); + } + } + + State = 195; oC_Statement(); + State = 200; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,2,Context) ) { + case 1: + { + State = 197; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 196; Match(SP); + } + } + + State = 199; Match(T__0); + } + break; + } + State = 203; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 202; Match(SP); + } + } + + State = 205; Match(Eof); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_StatementContext : ParserRuleContext { + public OC_QueryContext oC_Query() { + return GetRuleContext(0); + } + public OC_StatementContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Statement; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Statement(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_StatementContext oC_Statement() { + OC_StatementContext _localctx = new OC_StatementContext(Context, State); + EnterRule(_localctx, 2, RULE_oC_Statement); + try { + EnterOuterAlt(_localctx, 1); + { + State = 207; oC_Query(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_QueryContext : ParserRuleContext { + public OC_RegularQueryContext oC_RegularQuery() { + return GetRuleContext(0); + } + public OC_StandaloneCallContext oC_StandaloneCall() { + return GetRuleContext(0); + } + public OC_QueryContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Query; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Query(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_QueryContext oC_Query() { + OC_QueryContext _localctx = new OC_QueryContext(Context, State); + EnterRule(_localctx, 4, RULE_oC_Query); + try { + State = 211; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,4,Context) ) { + case 1: + EnterOuterAlt(_localctx, 1); + { + State = 209; oC_RegularQuery(); + } + break; + case 2: + EnterOuterAlt(_localctx, 2); + { + State = 210; oC_StandaloneCall(); + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_RegularQueryContext : ParserRuleContext { + public OC_SingleQueryContext oC_SingleQuery() { + return GetRuleContext(0); + } + public OC_UnionContext[] oC_Union() { + return GetRuleContexts(); + } + public OC_UnionContext oC_Union(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_RegularQueryContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_RegularQuery; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_RegularQuery(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_RegularQueryContext oC_RegularQuery() { + OC_RegularQueryContext _localctx = new OC_RegularQueryContext(Context, State); + EnterRule(_localctx, 6, RULE_oC_RegularQuery); + int _la; + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 213; oC_SingleQuery(); + State = 220; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,6,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 215; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 214; Match(SP); + } + } + + State = 217; oC_Union(); + } + } + } + State = 222; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,6,Context); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_UnionContext : ParserRuleContext { + public ITerminalNode UNION() { return GetToken(CypherParser.UNION, 0); } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public ITerminalNode ALL() { return GetToken(CypherParser.ALL, 0); } + public OC_SingleQueryContext oC_SingleQuery() { + return GetRuleContext(0); + } + public OC_UnionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Union; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Union(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_UnionContext oC_Union() { + OC_UnionContext _localctx = new OC_UnionContext(Context, State); + EnterRule(_localctx, 8, RULE_oC_Union); + int _la; + try { + State = 235; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,9,Context) ) { + case 1: + EnterOuterAlt(_localctx, 1); + { + { + State = 223; Match(UNION); + State = 224; Match(SP); + State = 225; Match(ALL); + State = 227; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 226; Match(SP); + } + } + + State = 229; oC_SingleQuery(); + } + } + break; + case 2: + EnterOuterAlt(_localctx, 2); + { + { + State = 230; Match(UNION); + State = 232; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 231; Match(SP); + } + } + + State = 234; oC_SingleQuery(); + } + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_SingleQueryContext : ParserRuleContext { + public OC_SinglePartQueryContext oC_SinglePartQuery() { + return GetRuleContext(0); + } + public OC_MultiPartQueryContext oC_MultiPartQuery() { + return GetRuleContext(0); + } + public OC_SingleQueryContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_SingleQuery; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_SingleQuery(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_SingleQueryContext oC_SingleQuery() { + OC_SingleQueryContext _localctx = new OC_SingleQueryContext(Context, State); + EnterRule(_localctx, 10, RULE_oC_SingleQuery); + try { + State = 239; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,10,Context) ) { + case 1: + EnterOuterAlt(_localctx, 1); + { + State = 237; oC_SinglePartQuery(); + } + break; + case 2: + EnterOuterAlt(_localctx, 2); + { + State = 238; oC_MultiPartQuery(); + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_SinglePartQueryContext : ParserRuleContext { + public OC_ReturnContext oC_Return() { + return GetRuleContext(0); + } + public OC_ReadingClauseContext[] oC_ReadingClause() { + return GetRuleContexts(); + } + public OC_ReadingClauseContext oC_ReadingClause(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_UpdatingClauseContext[] oC_UpdatingClause() { + return GetRuleContexts(); + } + public OC_UpdatingClauseContext oC_UpdatingClause(int i) { + return GetRuleContext(i); + } + public OC_SinglePartQueryContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_SinglePartQuery; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_SinglePartQuery(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_SinglePartQueryContext oC_SinglePartQuery() { + OC_SinglePartQueryContext _localctx = new OC_SinglePartQueryContext(Context, State); + EnterRule(_localctx, 12, RULE_oC_SinglePartQuery); + int _la; + try { + int _alt; + State = 276; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,19,Context) ) { + case 1: + EnterOuterAlt(_localctx, 1); + { + { + State = 247; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << OPTIONAL) | (1L << MATCH) | (1L << UNWIND) | (1L << CALL))) != 0)) { + { + { + State = 241; oC_ReadingClause(); + State = 243; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 242; Match(SP); + } + } + + } + } + State = 249; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + } + State = 250; oC_Return(); + } + } + break; + case 2: + EnterOuterAlt(_localctx, 2); + { + { + State = 257; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << OPTIONAL) | (1L << MATCH) | (1L << UNWIND) | (1L << CALL))) != 0)) { + { + { + State = 251; oC_ReadingClause(); + State = 253; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 252; Match(SP); + } + } + + } + } + State = 259; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + } + State = 260; oC_UpdatingClause(); + State = 267; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,16,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 262; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 261; Match(SP); + } + } + + State = 264; oC_UpdatingClause(); + } + } + } + State = 269; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,16,Context); + } + State = 274; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,18,Context) ) { + case 1: + { + State = 271; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 270; Match(SP); + } + } + + State = 273; oC_Return(); + } + break; + } + } + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_MultiPartQueryContext : ParserRuleContext { + public OC_SinglePartQueryContext oC_SinglePartQuery() { + return GetRuleContext(0); + } + public OC_WithContext[] oC_With() { + return GetRuleContexts(); + } + public OC_WithContext oC_With(int i) { + return GetRuleContext(i); + } + public OC_ReadingClauseContext[] oC_ReadingClause() { + return GetRuleContexts(); + } + public OC_ReadingClauseContext oC_ReadingClause(int i) { + return GetRuleContext(i); + } + public OC_UpdatingClauseContext[] oC_UpdatingClause() { + return GetRuleContexts(); + } + public OC_UpdatingClauseContext oC_UpdatingClause(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_MultiPartQueryContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_MultiPartQuery; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_MultiPartQuery(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_MultiPartQueryContext oC_MultiPartQuery() { + OC_MultiPartQueryContext _localctx = new OC_MultiPartQueryContext(Context, State); + EnterRule(_localctx, 14, RULE_oC_MultiPartQuery); + int _la; + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 300; + ErrorHandler.Sync(this); + _alt = 1; + do { + switch (_alt) { + case 1: + { + { + State = 284; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << OPTIONAL) | (1L << MATCH) | (1L << UNWIND) | (1L << CALL))) != 0)) { + { + { + State = 278; oC_ReadingClause(); + State = 280; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 279; Match(SP); + } + } + + } + } + State = 286; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + } + State = 293; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << MERGE) | (1L << CREATE) | (1L << SET) | (1L << DETACH) | (1L << DELETE) | (1L << REMOVE))) != 0)) { + { + { + State = 287; oC_UpdatingClause(); + State = 289; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 288; Match(SP); + } + } + + } + } + State = 295; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + } + State = 296; oC_With(); + State = 298; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 297; Match(SP); + } + } + + } + } + break; + default: + throw new NoViableAltException(this); + } + State = 302; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,25,Context); + } while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ); + State = 304; oC_SinglePartQuery(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_UpdatingClauseContext : ParserRuleContext { + public OC_CreateContext oC_Create() { + return GetRuleContext(0); + } + public OC_MergeContext oC_Merge() { + return GetRuleContext(0); + } + public OC_DeleteContext oC_Delete() { + return GetRuleContext(0); + } + public OC_SetContext oC_Set() { + return GetRuleContext(0); + } + public OC_RemoveContext oC_Remove() { + return GetRuleContext(0); + } + public OC_UpdatingClauseContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_UpdatingClause; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_UpdatingClause(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_UpdatingClauseContext oC_UpdatingClause() { + OC_UpdatingClauseContext _localctx = new OC_UpdatingClauseContext(Context, State); + EnterRule(_localctx, 16, RULE_oC_UpdatingClause); + try { + State = 311; + ErrorHandler.Sync(this); + switch (TokenStream.LA(1)) { + case CREATE: + EnterOuterAlt(_localctx, 1); + { + State = 306; oC_Create(); + } + break; + case MERGE: + EnterOuterAlt(_localctx, 2); + { + State = 307; oC_Merge(); + } + break; + case DETACH: + case DELETE: + EnterOuterAlt(_localctx, 3); + { + State = 308; oC_Delete(); + } + break; + case SET: + EnterOuterAlt(_localctx, 4); + { + State = 309; oC_Set(); + } + break; + case REMOVE: + EnterOuterAlt(_localctx, 5); + { + State = 310; oC_Remove(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_ReadingClauseContext : ParserRuleContext { + public OC_MatchContext oC_Match() { + return GetRuleContext(0); + } + public OC_UnwindContext oC_Unwind() { + return GetRuleContext(0); + } + public OC_InQueryCallContext oC_InQueryCall() { + return GetRuleContext(0); + } + public OC_ReadingClauseContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_ReadingClause; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_ReadingClause(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_ReadingClauseContext oC_ReadingClause() { + OC_ReadingClauseContext _localctx = new OC_ReadingClauseContext(Context, State); + EnterRule(_localctx, 18, RULE_oC_ReadingClause); + try { + State = 316; + ErrorHandler.Sync(this); + switch (TokenStream.LA(1)) { + case OPTIONAL: + case MATCH: + EnterOuterAlt(_localctx, 1); + { + State = 313; oC_Match(); + } + break; + case UNWIND: + EnterOuterAlt(_localctx, 2); + { + State = 314; oC_Unwind(); + } + break; + case CALL: + EnterOuterAlt(_localctx, 3); + { + State = 315; oC_InQueryCall(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_MatchContext : ParserRuleContext { + public ITerminalNode MATCH() { return GetToken(CypherParser.MATCH, 0); } + public OC_PatternContext oC_Pattern() { + return GetRuleContext(0); + } + public ITerminalNode OPTIONAL() { return GetToken(CypherParser.OPTIONAL, 0); } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_WhereContext oC_Where() { + return GetRuleContext(0); + } + public OC_MatchContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Match; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Match(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_MatchContext oC_Match() { + OC_MatchContext _localctx = new OC_MatchContext(Context, State); + EnterRule(_localctx, 20, RULE_oC_Match); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 320; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==OPTIONAL) { + { + State = 318; Match(OPTIONAL); + State = 319; Match(SP); + } + } + + State = 322; Match(MATCH); + State = 324; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 323; Match(SP); + } + } + + State = 326; oC_Pattern(); + State = 331; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,31,Context) ) { + case 1: + { + State = 328; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 327; Match(SP); + } + } + + State = 330; oC_Where(); + } + break; + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_UnwindContext : ParserRuleContext { + public ITerminalNode UNWIND() { return GetToken(CypherParser.UNWIND, 0); } + public OC_ExpressionContext oC_Expression() { + return GetRuleContext(0); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public ITerminalNode AS() { return GetToken(CypherParser.AS, 0); } + public OC_VariableContext oC_Variable() { + return GetRuleContext(0); + } + public OC_UnwindContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Unwind; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Unwind(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_UnwindContext oC_Unwind() { + OC_UnwindContext _localctx = new OC_UnwindContext(Context, State); + EnterRule(_localctx, 22, RULE_oC_Unwind); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 333; Match(UNWIND); + State = 335; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 334; Match(SP); + } + } + + State = 337; oC_Expression(); + State = 338; Match(SP); + State = 339; Match(AS); + State = 340; Match(SP); + State = 341; oC_Variable(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_MergeContext : ParserRuleContext { + public ITerminalNode MERGE() { return GetToken(CypherParser.MERGE, 0); } + public OC_PatternPartContext oC_PatternPart() { + return GetRuleContext(0); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_MergeActionContext[] oC_MergeAction() { + return GetRuleContexts(); + } + public OC_MergeActionContext oC_MergeAction(int i) { + return GetRuleContext(i); + } + public OC_MergeContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Merge; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Merge(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_MergeContext oC_Merge() { + OC_MergeContext _localctx = new OC_MergeContext(Context, State); + EnterRule(_localctx, 24, RULE_oC_Merge); + int _la; + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 343; Match(MERGE); + State = 345; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 344; Match(SP); + } + } + + State = 347; oC_PatternPart(); + State = 352; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,34,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 348; Match(SP); + State = 349; oC_MergeAction(); + } + } + } + State = 354; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,34,Context); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_MergeActionContext : ParserRuleContext { + public ITerminalNode ON() { return GetToken(CypherParser.ON, 0); } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public ITerminalNode MATCH() { return GetToken(CypherParser.MATCH, 0); } + public OC_SetContext oC_Set() { + return GetRuleContext(0); + } + public ITerminalNode CREATE() { return GetToken(CypherParser.CREATE, 0); } + public OC_MergeActionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_MergeAction; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_MergeAction(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_MergeActionContext oC_MergeAction() { + OC_MergeActionContext _localctx = new OC_MergeActionContext(Context, State); + EnterRule(_localctx, 26, RULE_oC_MergeAction); + try { + State = 365; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,35,Context) ) { + case 1: + EnterOuterAlt(_localctx, 1); + { + { + State = 355; Match(ON); + State = 356; Match(SP); + State = 357; Match(MATCH); + State = 358; Match(SP); + State = 359; oC_Set(); + } + } + break; + case 2: + EnterOuterAlt(_localctx, 2); + { + { + State = 360; Match(ON); + State = 361; Match(SP); + State = 362; Match(CREATE); + State = 363; Match(SP); + State = 364; oC_Set(); + } + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_CreateContext : ParserRuleContext { + public ITerminalNode CREATE() { return GetToken(CypherParser.CREATE, 0); } + public OC_PatternContext oC_Pattern() { + return GetRuleContext(0); + } + public ITerminalNode SP() { return GetToken(CypherParser.SP, 0); } + public OC_CreateContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Create; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Create(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_CreateContext oC_Create() { + OC_CreateContext _localctx = new OC_CreateContext(Context, State); + EnterRule(_localctx, 28, RULE_oC_Create); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 367; Match(CREATE); + State = 369; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 368; Match(SP); + } + } + + State = 371; oC_Pattern(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_SetContext : ParserRuleContext { + public ITerminalNode SET() { return GetToken(CypherParser.SET, 0); } + public OC_SetItemContext[] oC_SetItem() { + return GetRuleContexts(); + } + public OC_SetItemContext oC_SetItem(int i) { + return GetRuleContext(i); + } + public ITerminalNode SP() { return GetToken(CypherParser.SP, 0); } + public OC_SetContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Set; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Set(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_SetContext oC_Set() { + OC_SetContext _localctx = new OC_SetContext(Context, State); + EnterRule(_localctx, 30, RULE_oC_Set); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 373; Match(SET); + State = 375; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 374; Match(SP); + } + } + + State = 377; oC_SetItem(); + State = 382; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + while (_la==T__1) { + { + { + State = 378; Match(T__1); + State = 379; oC_SetItem(); + } + } + State = 384; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_SetItemContext : ParserRuleContext { + public OC_PropertyExpressionContext oC_PropertyExpression() { + return GetRuleContext(0); + } + public OC_ExpressionContext oC_Expression() { + return GetRuleContext(0); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_VariableContext oC_Variable() { + return GetRuleContext(0); + } + public OC_NodeLabelsContext oC_NodeLabels() { + return GetRuleContext(0); + } + public OC_SetItemContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_SetItem; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_SetItem(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_SetItemContext oC_SetItem() { + OC_SetItemContext _localctx = new OC_SetItemContext(Context, State); + EnterRule(_localctx, 32, RULE_oC_SetItem); + int _la; + try { + State = 421; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,46,Context) ) { + case 1: + EnterOuterAlt(_localctx, 1); + { + { + State = 385; oC_PropertyExpression(); + State = 387; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 386; Match(SP); + } + } + + State = 389; Match(T__2); + State = 391; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 390; Match(SP); + } + } + + State = 393; oC_Expression(); + } + } + break; + case 2: + EnterOuterAlt(_localctx, 2); + { + { + State = 395; oC_Variable(); + State = 397; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 396; Match(SP); + } + } + + State = 399; Match(T__2); + State = 401; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 400; Match(SP); + } + } + + State = 403; oC_Expression(); + } + } + break; + case 3: + EnterOuterAlt(_localctx, 3); + { + { + State = 405; oC_Variable(); + State = 407; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 406; Match(SP); + } + } + + State = 409; Match(T__3); + State = 411; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 410; Match(SP); + } + } + + State = 413; oC_Expression(); + } + } + break; + case 4: + EnterOuterAlt(_localctx, 4); + { + { + State = 415; oC_Variable(); + State = 417; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 416; Match(SP); + } + } + + State = 419; oC_NodeLabels(); + } + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_DeleteContext : ParserRuleContext { + public ITerminalNode DELETE() { return GetToken(CypherParser.DELETE, 0); } + public OC_ExpressionContext[] oC_Expression() { + return GetRuleContexts(); + } + public OC_ExpressionContext oC_Expression(int i) { + return GetRuleContext(i); + } + public ITerminalNode DETACH() { return GetToken(CypherParser.DETACH, 0); } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_DeleteContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Delete; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Delete(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_DeleteContext oC_Delete() { + OC_DeleteContext _localctx = new OC_DeleteContext(Context, State); + EnterRule(_localctx, 34, RULE_oC_Delete); + int _la; + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 425; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==DETACH) { + { + State = 423; Match(DETACH); + State = 424; Match(SP); + } + } + + State = 427; Match(DELETE); + State = 429; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 428; Match(SP); + } + } + + State = 431; oC_Expression(); + State = 442; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,51,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 433; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 432; Match(SP); + } + } + + State = 435; Match(T__1); + State = 437; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 436; Match(SP); + } + } + + State = 439; oC_Expression(); + } + } + } + State = 444; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,51,Context); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_RemoveContext : ParserRuleContext { + public ITerminalNode REMOVE() { return GetToken(CypherParser.REMOVE, 0); } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_RemoveItemContext[] oC_RemoveItem() { + return GetRuleContexts(); + } + public OC_RemoveItemContext oC_RemoveItem(int i) { + return GetRuleContext(i); + } + public OC_RemoveContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Remove; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Remove(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_RemoveContext oC_Remove() { + OC_RemoveContext _localctx = new OC_RemoveContext(Context, State); + EnterRule(_localctx, 36, RULE_oC_Remove); + int _la; + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 445; Match(REMOVE); + State = 446; Match(SP); + State = 447; oC_RemoveItem(); + State = 458; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,54,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 449; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 448; Match(SP); + } + } + + State = 451; Match(T__1); + State = 453; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 452; Match(SP); + } + } + + State = 455; oC_RemoveItem(); + } + } + } + State = 460; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,54,Context); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_RemoveItemContext : ParserRuleContext { + public OC_VariableContext oC_Variable() { + return GetRuleContext(0); + } + public OC_NodeLabelsContext oC_NodeLabels() { + return GetRuleContext(0); + } + public OC_PropertyExpressionContext oC_PropertyExpression() { + return GetRuleContext(0); + } + public OC_RemoveItemContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_RemoveItem; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_RemoveItem(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_RemoveItemContext oC_RemoveItem() { + OC_RemoveItemContext _localctx = new OC_RemoveItemContext(Context, State); + EnterRule(_localctx, 38, RULE_oC_RemoveItem); + try { + State = 465; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,55,Context) ) { + case 1: + EnterOuterAlt(_localctx, 1); + { + { + State = 461; oC_Variable(); + State = 462; oC_NodeLabels(); + } + } + break; + case 2: + EnterOuterAlt(_localctx, 2); + { + State = 464; oC_PropertyExpression(); + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_InQueryCallContext : ParserRuleContext { + public ITerminalNode CALL() { return GetToken(CypherParser.CALL, 0); } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_ExplicitProcedureInvocationContext oC_ExplicitProcedureInvocation() { + return GetRuleContext(0); + } + public ITerminalNode YIELD() { return GetToken(CypherParser.YIELD, 0); } + public OC_YieldItemsContext oC_YieldItems() { + return GetRuleContext(0); + } + public OC_InQueryCallContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_InQueryCall; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_InQueryCall(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_InQueryCallContext oC_InQueryCall() { + OC_InQueryCallContext _localctx = new OC_InQueryCallContext(Context, State); + EnterRule(_localctx, 40, RULE_oC_InQueryCall); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 467; Match(CALL); + State = 468; Match(SP); + State = 469; oC_ExplicitProcedureInvocation(); + State = 476; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,57,Context) ) { + case 1: + { + State = 471; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 470; Match(SP); + } + } + + State = 473; Match(YIELD); + State = 474; Match(SP); + State = 475; oC_YieldItems(); + } + break; + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_StandaloneCallContext : ParserRuleContext { + public ITerminalNode CALL() { return GetToken(CypherParser.CALL, 0); } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_ExplicitProcedureInvocationContext oC_ExplicitProcedureInvocation() { + return GetRuleContext(0); + } + public OC_ImplicitProcedureInvocationContext oC_ImplicitProcedureInvocation() { + return GetRuleContext(0); + } + public ITerminalNode YIELD() { return GetToken(CypherParser.YIELD, 0); } + public OC_YieldItemsContext oC_YieldItems() { + return GetRuleContext(0); + } + public OC_StandaloneCallContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_StandaloneCall; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_StandaloneCall(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_StandaloneCallContext oC_StandaloneCall() { + OC_StandaloneCallContext _localctx = new OC_StandaloneCallContext(Context, State); + EnterRule(_localctx, 42, RULE_oC_StandaloneCall); + try { + EnterOuterAlt(_localctx, 1); + { + State = 478; Match(CALL); + State = 479; Match(SP); + State = 482; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,58,Context) ) { + case 1: + { + State = 480; oC_ExplicitProcedureInvocation(); + } + break; + case 2: + { + State = 481; oC_ImplicitProcedureInvocation(); + } + break; + } + State = 488; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,59,Context) ) { + case 1: + { + State = 484; Match(SP); + State = 485; Match(YIELD); + State = 486; Match(SP); + State = 487; oC_YieldItems(); + } + break; + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_YieldItemsContext : ParserRuleContext { + public OC_YieldItemContext[] oC_YieldItem() { + return GetRuleContexts(); + } + public OC_YieldItemContext oC_YieldItem(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_YieldItemsContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_YieldItems; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_YieldItems(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_YieldItemsContext oC_YieldItems() { + OC_YieldItemsContext _localctx = new OC_YieldItemsContext(Context, State); + EnterRule(_localctx, 44, RULE_oC_YieldItems); + int _la; + try { + int _alt; + State = 505; + ErrorHandler.Sync(this); + switch (TokenStream.LA(1)) { + case COUNT: + case FILTER: + case EXTRACT: + case ANY: + case NONE: + case SINGLE: + case HexLetter: + case UnescapedSymbolicName: + case EscapedSymbolicName: + EnterOuterAlt(_localctx, 1); + { + { + State = 490; oC_YieldItem(); + State = 501; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,62,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 492; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 491; Match(SP); + } + } + + State = 494; Match(T__1); + State = 496; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 495; Match(SP); + } + } + + State = 498; oC_YieldItem(); + } + } + } + State = 503; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,62,Context); + } + } + } + break; + case T__4: + EnterOuterAlt(_localctx, 2); + { + State = 504; Match(T__4); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_YieldItemContext : ParserRuleContext { + public OC_VariableContext oC_Variable() { + return GetRuleContext(0); + } + public OC_ProcedureResultFieldContext oC_ProcedureResultField() { + return GetRuleContext(0); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public ITerminalNode AS() { return GetToken(CypherParser.AS, 0); } + public OC_YieldItemContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_YieldItem; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_YieldItem(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_YieldItemContext oC_YieldItem() { + OC_YieldItemContext _localctx = new OC_YieldItemContext(Context, State); + EnterRule(_localctx, 46, RULE_oC_YieldItem); + try { + EnterOuterAlt(_localctx, 1); + { + State = 512; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,64,Context) ) { + case 1: + { + State = 507; oC_ProcedureResultField(); + State = 508; Match(SP); + State = 509; Match(AS); + State = 510; Match(SP); + } + break; + } + State = 514; oC_Variable(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_WithContext : ParserRuleContext { + public ITerminalNode WITH() { return GetToken(CypherParser.WITH, 0); } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_ReturnBodyContext oC_ReturnBody() { + return GetRuleContext(0); + } + public ITerminalNode DISTINCT() { return GetToken(CypherParser.DISTINCT, 0); } + public OC_WhereContext oC_Where() { + return GetRuleContext(0); + } + public OC_WithContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_With; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_With(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_WithContext oC_With() { + OC_WithContext _localctx = new OC_WithContext(Context, State); + EnterRule(_localctx, 48, RULE_oC_With); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 516; Match(WITH); + State = 521; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,66,Context) ) { + case 1: + { + State = 518; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 517; Match(SP); + } + } + + State = 520; Match(DISTINCT); + } + break; + } + State = 523; Match(SP); + State = 524; oC_ReturnBody(); + State = 529; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,68,Context) ) { + case 1: + { + State = 526; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 525; Match(SP); + } + } + + State = 528; oC_Where(); + } + break; + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_ReturnContext : ParserRuleContext { + public ITerminalNode RETURN() { return GetToken(CypherParser.RETURN, 0); } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_ReturnBodyContext oC_ReturnBody() { + return GetRuleContext(0); + } + public ITerminalNode DISTINCT() { return GetToken(CypherParser.DISTINCT, 0); } + public OC_ReturnContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Return; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Return(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_ReturnContext oC_Return() { + OC_ReturnContext _localctx = new OC_ReturnContext(Context, State); + EnterRule(_localctx, 50, RULE_oC_Return); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 531; Match(RETURN); + State = 536; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,70,Context) ) { + case 1: + { + State = 533; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 532; Match(SP); + } + } + + State = 535; Match(DISTINCT); + } + break; + } + State = 538; Match(SP); + State = 539; oC_ReturnBody(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_ReturnBodyContext : ParserRuleContext { + public OC_ReturnItemsContext oC_ReturnItems() { + return GetRuleContext(0); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_OrderContext oC_Order() { + return GetRuleContext(0); + } + public OC_SkipContext oC_Skip() { + return GetRuleContext(0); + } + public OC_LimitContext oC_Limit() { + return GetRuleContext(0); + } + public OC_ReturnBodyContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_ReturnBody; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_ReturnBody(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_ReturnBodyContext oC_ReturnBody() { + OC_ReturnBodyContext _localctx = new OC_ReturnBodyContext(Context, State); + EnterRule(_localctx, 52, RULE_oC_ReturnBody); + try { + EnterOuterAlt(_localctx, 1); + { + State = 541; oC_ReturnItems(); + State = 544; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,71,Context) ) { + case 1: + { + State = 542; Match(SP); + State = 543; oC_Order(); + } + break; + } + State = 548; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,72,Context) ) { + case 1: + { + State = 546; Match(SP); + State = 547; oC_Skip(); + } + break; + } + State = 552; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,73,Context) ) { + case 1: + { + State = 550; Match(SP); + State = 551; oC_Limit(); + } + break; + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_ReturnItemsContext : ParserRuleContext { + public OC_ReturnItemContext[] oC_ReturnItem() { + return GetRuleContexts(); + } + public OC_ReturnItemContext oC_ReturnItem(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_ReturnItemsContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_ReturnItems; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_ReturnItems(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_ReturnItemsContext oC_ReturnItems() { + OC_ReturnItemsContext _localctx = new OC_ReturnItemsContext(Context, State); + EnterRule(_localctx, 54, RULE_oC_ReturnItems); + int _la; + try { + int _alt; + State = 582; + ErrorHandler.Sync(this); + switch (TokenStream.LA(1)) { + case T__5: + EnterOuterAlt(_localctx, 1); + { + { + State = 554; Match(T__5); + State = 565; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,76,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 556; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 555; Match(SP); + } + } + + State = 558; Match(T__1); + State = 560; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 559; Match(SP); + } + } + + State = 562; oC_ReturnItem(); + } + } + } + State = 567; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,76,Context); + } + } + } + break; + case T__4: + case T__6: + case T__8: + case T__13: + case T__23: + case T__25: + case ALL: + case NOT: + case NULL: + case COUNT: + case FILTER: + case EXTRACT: + case ANY: + case NONE: + case SINGLE: + case TRUE: + case FALSE: + case EXISTS: + case CASE: + case StringLiteral: + case HexInteger: + case DecimalInteger: + case OctalInteger: + case HexLetter: + case ExponentDecimalReal: + case RegularDecimalReal: + case UnescapedSymbolicName: + case EscapedSymbolicName: + EnterOuterAlt(_localctx, 2); + { + { + State = 568; oC_ReturnItem(); + State = 579; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,79,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 570; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 569; Match(SP); + } + } + + State = 572; Match(T__1); + State = 574; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 573; Match(SP); + } + } + + State = 576; oC_ReturnItem(); + } + } + } + State = 581; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,79,Context); + } + } + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_ReturnItemContext : ParserRuleContext { + public OC_ExpressionContext oC_Expression() { + return GetRuleContext(0); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public ITerminalNode AS() { return GetToken(CypherParser.AS, 0); } + public OC_VariableContext oC_Variable() { + return GetRuleContext(0); + } + public OC_ReturnItemContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_ReturnItem; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_ReturnItem(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_ReturnItemContext oC_ReturnItem() { + OC_ReturnItemContext _localctx = new OC_ReturnItemContext(Context, State); + EnterRule(_localctx, 56, RULE_oC_ReturnItem); + try { + State = 591; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,81,Context) ) { + case 1: + EnterOuterAlt(_localctx, 1); + { + { + State = 584; oC_Expression(); + State = 585; Match(SP); + State = 586; Match(AS); + State = 587; Match(SP); + State = 588; oC_Variable(); + } + } + break; + case 2: + EnterOuterAlt(_localctx, 2); + { + State = 590; oC_Expression(); + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_OrderContext : ParserRuleContext { + public ITerminalNode ORDER() { return GetToken(CypherParser.ORDER, 0); } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public ITerminalNode BY() { return GetToken(CypherParser.BY, 0); } + public OC_SortItemContext[] oC_SortItem() { + return GetRuleContexts(); + } + public OC_SortItemContext oC_SortItem(int i) { + return GetRuleContext(i); + } + public OC_OrderContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Order; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Order(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_OrderContext oC_Order() { + OC_OrderContext _localctx = new OC_OrderContext(Context, State); + EnterRule(_localctx, 58, RULE_oC_Order); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 593; Match(ORDER); + State = 594; Match(SP); + State = 595; Match(BY); + State = 596; Match(SP); + State = 597; oC_SortItem(); + State = 605; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + while (_la==T__1) { + { + { + State = 598; Match(T__1); + State = 600; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 599; Match(SP); + } + } + + State = 602; oC_SortItem(); + } + } + State = 607; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_SkipContext : ParserRuleContext { + public ITerminalNode L_SKIP() { return GetToken(CypherParser.L_SKIP, 0); } + public ITerminalNode SP() { return GetToken(CypherParser.SP, 0); } + public OC_ExpressionContext oC_Expression() { + return GetRuleContext(0); + } + public OC_SkipContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Skip; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Skip(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_SkipContext oC_Skip() { + OC_SkipContext _localctx = new OC_SkipContext(Context, State); + EnterRule(_localctx, 60, RULE_oC_Skip); + try { + EnterOuterAlt(_localctx, 1); + { + State = 608; Match(L_SKIP); + State = 609; Match(SP); + State = 610; oC_Expression(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_LimitContext : ParserRuleContext { + public ITerminalNode LIMIT() { return GetToken(CypherParser.LIMIT, 0); } + public ITerminalNode SP() { return GetToken(CypherParser.SP, 0); } + public OC_ExpressionContext oC_Expression() { + return GetRuleContext(0); + } + public OC_LimitContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Limit; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Limit(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_LimitContext oC_Limit() { + OC_LimitContext _localctx = new OC_LimitContext(Context, State); + EnterRule(_localctx, 62, RULE_oC_Limit); + try { + EnterOuterAlt(_localctx, 1); + { + State = 612; Match(LIMIT); + State = 613; Match(SP); + State = 614; oC_Expression(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_SortItemContext : ParserRuleContext { + public OC_ExpressionContext oC_Expression() { + return GetRuleContext(0); + } + public ITerminalNode ASCENDING() { return GetToken(CypherParser.ASCENDING, 0); } + public ITerminalNode ASC() { return GetToken(CypherParser.ASC, 0); } + public ITerminalNode DESCENDING() { return GetToken(CypherParser.DESCENDING, 0); } + public ITerminalNode DESC() { return GetToken(CypherParser.DESC, 0); } + public ITerminalNode SP() { return GetToken(CypherParser.SP, 0); } + public OC_SortItemContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_SortItem; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_SortItem(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_SortItemContext oC_SortItem() { + OC_SortItemContext _localctx = new OC_SortItemContext(Context, State); + EnterRule(_localctx, 64, RULE_oC_SortItem); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 616; oC_Expression(); + State = 621; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,85,Context) ) { + case 1: + { + State = 618; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 617; Match(SP); + } + } + + State = 620; + _la = TokenStream.LA(1); + if ( !(((((_la - 68)) & ~0x3f) == 0 && ((1L << (_la - 68)) & ((1L << (ASCENDING - 68)) | (1L << (ASC - 68)) | (1L << (DESCENDING - 68)) | (1L << (DESC - 68)))) != 0)) ) { + ErrorHandler.RecoverInline(this); + } + else { + ErrorHandler.ReportMatch(this); + Consume(); + } + } + break; + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_WhereContext : ParserRuleContext { + public ITerminalNode WHERE() { return GetToken(CypherParser.WHERE, 0); } + public ITerminalNode SP() { return GetToken(CypherParser.SP, 0); } + public OC_ExpressionContext oC_Expression() { + return GetRuleContext(0); + } + public OC_WhereContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Where; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Where(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_WhereContext oC_Where() { + OC_WhereContext _localctx = new OC_WhereContext(Context, State); + EnterRule(_localctx, 66, RULE_oC_Where); + try { + EnterOuterAlt(_localctx, 1); + { + State = 623; Match(WHERE); + State = 624; Match(SP); + State = 625; oC_Expression(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_PatternContext : ParserRuleContext { + public OC_PatternPartContext[] oC_PatternPart() { + return GetRuleContexts(); + } + public OC_PatternPartContext oC_PatternPart(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_PatternContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Pattern; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Pattern(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_PatternContext oC_Pattern() { + OC_PatternContext _localctx = new OC_PatternContext(Context, State); + EnterRule(_localctx, 68, RULE_oC_Pattern); + int _la; + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 627; oC_PatternPart(); + State = 638; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,88,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 629; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 628; Match(SP); + } + } + + State = 631; Match(T__1); + State = 633; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 632; Match(SP); + } + } + + State = 635; oC_PatternPart(); + } + } + } + State = 640; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,88,Context); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_PatternPartContext : ParserRuleContext { + public OC_VariableContext oC_Variable() { + return GetRuleContext(0); + } + public OC_AnonymousPatternPartContext oC_AnonymousPatternPart() { + return GetRuleContext(0); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_PatternPartContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_PatternPart; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_PatternPart(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_PatternPartContext oC_PatternPart() { + OC_PatternPartContext _localctx = new OC_PatternPartContext(Context, State); + EnterRule(_localctx, 70, RULE_oC_PatternPart); + int _la; + try { + State = 652; + ErrorHandler.Sync(this); + switch (TokenStream.LA(1)) { + case COUNT: + case FILTER: + case EXTRACT: + case ANY: + case NONE: + case SINGLE: + case HexLetter: + case UnescapedSymbolicName: + case EscapedSymbolicName: + EnterOuterAlt(_localctx, 1); + { + { + State = 641; oC_Variable(); + State = 643; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 642; Match(SP); + } + } + + State = 645; Match(T__2); + State = 647; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 646; Match(SP); + } + } + + State = 649; oC_AnonymousPatternPart(); + } + } + break; + case T__6: + EnterOuterAlt(_localctx, 2); + { + State = 651; oC_AnonymousPatternPart(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_AnonymousPatternPartContext : ParserRuleContext { + public OC_PatternElementContext oC_PatternElement() { + return GetRuleContext(0); + } + public OC_AnonymousPatternPartContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_AnonymousPatternPart; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_AnonymousPatternPart(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_AnonymousPatternPartContext oC_AnonymousPatternPart() { + OC_AnonymousPatternPartContext _localctx = new OC_AnonymousPatternPartContext(Context, State); + EnterRule(_localctx, 72, RULE_oC_AnonymousPatternPart); + try { + EnterOuterAlt(_localctx, 1); + { + State = 654; oC_PatternElement(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_PatternElementContext : ParserRuleContext { + public OC_NodePatternContext oC_NodePattern() { + return GetRuleContext(0); + } + public OC_PatternElementChainContext[] oC_PatternElementChain() { + return GetRuleContexts(); + } + public OC_PatternElementChainContext oC_PatternElementChain(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_PatternElementContext oC_PatternElement() { + return GetRuleContext(0); + } + public OC_PatternElementContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_PatternElement; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_PatternElement(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_PatternElementContext oC_PatternElement() { + OC_PatternElementContext _localctx = new OC_PatternElementContext(Context, State); + EnterRule(_localctx, 74, RULE_oC_PatternElement); + int _la; + try { + int _alt; + State = 670; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,94,Context) ) { + case 1: + EnterOuterAlt(_localctx, 1); + { + { + State = 656; oC_NodePattern(); + State = 663; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,93,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 658; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 657; Match(SP); + } + } + + State = 660; oC_PatternElementChain(); + } + } + } + State = 665; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,93,Context); + } + } + } + break; + case 2: + EnterOuterAlt(_localctx, 2); + { + { + State = 666; Match(T__6); + State = 667; oC_PatternElement(); + State = 668; Match(T__7); + } + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_NodePatternContext : ParserRuleContext { + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_VariableContext oC_Variable() { + return GetRuleContext(0); + } + public OC_NodeLabelsContext oC_NodeLabels() { + return GetRuleContext(0); + } + public OC_PropertiesContext oC_Properties() { + return GetRuleContext(0); + } + public OC_NodePatternContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_NodePattern; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_NodePattern(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_NodePatternContext oC_NodePattern() { + OC_NodePatternContext _localctx = new OC_NodePatternContext(Context, State); + EnterRule(_localctx, 76, RULE_oC_NodePattern); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 672; Match(T__6); + State = 674; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 673; Match(SP); + } + } + + State = 680; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (((((_la - 83)) & ~0x3f) == 0 && ((1L << (_la - 83)) & ((1L << (COUNT - 83)) | (1L << (FILTER - 83)) | (1L << (EXTRACT - 83)) | (1L << (ANY - 83)) | (1L << (NONE - 83)) | (1L << (SINGLE - 83)) | (1L << (HexLetter - 83)) | (1L << (UnescapedSymbolicName - 83)) | (1L << (EscapedSymbolicName - 83)))) != 0)) { + { + State = 676; oC_Variable(); + State = 678; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 677; Match(SP); + } + } + + } + } + + State = 686; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==T__10) { + { + State = 682; oC_NodeLabels(); + State = 684; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 683; Match(SP); + } + } + + } + } + + State = 692; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==T__23 || _la==T__25) { + { + State = 688; oC_Properties(); + State = 690; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 689; Match(SP); + } + } + + } + } + + State = 694; Match(T__7); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_PatternElementChainContext : ParserRuleContext { + public OC_RelationshipPatternContext oC_RelationshipPattern() { + return GetRuleContext(0); + } + public OC_NodePatternContext oC_NodePattern() { + return GetRuleContext(0); + } + public ITerminalNode SP() { return GetToken(CypherParser.SP, 0); } + public OC_PatternElementChainContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_PatternElementChain; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_PatternElementChain(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_PatternElementChainContext oC_PatternElementChain() { + OC_PatternElementChainContext _localctx = new OC_PatternElementChainContext(Context, State); + EnterRule(_localctx, 78, RULE_oC_PatternElementChain); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 696; oC_RelationshipPattern(); + State = 698; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 697; Match(SP); + } + } + + State = 700; oC_NodePattern(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_RelationshipPatternContext : ParserRuleContext { + public OC_LeftArrowHeadContext oC_LeftArrowHead() { + return GetRuleContext(0); + } + public OC_DashContext[] oC_Dash() { + return GetRuleContexts(); + } + public OC_DashContext oC_Dash(int i) { + return GetRuleContext(i); + } + public OC_RightArrowHeadContext oC_RightArrowHead() { + return GetRuleContext(0); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_RelationshipDetailContext oC_RelationshipDetail() { + return GetRuleContext(0); + } + public OC_RelationshipPatternContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_RelationshipPattern; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_RelationshipPattern(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_RelationshipPatternContext oC_RelationshipPattern() { + OC_RelationshipPatternContext _localctx = new OC_RelationshipPatternContext(Context, State); + EnterRule(_localctx, 80, RULE_oC_RelationshipPattern); + int _la; + try { + State = 766; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,119,Context) ) { + case 1: + EnterOuterAlt(_localctx, 1); + { + { + State = 702; oC_LeftArrowHead(); + State = 704; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 703; Match(SP); + } + } + + State = 706; oC_Dash(); + State = 708; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,104,Context) ) { + case 1: + { + State = 707; Match(SP); + } + break; + } + State = 711; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==T__8) { + { + State = 710; oC_RelationshipDetail(); + } + } + + State = 714; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 713; Match(SP); + } + } + + State = 716; oC_Dash(); + State = 718; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 717; Match(SP); + } + } + + State = 720; oC_RightArrowHead(); + } + } + break; + case 2: + EnterOuterAlt(_localctx, 2); + { + { + State = 722; oC_LeftArrowHead(); + State = 724; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 723; Match(SP); + } + } + + State = 726; oC_Dash(); + State = 728; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,109,Context) ) { + case 1: + { + State = 727; Match(SP); + } + break; + } + State = 731; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==T__8) { + { + State = 730; oC_RelationshipDetail(); + } + } + + State = 734; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 733; Match(SP); + } + } + + State = 736; oC_Dash(); + } + } + break; + case 3: + EnterOuterAlt(_localctx, 3); + { + { + State = 738; oC_Dash(); + State = 740; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,112,Context) ) { + case 1: + { + State = 739; Match(SP); + } + break; + } + State = 743; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==T__8) { + { + State = 742; oC_RelationshipDetail(); + } + } + + State = 746; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 745; Match(SP); + } + } + + State = 748; oC_Dash(); + State = 750; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 749; Match(SP); + } + } + + State = 752; oC_RightArrowHead(); + } + } + break; + case 4: + EnterOuterAlt(_localctx, 4); + { + { + State = 754; oC_Dash(); + State = 756; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,116,Context) ) { + case 1: + { + State = 755; Match(SP); + } + break; + } + State = 759; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==T__8) { + { + State = 758; oC_RelationshipDetail(); + } + } + + State = 762; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 761; Match(SP); + } + } + + State = 764; oC_Dash(); + } + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_RelationshipDetailContext : ParserRuleContext { + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_VariableContext oC_Variable() { + return GetRuleContext(0); + } + public OC_RelationshipTypesContext oC_RelationshipTypes() { + return GetRuleContext(0); + } + public OC_RangeLiteralContext oC_RangeLiteral() { + return GetRuleContext(0); + } + public OC_PropertiesContext oC_Properties() { + return GetRuleContext(0); + } + public OC_RelationshipDetailContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_RelationshipDetail; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_RelationshipDetail(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_RelationshipDetailContext oC_RelationshipDetail() { + OC_RelationshipDetailContext _localctx = new OC_RelationshipDetailContext(Context, State); + EnterRule(_localctx, 82, RULE_oC_RelationshipDetail); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 768; Match(T__8); + State = 770; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 769; Match(SP); + } + } + + State = 776; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (((((_la - 83)) & ~0x3f) == 0 && ((1L << (_la - 83)) & ((1L << (COUNT - 83)) | (1L << (FILTER - 83)) | (1L << (EXTRACT - 83)) | (1L << (ANY - 83)) | (1L << (NONE - 83)) | (1L << (SINGLE - 83)) | (1L << (HexLetter - 83)) | (1L << (UnescapedSymbolicName - 83)) | (1L << (EscapedSymbolicName - 83)))) != 0)) { + { + State = 772; oC_Variable(); + State = 774; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 773; Match(SP); + } + } + + } + } + + State = 782; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==T__10) { + { + State = 778; oC_RelationshipTypes(); + State = 780; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 779; Match(SP); + } + } + + } + } + + State = 785; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==T__5) { + { + State = 784; oC_RangeLiteral(); + } + } + + State = 791; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==T__23 || _la==T__25) { + { + State = 787; oC_Properties(); + State = 789; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 788; Match(SP); + } + } + + } + } + + State = 793; Match(T__9); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_PropertiesContext : ParserRuleContext { + public OC_MapLiteralContext oC_MapLiteral() { + return GetRuleContext(0); + } + public OC_ParameterContext oC_Parameter() { + return GetRuleContext(0); + } + public OC_PropertiesContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Properties; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Properties(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_PropertiesContext oC_Properties() { + OC_PropertiesContext _localctx = new OC_PropertiesContext(Context, State); + EnterRule(_localctx, 84, RULE_oC_Properties); + try { + State = 797; + ErrorHandler.Sync(this); + switch (TokenStream.LA(1)) { + case T__23: + EnterOuterAlt(_localctx, 1); + { + State = 795; oC_MapLiteral(); + } + break; + case T__25: + EnterOuterAlt(_localctx, 2); + { + State = 796; oC_Parameter(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_RelationshipTypesContext : ParserRuleContext { + public OC_RelTypeNameContext[] oC_RelTypeName() { + return GetRuleContexts(); + } + public OC_RelTypeNameContext oC_RelTypeName(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_RelationshipTypesContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_RelationshipTypes; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_RelationshipTypes(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_RelationshipTypesContext oC_RelationshipTypes() { + OC_RelationshipTypesContext _localctx = new OC_RelationshipTypesContext(Context, State); + EnterRule(_localctx, 86, RULE_oC_RelationshipTypes); + int _la; + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 799; Match(T__10); + State = 801; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 800; Match(SP); + } + } + + State = 803; oC_RelTypeName(); + State = 817; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,133,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 805; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 804; Match(SP); + } + } + + State = 807; Match(T__11); + State = 809; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==T__10) { + { + State = 808; Match(T__10); + } + } + + State = 812; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 811; Match(SP); + } + } + + State = 814; oC_RelTypeName(); + } + } + } + State = 819; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,133,Context); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_NodeLabelsContext : ParserRuleContext { + public OC_NodeLabelContext[] oC_NodeLabel() { + return GetRuleContexts(); + } + public OC_NodeLabelContext oC_NodeLabel(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_NodeLabelsContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_NodeLabels; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_NodeLabels(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_NodeLabelsContext oC_NodeLabels() { + OC_NodeLabelsContext _localctx = new OC_NodeLabelsContext(Context, State); + EnterRule(_localctx, 88, RULE_oC_NodeLabels); + int _la; + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 820; oC_NodeLabel(); + State = 827; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,135,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 822; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 821; Match(SP); + } + } + + State = 824; oC_NodeLabel(); + } + } + } + State = 829; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,135,Context); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_NodeLabelContext : ParserRuleContext { + public OC_LabelNameContext oC_LabelName() { + return GetRuleContext(0); + } + public ITerminalNode SP() { return GetToken(CypherParser.SP, 0); } + public OC_NodeLabelContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_NodeLabel; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_NodeLabel(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_NodeLabelContext oC_NodeLabel() { + OC_NodeLabelContext _localctx = new OC_NodeLabelContext(Context, State); + EnterRule(_localctx, 90, RULE_oC_NodeLabel); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 830; Match(T__10); + State = 832; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 831; Match(SP); + } + } + + State = 834; oC_LabelName(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_RangeLiteralContext : ParserRuleContext { + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_IntegerLiteralContext[] oC_IntegerLiteral() { + return GetRuleContexts(); + } + public OC_IntegerLiteralContext oC_IntegerLiteral(int i) { + return GetRuleContext(i); + } + public OC_RangeLiteralContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_RangeLiteral; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_RangeLiteral(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_RangeLiteralContext oC_RangeLiteral() { + OC_RangeLiteralContext _localctx = new OC_RangeLiteralContext(Context, State); + EnterRule(_localctx, 92, RULE_oC_RangeLiteral); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 836; Match(T__5); + State = 838; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 837; Match(SP); + } + } + + State = 844; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (((((_la - 99)) & ~0x3f) == 0 && ((1L << (_la - 99)) & ((1L << (HexInteger - 99)) | (1L << (DecimalInteger - 99)) | (1L << (OctalInteger - 99)))) != 0)) { + { + State = 840; oC_IntegerLiteral(); + State = 842; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 841; Match(SP); + } + } + + } + } + + State = 856; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==T__12) { + { + State = 846; Match(T__12); + State = 848; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 847; Match(SP); + } + } + + State = 854; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (((((_la - 99)) & ~0x3f) == 0 && ((1L << (_la - 99)) & ((1L << (HexInteger - 99)) | (1L << (DecimalInteger - 99)) | (1L << (OctalInteger - 99)))) != 0)) { + { + State = 850; oC_IntegerLiteral(); + State = 852; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 851; Match(SP); + } + } + + } + } + + } + } + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_LabelNameContext : ParserRuleContext { + public OC_SchemaNameContext oC_SchemaName() { + return GetRuleContext(0); + } + public OC_LabelNameContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_LabelName; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_LabelName(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_LabelNameContext oC_LabelName() { + OC_LabelNameContext _localctx = new OC_LabelNameContext(Context, State); + EnterRule(_localctx, 94, RULE_oC_LabelName); + try { + EnterOuterAlt(_localctx, 1); + { + State = 858; oC_SchemaName(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_RelTypeNameContext : ParserRuleContext { + public OC_SchemaNameContext oC_SchemaName() { + return GetRuleContext(0); + } + public OC_RelTypeNameContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_RelTypeName; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_RelTypeName(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_RelTypeNameContext oC_RelTypeName() { + OC_RelTypeNameContext _localctx = new OC_RelTypeNameContext(Context, State); + EnterRule(_localctx, 96, RULE_oC_RelTypeName); + try { + EnterOuterAlt(_localctx, 1); + { + State = 860; oC_SchemaName(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_ExpressionContext : ParserRuleContext { + public OC_OrExpressionContext oC_OrExpression() { + return GetRuleContext(0); + } + public OC_ExpressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Expression; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Expression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_ExpressionContext oC_Expression() { + OC_ExpressionContext _localctx = new OC_ExpressionContext(Context, State); + EnterRule(_localctx, 98, RULE_oC_Expression); + try { + EnterOuterAlt(_localctx, 1); + { + State = 862; oC_OrExpression(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_OrExpressionContext : ParserRuleContext { + public OC_XorExpressionContext[] oC_XorExpression() { + return GetRuleContexts(); + } + public OC_XorExpressionContext oC_XorExpression(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public ITerminalNode[] OR() { return GetTokens(CypherParser.OR); } + public ITerminalNode OR(int i) { + return GetToken(CypherParser.OR, i); + } + public OC_OrExpressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_OrExpression; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_OrExpression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_OrExpressionContext oC_OrExpression() { + OC_OrExpressionContext _localctx = new OC_OrExpressionContext(Context, State); + EnterRule(_localctx, 100, RULE_oC_OrExpression); + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 864; oC_XorExpression(); + State = 871; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,144,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 865; Match(SP); + State = 866; Match(OR); + State = 867; Match(SP); + State = 868; oC_XorExpression(); + } + } + } + State = 873; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,144,Context); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_XorExpressionContext : ParserRuleContext { + public OC_AndExpressionContext[] oC_AndExpression() { + return GetRuleContexts(); + } + public OC_AndExpressionContext oC_AndExpression(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public ITerminalNode[] XOR() { return GetTokens(CypherParser.XOR); } + public ITerminalNode XOR(int i) { + return GetToken(CypherParser.XOR, i); + } + public OC_XorExpressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_XorExpression; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_XorExpression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_XorExpressionContext oC_XorExpression() { + OC_XorExpressionContext _localctx = new OC_XorExpressionContext(Context, State); + EnterRule(_localctx, 102, RULE_oC_XorExpression); + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 874; oC_AndExpression(); + State = 881; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,145,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 875; Match(SP); + State = 876; Match(XOR); + State = 877; Match(SP); + State = 878; oC_AndExpression(); + } + } + } + State = 883; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,145,Context); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_AndExpressionContext : ParserRuleContext { + public OC_NotExpressionContext[] oC_NotExpression() { + return GetRuleContexts(); + } + public OC_NotExpressionContext oC_NotExpression(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public ITerminalNode[] AND() { return GetTokens(CypherParser.AND); } + public ITerminalNode AND(int i) { + return GetToken(CypherParser.AND, i); + } + public OC_AndExpressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_AndExpression; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_AndExpression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_AndExpressionContext oC_AndExpression() { + OC_AndExpressionContext _localctx = new OC_AndExpressionContext(Context, State); + EnterRule(_localctx, 104, RULE_oC_AndExpression); + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 884; oC_NotExpression(); + State = 891; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,146,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 885; Match(SP); + State = 886; Match(AND); + State = 887; Match(SP); + State = 888; oC_NotExpression(); + } + } + } + State = 893; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,146,Context); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_NotExpressionContext : ParserRuleContext { + public OC_ComparisonExpressionContext oC_ComparisonExpression() { + return GetRuleContext(0); + } + public ITerminalNode[] NOT() { return GetTokens(CypherParser.NOT); } + public ITerminalNode NOT(int i) { + return GetToken(CypherParser.NOT, i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_NotExpressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_NotExpression; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_NotExpression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_NotExpressionContext oC_NotExpression() { + OC_NotExpressionContext _localctx = new OC_NotExpressionContext(Context, State); + EnterRule(_localctx, 106, RULE_oC_NotExpression); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 900; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + while (_la==NOT) { + { + { + State = 894; Match(NOT); + State = 896; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 895; Match(SP); + } + } + + } + } + State = 902; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + } + State = 903; oC_ComparisonExpression(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_ComparisonExpressionContext : ParserRuleContext { + public OC_AddOrSubtractExpressionContext oC_AddOrSubtractExpression() { + return GetRuleContext(0); + } + public OC_PartialComparisonExpressionContext[] oC_PartialComparisonExpression() { + return GetRuleContexts(); + } + public OC_PartialComparisonExpressionContext oC_PartialComparisonExpression(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_ComparisonExpressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_ComparisonExpression; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_ComparisonExpression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_ComparisonExpressionContext oC_ComparisonExpression() { + OC_ComparisonExpressionContext _localctx = new OC_ComparisonExpressionContext(Context, State); + EnterRule(_localctx, 108, RULE_oC_ComparisonExpression); + int _la; + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 905; oC_AddOrSubtractExpression(); + State = 912; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,150,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 907; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 906; Match(SP); + } + } + + State = 909; oC_PartialComparisonExpression(); + } + } + } + State = 914; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,150,Context); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_AddOrSubtractExpressionContext : ParserRuleContext { + public OC_MultiplyDivideModuloExpressionContext[] oC_MultiplyDivideModuloExpression() { + return GetRuleContexts(); + } + public OC_MultiplyDivideModuloExpressionContext oC_MultiplyDivideModuloExpression(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_AddOrSubtractExpressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_AddOrSubtractExpression; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_AddOrSubtractExpression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_AddOrSubtractExpressionContext oC_AddOrSubtractExpression() { + OC_AddOrSubtractExpressionContext _localctx = new OC_AddOrSubtractExpressionContext(Context, State); + EnterRule(_localctx, 110, RULE_oC_AddOrSubtractExpression); + int _la; + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 915; oC_MultiplyDivideModuloExpression(); + State = 934; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,156,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + State = 932; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,155,Context) ) { + case 1: + { + { + State = 917; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 916; Match(SP); + } + } + + State = 919; Match(T__13); + State = 921; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 920; Match(SP); + } + } + + State = 923; oC_MultiplyDivideModuloExpression(); + } + } + break; + case 2: + { + { + State = 925; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 924; Match(SP); + } + } + + State = 927; Match(T__4); + State = 929; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 928; Match(SP); + } + } + + State = 931; oC_MultiplyDivideModuloExpression(); + } + } + break; + } + } + } + State = 936; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,156,Context); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_MultiplyDivideModuloExpressionContext : ParserRuleContext { + public OC_PowerOfExpressionContext[] oC_PowerOfExpression() { + return GetRuleContexts(); + } + public OC_PowerOfExpressionContext oC_PowerOfExpression(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_MultiplyDivideModuloExpressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_MultiplyDivideModuloExpression; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_MultiplyDivideModuloExpression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_MultiplyDivideModuloExpressionContext oC_MultiplyDivideModuloExpression() { + OC_MultiplyDivideModuloExpressionContext _localctx = new OC_MultiplyDivideModuloExpressionContext(Context, State); + EnterRule(_localctx, 112, RULE_oC_MultiplyDivideModuloExpression); + int _la; + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 937; oC_PowerOfExpression(); + State = 964; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,164,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + State = 962; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,163,Context) ) { + case 1: + { + { + State = 939; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 938; Match(SP); + } + } + + State = 941; Match(T__5); + State = 943; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 942; Match(SP); + } + } + + State = 945; oC_PowerOfExpression(); + } + } + break; + case 2: + { + { + State = 947; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 946; Match(SP); + } + } + + State = 949; Match(T__14); + State = 951; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 950; Match(SP); + } + } + + State = 953; oC_PowerOfExpression(); + } + } + break; + case 3: + { + { + State = 955; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 954; Match(SP); + } + } + + State = 957; Match(T__15); + State = 959; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 958; Match(SP); + } + } + + State = 961; oC_PowerOfExpression(); + } + } + break; + } + } + } + State = 966; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,164,Context); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_PowerOfExpressionContext : ParserRuleContext { + public OC_UnaryAddOrSubtractExpressionContext[] oC_UnaryAddOrSubtractExpression() { + return GetRuleContexts(); + } + public OC_UnaryAddOrSubtractExpressionContext oC_UnaryAddOrSubtractExpression(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_PowerOfExpressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_PowerOfExpression; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_PowerOfExpression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_PowerOfExpressionContext oC_PowerOfExpression() { + OC_PowerOfExpressionContext _localctx = new OC_PowerOfExpressionContext(Context, State); + EnterRule(_localctx, 114, RULE_oC_PowerOfExpression); + int _la; + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 967; oC_UnaryAddOrSubtractExpression(); + State = 978; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,167,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 969; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 968; Match(SP); + } + } + + State = 971; Match(T__16); + State = 973; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 972; Match(SP); + } + } + + State = 975; oC_UnaryAddOrSubtractExpression(); + } + } + } + State = 980; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,167,Context); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_UnaryAddOrSubtractExpressionContext : ParserRuleContext { + public OC_StringListNullOperatorExpressionContext oC_StringListNullOperatorExpression() { + return GetRuleContext(0); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_UnaryAddOrSubtractExpressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_UnaryAddOrSubtractExpression; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_UnaryAddOrSubtractExpression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_UnaryAddOrSubtractExpressionContext oC_UnaryAddOrSubtractExpression() { + OC_UnaryAddOrSubtractExpressionContext _localctx = new OC_UnaryAddOrSubtractExpressionContext(Context, State); + EnterRule(_localctx, 116, RULE_oC_UnaryAddOrSubtractExpression); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 987; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + while (_la==T__4 || _la==T__13) { + { + { + State = 981; + _la = TokenStream.LA(1); + if ( !(_la==T__4 || _la==T__13) ) { + ErrorHandler.RecoverInline(this); + } + else { + ErrorHandler.ReportMatch(this); + Consume(); + } + State = 983; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 982; Match(SP); + } + } + + } + } + State = 989; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + } + State = 990; oC_StringListNullOperatorExpression(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_StringListNullOperatorExpressionContext : ParserRuleContext { + public OC_PropertyOrLabelsExpressionContext[] oC_PropertyOrLabelsExpression() { + return GetRuleContexts(); + } + public OC_PropertyOrLabelsExpressionContext oC_PropertyOrLabelsExpression(int i) { + return GetRuleContext(i); + } + public OC_ExpressionContext[] oC_Expression() { + return GetRuleContexts(); + } + public OC_ExpressionContext oC_Expression(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public ITerminalNode[] IS() { return GetTokens(CypherParser.IS); } + public ITerminalNode IS(int i) { + return GetToken(CypherParser.IS, i); + } + public ITerminalNode[] NULL() { return GetTokens(CypherParser.NULL); } + public ITerminalNode NULL(int i) { + return GetToken(CypherParser.NULL, i); + } + public ITerminalNode[] NOT() { return GetTokens(CypherParser.NOT); } + public ITerminalNode NOT(int i) { + return GetToken(CypherParser.NOT, i); + } + public ITerminalNode[] IN() { return GetTokens(CypherParser.IN); } + public ITerminalNode IN(int i) { + return GetToken(CypherParser.IN, i); + } + public ITerminalNode[] STARTS() { return GetTokens(CypherParser.STARTS); } + public ITerminalNode STARTS(int i) { + return GetToken(CypherParser.STARTS, i); + } + public ITerminalNode[] WITH() { return GetTokens(CypherParser.WITH); } + public ITerminalNode WITH(int i) { + return GetToken(CypherParser.WITH, i); + } + public ITerminalNode[] ENDS() { return GetTokens(CypherParser.ENDS); } + public ITerminalNode ENDS(int i) { + return GetToken(CypherParser.ENDS, i); + } + public ITerminalNode[] CONTAINS() { return GetTokens(CypherParser.CONTAINS); } + public ITerminalNode CONTAINS(int i) { + return GetToken(CypherParser.CONTAINS, i); + } + public OC_StringListNullOperatorExpressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_StringListNullOperatorExpression; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_StringListNullOperatorExpression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_StringListNullOperatorExpressionContext oC_StringListNullOperatorExpression() { + OC_StringListNullOperatorExpressionContext _localctx = new OC_StringListNullOperatorExpressionContext(Context, State); + EnterRule(_localctx, 118, RULE_oC_StringListNullOperatorExpression); + int _la; + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 992; oC_PropertyOrLabelsExpression(); + State = 1042; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,177,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + State = 1040; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,176,Context) ) { + case 1: + { + { + State = 994; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 993; Match(SP); + } + } + + State = 996; Match(T__8); + State = 997; oC_Expression(); + State = 998; Match(T__9); + } + } + break; + case 2: + { + { + State = 1001; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1000; Match(SP); + } + } + + State = 1003; Match(T__8); + State = 1005; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__13) | (1L << T__23) | (1L << T__25) | (1L << ALL))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (NOT - 76)) | (1L << (NULL - 76)) | (1L << (COUNT - 76)) | (1L << (FILTER - 76)) | (1L << (EXTRACT - 76)) | (1L << (ANY - 76)) | (1L << (NONE - 76)) | (1L << (SINGLE - 76)) | (1L << (TRUE - 76)) | (1L << (FALSE - 76)) | (1L << (EXISTS - 76)) | (1L << (CASE - 76)) | (1L << (StringLiteral - 76)) | (1L << (HexInteger - 76)) | (1L << (DecimalInteger - 76)) | (1L << (OctalInteger - 76)) | (1L << (HexLetter - 76)) | (1L << (ExponentDecimalReal - 76)) | (1L << (RegularDecimalReal - 76)) | (1L << (UnescapedSymbolicName - 76)) | (1L << (EscapedSymbolicName - 76)))) != 0)) { + { + State = 1004; oC_Expression(); + } + } + + State = 1007; Match(T__12); + State = 1009; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__13) | (1L << T__23) | (1L << T__25) | (1L << ALL))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (NOT - 76)) | (1L << (NULL - 76)) | (1L << (COUNT - 76)) | (1L << (FILTER - 76)) | (1L << (EXTRACT - 76)) | (1L << (ANY - 76)) | (1L << (NONE - 76)) | (1L << (SINGLE - 76)) | (1L << (TRUE - 76)) | (1L << (FALSE - 76)) | (1L << (EXISTS - 76)) | (1L << (CASE - 76)) | (1L << (StringLiteral - 76)) | (1L << (HexInteger - 76)) | (1L << (DecimalInteger - 76)) | (1L << (OctalInteger - 76)) | (1L << (HexLetter - 76)) | (1L << (ExponentDecimalReal - 76)) | (1L << (RegularDecimalReal - 76)) | (1L << (UnescapedSymbolicName - 76)) | (1L << (EscapedSymbolicName - 76)))) != 0)) { + { + State = 1008; oC_Expression(); + } + } + + State = 1011; Match(T__9); + } + } + break; + case 3: + { + { + State = 1024; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,174,Context) ) { + case 1: + { + { + State = 1012; Match(SP); + State = 1013; Match(IN); + } + } + break; + case 2: + { + { + State = 1014; Match(SP); + State = 1015; Match(STARTS); + State = 1016; Match(SP); + State = 1017; Match(WITH); + } + } + break; + case 3: + { + { + State = 1018; Match(SP); + State = 1019; Match(ENDS); + State = 1020; Match(SP); + State = 1021; Match(WITH); + } + } + break; + case 4: + { + { + State = 1022; Match(SP); + State = 1023; Match(CONTAINS); + } + } + break; + } + State = 1027; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1026; Match(SP); + } + } + + State = 1029; oC_PropertyOrLabelsExpression(); + } + } + break; + case 4: + { + { + State = 1030; Match(SP); + State = 1031; Match(IS); + State = 1032; Match(SP); + State = 1033; Match(NULL); + } + } + break; + case 5: + { + { + State = 1034; Match(SP); + State = 1035; Match(IS); + State = 1036; Match(SP); + State = 1037; Match(NOT); + State = 1038; Match(SP); + State = 1039; Match(NULL); + } + } + break; + } + } + } + State = 1044; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,177,Context); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_PropertyOrLabelsExpressionContext : ParserRuleContext { + public OC_AtomContext oC_Atom() { + return GetRuleContext(0); + } + public OC_PropertyLookupContext[] oC_PropertyLookup() { + return GetRuleContexts(); + } + public OC_PropertyLookupContext oC_PropertyLookup(int i) { + return GetRuleContext(i); + } + public OC_NodeLabelsContext oC_NodeLabels() { + return GetRuleContext(0); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_PropertyOrLabelsExpressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_PropertyOrLabelsExpression; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_PropertyOrLabelsExpression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_PropertyOrLabelsExpressionContext oC_PropertyOrLabelsExpression() { + OC_PropertyOrLabelsExpressionContext _localctx = new OC_PropertyOrLabelsExpressionContext(Context, State); + EnterRule(_localctx, 120, RULE_oC_PropertyOrLabelsExpression); + int _la; + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 1045; oC_Atom(); + State = 1052; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,179,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 1047; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1046; Match(SP); + } + } + + State = 1049; oC_PropertyLookup(); + } + } + } + State = 1054; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,179,Context); + } + State = 1059; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,181,Context) ) { + case 1: + { + State = 1056; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1055; Match(SP); + } + } + + State = 1058; oC_NodeLabels(); + } + break; + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_AtomContext : ParserRuleContext { + public OC_LiteralContext oC_Literal() { + return GetRuleContext(0); + } + public OC_ParameterContext oC_Parameter() { + return GetRuleContext(0); + } + public OC_CaseExpressionContext oC_CaseExpression() { + return GetRuleContext(0); + } + public ITerminalNode COUNT() { return GetToken(CypherParser.COUNT, 0); } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_ListComprehensionContext oC_ListComprehension() { + return GetRuleContext(0); + } + public OC_PatternComprehensionContext oC_PatternComprehension() { + return GetRuleContext(0); + } + public ITerminalNode FILTER() { return GetToken(CypherParser.FILTER, 0); } + public OC_FilterExpressionContext oC_FilterExpression() { + return GetRuleContext(0); + } + public ITerminalNode EXTRACT() { return GetToken(CypherParser.EXTRACT, 0); } + public OC_ExpressionContext oC_Expression() { + return GetRuleContext(0); + } + public ITerminalNode ALL() { return GetToken(CypherParser.ALL, 0); } + public ITerminalNode ANY() { return GetToken(CypherParser.ANY, 0); } + public ITerminalNode NONE() { return GetToken(CypherParser.NONE, 0); } + public ITerminalNode SINGLE() { return GetToken(CypherParser.SINGLE, 0); } + public OC_RelationshipsPatternContext oC_RelationshipsPattern() { + return GetRuleContext(0); + } + public OC_ParenthesizedExpressionContext oC_ParenthesizedExpression() { + return GetRuleContext(0); + } + public OC_FunctionInvocationContext oC_FunctionInvocation() { + return GetRuleContext(0); + } + public OC_VariableContext oC_Variable() { + return GetRuleContext(0); + } + public OC_AtomContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Atom; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Atom(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_AtomContext oC_Atom() { + OC_AtomContext _localctx = new OC_AtomContext(Context, State); + EnterRule(_localctx, 122, RULE_oC_Atom); + int _la; + try { + State = 1174; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,205,Context) ) { + case 1: + EnterOuterAlt(_localctx, 1); + { + State = 1061; oC_Literal(); + } + break; + case 2: + EnterOuterAlt(_localctx, 2); + { + State = 1062; oC_Parameter(); + } + break; + case 3: + EnterOuterAlt(_localctx, 3); + { + State = 1063; oC_CaseExpression(); + } + break; + case 4: + EnterOuterAlt(_localctx, 4); + { + { + State = 1064; Match(COUNT); + State = 1066; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1065; Match(SP); + } + } + + State = 1068; Match(T__6); + State = 1070; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1069; Match(SP); + } + } + + State = 1072; Match(T__5); + State = 1074; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1073; Match(SP); + } + } + + State = 1076; Match(T__7); + } + } + break; + case 5: + EnterOuterAlt(_localctx, 5); + { + State = 1077; oC_ListComprehension(); + } + break; + case 6: + EnterOuterAlt(_localctx, 6); + { + State = 1078; oC_PatternComprehension(); + } + break; + case 7: + EnterOuterAlt(_localctx, 7); + { + { + State = 1079; Match(FILTER); + State = 1081; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1080; Match(SP); + } + } + + State = 1083; Match(T__6); + State = 1085; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1084; Match(SP); + } + } + + State = 1087; oC_FilterExpression(); + State = 1089; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1088; Match(SP); + } + } + + State = 1091; Match(T__7); + } + } + break; + case 8: + EnterOuterAlt(_localctx, 8); + { + { + State = 1093; Match(EXTRACT); + State = 1095; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1094; Match(SP); + } + } + + State = 1097; Match(T__6); + State = 1099; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1098; Match(SP); + } + } + + State = 1101; oC_FilterExpression(); + State = 1103; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,190,Context) ) { + case 1: + { + State = 1102; Match(SP); + } + break; + } + State = 1110; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==T__11 || _la==SP) { + { + State = 1106; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1105; Match(SP); + } + } + + State = 1108; Match(T__11); + State = 1109; oC_Expression(); + } + } + + State = 1112; Match(T__7); + } + } + break; + case 9: + EnterOuterAlt(_localctx, 9); + { + { + State = 1114; Match(ALL); + State = 1116; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1115; Match(SP); + } + } + + State = 1118; Match(T__6); + State = 1120; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1119; Match(SP); + } + } + + State = 1122; oC_FilterExpression(); + State = 1124; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1123; Match(SP); + } + } + + State = 1126; Match(T__7); + } + } + break; + case 10: + EnterOuterAlt(_localctx, 10); + { + { + State = 1128; Match(ANY); + State = 1130; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1129; Match(SP); + } + } + + State = 1132; Match(T__6); + State = 1134; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1133; Match(SP); + } + } + + State = 1136; oC_FilterExpression(); + State = 1138; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1137; Match(SP); + } + } + + State = 1140; Match(T__7); + } + } + break; + case 11: + EnterOuterAlt(_localctx, 11); + { + { + State = 1142; Match(NONE); + State = 1144; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1143; Match(SP); + } + } + + State = 1146; Match(T__6); + State = 1148; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1147; Match(SP); + } + } + + State = 1150; oC_FilterExpression(); + State = 1152; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1151; Match(SP); + } + } + + State = 1154; Match(T__7); + } + } + break; + case 12: + EnterOuterAlt(_localctx, 12); + { + { + State = 1156; Match(SINGLE); + State = 1158; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1157; Match(SP); + } + } + + State = 1160; Match(T__6); + State = 1162; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1161; Match(SP); + } + } + + State = 1164; oC_FilterExpression(); + State = 1166; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1165; Match(SP); + } + } + + State = 1168; Match(T__7); + } + } + break; + case 13: + EnterOuterAlt(_localctx, 13); + { + State = 1170; oC_RelationshipsPattern(); + } + break; + case 14: + EnterOuterAlt(_localctx, 14); + { + State = 1171; oC_ParenthesizedExpression(); + } + break; + case 15: + EnterOuterAlt(_localctx, 15); + { + State = 1172; oC_FunctionInvocation(); + } + break; + case 16: + EnterOuterAlt(_localctx, 16); + { + State = 1173; oC_Variable(); + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_LiteralContext : ParserRuleContext { + public OC_NumberLiteralContext oC_NumberLiteral() { + return GetRuleContext(0); + } + public ITerminalNode StringLiteral() { return GetToken(CypherParser.StringLiteral, 0); } + public OC_BooleanLiteralContext oC_BooleanLiteral() { + return GetRuleContext(0); + } + public ITerminalNode NULL() { return GetToken(CypherParser.NULL, 0); } + public OC_MapLiteralContext oC_MapLiteral() { + return GetRuleContext(0); + } + public OC_ListLiteralContext oC_ListLiteral() { + return GetRuleContext(0); + } + public OC_LiteralContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Literal; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Literal(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_LiteralContext oC_Literal() { + OC_LiteralContext _localctx = new OC_LiteralContext(Context, State); + EnterRule(_localctx, 124, RULE_oC_Literal); + try { + State = 1182; + ErrorHandler.Sync(this); + switch (TokenStream.LA(1)) { + case HexInteger: + case DecimalInteger: + case OctalInteger: + case ExponentDecimalReal: + case RegularDecimalReal: + EnterOuterAlt(_localctx, 1); + { + State = 1176; oC_NumberLiteral(); + } + break; + case StringLiteral: + EnterOuterAlt(_localctx, 2); + { + State = 1177; Match(StringLiteral); + } + break; + case TRUE: + case FALSE: + EnterOuterAlt(_localctx, 3); + { + State = 1178; oC_BooleanLiteral(); + } + break; + case NULL: + EnterOuterAlt(_localctx, 4); + { + State = 1179; Match(NULL); + } + break; + case T__23: + EnterOuterAlt(_localctx, 5); + { + State = 1180; oC_MapLiteral(); + } + break; + case T__8: + EnterOuterAlt(_localctx, 6); + { + State = 1181; oC_ListLiteral(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_BooleanLiteralContext : ParserRuleContext { + public ITerminalNode TRUE() { return GetToken(CypherParser.TRUE, 0); } + public ITerminalNode FALSE() { return GetToken(CypherParser.FALSE, 0); } + public OC_BooleanLiteralContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_BooleanLiteral; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_BooleanLiteral(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_BooleanLiteralContext oC_BooleanLiteral() { + OC_BooleanLiteralContext _localctx = new OC_BooleanLiteralContext(Context, State); + EnterRule(_localctx, 126, RULE_oC_BooleanLiteral); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1184; + _la = TokenStream.LA(1); + if ( !(_la==TRUE || _la==FALSE) ) { + ErrorHandler.RecoverInline(this); + } + else { + ErrorHandler.ReportMatch(this); + Consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_ListLiteralContext : ParserRuleContext { + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_ExpressionContext[] oC_Expression() { + return GetRuleContexts(); + } + public OC_ExpressionContext oC_Expression(int i) { + return GetRuleContext(i); + } + public OC_ListLiteralContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_ListLiteral; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_ListLiteral(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_ListLiteralContext oC_ListLiteral() { + OC_ListLiteralContext _localctx = new OC_ListLiteralContext(Context, State); + EnterRule(_localctx, 128, RULE_oC_ListLiteral); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1186; Match(T__8); + State = 1188; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1187; Match(SP); + } + } + + State = 1207; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__13) | (1L << T__23) | (1L << T__25) | (1L << ALL))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (NOT - 76)) | (1L << (NULL - 76)) | (1L << (COUNT - 76)) | (1L << (FILTER - 76)) | (1L << (EXTRACT - 76)) | (1L << (ANY - 76)) | (1L << (NONE - 76)) | (1L << (SINGLE - 76)) | (1L << (TRUE - 76)) | (1L << (FALSE - 76)) | (1L << (EXISTS - 76)) | (1L << (CASE - 76)) | (1L << (StringLiteral - 76)) | (1L << (HexInteger - 76)) | (1L << (DecimalInteger - 76)) | (1L << (OctalInteger - 76)) | (1L << (HexLetter - 76)) | (1L << (ExponentDecimalReal - 76)) | (1L << (RegularDecimalReal - 76)) | (1L << (UnescapedSymbolicName - 76)) | (1L << (EscapedSymbolicName - 76)))) != 0)) { + { + State = 1190; oC_Expression(); + State = 1192; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1191; Match(SP); + } + } + + State = 1204; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + while (_la==T__1) { + { + { + State = 1194; Match(T__1); + State = 1196; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1195; Match(SP); + } + } + + State = 1198; oC_Expression(); + State = 1200; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1199; Match(SP); + } + } + + } + } + State = 1206; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + } + } + } + + State = 1209; Match(T__9); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_PartialComparisonExpressionContext : ParserRuleContext { + public OC_AddOrSubtractExpressionContext oC_AddOrSubtractExpression() { + return GetRuleContext(0); + } + public ITerminalNode SP() { return GetToken(CypherParser.SP, 0); } + public OC_PartialComparisonExpressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_PartialComparisonExpression; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_PartialComparisonExpression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_PartialComparisonExpressionContext oC_PartialComparisonExpression() { + OC_PartialComparisonExpressionContext _localctx = new OC_PartialComparisonExpressionContext(Context, State); + EnterRule(_localctx, 130, RULE_oC_PartialComparisonExpression); + int _la; + try { + State = 1241; + ErrorHandler.Sync(this); + switch (TokenStream.LA(1)) { + case T__2: + EnterOuterAlt(_localctx, 1); + { + { + State = 1211; Match(T__2); + State = 1213; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1212; Match(SP); + } + } + + State = 1215; oC_AddOrSubtractExpression(); + } + } + break; + case T__17: + EnterOuterAlt(_localctx, 2); + { + { + State = 1216; Match(T__17); + State = 1218; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1217; Match(SP); + } + } + + State = 1220; oC_AddOrSubtractExpression(); + } + } + break; + case T__18: + EnterOuterAlt(_localctx, 3); + { + { + State = 1221; Match(T__18); + State = 1223; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1222; Match(SP); + } + } + + State = 1225; oC_AddOrSubtractExpression(); + } + } + break; + case T__19: + EnterOuterAlt(_localctx, 4); + { + { + State = 1226; Match(T__19); + State = 1228; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1227; Match(SP); + } + } + + State = 1230; oC_AddOrSubtractExpression(); + } + } + break; + case T__20: + EnterOuterAlt(_localctx, 5); + { + { + State = 1231; Match(T__20); + State = 1233; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1232; Match(SP); + } + } + + State = 1235; oC_AddOrSubtractExpression(); + } + } + break; + case T__21: + EnterOuterAlt(_localctx, 6); + { + { + State = 1236; Match(T__21); + State = 1238; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1237; Match(SP); + } + } + + State = 1240; oC_AddOrSubtractExpression(); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_ParenthesizedExpressionContext : ParserRuleContext { + public OC_ExpressionContext oC_Expression() { + return GetRuleContext(0); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_ParenthesizedExpressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_ParenthesizedExpression; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_ParenthesizedExpression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_ParenthesizedExpressionContext oC_ParenthesizedExpression() { + OC_ParenthesizedExpressionContext _localctx = new OC_ParenthesizedExpressionContext(Context, State); + EnterRule(_localctx, 132, RULE_oC_ParenthesizedExpression); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1243; Match(T__6); + State = 1245; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1244; Match(SP); + } + } + + State = 1247; oC_Expression(); + State = 1249; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1248; Match(SP); + } + } + + State = 1251; Match(T__7); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_RelationshipsPatternContext : ParserRuleContext { + public OC_NodePatternContext oC_NodePattern() { + return GetRuleContext(0); + } + public OC_PatternElementChainContext[] oC_PatternElementChain() { + return GetRuleContexts(); + } + public OC_PatternElementChainContext oC_PatternElementChain(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_RelationshipsPatternContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_RelationshipsPattern; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_RelationshipsPattern(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_RelationshipsPatternContext oC_RelationshipsPattern() { + OC_RelationshipsPatternContext _localctx = new OC_RelationshipsPatternContext(Context, State); + EnterRule(_localctx, 134, RULE_oC_RelationshipsPattern); + int _la; + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 1253; oC_NodePattern(); + State = 1258; + ErrorHandler.Sync(this); + _alt = 1; + do { + switch (_alt) { + case 1: + { + { + State = 1255; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1254; Match(SP); + } + } + + State = 1257; oC_PatternElementChain(); + } + } + break; + default: + throw new NoViableAltException(this); + } + State = 1260; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,223,Context); + } while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_FilterExpressionContext : ParserRuleContext { + public OC_IdInCollContext oC_IdInColl() { + return GetRuleContext(0); + } + public OC_WhereContext oC_Where() { + return GetRuleContext(0); + } + public ITerminalNode SP() { return GetToken(CypherParser.SP, 0); } + public OC_FilterExpressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_FilterExpression; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_FilterExpression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_FilterExpressionContext oC_FilterExpression() { + OC_FilterExpressionContext _localctx = new OC_FilterExpressionContext(Context, State); + EnterRule(_localctx, 136, RULE_oC_FilterExpression); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1262; oC_IdInColl(); + State = 1267; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,225,Context) ) { + case 1: + { + State = 1264; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1263; Match(SP); + } + } + + State = 1266; oC_Where(); + } + break; + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_IdInCollContext : ParserRuleContext { + public OC_VariableContext oC_Variable() { + return GetRuleContext(0); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public ITerminalNode IN() { return GetToken(CypherParser.IN, 0); } + public OC_ExpressionContext oC_Expression() { + return GetRuleContext(0); + } + public OC_IdInCollContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_IdInColl; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_IdInColl(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_IdInCollContext oC_IdInColl() { + OC_IdInCollContext _localctx = new OC_IdInCollContext(Context, State); + EnterRule(_localctx, 138, RULE_oC_IdInColl); + try { + EnterOuterAlt(_localctx, 1); + { + State = 1269; oC_Variable(); + State = 1270; Match(SP); + State = 1271; Match(IN); + State = 1272; Match(SP); + State = 1273; oC_Expression(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_FunctionInvocationContext : ParserRuleContext { + public OC_FunctionNameContext oC_FunctionName() { + return GetRuleContext(0); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public ITerminalNode DISTINCT() { return GetToken(CypherParser.DISTINCT, 0); } + public OC_ExpressionContext[] oC_Expression() { + return GetRuleContexts(); + } + public OC_ExpressionContext oC_Expression(int i) { + return GetRuleContext(i); + } + public OC_FunctionInvocationContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_FunctionInvocation; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_FunctionInvocation(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_FunctionInvocationContext oC_FunctionInvocation() { + OC_FunctionInvocationContext _localctx = new OC_FunctionInvocationContext(Context, State); + EnterRule(_localctx, 140, RULE_oC_FunctionInvocation); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1275; oC_FunctionName(); + State = 1277; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1276; Match(SP); + } + } + + State = 1279; Match(T__6); + State = 1281; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1280; Match(SP); + } + } + + State = 1287; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==DISTINCT) { + { + State = 1283; Match(DISTINCT); + State = 1285; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1284; Match(SP); + } + } + + } + } + + State = 1306; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__13) | (1L << T__23) | (1L << T__25) | (1L << ALL))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (NOT - 76)) | (1L << (NULL - 76)) | (1L << (COUNT - 76)) | (1L << (FILTER - 76)) | (1L << (EXTRACT - 76)) | (1L << (ANY - 76)) | (1L << (NONE - 76)) | (1L << (SINGLE - 76)) | (1L << (TRUE - 76)) | (1L << (FALSE - 76)) | (1L << (EXISTS - 76)) | (1L << (CASE - 76)) | (1L << (StringLiteral - 76)) | (1L << (HexInteger - 76)) | (1L << (DecimalInteger - 76)) | (1L << (OctalInteger - 76)) | (1L << (HexLetter - 76)) | (1L << (ExponentDecimalReal - 76)) | (1L << (RegularDecimalReal - 76)) | (1L << (UnescapedSymbolicName - 76)) | (1L << (EscapedSymbolicName - 76)))) != 0)) { + { + State = 1289; oC_Expression(); + State = 1291; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1290; Match(SP); + } + } + + State = 1303; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + while (_la==T__1) { + { + { + State = 1293; Match(T__1); + State = 1295; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1294; Match(SP); + } + } + + State = 1297; oC_Expression(); + State = 1299; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1298; Match(SP); + } + } + + } + } + State = 1305; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + } + } + } + + State = 1308; Match(T__7); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_FunctionNameContext : ParserRuleContext { + public OC_SymbolicNameContext oC_SymbolicName() { + return GetRuleContext(0); + } + public ITerminalNode EXISTS() { return GetToken(CypherParser.EXISTS, 0); } + public OC_FunctionNameContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_FunctionName; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_FunctionName(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_FunctionNameContext oC_FunctionName() { + OC_FunctionNameContext _localctx = new OC_FunctionNameContext(Context, State); + EnterRule(_localctx, 142, RULE_oC_FunctionName); + try { + State = 1312; + ErrorHandler.Sync(this); + switch (TokenStream.LA(1)) { + case COUNT: + case FILTER: + case EXTRACT: + case ANY: + case NONE: + case SINGLE: + case HexLetter: + case UnescapedSymbolicName: + case EscapedSymbolicName: + EnterOuterAlt(_localctx, 1); + { + State = 1310; oC_SymbolicName(); + } + break; + case EXISTS: + EnterOuterAlt(_localctx, 2); + { + State = 1311; Match(EXISTS); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_ExplicitProcedureInvocationContext : ParserRuleContext { + public OC_ProcedureNameContext oC_ProcedureName() { + return GetRuleContext(0); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_ExpressionContext[] oC_Expression() { + return GetRuleContexts(); + } + public OC_ExpressionContext oC_Expression(int i) { + return GetRuleContext(i); + } + public OC_ExplicitProcedureInvocationContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_ExplicitProcedureInvocation; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_ExplicitProcedureInvocation(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_ExplicitProcedureInvocationContext oC_ExplicitProcedureInvocation() { + OC_ExplicitProcedureInvocationContext _localctx = new OC_ExplicitProcedureInvocationContext(Context, State); + EnterRule(_localctx, 144, RULE_oC_ExplicitProcedureInvocation); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1314; oC_ProcedureName(); + State = 1316; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1315; Match(SP); + } + } + + State = 1318; Match(T__6); + State = 1320; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1319; Match(SP); + } + } + + State = 1339; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__13) | (1L << T__23) | (1L << T__25) | (1L << ALL))) != 0) || ((((_la - 76)) & ~0x3f) == 0 && ((1L << (_la - 76)) & ((1L << (NOT - 76)) | (1L << (NULL - 76)) | (1L << (COUNT - 76)) | (1L << (FILTER - 76)) | (1L << (EXTRACT - 76)) | (1L << (ANY - 76)) | (1L << (NONE - 76)) | (1L << (SINGLE - 76)) | (1L << (TRUE - 76)) | (1L << (FALSE - 76)) | (1L << (EXISTS - 76)) | (1L << (CASE - 76)) | (1L << (StringLiteral - 76)) | (1L << (HexInteger - 76)) | (1L << (DecimalInteger - 76)) | (1L << (OctalInteger - 76)) | (1L << (HexLetter - 76)) | (1L << (ExponentDecimalReal - 76)) | (1L << (RegularDecimalReal - 76)) | (1L << (UnescapedSymbolicName - 76)) | (1L << (EscapedSymbolicName - 76)))) != 0)) { + { + State = 1322; oC_Expression(); + State = 1324; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1323; Match(SP); + } + } + + State = 1336; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + while (_la==T__1) { + { + { + State = 1326; Match(T__1); + State = 1328; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1327; Match(SP); + } + } + + State = 1330; oC_Expression(); + State = 1332; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1331; Match(SP); + } + } + + } + } + State = 1338; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + } + } + } + + State = 1341; Match(T__7); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_ImplicitProcedureInvocationContext : ParserRuleContext { + public OC_ProcedureNameContext oC_ProcedureName() { + return GetRuleContext(0); + } + public OC_ImplicitProcedureInvocationContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_ImplicitProcedureInvocation; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_ImplicitProcedureInvocation(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_ImplicitProcedureInvocationContext oC_ImplicitProcedureInvocation() { + OC_ImplicitProcedureInvocationContext _localctx = new OC_ImplicitProcedureInvocationContext(Context, State); + EnterRule(_localctx, 146, RULE_oC_ImplicitProcedureInvocation); + try { + EnterOuterAlt(_localctx, 1); + { + State = 1343; oC_ProcedureName(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_ProcedureResultFieldContext : ParserRuleContext { + public OC_SymbolicNameContext oC_SymbolicName() { + return GetRuleContext(0); + } + public OC_ProcedureResultFieldContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_ProcedureResultField; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_ProcedureResultField(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_ProcedureResultFieldContext oC_ProcedureResultField() { + OC_ProcedureResultFieldContext _localctx = new OC_ProcedureResultFieldContext(Context, State); + EnterRule(_localctx, 148, RULE_oC_ProcedureResultField); + try { + EnterOuterAlt(_localctx, 1); + { + State = 1345; oC_SymbolicName(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_ProcedureNameContext : ParserRuleContext { + public OC_NamespaceContext oC_Namespace() { + return GetRuleContext(0); + } + public OC_SymbolicNameContext oC_SymbolicName() { + return GetRuleContext(0); + } + public OC_ProcedureNameContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_ProcedureName; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_ProcedureName(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_ProcedureNameContext oC_ProcedureName() { + OC_ProcedureNameContext _localctx = new OC_ProcedureNameContext(Context, State); + EnterRule(_localctx, 150, RULE_oC_ProcedureName); + try { + EnterOuterAlt(_localctx, 1); + { + State = 1347; oC_Namespace(); + State = 1348; oC_SymbolicName(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_NamespaceContext : ParserRuleContext { + public OC_SymbolicNameContext[] oC_SymbolicName() { + return GetRuleContexts(); + } + public OC_SymbolicNameContext oC_SymbolicName(int i) { + return GetRuleContext(i); + } + public OC_NamespaceContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Namespace; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Namespace(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_NamespaceContext oC_Namespace() { + OC_NamespaceContext _localctx = new OC_NamespaceContext(Context, State); + EnterRule(_localctx, 152, RULE_oC_Namespace); + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 1355; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,243,Context); + while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + { + { + State = 1350; oC_SymbolicName(); + State = 1351; Match(T__22); + } + } + } + State = 1357; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,243,Context); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_ListComprehensionContext : ParserRuleContext { + public OC_FilterExpressionContext oC_FilterExpression() { + return GetRuleContext(0); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_ExpressionContext oC_Expression() { + return GetRuleContext(0); + } + public OC_ListComprehensionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_ListComprehension; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_ListComprehension(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_ListComprehensionContext oC_ListComprehension() { + OC_ListComprehensionContext _localctx = new OC_ListComprehensionContext(Context, State); + EnterRule(_localctx, 154, RULE_oC_ListComprehension); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1358; Match(T__8); + State = 1360; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1359; Match(SP); + } + } + + State = 1362; oC_FilterExpression(); + State = 1371; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,247,Context) ) { + case 1: + { + State = 1364; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1363; Match(SP); + } + } + + State = 1366; Match(T__11); + State = 1368; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1367; Match(SP); + } + } + + State = 1370; oC_Expression(); + } + break; + } + State = 1374; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1373; Match(SP); + } + } + + State = 1376; Match(T__9); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_PatternComprehensionContext : ParserRuleContext { + public OC_RelationshipsPatternContext oC_RelationshipsPattern() { + return GetRuleContext(0); + } + public OC_ExpressionContext[] oC_Expression() { + return GetRuleContexts(); + } + public OC_ExpressionContext oC_Expression(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_VariableContext oC_Variable() { + return GetRuleContext(0); + } + public ITerminalNode WHERE() { return GetToken(CypherParser.WHERE, 0); } + public OC_PatternComprehensionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_PatternComprehension; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_PatternComprehension(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_PatternComprehensionContext oC_PatternComprehension() { + OC_PatternComprehensionContext _localctx = new OC_PatternComprehensionContext(Context, State); + EnterRule(_localctx, 156, RULE_oC_PatternComprehension); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1378; Match(T__8); + State = 1380; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1379; Match(SP); + } + } + + State = 1390; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (((((_la - 83)) & ~0x3f) == 0 && ((1L << (_la - 83)) & ((1L << (COUNT - 83)) | (1L << (FILTER - 83)) | (1L << (EXTRACT - 83)) | (1L << (ANY - 83)) | (1L << (NONE - 83)) | (1L << (SINGLE - 83)) | (1L << (HexLetter - 83)) | (1L << (UnescapedSymbolicName - 83)) | (1L << (EscapedSymbolicName - 83)))) != 0)) { + { + State = 1382; oC_Variable(); + State = 1384; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1383; Match(SP); + } + } + + State = 1386; Match(T__2); + State = 1388; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1387; Match(SP); + } + } + + } + } + + State = 1392; oC_RelationshipsPattern(); + State = 1394; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1393; Match(SP); + } + } + + State = 1404; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==WHERE) { + { + State = 1396; Match(WHERE); + State = 1398; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1397; Match(SP); + } + } + + State = 1400; oC_Expression(); + State = 1402; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1401; Match(SP); + } + } + + } + } + + State = 1406; Match(T__11); + State = 1408; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1407; Match(SP); + } + } + + State = 1410; oC_Expression(); + State = 1412; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1411; Match(SP); + } + } + + State = 1414; Match(T__9); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_PropertyLookupContext : ParserRuleContext { + public OC_PropertyKeyNameContext oC_PropertyKeyName() { + return GetRuleContext(0); + } + public ITerminalNode SP() { return GetToken(CypherParser.SP, 0); } + public OC_PropertyLookupContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_PropertyLookup; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_PropertyLookup(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_PropertyLookupContext oC_PropertyLookup() { + OC_PropertyLookupContext _localctx = new OC_PropertyLookupContext(Context, State); + EnterRule(_localctx, 158, RULE_oC_PropertyLookup); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1416; Match(T__22); + State = 1418; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1417; Match(SP); + } + } + + { + State = 1420; oC_PropertyKeyName(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_CaseExpressionContext : ParserRuleContext { + public ITerminalNode END() { return GetToken(CypherParser.END, 0); } + public ITerminalNode ELSE() { return GetToken(CypherParser.ELSE, 0); } + public OC_ExpressionContext[] oC_Expression() { + return GetRuleContexts(); + } + public OC_ExpressionContext oC_Expression(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public ITerminalNode CASE() { return GetToken(CypherParser.CASE, 0); } + public OC_CaseAlternativesContext[] oC_CaseAlternatives() { + return GetRuleContexts(); + } + public OC_CaseAlternativesContext oC_CaseAlternatives(int i) { + return GetRuleContext(i); + } + public OC_CaseExpressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_CaseExpression; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_CaseExpression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_CaseExpressionContext oC_CaseExpression() { + OC_CaseExpressionContext _localctx = new OC_CaseExpressionContext(Context, State); + EnterRule(_localctx, 160, RULE_oC_CaseExpression); + int _la; + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 1444; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,265,Context) ) { + case 1: + { + { + State = 1422; Match(CASE); + State = 1427; + ErrorHandler.Sync(this); + _alt = 1; + do { + switch (_alt) { + case 1: + { + { + State = 1424; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1423; Match(SP); + } + } + + State = 1426; oC_CaseAlternatives(); + } + } + break; + default: + throw new NoViableAltException(this); + } + State = 1429; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,261,Context); + } while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ); + } + } + break; + case 2: + { + { + State = 1431; Match(CASE); + State = 1433; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1432; Match(SP); + } + } + + State = 1435; oC_Expression(); + State = 1440; + ErrorHandler.Sync(this); + _alt = 1; + do { + switch (_alt) { + case 1: + { + { + State = 1437; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1436; Match(SP); + } + } + + State = 1439; oC_CaseAlternatives(); + } + } + break; + default: + throw new NoViableAltException(this); + } + State = 1442; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,264,Context); + } while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ); + } + } + break; + } + State = 1454; + ErrorHandler.Sync(this); + switch ( Interpreter.AdaptivePredict(TokenStream,268,Context) ) { + case 1: + { + State = 1447; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1446; Match(SP); + } + } + + State = 1449; Match(ELSE); + State = 1451; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1450; Match(SP); + } + } + + State = 1453; oC_Expression(); + } + break; + } + State = 1457; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1456; Match(SP); + } + } + + State = 1459; Match(END); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_CaseAlternativesContext : ParserRuleContext { + public ITerminalNode WHEN() { return GetToken(CypherParser.WHEN, 0); } + public OC_ExpressionContext[] oC_Expression() { + return GetRuleContexts(); + } + public OC_ExpressionContext oC_Expression(int i) { + return GetRuleContext(i); + } + public ITerminalNode THEN() { return GetToken(CypherParser.THEN, 0); } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_CaseAlternativesContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_CaseAlternatives; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_CaseAlternatives(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_CaseAlternativesContext oC_CaseAlternatives() { + OC_CaseAlternativesContext _localctx = new OC_CaseAlternativesContext(Context, State); + EnterRule(_localctx, 162, RULE_oC_CaseAlternatives); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1461; Match(WHEN); + State = 1463; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1462; Match(SP); + } + } + + State = 1465; oC_Expression(); + State = 1467; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1466; Match(SP); + } + } + + State = 1469; Match(THEN); + State = 1471; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1470; Match(SP); + } + } + + State = 1473; oC_Expression(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_VariableContext : ParserRuleContext { + public OC_SymbolicNameContext oC_SymbolicName() { + return GetRuleContext(0); + } + public OC_VariableContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Variable; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Variable(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_VariableContext oC_Variable() { + OC_VariableContext _localctx = new OC_VariableContext(Context, State); + EnterRule(_localctx, 164, RULE_oC_Variable); + try { + EnterOuterAlt(_localctx, 1); + { + State = 1475; oC_SymbolicName(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_NumberLiteralContext : ParserRuleContext { + public OC_DoubleLiteralContext oC_DoubleLiteral() { + return GetRuleContext(0); + } + public OC_IntegerLiteralContext oC_IntegerLiteral() { + return GetRuleContext(0); + } + public OC_NumberLiteralContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_NumberLiteral; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_NumberLiteral(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_NumberLiteralContext oC_NumberLiteral() { + OC_NumberLiteralContext _localctx = new OC_NumberLiteralContext(Context, State); + EnterRule(_localctx, 166, RULE_oC_NumberLiteral); + try { + State = 1479; + ErrorHandler.Sync(this); + switch (TokenStream.LA(1)) { + case ExponentDecimalReal: + case RegularDecimalReal: + EnterOuterAlt(_localctx, 1); + { + State = 1477; oC_DoubleLiteral(); + } + break; + case HexInteger: + case DecimalInteger: + case OctalInteger: + EnterOuterAlt(_localctx, 2); + { + State = 1478; oC_IntegerLiteral(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_MapLiteralContext : ParserRuleContext { + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_PropertyKeyNameContext[] oC_PropertyKeyName() { + return GetRuleContexts(); + } + public OC_PropertyKeyNameContext oC_PropertyKeyName(int i) { + return GetRuleContext(i); + } + public OC_ExpressionContext[] oC_Expression() { + return GetRuleContexts(); + } + public OC_ExpressionContext oC_Expression(int i) { + return GetRuleContext(i); + } + public OC_MapLiteralContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_MapLiteral; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_MapLiteral(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_MapLiteralContext oC_MapLiteral() { + OC_MapLiteralContext _localctx = new OC_MapLiteralContext(Context, State); + EnterRule(_localctx, 168, RULE_oC_MapLiteral); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1481; Match(T__23); + State = 1483; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1482; Match(SP); + } + } + + State = 1518; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << UNION) | (1L << ALL) | (1L << OPTIONAL) | (1L << MATCH) | (1L << UNWIND) | (1L << AS) | (1L << MERGE) | (1L << ON) | (1L << CREATE) | (1L << SET) | (1L << DETACH) | (1L << DELETE) | (1L << REMOVE) | (1L << WITH) | (1L << DISTINCT) | (1L << RETURN))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (ORDER - 64)) | (1L << (BY - 64)) | (1L << (L_SKIP - 64)) | (1L << (LIMIT - 64)) | (1L << (ASCENDING - 64)) | (1L << (ASC - 64)) | (1L << (DESCENDING - 64)) | (1L << (DESC - 64)) | (1L << (WHERE - 64)) | (1L << (OR - 64)) | (1L << (XOR - 64)) | (1L << (AND - 64)) | (1L << (NOT - 64)) | (1L << (IN - 64)) | (1L << (STARTS - 64)) | (1L << (ENDS - 64)) | (1L << (CONTAINS - 64)) | (1L << (IS - 64)) | (1L << (NULL - 64)) | (1L << (COUNT - 64)) | (1L << (FILTER - 64)) | (1L << (EXTRACT - 64)) | (1L << (ANY - 64)) | (1L << (NONE - 64)) | (1L << (SINGLE - 64)) | (1L << (TRUE - 64)) | (1L << (FALSE - 64)) | (1L << (EXISTS - 64)) | (1L << (CASE - 64)) | (1L << (ELSE - 64)) | (1L << (END - 64)) | (1L << (WHEN - 64)) | (1L << (THEN - 64)) | (1L << (HexLetter - 64)) | (1L << (CONSTRAINT - 64)) | (1L << (DO - 64)) | (1L << (FOR - 64)) | (1L << (REQUIRE - 64)) | (1L << (UNIQUE - 64)) | (1L << (MANDATORY - 64)) | (1L << (SCALAR - 64)) | (1L << (OF - 64)) | (1L << (ADD - 64)) | (1L << (DROP - 64)) | (1L << (UnescapedSymbolicName - 64)) | (1L << (EscapedSymbolicName - 64)))) != 0)) { + { + State = 1485; oC_PropertyKeyName(); + State = 1487; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1486; Match(SP); + } + } + + State = 1489; Match(T__10); + State = 1491; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1490; Match(SP); + } + } + + State = 1493; oC_Expression(); + State = 1495; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1494; Match(SP); + } + } + + State = 1515; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + while (_la==T__1) { + { + { + State = 1497; Match(T__1); + State = 1499; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1498; Match(SP); + } + } + + State = 1501; oC_PropertyKeyName(); + State = 1503; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1502; Match(SP); + } + } + + State = 1505; Match(T__10); + State = 1507; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1506; Match(SP); + } + } + + State = 1509; oC_Expression(); + State = 1511; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1510; Match(SP); + } + } + + } + } + State = 1517; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + } + } + } + + State = 1520; Match(T__24); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_ParameterContext : ParserRuleContext { + public OC_SymbolicNameContext oC_SymbolicName() { + return GetRuleContext(0); + } + public ITerminalNode DecimalInteger() { return GetToken(CypherParser.DecimalInteger, 0); } + public OC_ParameterContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Parameter; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Parameter(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_ParameterContext oC_Parameter() { + OC_ParameterContext _localctx = new OC_ParameterContext(Context, State); + EnterRule(_localctx, 170, RULE_oC_Parameter); + try { + EnterOuterAlt(_localctx, 1); + { + State = 1522; Match(T__25); + State = 1525; + ErrorHandler.Sync(this); + switch (TokenStream.LA(1)) { + case COUNT: + case FILTER: + case EXTRACT: + case ANY: + case NONE: + case SINGLE: + case HexLetter: + case UnescapedSymbolicName: + case EscapedSymbolicName: + { + State = 1523; oC_SymbolicName(); + } + break; + case DecimalInteger: + { + State = 1524; Match(DecimalInteger); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_PropertyExpressionContext : ParserRuleContext { + public OC_AtomContext oC_Atom() { + return GetRuleContext(0); + } + public OC_PropertyLookupContext[] oC_PropertyLookup() { + return GetRuleContexts(); + } + public OC_PropertyLookupContext oC_PropertyLookup(int i) { + return GetRuleContext(i); + } + public ITerminalNode[] SP() { return GetTokens(CypherParser.SP); } + public ITerminalNode SP(int i) { + return GetToken(CypherParser.SP, i); + } + public OC_PropertyExpressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_PropertyExpression; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_PropertyExpression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_PropertyExpressionContext oC_PropertyExpression() { + OC_PropertyExpressionContext _localctx = new OC_PropertyExpressionContext(Context, State); + EnterRule(_localctx, 172, RULE_oC_PropertyExpression); + int _la; + try { + int _alt; + EnterOuterAlt(_localctx, 1); + { + State = 1527; oC_Atom(); + State = 1532; + ErrorHandler.Sync(this); + _alt = 1; + do { + switch (_alt) { + case 1: + { + { + State = 1529; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==SP) { + { + State = 1528; Match(SP); + } + } + + State = 1531; oC_PropertyLookup(); + } + } + break; + default: + throw new NoViableAltException(this); + } + State = 1534; + ErrorHandler.Sync(this); + _alt = Interpreter.AdaptivePredict(TokenStream,286,Context); + } while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_PropertyKeyNameContext : ParserRuleContext { + public OC_SchemaNameContext oC_SchemaName() { + return GetRuleContext(0); + } + public OC_PropertyKeyNameContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_PropertyKeyName; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_PropertyKeyName(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_PropertyKeyNameContext oC_PropertyKeyName() { + OC_PropertyKeyNameContext _localctx = new OC_PropertyKeyNameContext(Context, State); + EnterRule(_localctx, 174, RULE_oC_PropertyKeyName); + try { + EnterOuterAlt(_localctx, 1); + { + State = 1536; oC_SchemaName(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_IntegerLiteralContext : ParserRuleContext { + public ITerminalNode HexInteger() { return GetToken(CypherParser.HexInteger, 0); } + public ITerminalNode OctalInteger() { return GetToken(CypherParser.OctalInteger, 0); } + public ITerminalNode DecimalInteger() { return GetToken(CypherParser.DecimalInteger, 0); } + public OC_IntegerLiteralContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_IntegerLiteral; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_IntegerLiteral(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_IntegerLiteralContext oC_IntegerLiteral() { + OC_IntegerLiteralContext _localctx = new OC_IntegerLiteralContext(Context, State); + EnterRule(_localctx, 176, RULE_oC_IntegerLiteral); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1538; + _la = TokenStream.LA(1); + if ( !(((((_la - 99)) & ~0x3f) == 0 && ((1L << (_la - 99)) & ((1L << (HexInteger - 99)) | (1L << (DecimalInteger - 99)) | (1L << (OctalInteger - 99)))) != 0)) ) { + ErrorHandler.RecoverInline(this); + } + else { + ErrorHandler.ReportMatch(this); + Consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_DoubleLiteralContext : ParserRuleContext { + public ITerminalNode ExponentDecimalReal() { return GetToken(CypherParser.ExponentDecimalReal, 0); } + public ITerminalNode RegularDecimalReal() { return GetToken(CypherParser.RegularDecimalReal, 0); } + public OC_DoubleLiteralContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_DoubleLiteral; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_DoubleLiteral(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_DoubleLiteralContext oC_DoubleLiteral() { + OC_DoubleLiteralContext _localctx = new OC_DoubleLiteralContext(Context, State); + EnterRule(_localctx, 178, RULE_oC_DoubleLiteral); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1540; + _la = TokenStream.LA(1); + if ( !(_la==ExponentDecimalReal || _la==RegularDecimalReal) ) { + ErrorHandler.RecoverInline(this); + } + else { + ErrorHandler.ReportMatch(this); + Consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_SchemaNameContext : ParserRuleContext { + public OC_SymbolicNameContext oC_SymbolicName() { + return GetRuleContext(0); + } + public OC_ReservedWordContext oC_ReservedWord() { + return GetRuleContext(0); + } + public OC_SchemaNameContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_SchemaName; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_SchemaName(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_SchemaNameContext oC_SchemaName() { + OC_SchemaNameContext _localctx = new OC_SchemaNameContext(Context, State); + EnterRule(_localctx, 180, RULE_oC_SchemaName); + try { + State = 1544; + ErrorHandler.Sync(this); + switch (TokenStream.LA(1)) { + case COUNT: + case FILTER: + case EXTRACT: + case ANY: + case NONE: + case SINGLE: + case HexLetter: + case UnescapedSymbolicName: + case EscapedSymbolicName: + EnterOuterAlt(_localctx, 1); + { + State = 1542; oC_SymbolicName(); + } + break; + case UNION: + case ALL: + case OPTIONAL: + case MATCH: + case UNWIND: + case AS: + case MERGE: + case ON: + case CREATE: + case SET: + case DETACH: + case DELETE: + case REMOVE: + case WITH: + case DISTINCT: + case RETURN: + case ORDER: + case BY: + case L_SKIP: + case LIMIT: + case ASCENDING: + case ASC: + case DESCENDING: + case DESC: + case WHERE: + case OR: + case XOR: + case AND: + case NOT: + case IN: + case STARTS: + case ENDS: + case CONTAINS: + case IS: + case NULL: + case TRUE: + case FALSE: + case EXISTS: + case CASE: + case ELSE: + case END: + case WHEN: + case THEN: + case CONSTRAINT: + case DO: + case FOR: + case REQUIRE: + case UNIQUE: + case MANDATORY: + case SCALAR: + case OF: + case ADD: + case DROP: + EnterOuterAlt(_localctx, 2); + { + State = 1543; oC_ReservedWord(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_ReservedWordContext : ParserRuleContext { + public ITerminalNode ALL() { return GetToken(CypherParser.ALL, 0); } + public ITerminalNode ASC() { return GetToken(CypherParser.ASC, 0); } + public ITerminalNode ASCENDING() { return GetToken(CypherParser.ASCENDING, 0); } + public ITerminalNode BY() { return GetToken(CypherParser.BY, 0); } + public ITerminalNode CREATE() { return GetToken(CypherParser.CREATE, 0); } + public ITerminalNode DELETE() { return GetToken(CypherParser.DELETE, 0); } + public ITerminalNode DESC() { return GetToken(CypherParser.DESC, 0); } + public ITerminalNode DESCENDING() { return GetToken(CypherParser.DESCENDING, 0); } + public ITerminalNode DETACH() { return GetToken(CypherParser.DETACH, 0); } + public ITerminalNode EXISTS() { return GetToken(CypherParser.EXISTS, 0); } + public ITerminalNode LIMIT() { return GetToken(CypherParser.LIMIT, 0); } + public ITerminalNode MATCH() { return GetToken(CypherParser.MATCH, 0); } + public ITerminalNode MERGE() { return GetToken(CypherParser.MERGE, 0); } + public ITerminalNode ON() { return GetToken(CypherParser.ON, 0); } + public ITerminalNode OPTIONAL() { return GetToken(CypherParser.OPTIONAL, 0); } + public ITerminalNode ORDER() { return GetToken(CypherParser.ORDER, 0); } + public ITerminalNode REMOVE() { return GetToken(CypherParser.REMOVE, 0); } + public ITerminalNode RETURN() { return GetToken(CypherParser.RETURN, 0); } + public ITerminalNode SET() { return GetToken(CypherParser.SET, 0); } + public ITerminalNode L_SKIP() { return GetToken(CypherParser.L_SKIP, 0); } + public ITerminalNode WHERE() { return GetToken(CypherParser.WHERE, 0); } + public ITerminalNode WITH() { return GetToken(CypherParser.WITH, 0); } + public ITerminalNode UNION() { return GetToken(CypherParser.UNION, 0); } + public ITerminalNode UNWIND() { return GetToken(CypherParser.UNWIND, 0); } + public ITerminalNode AND() { return GetToken(CypherParser.AND, 0); } + public ITerminalNode AS() { return GetToken(CypherParser.AS, 0); } + public ITerminalNode CONTAINS() { return GetToken(CypherParser.CONTAINS, 0); } + public ITerminalNode DISTINCT() { return GetToken(CypherParser.DISTINCT, 0); } + public ITerminalNode ENDS() { return GetToken(CypherParser.ENDS, 0); } + public ITerminalNode IN() { return GetToken(CypherParser.IN, 0); } + public ITerminalNode IS() { return GetToken(CypherParser.IS, 0); } + public ITerminalNode NOT() { return GetToken(CypherParser.NOT, 0); } + public ITerminalNode OR() { return GetToken(CypherParser.OR, 0); } + public ITerminalNode STARTS() { return GetToken(CypherParser.STARTS, 0); } + public ITerminalNode XOR() { return GetToken(CypherParser.XOR, 0); } + public ITerminalNode FALSE() { return GetToken(CypherParser.FALSE, 0); } + public ITerminalNode TRUE() { return GetToken(CypherParser.TRUE, 0); } + public ITerminalNode NULL() { return GetToken(CypherParser.NULL, 0); } + public ITerminalNode CONSTRAINT() { return GetToken(CypherParser.CONSTRAINT, 0); } + public ITerminalNode DO() { return GetToken(CypherParser.DO, 0); } + public ITerminalNode FOR() { return GetToken(CypherParser.FOR, 0); } + public ITerminalNode REQUIRE() { return GetToken(CypherParser.REQUIRE, 0); } + public ITerminalNode UNIQUE() { return GetToken(CypherParser.UNIQUE, 0); } + public ITerminalNode CASE() { return GetToken(CypherParser.CASE, 0); } + public ITerminalNode WHEN() { return GetToken(CypherParser.WHEN, 0); } + public ITerminalNode THEN() { return GetToken(CypherParser.THEN, 0); } + public ITerminalNode ELSE() { return GetToken(CypherParser.ELSE, 0); } + public ITerminalNode END() { return GetToken(CypherParser.END, 0); } + public ITerminalNode MANDATORY() { return GetToken(CypherParser.MANDATORY, 0); } + public ITerminalNode SCALAR() { return GetToken(CypherParser.SCALAR, 0); } + public ITerminalNode OF() { return GetToken(CypherParser.OF, 0); } + public ITerminalNode ADD() { return GetToken(CypherParser.ADD, 0); } + public ITerminalNode DROP() { return GetToken(CypherParser.DROP, 0); } + public OC_ReservedWordContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_ReservedWord; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_ReservedWord(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_ReservedWordContext oC_ReservedWord() { + OC_ReservedWordContext _localctx = new OC_ReservedWordContext(Context, State); + EnterRule(_localctx, 182, RULE_oC_ReservedWord); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1546; + _la = TokenStream.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << UNION) | (1L << ALL) | (1L << OPTIONAL) | (1L << MATCH) | (1L << UNWIND) | (1L << AS) | (1L << MERGE) | (1L << ON) | (1L << CREATE) | (1L << SET) | (1L << DETACH) | (1L << DELETE) | (1L << REMOVE) | (1L << WITH) | (1L << DISTINCT) | (1L << RETURN))) != 0) || ((((_la - 64)) & ~0x3f) == 0 && ((1L << (_la - 64)) & ((1L << (ORDER - 64)) | (1L << (BY - 64)) | (1L << (L_SKIP - 64)) | (1L << (LIMIT - 64)) | (1L << (ASCENDING - 64)) | (1L << (ASC - 64)) | (1L << (DESCENDING - 64)) | (1L << (DESC - 64)) | (1L << (WHERE - 64)) | (1L << (OR - 64)) | (1L << (XOR - 64)) | (1L << (AND - 64)) | (1L << (NOT - 64)) | (1L << (IN - 64)) | (1L << (STARTS - 64)) | (1L << (ENDS - 64)) | (1L << (CONTAINS - 64)) | (1L << (IS - 64)) | (1L << (NULL - 64)) | (1L << (TRUE - 64)) | (1L << (FALSE - 64)) | (1L << (EXISTS - 64)) | (1L << (CASE - 64)) | (1L << (ELSE - 64)) | (1L << (END - 64)) | (1L << (WHEN - 64)) | (1L << (THEN - 64)) | (1L << (CONSTRAINT - 64)) | (1L << (DO - 64)) | (1L << (FOR - 64)) | (1L << (REQUIRE - 64)) | (1L << (UNIQUE - 64)) | (1L << (MANDATORY - 64)) | (1L << (SCALAR - 64)) | (1L << (OF - 64)) | (1L << (ADD - 64)) | (1L << (DROP - 64)))) != 0)) ) { + ErrorHandler.RecoverInline(this); + } + else { + ErrorHandler.ReportMatch(this); + Consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_SymbolicNameContext : ParserRuleContext { + public ITerminalNode UnescapedSymbolicName() { return GetToken(CypherParser.UnescapedSymbolicName, 0); } + public ITerminalNode EscapedSymbolicName() { return GetToken(CypherParser.EscapedSymbolicName, 0); } + public ITerminalNode HexLetter() { return GetToken(CypherParser.HexLetter, 0); } + public ITerminalNode COUNT() { return GetToken(CypherParser.COUNT, 0); } + public ITerminalNode FILTER() { return GetToken(CypherParser.FILTER, 0); } + public ITerminalNode EXTRACT() { return GetToken(CypherParser.EXTRACT, 0); } + public ITerminalNode ANY() { return GetToken(CypherParser.ANY, 0); } + public ITerminalNode NONE() { return GetToken(CypherParser.NONE, 0); } + public ITerminalNode SINGLE() { return GetToken(CypherParser.SINGLE, 0); } + public OC_SymbolicNameContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_SymbolicName; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_SymbolicName(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_SymbolicNameContext oC_SymbolicName() { + OC_SymbolicNameContext _localctx = new OC_SymbolicNameContext(Context, State); + EnterRule(_localctx, 184, RULE_oC_SymbolicName); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1548; + _la = TokenStream.LA(1); + if ( !(((((_la - 83)) & ~0x3f) == 0 && ((1L << (_la - 83)) & ((1L << (COUNT - 83)) | (1L << (FILTER - 83)) | (1L << (EXTRACT - 83)) | (1L << (ANY - 83)) | (1L << (NONE - 83)) | (1L << (SINGLE - 83)) | (1L << (HexLetter - 83)) | (1L << (UnescapedSymbolicName - 83)) | (1L << (EscapedSymbolicName - 83)))) != 0)) ) { + ErrorHandler.RecoverInline(this); + } + else { + ErrorHandler.ReportMatch(this); + Consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_LeftArrowHeadContext : ParserRuleContext { + public OC_LeftArrowHeadContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_LeftArrowHead; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_LeftArrowHead(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_LeftArrowHeadContext oC_LeftArrowHead() { + OC_LeftArrowHeadContext _localctx = new OC_LeftArrowHeadContext(Context, State); + EnterRule(_localctx, 186, RULE_oC_LeftArrowHead); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1550; + _la = TokenStream.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__18) | (1L << T__26) | (1L << T__27) | (1L << T__28) | (1L << T__29))) != 0)) ) { + ErrorHandler.RecoverInline(this); + } + else { + ErrorHandler.ReportMatch(this); + Consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_RightArrowHeadContext : ParserRuleContext { + public OC_RightArrowHeadContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_RightArrowHead; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_RightArrowHead(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_RightArrowHeadContext oC_RightArrowHead() { + OC_RightArrowHeadContext _localctx = new OC_RightArrowHeadContext(Context, State); + EnterRule(_localctx, 188, RULE_oC_RightArrowHead); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1552; + _la = TokenStream.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__19) | (1L << T__30) | (1L << T__31) | (1L << T__32) | (1L << T__33))) != 0)) ) { + ErrorHandler.RecoverInline(this); + } + else { + ErrorHandler.ReportMatch(this); + Consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class OC_DashContext : ParserRuleContext { + public OC_DashContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_oC_Dash; } } + public override TResult Accept(IParseTreeVisitor visitor) { + ICypherVisitor typedVisitor = visitor as ICypherVisitor; + if (typedVisitor != null) return typedVisitor.VisitOC_Dash(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public OC_DashContext oC_Dash() { + OC_DashContext _localctx = new OC_DashContext(Context, State); + EnterRule(_localctx, 190, RULE_oC_Dash); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 1554; + _la = TokenStream.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__44))) != 0)) ) { + ErrorHandler.RecoverInline(this); + } + else { + ErrorHandler.ReportMatch(this); + Consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + private static char[] _serializedATN = { + '\x3', '\x608B', '\xA72A', '\x8133', '\xB9ED', '\x417C', '\x3BE7', '\x7786', + '\x5964', '\x3', '\x81', '\x617', '\x4', '\x2', '\t', '\x2', '\x4', '\x3', + '\t', '\x3', '\x4', '\x4', '\t', '\x4', '\x4', '\x5', '\t', '\x5', '\x4', + '\x6', '\t', '\x6', '\x4', '\a', '\t', '\a', '\x4', '\b', '\t', '\b', + '\x4', '\t', '\t', '\t', '\x4', '\n', '\t', '\n', '\x4', '\v', '\t', '\v', + '\x4', '\f', '\t', '\f', '\x4', '\r', '\t', '\r', '\x4', '\xE', '\t', + '\xE', '\x4', '\xF', '\t', '\xF', '\x4', '\x10', '\t', '\x10', '\x4', + '\x11', '\t', '\x11', '\x4', '\x12', '\t', '\x12', '\x4', '\x13', '\t', + '\x13', '\x4', '\x14', '\t', '\x14', '\x4', '\x15', '\t', '\x15', '\x4', + '\x16', '\t', '\x16', '\x4', '\x17', '\t', '\x17', '\x4', '\x18', '\t', + '\x18', '\x4', '\x19', '\t', '\x19', '\x4', '\x1A', '\t', '\x1A', '\x4', + '\x1B', '\t', '\x1B', '\x4', '\x1C', '\t', '\x1C', '\x4', '\x1D', '\t', + '\x1D', '\x4', '\x1E', '\t', '\x1E', '\x4', '\x1F', '\t', '\x1F', '\x4', + ' ', '\t', ' ', '\x4', '!', '\t', '!', '\x4', '\"', '\t', '\"', '\x4', + '#', '\t', '#', '\x4', '$', '\t', '$', '\x4', '%', '\t', '%', '\x4', '&', + '\t', '&', '\x4', '\'', '\t', '\'', '\x4', '(', '\t', '(', '\x4', ')', + '\t', ')', '\x4', '*', '\t', '*', '\x4', '+', '\t', '+', '\x4', ',', '\t', + ',', '\x4', '-', '\t', '-', '\x4', '.', '\t', '.', '\x4', '/', '\t', '/', + '\x4', '\x30', '\t', '\x30', '\x4', '\x31', '\t', '\x31', '\x4', '\x32', + '\t', '\x32', '\x4', '\x33', '\t', '\x33', '\x4', '\x34', '\t', '\x34', + '\x4', '\x35', '\t', '\x35', '\x4', '\x36', '\t', '\x36', '\x4', '\x37', + '\t', '\x37', '\x4', '\x38', '\t', '\x38', '\x4', '\x39', '\t', '\x39', + '\x4', ':', '\t', ':', '\x4', ';', '\t', ';', '\x4', '<', '\t', '<', '\x4', + '=', '\t', '=', '\x4', '>', '\t', '>', '\x4', '?', '\t', '?', '\x4', '@', + '\t', '@', '\x4', '\x41', '\t', '\x41', '\x4', '\x42', '\t', '\x42', '\x4', + '\x43', '\t', '\x43', '\x4', '\x44', '\t', '\x44', '\x4', '\x45', '\t', + '\x45', '\x4', '\x46', '\t', '\x46', '\x4', 'G', '\t', 'G', '\x4', 'H', + '\t', 'H', '\x4', 'I', '\t', 'I', '\x4', 'J', '\t', 'J', '\x4', 'K', '\t', + 'K', '\x4', 'L', '\t', 'L', '\x4', 'M', '\t', 'M', '\x4', 'N', '\t', 'N', + '\x4', 'O', '\t', 'O', '\x4', 'P', '\t', 'P', '\x4', 'Q', '\t', 'Q', '\x4', + 'R', '\t', 'R', '\x4', 'S', '\t', 'S', '\x4', 'T', '\t', 'T', '\x4', 'U', + '\t', 'U', '\x4', 'V', '\t', 'V', '\x4', 'W', '\t', 'W', '\x4', 'X', '\t', + 'X', '\x4', 'Y', '\t', 'Y', '\x4', 'Z', '\t', 'Z', '\x4', '[', '\t', '[', + '\x4', '\\', '\t', '\\', '\x4', ']', '\t', ']', '\x4', '^', '\t', '^', + '\x4', '_', '\t', '_', '\x4', '`', '\t', '`', '\x4', '\x61', '\t', '\x61', + '\x3', '\x2', '\x5', '\x2', '\xC4', '\n', '\x2', '\x3', '\x2', '\x3', + '\x2', '\x5', '\x2', '\xC8', '\n', '\x2', '\x3', '\x2', '\x5', '\x2', + '\xCB', '\n', '\x2', '\x3', '\x2', '\x5', '\x2', '\xCE', '\n', '\x2', + '\x3', '\x2', '\x3', '\x2', '\x3', '\x3', '\x3', '\x3', '\x3', '\x4', + '\x3', '\x4', '\x5', '\x4', '\xD6', '\n', '\x4', '\x3', '\x5', '\x3', + '\x5', '\x5', '\x5', '\xDA', '\n', '\x5', '\x3', '\x5', '\a', '\x5', '\xDD', + '\n', '\x5', '\f', '\x5', '\xE', '\x5', '\xE0', '\v', '\x5', '\x3', '\x6', + '\x3', '\x6', '\x3', '\x6', '\x3', '\x6', '\x5', '\x6', '\xE6', '\n', + '\x6', '\x3', '\x6', '\x3', '\x6', '\x3', '\x6', '\x5', '\x6', '\xEB', + '\n', '\x6', '\x3', '\x6', '\x5', '\x6', '\xEE', '\n', '\x6', '\x3', '\a', + '\x3', '\a', '\x5', '\a', '\xF2', '\n', '\a', '\x3', '\b', '\x3', '\b', + '\x5', '\b', '\xF6', '\n', '\b', '\a', '\b', '\xF8', '\n', '\b', '\f', + '\b', '\xE', '\b', '\xFB', '\v', '\b', '\x3', '\b', '\x3', '\b', '\x3', + '\b', '\x5', '\b', '\x100', '\n', '\b', '\a', '\b', '\x102', '\n', '\b', + '\f', '\b', '\xE', '\b', '\x105', '\v', '\b', '\x3', '\b', '\x3', '\b', + '\x5', '\b', '\x109', '\n', '\b', '\x3', '\b', '\a', '\b', '\x10C', '\n', + '\b', '\f', '\b', '\xE', '\b', '\x10F', '\v', '\b', '\x3', '\b', '\x5', + '\b', '\x112', '\n', '\b', '\x3', '\b', '\x5', '\b', '\x115', '\n', '\b', + '\x5', '\b', '\x117', '\n', '\b', '\x3', '\t', '\x3', '\t', '\x5', '\t', + '\x11B', '\n', '\t', '\a', '\t', '\x11D', '\n', '\t', '\f', '\t', '\xE', + '\t', '\x120', '\v', '\t', '\x3', '\t', '\x3', '\t', '\x5', '\t', '\x124', + '\n', '\t', '\a', '\t', '\x126', '\n', '\t', '\f', '\t', '\xE', '\t', + '\x129', '\v', '\t', '\x3', '\t', '\x3', '\t', '\x5', '\t', '\x12D', '\n', + '\t', '\x6', '\t', '\x12F', '\n', '\t', '\r', '\t', '\xE', '\t', '\x130', + '\x3', '\t', '\x3', '\t', '\x3', '\n', '\x3', '\n', '\x3', '\n', '\x3', + '\n', '\x3', '\n', '\x5', '\n', '\x13A', '\n', '\n', '\x3', '\v', '\x3', + '\v', '\x3', '\v', '\x5', '\v', '\x13F', '\n', '\v', '\x3', '\f', '\x3', + '\f', '\x5', '\f', '\x143', '\n', '\f', '\x3', '\f', '\x3', '\f', '\x5', + '\f', '\x147', '\n', '\f', '\x3', '\f', '\x3', '\f', '\x5', '\f', '\x14B', + '\n', '\f', '\x3', '\f', '\x5', '\f', '\x14E', '\n', '\f', '\x3', '\r', + '\x3', '\r', '\x5', '\r', '\x152', '\n', '\r', '\x3', '\r', '\x3', '\r', + '\x3', '\r', '\x3', '\r', '\x3', '\r', '\x3', '\r', '\x3', '\xE', '\x3', + '\xE', '\x5', '\xE', '\x15C', '\n', '\xE', '\x3', '\xE', '\x3', '\xE', + '\x3', '\xE', '\a', '\xE', '\x161', '\n', '\xE', '\f', '\xE', '\xE', '\xE', + '\x164', '\v', '\xE', '\x3', '\xF', '\x3', '\xF', '\x3', '\xF', '\x3', + '\xF', '\x3', '\xF', '\x3', '\xF', '\x3', '\xF', '\x3', '\xF', '\x3', + '\xF', '\x3', '\xF', '\x5', '\xF', '\x170', '\n', '\xF', '\x3', '\x10', + '\x3', '\x10', '\x5', '\x10', '\x174', '\n', '\x10', '\x3', '\x10', '\x3', + '\x10', '\x3', '\x11', '\x3', '\x11', '\x5', '\x11', '\x17A', '\n', '\x11', + '\x3', '\x11', '\x3', '\x11', '\x3', '\x11', '\a', '\x11', '\x17F', '\n', + '\x11', '\f', '\x11', '\xE', '\x11', '\x182', '\v', '\x11', '\x3', '\x12', + '\x3', '\x12', '\x5', '\x12', '\x186', '\n', '\x12', '\x3', '\x12', '\x3', + '\x12', '\x5', '\x12', '\x18A', '\n', '\x12', '\x3', '\x12', '\x3', '\x12', + '\x3', '\x12', '\x3', '\x12', '\x5', '\x12', '\x190', '\n', '\x12', '\x3', + '\x12', '\x3', '\x12', '\x5', '\x12', '\x194', '\n', '\x12', '\x3', '\x12', + '\x3', '\x12', '\x3', '\x12', '\x3', '\x12', '\x5', '\x12', '\x19A', '\n', + '\x12', '\x3', '\x12', '\x3', '\x12', '\x5', '\x12', '\x19E', '\n', '\x12', + '\x3', '\x12', '\x3', '\x12', '\x3', '\x12', '\x3', '\x12', '\x5', '\x12', + '\x1A4', '\n', '\x12', '\x3', '\x12', '\x3', '\x12', '\x5', '\x12', '\x1A8', + '\n', '\x12', '\x3', '\x13', '\x3', '\x13', '\x5', '\x13', '\x1AC', '\n', + '\x13', '\x3', '\x13', '\x3', '\x13', '\x5', '\x13', '\x1B0', '\n', '\x13', + '\x3', '\x13', '\x3', '\x13', '\x5', '\x13', '\x1B4', '\n', '\x13', '\x3', + '\x13', '\x3', '\x13', '\x5', '\x13', '\x1B8', '\n', '\x13', '\x3', '\x13', + '\a', '\x13', '\x1BB', '\n', '\x13', '\f', '\x13', '\xE', '\x13', '\x1BE', + '\v', '\x13', '\x3', '\x14', '\x3', '\x14', '\x3', '\x14', '\x3', '\x14', + '\x5', '\x14', '\x1C4', '\n', '\x14', '\x3', '\x14', '\x3', '\x14', '\x5', + '\x14', '\x1C8', '\n', '\x14', '\x3', '\x14', '\a', '\x14', '\x1CB', '\n', + '\x14', '\f', '\x14', '\xE', '\x14', '\x1CE', '\v', '\x14', '\x3', '\x15', + '\x3', '\x15', '\x3', '\x15', '\x3', '\x15', '\x5', '\x15', '\x1D4', '\n', + '\x15', '\x3', '\x16', '\x3', '\x16', '\x3', '\x16', '\x3', '\x16', '\x5', + '\x16', '\x1DA', '\n', '\x16', '\x3', '\x16', '\x3', '\x16', '\x3', '\x16', + '\x5', '\x16', '\x1DF', '\n', '\x16', '\x3', '\x17', '\x3', '\x17', '\x3', + '\x17', '\x3', '\x17', '\x5', '\x17', '\x1E5', '\n', '\x17', '\x3', '\x17', + '\x3', '\x17', '\x3', '\x17', '\x3', '\x17', '\x5', '\x17', '\x1EB', '\n', + '\x17', '\x3', '\x18', '\x3', '\x18', '\x5', '\x18', '\x1EF', '\n', '\x18', + '\x3', '\x18', '\x3', '\x18', '\x5', '\x18', '\x1F3', '\n', '\x18', '\x3', + '\x18', '\a', '\x18', '\x1F6', '\n', '\x18', '\f', '\x18', '\xE', '\x18', + '\x1F9', '\v', '\x18', '\x3', '\x18', '\x5', '\x18', '\x1FC', '\n', '\x18', + '\x3', '\x19', '\x3', '\x19', '\x3', '\x19', '\x3', '\x19', '\x3', '\x19', + '\x5', '\x19', '\x203', '\n', '\x19', '\x3', '\x19', '\x3', '\x19', '\x3', + '\x1A', '\x3', '\x1A', '\x5', '\x1A', '\x209', '\n', '\x1A', '\x3', '\x1A', + '\x5', '\x1A', '\x20C', '\n', '\x1A', '\x3', '\x1A', '\x3', '\x1A', '\x3', + '\x1A', '\x5', '\x1A', '\x211', '\n', '\x1A', '\x3', '\x1A', '\x5', '\x1A', + '\x214', '\n', '\x1A', '\x3', '\x1B', '\x3', '\x1B', '\x5', '\x1B', '\x218', + '\n', '\x1B', '\x3', '\x1B', '\x5', '\x1B', '\x21B', '\n', '\x1B', '\x3', + '\x1B', '\x3', '\x1B', '\x3', '\x1B', '\x3', '\x1C', '\x3', '\x1C', '\x3', + '\x1C', '\x5', '\x1C', '\x223', '\n', '\x1C', '\x3', '\x1C', '\x3', '\x1C', + '\x5', '\x1C', '\x227', '\n', '\x1C', '\x3', '\x1C', '\x3', '\x1C', '\x5', + '\x1C', '\x22B', '\n', '\x1C', '\x3', '\x1D', '\x3', '\x1D', '\x5', '\x1D', + '\x22F', '\n', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x5', '\x1D', '\x233', + '\n', '\x1D', '\x3', '\x1D', '\a', '\x1D', '\x236', '\n', '\x1D', '\f', + '\x1D', '\xE', '\x1D', '\x239', '\v', '\x1D', '\x3', '\x1D', '\x3', '\x1D', + '\x5', '\x1D', '\x23D', '\n', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x5', + '\x1D', '\x241', '\n', '\x1D', '\x3', '\x1D', '\a', '\x1D', '\x244', '\n', + '\x1D', '\f', '\x1D', '\xE', '\x1D', '\x247', '\v', '\x1D', '\x5', '\x1D', + '\x249', '\n', '\x1D', '\x3', '\x1E', '\x3', '\x1E', '\x3', '\x1E', '\x3', + '\x1E', '\x3', '\x1E', '\x3', '\x1E', '\x3', '\x1E', '\x5', '\x1E', '\x252', + '\n', '\x1E', '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', + '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', '\x5', '\x1F', '\x25B', '\n', + '\x1F', '\x3', '\x1F', '\a', '\x1F', '\x25E', '\n', '\x1F', '\f', '\x1F', + '\xE', '\x1F', '\x261', '\v', '\x1F', '\x3', ' ', '\x3', ' ', '\x3', ' ', + '\x3', ' ', '\x3', '!', '\x3', '!', '\x3', '!', '\x3', '!', '\x3', '\"', + '\x3', '\"', '\x5', '\"', '\x26D', '\n', '\"', '\x3', '\"', '\x5', '\"', + '\x270', '\n', '\"', '\x3', '#', '\x3', '#', '\x3', '#', '\x3', '#', '\x3', + '$', '\x3', '$', '\x5', '$', '\x278', '\n', '$', '\x3', '$', '\x3', '$', + '\x5', '$', '\x27C', '\n', '$', '\x3', '$', '\a', '$', '\x27F', '\n', + '$', '\f', '$', '\xE', '$', '\x282', '\v', '$', '\x3', '%', '\x3', '%', + '\x5', '%', '\x286', '\n', '%', '\x3', '%', '\x3', '%', '\x5', '%', '\x28A', + '\n', '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x5', '%', '\x28F', '\n', + '%', '\x3', '&', '\x3', '&', '\x3', '\'', '\x3', '\'', '\x5', '\'', '\x295', + '\n', '\'', '\x3', '\'', '\a', '\'', '\x298', '\n', '\'', '\f', '\'', + '\xE', '\'', '\x29B', '\v', '\'', '\x3', '\'', '\x3', '\'', '\x3', '\'', + '\x3', '\'', '\x5', '\'', '\x2A1', '\n', '\'', '\x3', '(', '\x3', '(', + '\x5', '(', '\x2A5', '\n', '(', '\x3', '(', '\x3', '(', '\x5', '(', '\x2A9', + '\n', '(', '\x5', '(', '\x2AB', '\n', '(', '\x3', '(', '\x3', '(', '\x5', + '(', '\x2AF', '\n', '(', '\x5', '(', '\x2B1', '\n', '(', '\x3', '(', '\x3', + '(', '\x5', '(', '\x2B5', '\n', '(', '\x5', '(', '\x2B7', '\n', '(', '\x3', + '(', '\x3', '(', '\x3', ')', '\x3', ')', '\x5', ')', '\x2BD', '\n', ')', + '\x3', ')', '\x3', ')', '\x3', '*', '\x3', '*', '\x5', '*', '\x2C3', '\n', + '*', '\x3', '*', '\x3', '*', '\x5', '*', '\x2C7', '\n', '*', '\x3', '*', + '\x5', '*', '\x2CA', '\n', '*', '\x3', '*', '\x5', '*', '\x2CD', '\n', + '*', '\x3', '*', '\x3', '*', '\x5', '*', '\x2D1', '\n', '*', '\x3', '*', + '\x3', '*', '\x3', '*', '\x3', '*', '\x5', '*', '\x2D7', '\n', '*', '\x3', + '*', '\x3', '*', '\x5', '*', '\x2DB', '\n', '*', '\x3', '*', '\x5', '*', + '\x2DE', '\n', '*', '\x3', '*', '\x5', '*', '\x2E1', '\n', '*', '\x3', + '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x5', '*', '\x2E7', '\n', '*', + '\x3', '*', '\x5', '*', '\x2EA', '\n', '*', '\x3', '*', '\x5', '*', '\x2ED', + '\n', '*', '\x3', '*', '\x3', '*', '\x5', '*', '\x2F1', '\n', '*', '\x3', + '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x5', '*', '\x2F7', '\n', '*', + '\x3', '*', '\x5', '*', '\x2FA', '\n', '*', '\x3', '*', '\x5', '*', '\x2FD', + '\n', '*', '\x3', '*', '\x3', '*', '\x5', '*', '\x301', '\n', '*', '\x3', + '+', '\x3', '+', '\x5', '+', '\x305', '\n', '+', '\x3', '+', '\x3', '+', + '\x5', '+', '\x309', '\n', '+', '\x5', '+', '\x30B', '\n', '+', '\x3', + '+', '\x3', '+', '\x5', '+', '\x30F', '\n', '+', '\x5', '+', '\x311', + '\n', '+', '\x3', '+', '\x5', '+', '\x314', '\n', '+', '\x3', '+', '\x3', + '+', '\x5', '+', '\x318', '\n', '+', '\x5', '+', '\x31A', '\n', '+', '\x3', + '+', '\x3', '+', '\x3', ',', '\x3', ',', '\x5', ',', '\x320', '\n', ',', + '\x3', '-', '\x3', '-', '\x5', '-', '\x324', '\n', '-', '\x3', '-', '\x3', + '-', '\x5', '-', '\x328', '\n', '-', '\x3', '-', '\x3', '-', '\x5', '-', + '\x32C', '\n', '-', '\x3', '-', '\x5', '-', '\x32F', '\n', '-', '\x3', + '-', '\a', '-', '\x332', '\n', '-', '\f', '-', '\xE', '-', '\x335', '\v', + '-', '\x3', '.', '\x3', '.', '\x5', '.', '\x339', '\n', '.', '\x3', '.', + '\a', '.', '\x33C', '\n', '.', '\f', '.', '\xE', '.', '\x33F', '\v', '.', + '\x3', '/', '\x3', '/', '\x5', '/', '\x343', '\n', '/', '\x3', '/', '\x3', + '/', '\x3', '\x30', '\x3', '\x30', '\x5', '\x30', '\x349', '\n', '\x30', + '\x3', '\x30', '\x3', '\x30', '\x5', '\x30', '\x34D', '\n', '\x30', '\x5', + '\x30', '\x34F', '\n', '\x30', '\x3', '\x30', '\x3', '\x30', '\x5', '\x30', + '\x353', '\n', '\x30', '\x3', '\x30', '\x3', '\x30', '\x5', '\x30', '\x357', + '\n', '\x30', '\x5', '\x30', '\x359', '\n', '\x30', '\x5', '\x30', '\x35B', + '\n', '\x30', '\x3', '\x31', '\x3', '\x31', '\x3', '\x32', '\x3', '\x32', + '\x3', '\x33', '\x3', '\x33', '\x3', '\x34', '\x3', '\x34', '\x3', '\x34', + '\x3', '\x34', '\x3', '\x34', '\a', '\x34', '\x368', '\n', '\x34', '\f', + '\x34', '\xE', '\x34', '\x36B', '\v', '\x34', '\x3', '\x35', '\x3', '\x35', + '\x3', '\x35', '\x3', '\x35', '\x3', '\x35', '\a', '\x35', '\x372', '\n', + '\x35', '\f', '\x35', '\xE', '\x35', '\x375', '\v', '\x35', '\x3', '\x36', + '\x3', '\x36', '\x3', '\x36', '\x3', '\x36', '\x3', '\x36', '\a', '\x36', + '\x37C', '\n', '\x36', '\f', '\x36', '\xE', '\x36', '\x37F', '\v', '\x36', + '\x3', '\x37', '\x3', '\x37', '\x5', '\x37', '\x383', '\n', '\x37', '\a', + '\x37', '\x385', '\n', '\x37', '\f', '\x37', '\xE', '\x37', '\x388', '\v', + '\x37', '\x3', '\x37', '\x3', '\x37', '\x3', '\x38', '\x3', '\x38', '\x5', + '\x38', '\x38E', '\n', '\x38', '\x3', '\x38', '\a', '\x38', '\x391', '\n', + '\x38', '\f', '\x38', '\xE', '\x38', '\x394', '\v', '\x38', '\x3', '\x39', + '\x3', '\x39', '\x5', '\x39', '\x398', '\n', '\x39', '\x3', '\x39', '\x3', + '\x39', '\x5', '\x39', '\x39C', '\n', '\x39', '\x3', '\x39', '\x3', '\x39', + '\x5', '\x39', '\x3A0', '\n', '\x39', '\x3', '\x39', '\x3', '\x39', '\x5', + '\x39', '\x3A4', '\n', '\x39', '\x3', '\x39', '\a', '\x39', '\x3A7', '\n', + '\x39', '\f', '\x39', '\xE', '\x39', '\x3AA', '\v', '\x39', '\x3', ':', + '\x3', ':', '\x5', ':', '\x3AE', '\n', ':', '\x3', ':', '\x3', ':', '\x5', + ':', '\x3B2', '\n', ':', '\x3', ':', '\x3', ':', '\x5', ':', '\x3B6', + '\n', ':', '\x3', ':', '\x3', ':', '\x5', ':', '\x3BA', '\n', ':', '\x3', + ':', '\x3', ':', '\x5', ':', '\x3BE', '\n', ':', '\x3', ':', '\x3', ':', + '\x5', ':', '\x3C2', '\n', ':', '\x3', ':', '\a', ':', '\x3C5', '\n', + ':', '\f', ':', '\xE', ':', '\x3C8', '\v', ':', '\x3', ';', '\x3', ';', + '\x5', ';', '\x3CC', '\n', ';', '\x3', ';', '\x3', ';', '\x5', ';', '\x3D0', + '\n', ';', '\x3', ';', '\a', ';', '\x3D3', '\n', ';', '\f', ';', '\xE', + ';', '\x3D6', '\v', ';', '\x3', '<', '\x3', '<', '\x5', '<', '\x3DA', + '\n', '<', '\a', '<', '\x3DC', '\n', '<', '\f', '<', '\xE', '<', '\x3DF', + '\v', '<', '\x3', '<', '\x3', '<', '\x3', '=', '\x3', '=', '\x5', '=', + '\x3E5', '\n', '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', + '=', '\x5', '=', '\x3EC', '\n', '=', '\x3', '=', '\x3', '=', '\x5', '=', + '\x3F0', '\n', '=', '\x3', '=', '\x3', '=', '\x5', '=', '\x3F4', '\n', + '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', + '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', + '=', '\x3', '=', '\x5', '=', '\x403', '\n', '=', '\x3', '=', '\x5', '=', + '\x406', '\n', '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', + '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', '=', '\x3', + '=', '\a', '=', '\x413', '\n', '=', '\f', '=', '\xE', '=', '\x416', '\v', + '=', '\x3', '>', '\x3', '>', '\x5', '>', '\x41A', '\n', '>', '\x3', '>', + '\a', '>', '\x41D', '\n', '>', '\f', '>', '\xE', '>', '\x420', '\v', '>', + '\x3', '>', '\x5', '>', '\x423', '\n', '>', '\x3', '>', '\x5', '>', '\x426', + '\n', '>', '\x3', '?', '\x3', '?', '\x3', '?', '\x3', '?', '\x3', '?', + '\x5', '?', '\x42D', '\n', '?', '\x3', '?', '\x3', '?', '\x5', '?', '\x431', + '\n', '?', '\x3', '?', '\x3', '?', '\x5', '?', '\x435', '\n', '?', '\x3', + '?', '\x3', '?', '\x3', '?', '\x3', '?', '\x3', '?', '\x5', '?', '\x43C', + '\n', '?', '\x3', '?', '\x3', '?', '\x5', '?', '\x440', '\n', '?', '\x3', + '?', '\x3', '?', '\x5', '?', '\x444', '\n', '?', '\x3', '?', '\x3', '?', + '\x3', '?', '\x3', '?', '\x5', '?', '\x44A', '\n', '?', '\x3', '?', '\x3', + '?', '\x5', '?', '\x44E', '\n', '?', '\x3', '?', '\x3', '?', '\x5', '?', + '\x452', '\n', '?', '\x3', '?', '\x5', '?', '\x455', '\n', '?', '\x3', + '?', '\x3', '?', '\x5', '?', '\x459', '\n', '?', '\x3', '?', '\x3', '?', + '\x3', '?', '\x3', '?', '\x5', '?', '\x45F', '\n', '?', '\x3', '?', '\x3', + '?', '\x5', '?', '\x463', '\n', '?', '\x3', '?', '\x3', '?', '\x5', '?', + '\x467', '\n', '?', '\x3', '?', '\x3', '?', '\x3', '?', '\x3', '?', '\x5', + '?', '\x46D', '\n', '?', '\x3', '?', '\x3', '?', '\x5', '?', '\x471', + '\n', '?', '\x3', '?', '\x3', '?', '\x5', '?', '\x475', '\n', '?', '\x3', + '?', '\x3', '?', '\x3', '?', '\x3', '?', '\x5', '?', '\x47B', '\n', '?', + '\x3', '?', '\x3', '?', '\x5', '?', '\x47F', '\n', '?', '\x3', '?', '\x3', + '?', '\x5', '?', '\x483', '\n', '?', '\x3', '?', '\x3', '?', '\x3', '?', + '\x3', '?', '\x5', '?', '\x489', '\n', '?', '\x3', '?', '\x3', '?', '\x5', + '?', '\x48D', '\n', '?', '\x3', '?', '\x3', '?', '\x5', '?', '\x491', + '\n', '?', '\x3', '?', '\x3', '?', '\x3', '?', '\x3', '?', '\x3', '?', + '\x3', '?', '\x5', '?', '\x499', '\n', '?', '\x3', '@', '\x3', '@', '\x3', + '@', '\x3', '@', '\x3', '@', '\x3', '@', '\x5', '@', '\x4A1', '\n', '@', + '\x3', '\x41', '\x3', '\x41', '\x3', '\x42', '\x3', '\x42', '\x5', '\x42', + '\x4A7', '\n', '\x42', '\x3', '\x42', '\x3', '\x42', '\x5', '\x42', '\x4AB', + '\n', '\x42', '\x3', '\x42', '\x3', '\x42', '\x5', '\x42', '\x4AF', '\n', + '\x42', '\x3', '\x42', '\x3', '\x42', '\x5', '\x42', '\x4B3', '\n', '\x42', + '\a', '\x42', '\x4B5', '\n', '\x42', '\f', '\x42', '\xE', '\x42', '\x4B8', + '\v', '\x42', '\x5', '\x42', '\x4BA', '\n', '\x42', '\x3', '\x42', '\x3', + '\x42', '\x3', '\x43', '\x3', '\x43', '\x5', '\x43', '\x4C0', '\n', '\x43', + '\x3', '\x43', '\x3', '\x43', '\x3', '\x43', '\x5', '\x43', '\x4C5', '\n', + '\x43', '\x3', '\x43', '\x3', '\x43', '\x3', '\x43', '\x5', '\x43', '\x4CA', + '\n', '\x43', '\x3', '\x43', '\x3', '\x43', '\x3', '\x43', '\x5', '\x43', + '\x4CF', '\n', '\x43', '\x3', '\x43', '\x3', '\x43', '\x3', '\x43', '\x5', + '\x43', '\x4D4', '\n', '\x43', '\x3', '\x43', '\x3', '\x43', '\x3', '\x43', + '\x5', '\x43', '\x4D9', '\n', '\x43', '\x3', '\x43', '\x5', '\x43', '\x4DC', + '\n', '\x43', '\x3', '\x44', '\x3', '\x44', '\x5', '\x44', '\x4E0', '\n', + '\x44', '\x3', '\x44', '\x3', '\x44', '\x5', '\x44', '\x4E4', '\n', '\x44', + '\x3', '\x44', '\x3', '\x44', '\x3', '\x45', '\x3', '\x45', '\x5', '\x45', + '\x4EA', '\n', '\x45', '\x3', '\x45', '\x6', '\x45', '\x4ED', '\n', '\x45', + '\r', '\x45', '\xE', '\x45', '\x4EE', '\x3', '\x46', '\x3', '\x46', '\x5', + '\x46', '\x4F3', '\n', '\x46', '\x3', '\x46', '\x5', '\x46', '\x4F6', + '\n', '\x46', '\x3', 'G', '\x3', 'G', '\x3', 'G', '\x3', 'G', '\x3', 'G', + '\x3', 'G', '\x3', 'H', '\x3', 'H', '\x5', 'H', '\x500', '\n', 'H', '\x3', + 'H', '\x3', 'H', '\x5', 'H', '\x504', '\n', 'H', '\x3', 'H', '\x3', 'H', + '\x5', 'H', '\x508', '\n', 'H', '\x5', 'H', '\x50A', '\n', 'H', '\x3', + 'H', '\x3', 'H', '\x5', 'H', '\x50E', '\n', 'H', '\x3', 'H', '\x3', 'H', + '\x5', 'H', '\x512', '\n', 'H', '\x3', 'H', '\x3', 'H', '\x5', 'H', '\x516', + '\n', 'H', '\a', 'H', '\x518', '\n', 'H', '\f', 'H', '\xE', 'H', '\x51B', + '\v', 'H', '\x5', 'H', '\x51D', '\n', 'H', '\x3', 'H', '\x3', 'H', '\x3', + 'I', '\x3', 'I', '\x5', 'I', '\x523', '\n', 'I', '\x3', 'J', '\x3', 'J', + '\x5', 'J', '\x527', '\n', 'J', '\x3', 'J', '\x3', 'J', '\x5', 'J', '\x52B', + '\n', 'J', '\x3', 'J', '\x3', 'J', '\x5', 'J', '\x52F', '\n', 'J', '\x3', + 'J', '\x3', 'J', '\x5', 'J', '\x533', '\n', 'J', '\x3', 'J', '\x3', 'J', + '\x5', 'J', '\x537', '\n', 'J', '\a', 'J', '\x539', '\n', 'J', '\f', 'J', + '\xE', 'J', '\x53C', '\v', 'J', '\x5', 'J', '\x53E', '\n', 'J', '\x3', + 'J', '\x3', 'J', '\x3', 'K', '\x3', 'K', '\x3', 'L', '\x3', 'L', '\x3', + 'M', '\x3', 'M', '\x3', 'M', '\x3', 'N', '\x3', 'N', '\x3', 'N', '\a', + 'N', '\x54C', '\n', 'N', '\f', 'N', '\xE', 'N', '\x54F', '\v', 'N', '\x3', + 'O', '\x3', 'O', '\x5', 'O', '\x553', '\n', 'O', '\x3', 'O', '\x3', 'O', + '\x5', 'O', '\x557', '\n', 'O', '\x3', 'O', '\x3', 'O', '\x5', 'O', '\x55B', + '\n', 'O', '\x3', 'O', '\x5', 'O', '\x55E', '\n', 'O', '\x3', 'O', '\x5', + 'O', '\x561', '\n', 'O', '\x3', 'O', '\x3', 'O', '\x3', 'P', '\x3', 'P', + '\x5', 'P', '\x567', '\n', 'P', '\x3', 'P', '\x3', 'P', '\x5', 'P', '\x56B', + '\n', 'P', '\x3', 'P', '\x3', 'P', '\x5', 'P', '\x56F', '\n', 'P', '\x5', + 'P', '\x571', '\n', 'P', '\x3', 'P', '\x3', 'P', '\x5', 'P', '\x575', + '\n', 'P', '\x3', 'P', '\x3', 'P', '\x5', 'P', '\x579', '\n', 'P', '\x3', + 'P', '\x3', 'P', '\x5', 'P', '\x57D', '\n', 'P', '\x5', 'P', '\x57F', + '\n', 'P', '\x3', 'P', '\x3', 'P', '\x5', 'P', '\x583', '\n', 'P', '\x3', + 'P', '\x3', 'P', '\x5', 'P', '\x587', '\n', 'P', '\x3', 'P', '\x3', 'P', + '\x3', 'Q', '\x3', 'Q', '\x5', 'Q', '\x58D', '\n', 'Q', '\x3', 'Q', '\x3', + 'Q', '\x3', 'R', '\x3', 'R', '\x5', 'R', '\x593', '\n', 'R', '\x3', 'R', + '\x6', 'R', '\x596', '\n', 'R', '\r', 'R', '\xE', 'R', '\x597', '\x3', + 'R', '\x3', 'R', '\x5', 'R', '\x59C', '\n', 'R', '\x3', 'R', '\x3', 'R', + '\x5', 'R', '\x5A0', '\n', 'R', '\x3', 'R', '\x6', 'R', '\x5A3', '\n', + 'R', '\r', 'R', '\xE', 'R', '\x5A4', '\x5', 'R', '\x5A7', '\n', 'R', '\x3', + 'R', '\x5', 'R', '\x5AA', '\n', 'R', '\x3', 'R', '\x3', 'R', '\x5', 'R', + '\x5AE', '\n', 'R', '\x3', 'R', '\x5', 'R', '\x5B1', '\n', 'R', '\x3', + 'R', '\x5', 'R', '\x5B4', '\n', 'R', '\x3', 'R', '\x3', 'R', '\x3', 'S', + '\x3', 'S', '\x5', 'S', '\x5BA', '\n', 'S', '\x3', 'S', '\x3', 'S', '\x5', + 'S', '\x5BE', '\n', 'S', '\x3', 'S', '\x3', 'S', '\x5', 'S', '\x5C2', + '\n', 'S', '\x3', 'S', '\x3', 'S', '\x3', 'T', '\x3', 'T', '\x3', 'U', + '\x3', 'U', '\x5', 'U', '\x5CA', '\n', 'U', '\x3', 'V', '\x3', 'V', '\x5', + 'V', '\x5CE', '\n', 'V', '\x3', 'V', '\x3', 'V', '\x5', 'V', '\x5D2', + '\n', 'V', '\x3', 'V', '\x3', 'V', '\x5', 'V', '\x5D6', '\n', 'V', '\x3', + 'V', '\x3', 'V', '\x5', 'V', '\x5DA', '\n', 'V', '\x3', 'V', '\x3', 'V', + '\x5', 'V', '\x5DE', '\n', 'V', '\x3', 'V', '\x3', 'V', '\x5', 'V', '\x5E2', + '\n', 'V', '\x3', 'V', '\x3', 'V', '\x5', 'V', '\x5E6', '\n', 'V', '\x3', + 'V', '\x3', 'V', '\x5', 'V', '\x5EA', '\n', 'V', '\a', 'V', '\x5EC', '\n', + 'V', '\f', 'V', '\xE', 'V', '\x5EF', '\v', 'V', '\x5', 'V', '\x5F1', '\n', + 'V', '\x3', 'V', '\x3', 'V', '\x3', 'W', '\x3', 'W', '\x3', 'W', '\x5', + 'W', '\x5F8', '\n', 'W', '\x3', 'X', '\x3', 'X', '\x5', 'X', '\x5FC', + '\n', 'X', '\x3', 'X', '\x6', 'X', '\x5FF', '\n', 'X', '\r', 'X', '\xE', + 'X', '\x600', '\x3', 'Y', '\x3', 'Y', '\x3', 'Z', '\x3', 'Z', '\x3', '[', + '\x3', '[', '\x3', '\\', '\x3', '\\', '\x5', '\\', '\x60B', '\n', '\\', + '\x3', ']', '\x3', ']', '\x3', '^', '\x3', '^', '\x3', '_', '\x3', '_', + '\x3', '`', '\x3', '`', '\x3', '\x61', '\x3', '\x61', '\x3', '\x61', '\x2', + '\x2', '\x62', '\x2', '\x4', '\x6', '\b', '\n', '\f', '\xE', '\x10', '\x12', + '\x14', '\x16', '\x18', '\x1A', '\x1C', '\x1E', ' ', '\"', '$', '&', '(', + '*', ',', '.', '\x30', '\x32', '\x34', '\x36', '\x38', ':', '<', '>', + '@', '\x42', '\x44', '\x46', 'H', 'J', 'L', 'N', 'P', 'R', 'T', 'V', 'X', + 'Z', '\\', '^', '`', '\x62', '\x64', '\x66', 'h', 'j', 'l', 'n', 'p', + 'r', 't', 'v', 'x', 'z', '|', '~', '\x80', '\x82', '\x84', '\x86', '\x88', + '\x8A', '\x8C', '\x8E', '\x90', '\x92', '\x94', '\x96', '\x98', '\x9A', + '\x9C', '\x9E', '\xA0', '\xA2', '\xA4', '\xA6', '\xA8', '\xAA', '\xAC', + '\xAE', '\xB0', '\xB2', '\xB4', '\xB6', '\xB8', '\xBA', '\xBC', '\xBE', + '\xC0', '\x2', '\f', '\x3', '\x2', '\x46', 'I', '\x4', '\x2', '\a', '\a', + '\x10', '\x10', '\x3', '\x2', '[', '\\', '\x3', '\x2', '\x65', 'g', '\x3', + '\x2', 'o', 'p', '\x6', '\x2', '\x30', '<', '?', 'T', '[', '\x62', 'q', + 'z', '\x6', '\x2', 'U', 'Z', 'h', 'h', '{', '{', '~', '~', '\x4', '\x2', + '\x15', '\x15', '\x1D', ' ', '\x4', '\x2', '\x16', '\x16', '!', '$', '\x4', + '\x2', '\a', '\a', '%', '/', '\x2', '\x6FA', '\x2', '\xC3', '\x3', '\x2', + '\x2', '\x2', '\x4', '\xD1', '\x3', '\x2', '\x2', '\x2', '\x6', '\xD5', + '\x3', '\x2', '\x2', '\x2', '\b', '\xD7', '\x3', '\x2', '\x2', '\x2', + '\n', '\xED', '\x3', '\x2', '\x2', '\x2', '\f', '\xF1', '\x3', '\x2', + '\x2', '\x2', '\xE', '\x116', '\x3', '\x2', '\x2', '\x2', '\x10', '\x12E', + '\x3', '\x2', '\x2', '\x2', '\x12', '\x139', '\x3', '\x2', '\x2', '\x2', + '\x14', '\x13E', '\x3', '\x2', '\x2', '\x2', '\x16', '\x142', '\x3', '\x2', + '\x2', '\x2', '\x18', '\x14F', '\x3', '\x2', '\x2', '\x2', '\x1A', '\x159', + '\x3', '\x2', '\x2', '\x2', '\x1C', '\x16F', '\x3', '\x2', '\x2', '\x2', + '\x1E', '\x171', '\x3', '\x2', '\x2', '\x2', ' ', '\x177', '\x3', '\x2', + '\x2', '\x2', '\"', '\x1A7', '\x3', '\x2', '\x2', '\x2', '$', '\x1AB', + '\x3', '\x2', '\x2', '\x2', '&', '\x1BF', '\x3', '\x2', '\x2', '\x2', + '(', '\x1D3', '\x3', '\x2', '\x2', '\x2', '*', '\x1D5', '\x3', '\x2', + '\x2', '\x2', ',', '\x1E0', '\x3', '\x2', '\x2', '\x2', '.', '\x1FB', + '\x3', '\x2', '\x2', '\x2', '\x30', '\x202', '\x3', '\x2', '\x2', '\x2', + '\x32', '\x206', '\x3', '\x2', '\x2', '\x2', '\x34', '\x215', '\x3', '\x2', + '\x2', '\x2', '\x36', '\x21F', '\x3', '\x2', '\x2', '\x2', '\x38', '\x248', + '\x3', '\x2', '\x2', '\x2', ':', '\x251', '\x3', '\x2', '\x2', '\x2', + '<', '\x253', '\x3', '\x2', '\x2', '\x2', '>', '\x262', '\x3', '\x2', + '\x2', '\x2', '@', '\x266', '\x3', '\x2', '\x2', '\x2', '\x42', '\x26A', + '\x3', '\x2', '\x2', '\x2', '\x44', '\x271', '\x3', '\x2', '\x2', '\x2', + '\x46', '\x275', '\x3', '\x2', '\x2', '\x2', 'H', '\x28E', '\x3', '\x2', + '\x2', '\x2', 'J', '\x290', '\x3', '\x2', '\x2', '\x2', 'L', '\x2A0', + '\x3', '\x2', '\x2', '\x2', 'N', '\x2A2', '\x3', '\x2', '\x2', '\x2', + 'P', '\x2BA', '\x3', '\x2', '\x2', '\x2', 'R', '\x300', '\x3', '\x2', + '\x2', '\x2', 'T', '\x302', '\x3', '\x2', '\x2', '\x2', 'V', '\x31F', + '\x3', '\x2', '\x2', '\x2', 'X', '\x321', '\x3', '\x2', '\x2', '\x2', + 'Z', '\x336', '\x3', '\x2', '\x2', '\x2', '\\', '\x340', '\x3', '\x2', + '\x2', '\x2', '^', '\x346', '\x3', '\x2', '\x2', '\x2', '`', '\x35C', + '\x3', '\x2', '\x2', '\x2', '\x62', '\x35E', '\x3', '\x2', '\x2', '\x2', + '\x64', '\x360', '\x3', '\x2', '\x2', '\x2', '\x66', '\x362', '\x3', '\x2', + '\x2', '\x2', 'h', '\x36C', '\x3', '\x2', '\x2', '\x2', 'j', '\x376', + '\x3', '\x2', '\x2', '\x2', 'l', '\x386', '\x3', '\x2', '\x2', '\x2', + 'n', '\x38B', '\x3', '\x2', '\x2', '\x2', 'p', '\x395', '\x3', '\x2', + '\x2', '\x2', 'r', '\x3AB', '\x3', '\x2', '\x2', '\x2', 't', '\x3C9', + '\x3', '\x2', '\x2', '\x2', 'v', '\x3DD', '\x3', '\x2', '\x2', '\x2', + 'x', '\x3E2', '\x3', '\x2', '\x2', '\x2', 'z', '\x417', '\x3', '\x2', + '\x2', '\x2', '|', '\x498', '\x3', '\x2', '\x2', '\x2', '~', '\x4A0', + '\x3', '\x2', '\x2', '\x2', '\x80', '\x4A2', '\x3', '\x2', '\x2', '\x2', + '\x82', '\x4A4', '\x3', '\x2', '\x2', '\x2', '\x84', '\x4DB', '\x3', '\x2', + '\x2', '\x2', '\x86', '\x4DD', '\x3', '\x2', '\x2', '\x2', '\x88', '\x4E7', + '\x3', '\x2', '\x2', '\x2', '\x8A', '\x4F0', '\x3', '\x2', '\x2', '\x2', + '\x8C', '\x4F7', '\x3', '\x2', '\x2', '\x2', '\x8E', '\x4FD', '\x3', '\x2', + '\x2', '\x2', '\x90', '\x522', '\x3', '\x2', '\x2', '\x2', '\x92', '\x524', + '\x3', '\x2', '\x2', '\x2', '\x94', '\x541', '\x3', '\x2', '\x2', '\x2', + '\x96', '\x543', '\x3', '\x2', '\x2', '\x2', '\x98', '\x545', '\x3', '\x2', + '\x2', '\x2', '\x9A', '\x54D', '\x3', '\x2', '\x2', '\x2', '\x9C', '\x550', + '\x3', '\x2', '\x2', '\x2', '\x9E', '\x564', '\x3', '\x2', '\x2', '\x2', + '\xA0', '\x58A', '\x3', '\x2', '\x2', '\x2', '\xA2', '\x5A6', '\x3', '\x2', + '\x2', '\x2', '\xA4', '\x5B7', '\x3', '\x2', '\x2', '\x2', '\xA6', '\x5C5', + '\x3', '\x2', '\x2', '\x2', '\xA8', '\x5C9', '\x3', '\x2', '\x2', '\x2', + '\xAA', '\x5CB', '\x3', '\x2', '\x2', '\x2', '\xAC', '\x5F4', '\x3', '\x2', + '\x2', '\x2', '\xAE', '\x5F9', '\x3', '\x2', '\x2', '\x2', '\xB0', '\x602', + '\x3', '\x2', '\x2', '\x2', '\xB2', '\x604', '\x3', '\x2', '\x2', '\x2', + '\xB4', '\x606', '\x3', '\x2', '\x2', '\x2', '\xB6', '\x60A', '\x3', '\x2', + '\x2', '\x2', '\xB8', '\x60C', '\x3', '\x2', '\x2', '\x2', '\xBA', '\x60E', + '\x3', '\x2', '\x2', '\x2', '\xBC', '\x610', '\x3', '\x2', '\x2', '\x2', + '\xBE', '\x612', '\x3', '\x2', '\x2', '\x2', '\xC0', '\x614', '\x3', '\x2', + '\x2', '\x2', '\xC2', '\xC4', '\a', '\x7F', '\x2', '\x2', '\xC3', '\xC2', + '\x3', '\x2', '\x2', '\x2', '\xC3', '\xC4', '\x3', '\x2', '\x2', '\x2', + '\xC4', '\xC5', '\x3', '\x2', '\x2', '\x2', '\xC5', '\xCA', '\x5', '\x4', + '\x3', '\x2', '\xC6', '\xC8', '\a', '\x7F', '\x2', '\x2', '\xC7', '\xC6', + '\x3', '\x2', '\x2', '\x2', '\xC7', '\xC8', '\x3', '\x2', '\x2', '\x2', + '\xC8', '\xC9', '\x3', '\x2', '\x2', '\x2', '\xC9', '\xCB', '\a', '\x3', + '\x2', '\x2', '\xCA', '\xC7', '\x3', '\x2', '\x2', '\x2', '\xCA', '\xCB', + '\x3', '\x2', '\x2', '\x2', '\xCB', '\xCD', '\x3', '\x2', '\x2', '\x2', + '\xCC', '\xCE', '\a', '\x7F', '\x2', '\x2', '\xCD', '\xCC', '\x3', '\x2', + '\x2', '\x2', '\xCD', '\xCE', '\x3', '\x2', '\x2', '\x2', '\xCE', '\xCF', + '\x3', '\x2', '\x2', '\x2', '\xCF', '\xD0', '\a', '\x2', '\x2', '\x3', + '\xD0', '\x3', '\x3', '\x2', '\x2', '\x2', '\xD1', '\xD2', '\x5', '\x6', + '\x4', '\x2', '\xD2', '\x5', '\x3', '\x2', '\x2', '\x2', '\xD3', '\xD6', + '\x5', '\b', '\x5', '\x2', '\xD4', '\xD6', '\x5', ',', '\x17', '\x2', + '\xD5', '\xD3', '\x3', '\x2', '\x2', '\x2', '\xD5', '\xD4', '\x3', '\x2', + '\x2', '\x2', '\xD6', '\a', '\x3', '\x2', '\x2', '\x2', '\xD7', '\xDE', + '\x5', '\f', '\a', '\x2', '\xD8', '\xDA', '\a', '\x7F', '\x2', '\x2', + '\xD9', '\xD8', '\x3', '\x2', '\x2', '\x2', '\xD9', '\xDA', '\x3', '\x2', + '\x2', '\x2', '\xDA', '\xDB', '\x3', '\x2', '\x2', '\x2', '\xDB', '\xDD', + '\x5', '\n', '\x6', '\x2', '\xDC', '\xD9', '\x3', '\x2', '\x2', '\x2', + '\xDD', '\xE0', '\x3', '\x2', '\x2', '\x2', '\xDE', '\xDC', '\x3', '\x2', + '\x2', '\x2', '\xDE', '\xDF', '\x3', '\x2', '\x2', '\x2', '\xDF', '\t', + '\x3', '\x2', '\x2', '\x2', '\xE0', '\xDE', '\x3', '\x2', '\x2', '\x2', + '\xE1', '\xE2', '\a', '\x30', '\x2', '\x2', '\xE2', '\xE3', '\a', '\x7F', + '\x2', '\x2', '\xE3', '\xE5', '\a', '\x31', '\x2', '\x2', '\xE4', '\xE6', + '\a', '\x7F', '\x2', '\x2', '\xE5', '\xE4', '\x3', '\x2', '\x2', '\x2', + '\xE5', '\xE6', '\x3', '\x2', '\x2', '\x2', '\xE6', '\xE7', '\x3', '\x2', + '\x2', '\x2', '\xE7', '\xEE', '\x5', '\f', '\a', '\x2', '\xE8', '\xEA', + '\a', '\x30', '\x2', '\x2', '\xE9', '\xEB', '\a', '\x7F', '\x2', '\x2', + '\xEA', '\xE9', '\x3', '\x2', '\x2', '\x2', '\xEA', '\xEB', '\x3', '\x2', + '\x2', '\x2', '\xEB', '\xEC', '\x3', '\x2', '\x2', '\x2', '\xEC', '\xEE', + '\x5', '\f', '\a', '\x2', '\xED', '\xE1', '\x3', '\x2', '\x2', '\x2', + '\xED', '\xE8', '\x3', '\x2', '\x2', '\x2', '\xEE', '\v', '\x3', '\x2', + '\x2', '\x2', '\xEF', '\xF2', '\x5', '\xE', '\b', '\x2', '\xF0', '\xF2', + '\x5', '\x10', '\t', '\x2', '\xF1', '\xEF', '\x3', '\x2', '\x2', '\x2', + '\xF1', '\xF0', '\x3', '\x2', '\x2', '\x2', '\xF2', '\r', '\x3', '\x2', + '\x2', '\x2', '\xF3', '\xF5', '\x5', '\x14', '\v', '\x2', '\xF4', '\xF6', + '\a', '\x7F', '\x2', '\x2', '\xF5', '\xF4', '\x3', '\x2', '\x2', '\x2', + '\xF5', '\xF6', '\x3', '\x2', '\x2', '\x2', '\xF6', '\xF8', '\x3', '\x2', + '\x2', '\x2', '\xF7', '\xF3', '\x3', '\x2', '\x2', '\x2', '\xF8', '\xFB', + '\x3', '\x2', '\x2', '\x2', '\xF9', '\xF7', '\x3', '\x2', '\x2', '\x2', + '\xF9', '\xFA', '\x3', '\x2', '\x2', '\x2', '\xFA', '\xFC', '\x3', '\x2', + '\x2', '\x2', '\xFB', '\xF9', '\x3', '\x2', '\x2', '\x2', '\xFC', '\x117', + '\x5', '\x34', '\x1B', '\x2', '\xFD', '\xFF', '\x5', '\x14', '\v', '\x2', + '\xFE', '\x100', '\a', '\x7F', '\x2', '\x2', '\xFF', '\xFE', '\x3', '\x2', + '\x2', '\x2', '\xFF', '\x100', '\x3', '\x2', '\x2', '\x2', '\x100', '\x102', + '\x3', '\x2', '\x2', '\x2', '\x101', '\xFD', '\x3', '\x2', '\x2', '\x2', + '\x102', '\x105', '\x3', '\x2', '\x2', '\x2', '\x103', '\x101', '\x3', + '\x2', '\x2', '\x2', '\x103', '\x104', '\x3', '\x2', '\x2', '\x2', '\x104', + '\x106', '\x3', '\x2', '\x2', '\x2', '\x105', '\x103', '\x3', '\x2', '\x2', + '\x2', '\x106', '\x10D', '\x5', '\x12', '\n', '\x2', '\x107', '\x109', + '\a', '\x7F', '\x2', '\x2', '\x108', '\x107', '\x3', '\x2', '\x2', '\x2', + '\x108', '\x109', '\x3', '\x2', '\x2', '\x2', '\x109', '\x10A', '\x3', + '\x2', '\x2', '\x2', '\x10A', '\x10C', '\x5', '\x12', '\n', '\x2', '\x10B', + '\x108', '\x3', '\x2', '\x2', '\x2', '\x10C', '\x10F', '\x3', '\x2', '\x2', + '\x2', '\x10D', '\x10B', '\x3', '\x2', '\x2', '\x2', '\x10D', '\x10E', + '\x3', '\x2', '\x2', '\x2', '\x10E', '\x114', '\x3', '\x2', '\x2', '\x2', + '\x10F', '\x10D', '\x3', '\x2', '\x2', '\x2', '\x110', '\x112', '\a', + '\x7F', '\x2', '\x2', '\x111', '\x110', '\x3', '\x2', '\x2', '\x2', '\x111', + '\x112', '\x3', '\x2', '\x2', '\x2', '\x112', '\x113', '\x3', '\x2', '\x2', + '\x2', '\x113', '\x115', '\x5', '\x34', '\x1B', '\x2', '\x114', '\x111', + '\x3', '\x2', '\x2', '\x2', '\x114', '\x115', '\x3', '\x2', '\x2', '\x2', + '\x115', '\x117', '\x3', '\x2', '\x2', '\x2', '\x116', '\xF9', '\x3', + '\x2', '\x2', '\x2', '\x116', '\x103', '\x3', '\x2', '\x2', '\x2', '\x117', + '\xF', '\x3', '\x2', '\x2', '\x2', '\x118', '\x11A', '\x5', '\x14', '\v', + '\x2', '\x119', '\x11B', '\a', '\x7F', '\x2', '\x2', '\x11A', '\x119', + '\x3', '\x2', '\x2', '\x2', '\x11A', '\x11B', '\x3', '\x2', '\x2', '\x2', + '\x11B', '\x11D', '\x3', '\x2', '\x2', '\x2', '\x11C', '\x118', '\x3', + '\x2', '\x2', '\x2', '\x11D', '\x120', '\x3', '\x2', '\x2', '\x2', '\x11E', + '\x11C', '\x3', '\x2', '\x2', '\x2', '\x11E', '\x11F', '\x3', '\x2', '\x2', + '\x2', '\x11F', '\x127', '\x3', '\x2', '\x2', '\x2', '\x120', '\x11E', + '\x3', '\x2', '\x2', '\x2', '\x121', '\x123', '\x5', '\x12', '\n', '\x2', + '\x122', '\x124', '\a', '\x7F', '\x2', '\x2', '\x123', '\x122', '\x3', + '\x2', '\x2', '\x2', '\x123', '\x124', '\x3', '\x2', '\x2', '\x2', '\x124', + '\x126', '\x3', '\x2', '\x2', '\x2', '\x125', '\x121', '\x3', '\x2', '\x2', + '\x2', '\x126', '\x129', '\x3', '\x2', '\x2', '\x2', '\x127', '\x125', + '\x3', '\x2', '\x2', '\x2', '\x127', '\x128', '\x3', '\x2', '\x2', '\x2', + '\x128', '\x12A', '\x3', '\x2', '\x2', '\x2', '\x129', '\x127', '\x3', + '\x2', '\x2', '\x2', '\x12A', '\x12C', '\x5', '\x32', '\x1A', '\x2', '\x12B', + '\x12D', '\a', '\x7F', '\x2', '\x2', '\x12C', '\x12B', '\x3', '\x2', '\x2', + '\x2', '\x12C', '\x12D', '\x3', '\x2', '\x2', '\x2', '\x12D', '\x12F', + '\x3', '\x2', '\x2', '\x2', '\x12E', '\x11E', '\x3', '\x2', '\x2', '\x2', + '\x12F', '\x130', '\x3', '\x2', '\x2', '\x2', '\x130', '\x12E', '\x3', + '\x2', '\x2', '\x2', '\x130', '\x131', '\x3', '\x2', '\x2', '\x2', '\x131', + '\x132', '\x3', '\x2', '\x2', '\x2', '\x132', '\x133', '\x5', '\xE', '\b', + '\x2', '\x133', '\x11', '\x3', '\x2', '\x2', '\x2', '\x134', '\x13A', + '\x5', '\x1E', '\x10', '\x2', '\x135', '\x13A', '\x5', '\x1A', '\xE', + '\x2', '\x136', '\x13A', '\x5', '$', '\x13', '\x2', '\x137', '\x13A', + '\x5', ' ', '\x11', '\x2', '\x138', '\x13A', '\x5', '&', '\x14', '\x2', + '\x139', '\x134', '\x3', '\x2', '\x2', '\x2', '\x139', '\x135', '\x3', + '\x2', '\x2', '\x2', '\x139', '\x136', '\x3', '\x2', '\x2', '\x2', '\x139', + '\x137', '\x3', '\x2', '\x2', '\x2', '\x139', '\x138', '\x3', '\x2', '\x2', + '\x2', '\x13A', '\x13', '\x3', '\x2', '\x2', '\x2', '\x13B', '\x13F', + '\x5', '\x16', '\f', '\x2', '\x13C', '\x13F', '\x5', '\x18', '\r', '\x2', + '\x13D', '\x13F', '\x5', '*', '\x16', '\x2', '\x13E', '\x13B', '\x3', + '\x2', '\x2', '\x2', '\x13E', '\x13C', '\x3', '\x2', '\x2', '\x2', '\x13E', + '\x13D', '\x3', '\x2', '\x2', '\x2', '\x13F', '\x15', '\x3', '\x2', '\x2', + '\x2', '\x140', '\x141', '\a', '\x32', '\x2', '\x2', '\x141', '\x143', + '\a', '\x7F', '\x2', '\x2', '\x142', '\x140', '\x3', '\x2', '\x2', '\x2', + '\x142', '\x143', '\x3', '\x2', '\x2', '\x2', '\x143', '\x144', '\x3', + '\x2', '\x2', '\x2', '\x144', '\x146', '\a', '\x33', '\x2', '\x2', '\x145', + '\x147', '\a', '\x7F', '\x2', '\x2', '\x146', '\x145', '\x3', '\x2', '\x2', + '\x2', '\x146', '\x147', '\x3', '\x2', '\x2', '\x2', '\x147', '\x148', + '\x3', '\x2', '\x2', '\x2', '\x148', '\x14D', '\x5', '\x46', '$', '\x2', + '\x149', '\x14B', '\a', '\x7F', '\x2', '\x2', '\x14A', '\x149', '\x3', + '\x2', '\x2', '\x2', '\x14A', '\x14B', '\x3', '\x2', '\x2', '\x2', '\x14B', + '\x14C', '\x3', '\x2', '\x2', '\x2', '\x14C', '\x14E', '\x5', '\x44', + '#', '\x2', '\x14D', '\x14A', '\x3', '\x2', '\x2', '\x2', '\x14D', '\x14E', + '\x3', '\x2', '\x2', '\x2', '\x14E', '\x17', '\x3', '\x2', '\x2', '\x2', + '\x14F', '\x151', '\a', '\x34', '\x2', '\x2', '\x150', '\x152', '\a', + '\x7F', '\x2', '\x2', '\x151', '\x150', '\x3', '\x2', '\x2', '\x2', '\x151', + '\x152', '\x3', '\x2', '\x2', '\x2', '\x152', '\x153', '\x3', '\x2', '\x2', + '\x2', '\x153', '\x154', '\x5', '\x64', '\x33', '\x2', '\x154', '\x155', + '\a', '\x7F', '\x2', '\x2', '\x155', '\x156', '\a', '\x35', '\x2', '\x2', + '\x156', '\x157', '\a', '\x7F', '\x2', '\x2', '\x157', '\x158', '\x5', + '\xA6', 'T', '\x2', '\x158', '\x19', '\x3', '\x2', '\x2', '\x2', '\x159', + '\x15B', '\a', '\x36', '\x2', '\x2', '\x15A', '\x15C', '\a', '\x7F', '\x2', + '\x2', '\x15B', '\x15A', '\x3', '\x2', '\x2', '\x2', '\x15B', '\x15C', + '\x3', '\x2', '\x2', '\x2', '\x15C', '\x15D', '\x3', '\x2', '\x2', '\x2', + '\x15D', '\x162', '\x5', 'H', '%', '\x2', '\x15E', '\x15F', '\a', '\x7F', + '\x2', '\x2', '\x15F', '\x161', '\x5', '\x1C', '\xF', '\x2', '\x160', + '\x15E', '\x3', '\x2', '\x2', '\x2', '\x161', '\x164', '\x3', '\x2', '\x2', + '\x2', '\x162', '\x160', '\x3', '\x2', '\x2', '\x2', '\x162', '\x163', + '\x3', '\x2', '\x2', '\x2', '\x163', '\x1B', '\x3', '\x2', '\x2', '\x2', + '\x164', '\x162', '\x3', '\x2', '\x2', '\x2', '\x165', '\x166', '\a', + '\x37', '\x2', '\x2', '\x166', '\x167', '\a', '\x7F', '\x2', '\x2', '\x167', + '\x168', '\a', '\x33', '\x2', '\x2', '\x168', '\x169', '\a', '\x7F', '\x2', + '\x2', '\x169', '\x170', '\x5', ' ', '\x11', '\x2', '\x16A', '\x16B', + '\a', '\x37', '\x2', '\x2', '\x16B', '\x16C', '\a', '\x7F', '\x2', '\x2', + '\x16C', '\x16D', '\a', '\x38', '\x2', '\x2', '\x16D', '\x16E', '\a', + '\x7F', '\x2', '\x2', '\x16E', '\x170', '\x5', ' ', '\x11', '\x2', '\x16F', + '\x165', '\x3', '\x2', '\x2', '\x2', '\x16F', '\x16A', '\x3', '\x2', '\x2', + '\x2', '\x170', '\x1D', '\x3', '\x2', '\x2', '\x2', '\x171', '\x173', + '\a', '\x38', '\x2', '\x2', '\x172', '\x174', '\a', '\x7F', '\x2', '\x2', + '\x173', '\x172', '\x3', '\x2', '\x2', '\x2', '\x173', '\x174', '\x3', + '\x2', '\x2', '\x2', '\x174', '\x175', '\x3', '\x2', '\x2', '\x2', '\x175', + '\x176', '\x5', '\x46', '$', '\x2', '\x176', '\x1F', '\x3', '\x2', '\x2', + '\x2', '\x177', '\x179', '\a', '\x39', '\x2', '\x2', '\x178', '\x17A', + '\a', '\x7F', '\x2', '\x2', '\x179', '\x178', '\x3', '\x2', '\x2', '\x2', + '\x179', '\x17A', '\x3', '\x2', '\x2', '\x2', '\x17A', '\x17B', '\x3', + '\x2', '\x2', '\x2', '\x17B', '\x180', '\x5', '\"', '\x12', '\x2', '\x17C', + '\x17D', '\a', '\x4', '\x2', '\x2', '\x17D', '\x17F', '\x5', '\"', '\x12', + '\x2', '\x17E', '\x17C', '\x3', '\x2', '\x2', '\x2', '\x17F', '\x182', + '\x3', '\x2', '\x2', '\x2', '\x180', '\x17E', '\x3', '\x2', '\x2', '\x2', + '\x180', '\x181', '\x3', '\x2', '\x2', '\x2', '\x181', '!', '\x3', '\x2', + '\x2', '\x2', '\x182', '\x180', '\x3', '\x2', '\x2', '\x2', '\x183', '\x185', + '\x5', '\xAE', 'X', '\x2', '\x184', '\x186', '\a', '\x7F', '\x2', '\x2', + '\x185', '\x184', '\x3', '\x2', '\x2', '\x2', '\x185', '\x186', '\x3', + '\x2', '\x2', '\x2', '\x186', '\x187', '\x3', '\x2', '\x2', '\x2', '\x187', + '\x189', '\a', '\x5', '\x2', '\x2', '\x188', '\x18A', '\a', '\x7F', '\x2', + '\x2', '\x189', '\x188', '\x3', '\x2', '\x2', '\x2', '\x189', '\x18A', + '\x3', '\x2', '\x2', '\x2', '\x18A', '\x18B', '\x3', '\x2', '\x2', '\x2', + '\x18B', '\x18C', '\x5', '\x64', '\x33', '\x2', '\x18C', '\x1A8', '\x3', + '\x2', '\x2', '\x2', '\x18D', '\x18F', '\x5', '\xA6', 'T', '\x2', '\x18E', + '\x190', '\a', '\x7F', '\x2', '\x2', '\x18F', '\x18E', '\x3', '\x2', '\x2', + '\x2', '\x18F', '\x190', '\x3', '\x2', '\x2', '\x2', '\x190', '\x191', + '\x3', '\x2', '\x2', '\x2', '\x191', '\x193', '\a', '\x5', '\x2', '\x2', + '\x192', '\x194', '\a', '\x7F', '\x2', '\x2', '\x193', '\x192', '\x3', + '\x2', '\x2', '\x2', '\x193', '\x194', '\x3', '\x2', '\x2', '\x2', '\x194', + '\x195', '\x3', '\x2', '\x2', '\x2', '\x195', '\x196', '\x5', '\x64', + '\x33', '\x2', '\x196', '\x1A8', '\x3', '\x2', '\x2', '\x2', '\x197', + '\x199', '\x5', '\xA6', 'T', '\x2', '\x198', '\x19A', '\a', '\x7F', '\x2', + '\x2', '\x199', '\x198', '\x3', '\x2', '\x2', '\x2', '\x199', '\x19A', + '\x3', '\x2', '\x2', '\x2', '\x19A', '\x19B', '\x3', '\x2', '\x2', '\x2', + '\x19B', '\x19D', '\a', '\x6', '\x2', '\x2', '\x19C', '\x19E', '\a', '\x7F', + '\x2', '\x2', '\x19D', '\x19C', '\x3', '\x2', '\x2', '\x2', '\x19D', '\x19E', + '\x3', '\x2', '\x2', '\x2', '\x19E', '\x19F', '\x3', '\x2', '\x2', '\x2', + '\x19F', '\x1A0', '\x5', '\x64', '\x33', '\x2', '\x1A0', '\x1A8', '\x3', + '\x2', '\x2', '\x2', '\x1A1', '\x1A3', '\x5', '\xA6', 'T', '\x2', '\x1A2', + '\x1A4', '\a', '\x7F', '\x2', '\x2', '\x1A3', '\x1A2', '\x3', '\x2', '\x2', + '\x2', '\x1A3', '\x1A4', '\x3', '\x2', '\x2', '\x2', '\x1A4', '\x1A5', + '\x3', '\x2', '\x2', '\x2', '\x1A5', '\x1A6', '\x5', 'Z', '.', '\x2', + '\x1A6', '\x1A8', '\x3', '\x2', '\x2', '\x2', '\x1A7', '\x183', '\x3', + '\x2', '\x2', '\x2', '\x1A7', '\x18D', '\x3', '\x2', '\x2', '\x2', '\x1A7', + '\x197', '\x3', '\x2', '\x2', '\x2', '\x1A7', '\x1A1', '\x3', '\x2', '\x2', + '\x2', '\x1A8', '#', '\x3', '\x2', '\x2', '\x2', '\x1A9', '\x1AA', '\a', + ':', '\x2', '\x2', '\x1AA', '\x1AC', '\a', '\x7F', '\x2', '\x2', '\x1AB', + '\x1A9', '\x3', '\x2', '\x2', '\x2', '\x1AB', '\x1AC', '\x3', '\x2', '\x2', + '\x2', '\x1AC', '\x1AD', '\x3', '\x2', '\x2', '\x2', '\x1AD', '\x1AF', + '\a', ';', '\x2', '\x2', '\x1AE', '\x1B0', '\a', '\x7F', '\x2', '\x2', + '\x1AF', '\x1AE', '\x3', '\x2', '\x2', '\x2', '\x1AF', '\x1B0', '\x3', + '\x2', '\x2', '\x2', '\x1B0', '\x1B1', '\x3', '\x2', '\x2', '\x2', '\x1B1', + '\x1BC', '\x5', '\x64', '\x33', '\x2', '\x1B2', '\x1B4', '\a', '\x7F', + '\x2', '\x2', '\x1B3', '\x1B2', '\x3', '\x2', '\x2', '\x2', '\x1B3', '\x1B4', + '\x3', '\x2', '\x2', '\x2', '\x1B4', '\x1B5', '\x3', '\x2', '\x2', '\x2', + '\x1B5', '\x1B7', '\a', '\x4', '\x2', '\x2', '\x1B6', '\x1B8', '\a', '\x7F', + '\x2', '\x2', '\x1B7', '\x1B6', '\x3', '\x2', '\x2', '\x2', '\x1B7', '\x1B8', + '\x3', '\x2', '\x2', '\x2', '\x1B8', '\x1B9', '\x3', '\x2', '\x2', '\x2', + '\x1B9', '\x1BB', '\x5', '\x64', '\x33', '\x2', '\x1BA', '\x1B3', '\x3', + '\x2', '\x2', '\x2', '\x1BB', '\x1BE', '\x3', '\x2', '\x2', '\x2', '\x1BC', + '\x1BA', '\x3', '\x2', '\x2', '\x2', '\x1BC', '\x1BD', '\x3', '\x2', '\x2', + '\x2', '\x1BD', '%', '\x3', '\x2', '\x2', '\x2', '\x1BE', '\x1BC', '\x3', + '\x2', '\x2', '\x2', '\x1BF', '\x1C0', '\a', '<', '\x2', '\x2', '\x1C0', + '\x1C1', '\a', '\x7F', '\x2', '\x2', '\x1C1', '\x1CC', '\x5', '(', '\x15', + '\x2', '\x1C2', '\x1C4', '\a', '\x7F', '\x2', '\x2', '\x1C3', '\x1C2', + '\x3', '\x2', '\x2', '\x2', '\x1C3', '\x1C4', '\x3', '\x2', '\x2', '\x2', + '\x1C4', '\x1C5', '\x3', '\x2', '\x2', '\x2', '\x1C5', '\x1C7', '\a', + '\x4', '\x2', '\x2', '\x1C6', '\x1C8', '\a', '\x7F', '\x2', '\x2', '\x1C7', + '\x1C6', '\x3', '\x2', '\x2', '\x2', '\x1C7', '\x1C8', '\x3', '\x2', '\x2', + '\x2', '\x1C8', '\x1C9', '\x3', '\x2', '\x2', '\x2', '\x1C9', '\x1CB', + '\x5', '(', '\x15', '\x2', '\x1CA', '\x1C3', '\x3', '\x2', '\x2', '\x2', + '\x1CB', '\x1CE', '\x3', '\x2', '\x2', '\x2', '\x1CC', '\x1CA', '\x3', + '\x2', '\x2', '\x2', '\x1CC', '\x1CD', '\x3', '\x2', '\x2', '\x2', '\x1CD', + '\'', '\x3', '\x2', '\x2', '\x2', '\x1CE', '\x1CC', '\x3', '\x2', '\x2', + '\x2', '\x1CF', '\x1D0', '\x5', '\xA6', 'T', '\x2', '\x1D0', '\x1D1', + '\x5', 'Z', '.', '\x2', '\x1D1', '\x1D4', '\x3', '\x2', '\x2', '\x2', + '\x1D2', '\x1D4', '\x5', '\xAE', 'X', '\x2', '\x1D3', '\x1CF', '\x3', + '\x2', '\x2', '\x2', '\x1D3', '\x1D2', '\x3', '\x2', '\x2', '\x2', '\x1D4', + ')', '\x3', '\x2', '\x2', '\x2', '\x1D5', '\x1D6', '\a', '=', '\x2', '\x2', + '\x1D6', '\x1D7', '\a', '\x7F', '\x2', '\x2', '\x1D7', '\x1DE', '\x5', + '\x92', 'J', '\x2', '\x1D8', '\x1DA', '\a', '\x7F', '\x2', '\x2', '\x1D9', + '\x1D8', '\x3', '\x2', '\x2', '\x2', '\x1D9', '\x1DA', '\x3', '\x2', '\x2', + '\x2', '\x1DA', '\x1DB', '\x3', '\x2', '\x2', '\x2', '\x1DB', '\x1DC', + '\a', '>', '\x2', '\x2', '\x1DC', '\x1DD', '\a', '\x7F', '\x2', '\x2', + '\x1DD', '\x1DF', '\x5', '.', '\x18', '\x2', '\x1DE', '\x1D9', '\x3', + '\x2', '\x2', '\x2', '\x1DE', '\x1DF', '\x3', '\x2', '\x2', '\x2', '\x1DF', + '+', '\x3', '\x2', '\x2', '\x2', '\x1E0', '\x1E1', '\a', '=', '\x2', '\x2', + '\x1E1', '\x1E4', '\a', '\x7F', '\x2', '\x2', '\x1E2', '\x1E5', '\x5', + '\x92', 'J', '\x2', '\x1E3', '\x1E5', '\x5', '\x94', 'K', '\x2', '\x1E4', + '\x1E2', '\x3', '\x2', '\x2', '\x2', '\x1E4', '\x1E3', '\x3', '\x2', '\x2', + '\x2', '\x1E5', '\x1EA', '\x3', '\x2', '\x2', '\x2', '\x1E6', '\x1E7', + '\a', '\x7F', '\x2', '\x2', '\x1E7', '\x1E8', '\a', '>', '\x2', '\x2', + '\x1E8', '\x1E9', '\a', '\x7F', '\x2', '\x2', '\x1E9', '\x1EB', '\x5', + '.', '\x18', '\x2', '\x1EA', '\x1E6', '\x3', '\x2', '\x2', '\x2', '\x1EA', + '\x1EB', '\x3', '\x2', '\x2', '\x2', '\x1EB', '-', '\x3', '\x2', '\x2', + '\x2', '\x1EC', '\x1F7', '\x5', '\x30', '\x19', '\x2', '\x1ED', '\x1EF', + '\a', '\x7F', '\x2', '\x2', '\x1EE', '\x1ED', '\x3', '\x2', '\x2', '\x2', + '\x1EE', '\x1EF', '\x3', '\x2', '\x2', '\x2', '\x1EF', '\x1F0', '\x3', + '\x2', '\x2', '\x2', '\x1F0', '\x1F2', '\a', '\x4', '\x2', '\x2', '\x1F1', + '\x1F3', '\a', '\x7F', '\x2', '\x2', '\x1F2', '\x1F1', '\x3', '\x2', '\x2', + '\x2', '\x1F2', '\x1F3', '\x3', '\x2', '\x2', '\x2', '\x1F3', '\x1F4', + '\x3', '\x2', '\x2', '\x2', '\x1F4', '\x1F6', '\x5', '\x30', '\x19', '\x2', + '\x1F5', '\x1EE', '\x3', '\x2', '\x2', '\x2', '\x1F6', '\x1F9', '\x3', + '\x2', '\x2', '\x2', '\x1F7', '\x1F5', '\x3', '\x2', '\x2', '\x2', '\x1F7', + '\x1F8', '\x3', '\x2', '\x2', '\x2', '\x1F8', '\x1FC', '\x3', '\x2', '\x2', + '\x2', '\x1F9', '\x1F7', '\x3', '\x2', '\x2', '\x2', '\x1FA', '\x1FC', + '\a', '\a', '\x2', '\x2', '\x1FB', '\x1EC', '\x3', '\x2', '\x2', '\x2', + '\x1FB', '\x1FA', '\x3', '\x2', '\x2', '\x2', '\x1FC', '/', '\x3', '\x2', + '\x2', '\x2', '\x1FD', '\x1FE', '\x5', '\x96', 'L', '\x2', '\x1FE', '\x1FF', + '\a', '\x7F', '\x2', '\x2', '\x1FF', '\x200', '\a', '\x35', '\x2', '\x2', + '\x200', '\x201', '\a', '\x7F', '\x2', '\x2', '\x201', '\x203', '\x3', + '\x2', '\x2', '\x2', '\x202', '\x1FD', '\x3', '\x2', '\x2', '\x2', '\x202', + '\x203', '\x3', '\x2', '\x2', '\x2', '\x203', '\x204', '\x3', '\x2', '\x2', + '\x2', '\x204', '\x205', '\x5', '\xA6', 'T', '\x2', '\x205', '\x31', '\x3', + '\x2', '\x2', '\x2', '\x206', '\x20B', '\a', '?', '\x2', '\x2', '\x207', + '\x209', '\a', '\x7F', '\x2', '\x2', '\x208', '\x207', '\x3', '\x2', '\x2', + '\x2', '\x208', '\x209', '\x3', '\x2', '\x2', '\x2', '\x209', '\x20A', + '\x3', '\x2', '\x2', '\x2', '\x20A', '\x20C', '\a', '@', '\x2', '\x2', + '\x20B', '\x208', '\x3', '\x2', '\x2', '\x2', '\x20B', '\x20C', '\x3', + '\x2', '\x2', '\x2', '\x20C', '\x20D', '\x3', '\x2', '\x2', '\x2', '\x20D', + '\x20E', '\a', '\x7F', '\x2', '\x2', '\x20E', '\x213', '\x5', '\x36', + '\x1C', '\x2', '\x20F', '\x211', '\a', '\x7F', '\x2', '\x2', '\x210', + '\x20F', '\x3', '\x2', '\x2', '\x2', '\x210', '\x211', '\x3', '\x2', '\x2', + '\x2', '\x211', '\x212', '\x3', '\x2', '\x2', '\x2', '\x212', '\x214', + '\x5', '\x44', '#', '\x2', '\x213', '\x210', '\x3', '\x2', '\x2', '\x2', + '\x213', '\x214', '\x3', '\x2', '\x2', '\x2', '\x214', '\x33', '\x3', + '\x2', '\x2', '\x2', '\x215', '\x21A', '\a', '\x41', '\x2', '\x2', '\x216', + '\x218', '\a', '\x7F', '\x2', '\x2', '\x217', '\x216', '\x3', '\x2', '\x2', + '\x2', '\x217', '\x218', '\x3', '\x2', '\x2', '\x2', '\x218', '\x219', + '\x3', '\x2', '\x2', '\x2', '\x219', '\x21B', '\a', '@', '\x2', '\x2', + '\x21A', '\x217', '\x3', '\x2', '\x2', '\x2', '\x21A', '\x21B', '\x3', + '\x2', '\x2', '\x2', '\x21B', '\x21C', '\x3', '\x2', '\x2', '\x2', '\x21C', + '\x21D', '\a', '\x7F', '\x2', '\x2', '\x21D', '\x21E', '\x5', '\x36', + '\x1C', '\x2', '\x21E', '\x35', '\x3', '\x2', '\x2', '\x2', '\x21F', '\x222', + '\x5', '\x38', '\x1D', '\x2', '\x220', '\x221', '\a', '\x7F', '\x2', '\x2', + '\x221', '\x223', '\x5', '<', '\x1F', '\x2', '\x222', '\x220', '\x3', + '\x2', '\x2', '\x2', '\x222', '\x223', '\x3', '\x2', '\x2', '\x2', '\x223', + '\x226', '\x3', '\x2', '\x2', '\x2', '\x224', '\x225', '\a', '\x7F', '\x2', + '\x2', '\x225', '\x227', '\x5', '>', ' ', '\x2', '\x226', '\x224', '\x3', + '\x2', '\x2', '\x2', '\x226', '\x227', '\x3', '\x2', '\x2', '\x2', '\x227', + '\x22A', '\x3', '\x2', '\x2', '\x2', '\x228', '\x229', '\a', '\x7F', '\x2', + '\x2', '\x229', '\x22B', '\x5', '@', '!', '\x2', '\x22A', '\x228', '\x3', + '\x2', '\x2', '\x2', '\x22A', '\x22B', '\x3', '\x2', '\x2', '\x2', '\x22B', + '\x37', '\x3', '\x2', '\x2', '\x2', '\x22C', '\x237', '\a', '\b', '\x2', + '\x2', '\x22D', '\x22F', '\a', '\x7F', '\x2', '\x2', '\x22E', '\x22D', + '\x3', '\x2', '\x2', '\x2', '\x22E', '\x22F', '\x3', '\x2', '\x2', '\x2', + '\x22F', '\x230', '\x3', '\x2', '\x2', '\x2', '\x230', '\x232', '\a', + '\x4', '\x2', '\x2', '\x231', '\x233', '\a', '\x7F', '\x2', '\x2', '\x232', + '\x231', '\x3', '\x2', '\x2', '\x2', '\x232', '\x233', '\x3', '\x2', '\x2', + '\x2', '\x233', '\x234', '\x3', '\x2', '\x2', '\x2', '\x234', '\x236', + '\x5', ':', '\x1E', '\x2', '\x235', '\x22E', '\x3', '\x2', '\x2', '\x2', + '\x236', '\x239', '\x3', '\x2', '\x2', '\x2', '\x237', '\x235', '\x3', + '\x2', '\x2', '\x2', '\x237', '\x238', '\x3', '\x2', '\x2', '\x2', '\x238', + '\x249', '\x3', '\x2', '\x2', '\x2', '\x239', '\x237', '\x3', '\x2', '\x2', + '\x2', '\x23A', '\x245', '\x5', ':', '\x1E', '\x2', '\x23B', '\x23D', + '\a', '\x7F', '\x2', '\x2', '\x23C', '\x23B', '\x3', '\x2', '\x2', '\x2', + '\x23C', '\x23D', '\x3', '\x2', '\x2', '\x2', '\x23D', '\x23E', '\x3', + '\x2', '\x2', '\x2', '\x23E', '\x240', '\a', '\x4', '\x2', '\x2', '\x23F', + '\x241', '\a', '\x7F', '\x2', '\x2', '\x240', '\x23F', '\x3', '\x2', '\x2', + '\x2', '\x240', '\x241', '\x3', '\x2', '\x2', '\x2', '\x241', '\x242', + '\x3', '\x2', '\x2', '\x2', '\x242', '\x244', '\x5', ':', '\x1E', '\x2', + '\x243', '\x23C', '\x3', '\x2', '\x2', '\x2', '\x244', '\x247', '\x3', + '\x2', '\x2', '\x2', '\x245', '\x243', '\x3', '\x2', '\x2', '\x2', '\x245', + '\x246', '\x3', '\x2', '\x2', '\x2', '\x246', '\x249', '\x3', '\x2', '\x2', + '\x2', '\x247', '\x245', '\x3', '\x2', '\x2', '\x2', '\x248', '\x22C', + '\x3', '\x2', '\x2', '\x2', '\x248', '\x23A', '\x3', '\x2', '\x2', '\x2', + '\x249', '\x39', '\x3', '\x2', '\x2', '\x2', '\x24A', '\x24B', '\x5', + '\x64', '\x33', '\x2', '\x24B', '\x24C', '\a', '\x7F', '\x2', '\x2', '\x24C', + '\x24D', '\a', '\x35', '\x2', '\x2', '\x24D', '\x24E', '\a', '\x7F', '\x2', + '\x2', '\x24E', '\x24F', '\x5', '\xA6', 'T', '\x2', '\x24F', '\x252', + '\x3', '\x2', '\x2', '\x2', '\x250', '\x252', '\x5', '\x64', '\x33', '\x2', + '\x251', '\x24A', '\x3', '\x2', '\x2', '\x2', '\x251', '\x250', '\x3', + '\x2', '\x2', '\x2', '\x252', ';', '\x3', '\x2', '\x2', '\x2', '\x253', + '\x254', '\a', '\x42', '\x2', '\x2', '\x254', '\x255', '\a', '\x7F', '\x2', + '\x2', '\x255', '\x256', '\a', '\x43', '\x2', '\x2', '\x256', '\x257', + '\a', '\x7F', '\x2', '\x2', '\x257', '\x25F', '\x5', '\x42', '\"', '\x2', + '\x258', '\x25A', '\a', '\x4', '\x2', '\x2', '\x259', '\x25B', '\a', '\x7F', + '\x2', '\x2', '\x25A', '\x259', '\x3', '\x2', '\x2', '\x2', '\x25A', '\x25B', + '\x3', '\x2', '\x2', '\x2', '\x25B', '\x25C', '\x3', '\x2', '\x2', '\x2', + '\x25C', '\x25E', '\x5', '\x42', '\"', '\x2', '\x25D', '\x258', '\x3', + '\x2', '\x2', '\x2', '\x25E', '\x261', '\x3', '\x2', '\x2', '\x2', '\x25F', + '\x25D', '\x3', '\x2', '\x2', '\x2', '\x25F', '\x260', '\x3', '\x2', '\x2', + '\x2', '\x260', '=', '\x3', '\x2', '\x2', '\x2', '\x261', '\x25F', '\x3', + '\x2', '\x2', '\x2', '\x262', '\x263', '\a', '\x44', '\x2', '\x2', '\x263', + '\x264', '\a', '\x7F', '\x2', '\x2', '\x264', '\x265', '\x5', '\x64', + '\x33', '\x2', '\x265', '?', '\x3', '\x2', '\x2', '\x2', '\x266', '\x267', + '\a', '\x45', '\x2', '\x2', '\x267', '\x268', '\a', '\x7F', '\x2', '\x2', + '\x268', '\x269', '\x5', '\x64', '\x33', '\x2', '\x269', '\x41', '\x3', + '\x2', '\x2', '\x2', '\x26A', '\x26F', '\x5', '\x64', '\x33', '\x2', '\x26B', + '\x26D', '\a', '\x7F', '\x2', '\x2', '\x26C', '\x26B', '\x3', '\x2', '\x2', + '\x2', '\x26C', '\x26D', '\x3', '\x2', '\x2', '\x2', '\x26D', '\x26E', + '\x3', '\x2', '\x2', '\x2', '\x26E', '\x270', '\t', '\x2', '\x2', '\x2', + '\x26F', '\x26C', '\x3', '\x2', '\x2', '\x2', '\x26F', '\x270', '\x3', + '\x2', '\x2', '\x2', '\x270', '\x43', '\x3', '\x2', '\x2', '\x2', '\x271', + '\x272', '\a', 'J', '\x2', '\x2', '\x272', '\x273', '\a', '\x7F', '\x2', + '\x2', '\x273', '\x274', '\x5', '\x64', '\x33', '\x2', '\x274', '\x45', + '\x3', '\x2', '\x2', '\x2', '\x275', '\x280', '\x5', 'H', '%', '\x2', + '\x276', '\x278', '\a', '\x7F', '\x2', '\x2', '\x277', '\x276', '\x3', + '\x2', '\x2', '\x2', '\x277', '\x278', '\x3', '\x2', '\x2', '\x2', '\x278', + '\x279', '\x3', '\x2', '\x2', '\x2', '\x279', '\x27B', '\a', '\x4', '\x2', + '\x2', '\x27A', '\x27C', '\a', '\x7F', '\x2', '\x2', '\x27B', '\x27A', + '\x3', '\x2', '\x2', '\x2', '\x27B', '\x27C', '\x3', '\x2', '\x2', '\x2', + '\x27C', '\x27D', '\x3', '\x2', '\x2', '\x2', '\x27D', '\x27F', '\x5', + 'H', '%', '\x2', '\x27E', '\x277', '\x3', '\x2', '\x2', '\x2', '\x27F', + '\x282', '\x3', '\x2', '\x2', '\x2', '\x280', '\x27E', '\x3', '\x2', '\x2', + '\x2', '\x280', '\x281', '\x3', '\x2', '\x2', '\x2', '\x281', 'G', '\x3', + '\x2', '\x2', '\x2', '\x282', '\x280', '\x3', '\x2', '\x2', '\x2', '\x283', + '\x285', '\x5', '\xA6', 'T', '\x2', '\x284', '\x286', '\a', '\x7F', '\x2', + '\x2', '\x285', '\x284', '\x3', '\x2', '\x2', '\x2', '\x285', '\x286', + '\x3', '\x2', '\x2', '\x2', '\x286', '\x287', '\x3', '\x2', '\x2', '\x2', + '\x287', '\x289', '\a', '\x5', '\x2', '\x2', '\x288', '\x28A', '\a', '\x7F', + '\x2', '\x2', '\x289', '\x288', '\x3', '\x2', '\x2', '\x2', '\x289', '\x28A', + '\x3', '\x2', '\x2', '\x2', '\x28A', '\x28B', '\x3', '\x2', '\x2', '\x2', + '\x28B', '\x28C', '\x5', 'J', '&', '\x2', '\x28C', '\x28F', '\x3', '\x2', + '\x2', '\x2', '\x28D', '\x28F', '\x5', 'J', '&', '\x2', '\x28E', '\x283', + '\x3', '\x2', '\x2', '\x2', '\x28E', '\x28D', '\x3', '\x2', '\x2', '\x2', + '\x28F', 'I', '\x3', '\x2', '\x2', '\x2', '\x290', '\x291', '\x5', 'L', + '\'', '\x2', '\x291', 'K', '\x3', '\x2', '\x2', '\x2', '\x292', '\x299', + '\x5', 'N', '(', '\x2', '\x293', '\x295', '\a', '\x7F', '\x2', '\x2', + '\x294', '\x293', '\x3', '\x2', '\x2', '\x2', '\x294', '\x295', '\x3', + '\x2', '\x2', '\x2', '\x295', '\x296', '\x3', '\x2', '\x2', '\x2', '\x296', + '\x298', '\x5', 'P', ')', '\x2', '\x297', '\x294', '\x3', '\x2', '\x2', + '\x2', '\x298', '\x29B', '\x3', '\x2', '\x2', '\x2', '\x299', '\x297', + '\x3', '\x2', '\x2', '\x2', '\x299', '\x29A', '\x3', '\x2', '\x2', '\x2', + '\x29A', '\x2A1', '\x3', '\x2', '\x2', '\x2', '\x29B', '\x299', '\x3', + '\x2', '\x2', '\x2', '\x29C', '\x29D', '\a', '\t', '\x2', '\x2', '\x29D', + '\x29E', '\x5', 'L', '\'', '\x2', '\x29E', '\x29F', '\a', '\n', '\x2', + '\x2', '\x29F', '\x2A1', '\x3', '\x2', '\x2', '\x2', '\x2A0', '\x292', + '\x3', '\x2', '\x2', '\x2', '\x2A0', '\x29C', '\x3', '\x2', '\x2', '\x2', + '\x2A1', 'M', '\x3', '\x2', '\x2', '\x2', '\x2A2', '\x2A4', '\a', '\t', + '\x2', '\x2', '\x2A3', '\x2A5', '\a', '\x7F', '\x2', '\x2', '\x2A4', '\x2A3', + '\x3', '\x2', '\x2', '\x2', '\x2A4', '\x2A5', '\x3', '\x2', '\x2', '\x2', + '\x2A5', '\x2AA', '\x3', '\x2', '\x2', '\x2', '\x2A6', '\x2A8', '\x5', + '\xA6', 'T', '\x2', '\x2A7', '\x2A9', '\a', '\x7F', '\x2', '\x2', '\x2A8', + '\x2A7', '\x3', '\x2', '\x2', '\x2', '\x2A8', '\x2A9', '\x3', '\x2', '\x2', + '\x2', '\x2A9', '\x2AB', '\x3', '\x2', '\x2', '\x2', '\x2AA', '\x2A6', + '\x3', '\x2', '\x2', '\x2', '\x2AA', '\x2AB', '\x3', '\x2', '\x2', '\x2', + '\x2AB', '\x2B0', '\x3', '\x2', '\x2', '\x2', '\x2AC', '\x2AE', '\x5', + 'Z', '.', '\x2', '\x2AD', '\x2AF', '\a', '\x7F', '\x2', '\x2', '\x2AE', + '\x2AD', '\x3', '\x2', '\x2', '\x2', '\x2AE', '\x2AF', '\x3', '\x2', '\x2', + '\x2', '\x2AF', '\x2B1', '\x3', '\x2', '\x2', '\x2', '\x2B0', '\x2AC', + '\x3', '\x2', '\x2', '\x2', '\x2B0', '\x2B1', '\x3', '\x2', '\x2', '\x2', + '\x2B1', '\x2B6', '\x3', '\x2', '\x2', '\x2', '\x2B2', '\x2B4', '\x5', + 'V', ',', '\x2', '\x2B3', '\x2B5', '\a', '\x7F', '\x2', '\x2', '\x2B4', + '\x2B3', '\x3', '\x2', '\x2', '\x2', '\x2B4', '\x2B5', '\x3', '\x2', '\x2', + '\x2', '\x2B5', '\x2B7', '\x3', '\x2', '\x2', '\x2', '\x2B6', '\x2B2', + '\x3', '\x2', '\x2', '\x2', '\x2B6', '\x2B7', '\x3', '\x2', '\x2', '\x2', + '\x2B7', '\x2B8', '\x3', '\x2', '\x2', '\x2', '\x2B8', '\x2B9', '\a', + '\n', '\x2', '\x2', '\x2B9', 'O', '\x3', '\x2', '\x2', '\x2', '\x2BA', + '\x2BC', '\x5', 'R', '*', '\x2', '\x2BB', '\x2BD', '\a', '\x7F', '\x2', + '\x2', '\x2BC', '\x2BB', '\x3', '\x2', '\x2', '\x2', '\x2BC', '\x2BD', + '\x3', '\x2', '\x2', '\x2', '\x2BD', '\x2BE', '\x3', '\x2', '\x2', '\x2', + '\x2BE', '\x2BF', '\x5', 'N', '(', '\x2', '\x2BF', 'Q', '\x3', '\x2', + '\x2', '\x2', '\x2C0', '\x2C2', '\x5', '\xBC', '_', '\x2', '\x2C1', '\x2C3', + '\a', '\x7F', '\x2', '\x2', '\x2C2', '\x2C1', '\x3', '\x2', '\x2', '\x2', + '\x2C2', '\x2C3', '\x3', '\x2', '\x2', '\x2', '\x2C3', '\x2C4', '\x3', + '\x2', '\x2', '\x2', '\x2C4', '\x2C6', '\x5', '\xC0', '\x61', '\x2', '\x2C5', + '\x2C7', '\a', '\x7F', '\x2', '\x2', '\x2C6', '\x2C5', '\x3', '\x2', '\x2', + '\x2', '\x2C6', '\x2C7', '\x3', '\x2', '\x2', '\x2', '\x2C7', '\x2C9', + '\x3', '\x2', '\x2', '\x2', '\x2C8', '\x2CA', '\x5', 'T', '+', '\x2', + '\x2C9', '\x2C8', '\x3', '\x2', '\x2', '\x2', '\x2C9', '\x2CA', '\x3', + '\x2', '\x2', '\x2', '\x2CA', '\x2CC', '\x3', '\x2', '\x2', '\x2', '\x2CB', + '\x2CD', '\a', '\x7F', '\x2', '\x2', '\x2CC', '\x2CB', '\x3', '\x2', '\x2', + '\x2', '\x2CC', '\x2CD', '\x3', '\x2', '\x2', '\x2', '\x2CD', '\x2CE', + '\x3', '\x2', '\x2', '\x2', '\x2CE', '\x2D0', '\x5', '\xC0', '\x61', '\x2', + '\x2CF', '\x2D1', '\a', '\x7F', '\x2', '\x2', '\x2D0', '\x2CF', '\x3', + '\x2', '\x2', '\x2', '\x2D0', '\x2D1', '\x3', '\x2', '\x2', '\x2', '\x2D1', + '\x2D2', '\x3', '\x2', '\x2', '\x2', '\x2D2', '\x2D3', '\x5', '\xBE', + '`', '\x2', '\x2D3', '\x301', '\x3', '\x2', '\x2', '\x2', '\x2D4', '\x2D6', + '\x5', '\xBC', '_', '\x2', '\x2D5', '\x2D7', '\a', '\x7F', '\x2', '\x2', + '\x2D6', '\x2D5', '\x3', '\x2', '\x2', '\x2', '\x2D6', '\x2D7', '\x3', + '\x2', '\x2', '\x2', '\x2D7', '\x2D8', '\x3', '\x2', '\x2', '\x2', '\x2D8', + '\x2DA', '\x5', '\xC0', '\x61', '\x2', '\x2D9', '\x2DB', '\a', '\x7F', + '\x2', '\x2', '\x2DA', '\x2D9', '\x3', '\x2', '\x2', '\x2', '\x2DA', '\x2DB', + '\x3', '\x2', '\x2', '\x2', '\x2DB', '\x2DD', '\x3', '\x2', '\x2', '\x2', + '\x2DC', '\x2DE', '\x5', 'T', '+', '\x2', '\x2DD', '\x2DC', '\x3', '\x2', + '\x2', '\x2', '\x2DD', '\x2DE', '\x3', '\x2', '\x2', '\x2', '\x2DE', '\x2E0', + '\x3', '\x2', '\x2', '\x2', '\x2DF', '\x2E1', '\a', '\x7F', '\x2', '\x2', + '\x2E0', '\x2DF', '\x3', '\x2', '\x2', '\x2', '\x2E0', '\x2E1', '\x3', + '\x2', '\x2', '\x2', '\x2E1', '\x2E2', '\x3', '\x2', '\x2', '\x2', '\x2E2', + '\x2E3', '\x5', '\xC0', '\x61', '\x2', '\x2E3', '\x301', '\x3', '\x2', + '\x2', '\x2', '\x2E4', '\x2E6', '\x5', '\xC0', '\x61', '\x2', '\x2E5', + '\x2E7', '\a', '\x7F', '\x2', '\x2', '\x2E6', '\x2E5', '\x3', '\x2', '\x2', + '\x2', '\x2E6', '\x2E7', '\x3', '\x2', '\x2', '\x2', '\x2E7', '\x2E9', + '\x3', '\x2', '\x2', '\x2', '\x2E8', '\x2EA', '\x5', 'T', '+', '\x2', + '\x2E9', '\x2E8', '\x3', '\x2', '\x2', '\x2', '\x2E9', '\x2EA', '\x3', + '\x2', '\x2', '\x2', '\x2EA', '\x2EC', '\x3', '\x2', '\x2', '\x2', '\x2EB', + '\x2ED', '\a', '\x7F', '\x2', '\x2', '\x2EC', '\x2EB', '\x3', '\x2', '\x2', + '\x2', '\x2EC', '\x2ED', '\x3', '\x2', '\x2', '\x2', '\x2ED', '\x2EE', + '\x3', '\x2', '\x2', '\x2', '\x2EE', '\x2F0', '\x5', '\xC0', '\x61', '\x2', + '\x2EF', '\x2F1', '\a', '\x7F', '\x2', '\x2', '\x2F0', '\x2EF', '\x3', + '\x2', '\x2', '\x2', '\x2F0', '\x2F1', '\x3', '\x2', '\x2', '\x2', '\x2F1', + '\x2F2', '\x3', '\x2', '\x2', '\x2', '\x2F2', '\x2F3', '\x5', '\xBE', + '`', '\x2', '\x2F3', '\x301', '\x3', '\x2', '\x2', '\x2', '\x2F4', '\x2F6', + '\x5', '\xC0', '\x61', '\x2', '\x2F5', '\x2F7', '\a', '\x7F', '\x2', '\x2', + '\x2F6', '\x2F5', '\x3', '\x2', '\x2', '\x2', '\x2F6', '\x2F7', '\x3', + '\x2', '\x2', '\x2', '\x2F7', '\x2F9', '\x3', '\x2', '\x2', '\x2', '\x2F8', + '\x2FA', '\x5', 'T', '+', '\x2', '\x2F9', '\x2F8', '\x3', '\x2', '\x2', + '\x2', '\x2F9', '\x2FA', '\x3', '\x2', '\x2', '\x2', '\x2FA', '\x2FC', + '\x3', '\x2', '\x2', '\x2', '\x2FB', '\x2FD', '\a', '\x7F', '\x2', '\x2', + '\x2FC', '\x2FB', '\x3', '\x2', '\x2', '\x2', '\x2FC', '\x2FD', '\x3', + '\x2', '\x2', '\x2', '\x2FD', '\x2FE', '\x3', '\x2', '\x2', '\x2', '\x2FE', + '\x2FF', '\x5', '\xC0', '\x61', '\x2', '\x2FF', '\x301', '\x3', '\x2', + '\x2', '\x2', '\x300', '\x2C0', '\x3', '\x2', '\x2', '\x2', '\x300', '\x2D4', + '\x3', '\x2', '\x2', '\x2', '\x300', '\x2E4', '\x3', '\x2', '\x2', '\x2', + '\x300', '\x2F4', '\x3', '\x2', '\x2', '\x2', '\x301', 'S', '\x3', '\x2', + '\x2', '\x2', '\x302', '\x304', '\a', '\v', '\x2', '\x2', '\x303', '\x305', + '\a', '\x7F', '\x2', '\x2', '\x304', '\x303', '\x3', '\x2', '\x2', '\x2', + '\x304', '\x305', '\x3', '\x2', '\x2', '\x2', '\x305', '\x30A', '\x3', + '\x2', '\x2', '\x2', '\x306', '\x308', '\x5', '\xA6', 'T', '\x2', '\x307', + '\x309', '\a', '\x7F', '\x2', '\x2', '\x308', '\x307', '\x3', '\x2', '\x2', + '\x2', '\x308', '\x309', '\x3', '\x2', '\x2', '\x2', '\x309', '\x30B', + '\x3', '\x2', '\x2', '\x2', '\x30A', '\x306', '\x3', '\x2', '\x2', '\x2', + '\x30A', '\x30B', '\x3', '\x2', '\x2', '\x2', '\x30B', '\x310', '\x3', + '\x2', '\x2', '\x2', '\x30C', '\x30E', '\x5', 'X', '-', '\x2', '\x30D', + '\x30F', '\a', '\x7F', '\x2', '\x2', '\x30E', '\x30D', '\x3', '\x2', '\x2', + '\x2', '\x30E', '\x30F', '\x3', '\x2', '\x2', '\x2', '\x30F', '\x311', + '\x3', '\x2', '\x2', '\x2', '\x310', '\x30C', '\x3', '\x2', '\x2', '\x2', + '\x310', '\x311', '\x3', '\x2', '\x2', '\x2', '\x311', '\x313', '\x3', + '\x2', '\x2', '\x2', '\x312', '\x314', '\x5', '^', '\x30', '\x2', '\x313', + '\x312', '\x3', '\x2', '\x2', '\x2', '\x313', '\x314', '\x3', '\x2', '\x2', + '\x2', '\x314', '\x319', '\x3', '\x2', '\x2', '\x2', '\x315', '\x317', + '\x5', 'V', ',', '\x2', '\x316', '\x318', '\a', '\x7F', '\x2', '\x2', + '\x317', '\x316', '\x3', '\x2', '\x2', '\x2', '\x317', '\x318', '\x3', + '\x2', '\x2', '\x2', '\x318', '\x31A', '\x3', '\x2', '\x2', '\x2', '\x319', + '\x315', '\x3', '\x2', '\x2', '\x2', '\x319', '\x31A', '\x3', '\x2', '\x2', + '\x2', '\x31A', '\x31B', '\x3', '\x2', '\x2', '\x2', '\x31B', '\x31C', + '\a', '\f', '\x2', '\x2', '\x31C', 'U', '\x3', '\x2', '\x2', '\x2', '\x31D', + '\x320', '\x5', '\xAA', 'V', '\x2', '\x31E', '\x320', '\x5', '\xAC', 'W', + '\x2', '\x31F', '\x31D', '\x3', '\x2', '\x2', '\x2', '\x31F', '\x31E', + '\x3', '\x2', '\x2', '\x2', '\x320', 'W', '\x3', '\x2', '\x2', '\x2', + '\x321', '\x323', '\a', '\r', '\x2', '\x2', '\x322', '\x324', '\a', '\x7F', + '\x2', '\x2', '\x323', '\x322', '\x3', '\x2', '\x2', '\x2', '\x323', '\x324', + '\x3', '\x2', '\x2', '\x2', '\x324', '\x325', '\x3', '\x2', '\x2', '\x2', + '\x325', '\x333', '\x5', '\x62', '\x32', '\x2', '\x326', '\x328', '\a', + '\x7F', '\x2', '\x2', '\x327', '\x326', '\x3', '\x2', '\x2', '\x2', '\x327', + '\x328', '\x3', '\x2', '\x2', '\x2', '\x328', '\x329', '\x3', '\x2', '\x2', + '\x2', '\x329', '\x32B', '\a', '\xE', '\x2', '\x2', '\x32A', '\x32C', + '\a', '\r', '\x2', '\x2', '\x32B', '\x32A', '\x3', '\x2', '\x2', '\x2', + '\x32B', '\x32C', '\x3', '\x2', '\x2', '\x2', '\x32C', '\x32E', '\x3', + '\x2', '\x2', '\x2', '\x32D', '\x32F', '\a', '\x7F', '\x2', '\x2', '\x32E', + '\x32D', '\x3', '\x2', '\x2', '\x2', '\x32E', '\x32F', '\x3', '\x2', '\x2', + '\x2', '\x32F', '\x330', '\x3', '\x2', '\x2', '\x2', '\x330', '\x332', + '\x5', '\x62', '\x32', '\x2', '\x331', '\x327', '\x3', '\x2', '\x2', '\x2', + '\x332', '\x335', '\x3', '\x2', '\x2', '\x2', '\x333', '\x331', '\x3', + '\x2', '\x2', '\x2', '\x333', '\x334', '\x3', '\x2', '\x2', '\x2', '\x334', + 'Y', '\x3', '\x2', '\x2', '\x2', '\x335', '\x333', '\x3', '\x2', '\x2', + '\x2', '\x336', '\x33D', '\x5', '\\', '/', '\x2', '\x337', '\x339', '\a', + '\x7F', '\x2', '\x2', '\x338', '\x337', '\x3', '\x2', '\x2', '\x2', '\x338', + '\x339', '\x3', '\x2', '\x2', '\x2', '\x339', '\x33A', '\x3', '\x2', '\x2', + '\x2', '\x33A', '\x33C', '\x5', '\\', '/', '\x2', '\x33B', '\x338', '\x3', + '\x2', '\x2', '\x2', '\x33C', '\x33F', '\x3', '\x2', '\x2', '\x2', '\x33D', + '\x33B', '\x3', '\x2', '\x2', '\x2', '\x33D', '\x33E', '\x3', '\x2', '\x2', + '\x2', '\x33E', '[', '\x3', '\x2', '\x2', '\x2', '\x33F', '\x33D', '\x3', + '\x2', '\x2', '\x2', '\x340', '\x342', '\a', '\r', '\x2', '\x2', '\x341', + '\x343', '\a', '\x7F', '\x2', '\x2', '\x342', '\x341', '\x3', '\x2', '\x2', + '\x2', '\x342', '\x343', '\x3', '\x2', '\x2', '\x2', '\x343', '\x344', + '\x3', '\x2', '\x2', '\x2', '\x344', '\x345', '\x5', '`', '\x31', '\x2', + '\x345', ']', '\x3', '\x2', '\x2', '\x2', '\x346', '\x348', '\a', '\b', + '\x2', '\x2', '\x347', '\x349', '\a', '\x7F', '\x2', '\x2', '\x348', '\x347', + '\x3', '\x2', '\x2', '\x2', '\x348', '\x349', '\x3', '\x2', '\x2', '\x2', + '\x349', '\x34E', '\x3', '\x2', '\x2', '\x2', '\x34A', '\x34C', '\x5', + '\xB2', 'Z', '\x2', '\x34B', '\x34D', '\a', '\x7F', '\x2', '\x2', '\x34C', + '\x34B', '\x3', '\x2', '\x2', '\x2', '\x34C', '\x34D', '\x3', '\x2', '\x2', + '\x2', '\x34D', '\x34F', '\x3', '\x2', '\x2', '\x2', '\x34E', '\x34A', + '\x3', '\x2', '\x2', '\x2', '\x34E', '\x34F', '\x3', '\x2', '\x2', '\x2', + '\x34F', '\x35A', '\x3', '\x2', '\x2', '\x2', '\x350', '\x352', '\a', + '\xF', '\x2', '\x2', '\x351', '\x353', '\a', '\x7F', '\x2', '\x2', '\x352', + '\x351', '\x3', '\x2', '\x2', '\x2', '\x352', '\x353', '\x3', '\x2', '\x2', + '\x2', '\x353', '\x358', '\x3', '\x2', '\x2', '\x2', '\x354', '\x356', + '\x5', '\xB2', 'Z', '\x2', '\x355', '\x357', '\a', '\x7F', '\x2', '\x2', + '\x356', '\x355', '\x3', '\x2', '\x2', '\x2', '\x356', '\x357', '\x3', + '\x2', '\x2', '\x2', '\x357', '\x359', '\x3', '\x2', '\x2', '\x2', '\x358', + '\x354', '\x3', '\x2', '\x2', '\x2', '\x358', '\x359', '\x3', '\x2', '\x2', + '\x2', '\x359', '\x35B', '\x3', '\x2', '\x2', '\x2', '\x35A', '\x350', + '\x3', '\x2', '\x2', '\x2', '\x35A', '\x35B', '\x3', '\x2', '\x2', '\x2', + '\x35B', '_', '\x3', '\x2', '\x2', '\x2', '\x35C', '\x35D', '\x5', '\xB6', + '\\', '\x2', '\x35D', '\x61', '\x3', '\x2', '\x2', '\x2', '\x35E', '\x35F', + '\x5', '\xB6', '\\', '\x2', '\x35F', '\x63', '\x3', '\x2', '\x2', '\x2', + '\x360', '\x361', '\x5', '\x66', '\x34', '\x2', '\x361', '\x65', '\x3', + '\x2', '\x2', '\x2', '\x362', '\x369', '\x5', 'h', '\x35', '\x2', '\x363', + '\x364', '\a', '\x7F', '\x2', '\x2', '\x364', '\x365', '\a', 'K', '\x2', + '\x2', '\x365', '\x366', '\a', '\x7F', '\x2', '\x2', '\x366', '\x368', + '\x5', 'h', '\x35', '\x2', '\x367', '\x363', '\x3', '\x2', '\x2', '\x2', + '\x368', '\x36B', '\x3', '\x2', '\x2', '\x2', '\x369', '\x367', '\x3', + '\x2', '\x2', '\x2', '\x369', '\x36A', '\x3', '\x2', '\x2', '\x2', '\x36A', + 'g', '\x3', '\x2', '\x2', '\x2', '\x36B', '\x369', '\x3', '\x2', '\x2', + '\x2', '\x36C', '\x373', '\x5', 'j', '\x36', '\x2', '\x36D', '\x36E', + '\a', '\x7F', '\x2', '\x2', '\x36E', '\x36F', '\a', 'L', '\x2', '\x2', + '\x36F', '\x370', '\a', '\x7F', '\x2', '\x2', '\x370', '\x372', '\x5', + 'j', '\x36', '\x2', '\x371', '\x36D', '\x3', '\x2', '\x2', '\x2', '\x372', + '\x375', '\x3', '\x2', '\x2', '\x2', '\x373', '\x371', '\x3', '\x2', '\x2', + '\x2', '\x373', '\x374', '\x3', '\x2', '\x2', '\x2', '\x374', 'i', '\x3', + '\x2', '\x2', '\x2', '\x375', '\x373', '\x3', '\x2', '\x2', '\x2', '\x376', + '\x37D', '\x5', 'l', '\x37', '\x2', '\x377', '\x378', '\a', '\x7F', '\x2', + '\x2', '\x378', '\x379', '\a', 'M', '\x2', '\x2', '\x379', '\x37A', '\a', + '\x7F', '\x2', '\x2', '\x37A', '\x37C', '\x5', 'l', '\x37', '\x2', '\x37B', + '\x377', '\x3', '\x2', '\x2', '\x2', '\x37C', '\x37F', '\x3', '\x2', '\x2', + '\x2', '\x37D', '\x37B', '\x3', '\x2', '\x2', '\x2', '\x37D', '\x37E', + '\x3', '\x2', '\x2', '\x2', '\x37E', 'k', '\x3', '\x2', '\x2', '\x2', + '\x37F', '\x37D', '\x3', '\x2', '\x2', '\x2', '\x380', '\x382', '\a', + 'N', '\x2', '\x2', '\x381', '\x383', '\a', '\x7F', '\x2', '\x2', '\x382', + '\x381', '\x3', '\x2', '\x2', '\x2', '\x382', '\x383', '\x3', '\x2', '\x2', + '\x2', '\x383', '\x385', '\x3', '\x2', '\x2', '\x2', '\x384', '\x380', + '\x3', '\x2', '\x2', '\x2', '\x385', '\x388', '\x3', '\x2', '\x2', '\x2', + '\x386', '\x384', '\x3', '\x2', '\x2', '\x2', '\x386', '\x387', '\x3', + '\x2', '\x2', '\x2', '\x387', '\x389', '\x3', '\x2', '\x2', '\x2', '\x388', + '\x386', '\x3', '\x2', '\x2', '\x2', '\x389', '\x38A', '\x5', 'n', '\x38', + '\x2', '\x38A', 'm', '\x3', '\x2', '\x2', '\x2', '\x38B', '\x392', '\x5', + 'p', '\x39', '\x2', '\x38C', '\x38E', '\a', '\x7F', '\x2', '\x2', '\x38D', + '\x38C', '\x3', '\x2', '\x2', '\x2', '\x38D', '\x38E', '\x3', '\x2', '\x2', + '\x2', '\x38E', '\x38F', '\x3', '\x2', '\x2', '\x2', '\x38F', '\x391', + '\x5', '\x84', '\x43', '\x2', '\x390', '\x38D', '\x3', '\x2', '\x2', '\x2', + '\x391', '\x394', '\x3', '\x2', '\x2', '\x2', '\x392', '\x390', '\x3', + '\x2', '\x2', '\x2', '\x392', '\x393', '\x3', '\x2', '\x2', '\x2', '\x393', + 'o', '\x3', '\x2', '\x2', '\x2', '\x394', '\x392', '\x3', '\x2', '\x2', + '\x2', '\x395', '\x3A8', '\x5', 'r', ':', '\x2', '\x396', '\x398', '\a', + '\x7F', '\x2', '\x2', '\x397', '\x396', '\x3', '\x2', '\x2', '\x2', '\x397', + '\x398', '\x3', '\x2', '\x2', '\x2', '\x398', '\x399', '\x3', '\x2', '\x2', + '\x2', '\x399', '\x39B', '\a', '\x10', '\x2', '\x2', '\x39A', '\x39C', + '\a', '\x7F', '\x2', '\x2', '\x39B', '\x39A', '\x3', '\x2', '\x2', '\x2', + '\x39B', '\x39C', '\x3', '\x2', '\x2', '\x2', '\x39C', '\x39D', '\x3', + '\x2', '\x2', '\x2', '\x39D', '\x3A7', '\x5', 'r', ':', '\x2', '\x39E', + '\x3A0', '\a', '\x7F', '\x2', '\x2', '\x39F', '\x39E', '\x3', '\x2', '\x2', + '\x2', '\x39F', '\x3A0', '\x3', '\x2', '\x2', '\x2', '\x3A0', '\x3A1', + '\x3', '\x2', '\x2', '\x2', '\x3A1', '\x3A3', '\a', '\a', '\x2', '\x2', + '\x3A2', '\x3A4', '\a', '\x7F', '\x2', '\x2', '\x3A3', '\x3A2', '\x3', + '\x2', '\x2', '\x2', '\x3A3', '\x3A4', '\x3', '\x2', '\x2', '\x2', '\x3A4', + '\x3A5', '\x3', '\x2', '\x2', '\x2', '\x3A5', '\x3A7', '\x5', 'r', ':', + '\x2', '\x3A6', '\x397', '\x3', '\x2', '\x2', '\x2', '\x3A6', '\x39F', + '\x3', '\x2', '\x2', '\x2', '\x3A7', '\x3AA', '\x3', '\x2', '\x2', '\x2', + '\x3A8', '\x3A6', '\x3', '\x2', '\x2', '\x2', '\x3A8', '\x3A9', '\x3', + '\x2', '\x2', '\x2', '\x3A9', 'q', '\x3', '\x2', '\x2', '\x2', '\x3AA', + '\x3A8', '\x3', '\x2', '\x2', '\x2', '\x3AB', '\x3C6', '\x5', 't', ';', + '\x2', '\x3AC', '\x3AE', '\a', '\x7F', '\x2', '\x2', '\x3AD', '\x3AC', + '\x3', '\x2', '\x2', '\x2', '\x3AD', '\x3AE', '\x3', '\x2', '\x2', '\x2', + '\x3AE', '\x3AF', '\x3', '\x2', '\x2', '\x2', '\x3AF', '\x3B1', '\a', + '\b', '\x2', '\x2', '\x3B0', '\x3B2', '\a', '\x7F', '\x2', '\x2', '\x3B1', + '\x3B0', '\x3', '\x2', '\x2', '\x2', '\x3B1', '\x3B2', '\x3', '\x2', '\x2', + '\x2', '\x3B2', '\x3B3', '\x3', '\x2', '\x2', '\x2', '\x3B3', '\x3C5', + '\x5', 't', ';', '\x2', '\x3B4', '\x3B6', '\a', '\x7F', '\x2', '\x2', + '\x3B5', '\x3B4', '\x3', '\x2', '\x2', '\x2', '\x3B5', '\x3B6', '\x3', + '\x2', '\x2', '\x2', '\x3B6', '\x3B7', '\x3', '\x2', '\x2', '\x2', '\x3B7', + '\x3B9', '\a', '\x11', '\x2', '\x2', '\x3B8', '\x3BA', '\a', '\x7F', '\x2', + '\x2', '\x3B9', '\x3B8', '\x3', '\x2', '\x2', '\x2', '\x3B9', '\x3BA', + '\x3', '\x2', '\x2', '\x2', '\x3BA', '\x3BB', '\x3', '\x2', '\x2', '\x2', + '\x3BB', '\x3C5', '\x5', 't', ';', '\x2', '\x3BC', '\x3BE', '\a', '\x7F', + '\x2', '\x2', '\x3BD', '\x3BC', '\x3', '\x2', '\x2', '\x2', '\x3BD', '\x3BE', + '\x3', '\x2', '\x2', '\x2', '\x3BE', '\x3BF', '\x3', '\x2', '\x2', '\x2', + '\x3BF', '\x3C1', '\a', '\x12', '\x2', '\x2', '\x3C0', '\x3C2', '\a', + '\x7F', '\x2', '\x2', '\x3C1', '\x3C0', '\x3', '\x2', '\x2', '\x2', '\x3C1', + '\x3C2', '\x3', '\x2', '\x2', '\x2', '\x3C2', '\x3C3', '\x3', '\x2', '\x2', + '\x2', '\x3C3', '\x3C5', '\x5', 't', ';', '\x2', '\x3C4', '\x3AD', '\x3', + '\x2', '\x2', '\x2', '\x3C4', '\x3B5', '\x3', '\x2', '\x2', '\x2', '\x3C4', + '\x3BD', '\x3', '\x2', '\x2', '\x2', '\x3C5', '\x3C8', '\x3', '\x2', '\x2', + '\x2', '\x3C6', '\x3C4', '\x3', '\x2', '\x2', '\x2', '\x3C6', '\x3C7', + '\x3', '\x2', '\x2', '\x2', '\x3C7', 's', '\x3', '\x2', '\x2', '\x2', + '\x3C8', '\x3C6', '\x3', '\x2', '\x2', '\x2', '\x3C9', '\x3D4', '\x5', + 'v', '<', '\x2', '\x3CA', '\x3CC', '\a', '\x7F', '\x2', '\x2', '\x3CB', + '\x3CA', '\x3', '\x2', '\x2', '\x2', '\x3CB', '\x3CC', '\x3', '\x2', '\x2', + '\x2', '\x3CC', '\x3CD', '\x3', '\x2', '\x2', '\x2', '\x3CD', '\x3CF', + '\a', '\x13', '\x2', '\x2', '\x3CE', '\x3D0', '\a', '\x7F', '\x2', '\x2', + '\x3CF', '\x3CE', '\x3', '\x2', '\x2', '\x2', '\x3CF', '\x3D0', '\x3', + '\x2', '\x2', '\x2', '\x3D0', '\x3D1', '\x3', '\x2', '\x2', '\x2', '\x3D1', + '\x3D3', '\x5', 'v', '<', '\x2', '\x3D2', '\x3CB', '\x3', '\x2', '\x2', + '\x2', '\x3D3', '\x3D6', '\x3', '\x2', '\x2', '\x2', '\x3D4', '\x3D2', + '\x3', '\x2', '\x2', '\x2', '\x3D4', '\x3D5', '\x3', '\x2', '\x2', '\x2', + '\x3D5', 'u', '\x3', '\x2', '\x2', '\x2', '\x3D6', '\x3D4', '\x3', '\x2', + '\x2', '\x2', '\x3D7', '\x3D9', '\t', '\x3', '\x2', '\x2', '\x3D8', '\x3DA', + '\a', '\x7F', '\x2', '\x2', '\x3D9', '\x3D8', '\x3', '\x2', '\x2', '\x2', + '\x3D9', '\x3DA', '\x3', '\x2', '\x2', '\x2', '\x3DA', '\x3DC', '\x3', + '\x2', '\x2', '\x2', '\x3DB', '\x3D7', '\x3', '\x2', '\x2', '\x2', '\x3DC', + '\x3DF', '\x3', '\x2', '\x2', '\x2', '\x3DD', '\x3DB', '\x3', '\x2', '\x2', + '\x2', '\x3DD', '\x3DE', '\x3', '\x2', '\x2', '\x2', '\x3DE', '\x3E0', + '\x3', '\x2', '\x2', '\x2', '\x3DF', '\x3DD', '\x3', '\x2', '\x2', '\x2', + '\x3E0', '\x3E1', '\x5', 'x', '=', '\x2', '\x3E1', 'w', '\x3', '\x2', + '\x2', '\x2', '\x3E2', '\x414', '\x5', 'z', '>', '\x2', '\x3E3', '\x3E5', + '\a', '\x7F', '\x2', '\x2', '\x3E4', '\x3E3', '\x3', '\x2', '\x2', '\x2', + '\x3E4', '\x3E5', '\x3', '\x2', '\x2', '\x2', '\x3E5', '\x3E6', '\x3', + '\x2', '\x2', '\x2', '\x3E6', '\x3E7', '\a', '\v', '\x2', '\x2', '\x3E7', + '\x3E8', '\x5', '\x64', '\x33', '\x2', '\x3E8', '\x3E9', '\a', '\f', '\x2', + '\x2', '\x3E9', '\x413', '\x3', '\x2', '\x2', '\x2', '\x3EA', '\x3EC', + '\a', '\x7F', '\x2', '\x2', '\x3EB', '\x3EA', '\x3', '\x2', '\x2', '\x2', + '\x3EB', '\x3EC', '\x3', '\x2', '\x2', '\x2', '\x3EC', '\x3ED', '\x3', + '\x2', '\x2', '\x2', '\x3ED', '\x3EF', '\a', '\v', '\x2', '\x2', '\x3EE', + '\x3F0', '\x5', '\x64', '\x33', '\x2', '\x3EF', '\x3EE', '\x3', '\x2', + '\x2', '\x2', '\x3EF', '\x3F0', '\x3', '\x2', '\x2', '\x2', '\x3F0', '\x3F1', + '\x3', '\x2', '\x2', '\x2', '\x3F1', '\x3F3', '\a', '\xF', '\x2', '\x2', + '\x3F2', '\x3F4', '\x5', '\x64', '\x33', '\x2', '\x3F3', '\x3F2', '\x3', + '\x2', '\x2', '\x2', '\x3F3', '\x3F4', '\x3', '\x2', '\x2', '\x2', '\x3F4', + '\x3F5', '\x3', '\x2', '\x2', '\x2', '\x3F5', '\x413', '\a', '\f', '\x2', + '\x2', '\x3F6', '\x3F7', '\a', '\x7F', '\x2', '\x2', '\x3F7', '\x403', + '\a', 'O', '\x2', '\x2', '\x3F8', '\x3F9', '\a', '\x7F', '\x2', '\x2', + '\x3F9', '\x3FA', '\a', 'P', '\x2', '\x2', '\x3FA', '\x3FB', '\a', '\x7F', + '\x2', '\x2', '\x3FB', '\x403', '\a', '?', '\x2', '\x2', '\x3FC', '\x3FD', + '\a', '\x7F', '\x2', '\x2', '\x3FD', '\x3FE', '\a', 'Q', '\x2', '\x2', + '\x3FE', '\x3FF', '\a', '\x7F', '\x2', '\x2', '\x3FF', '\x403', '\a', + '?', '\x2', '\x2', '\x400', '\x401', '\a', '\x7F', '\x2', '\x2', '\x401', + '\x403', '\a', 'R', '\x2', '\x2', '\x402', '\x3F6', '\x3', '\x2', '\x2', + '\x2', '\x402', '\x3F8', '\x3', '\x2', '\x2', '\x2', '\x402', '\x3FC', + '\x3', '\x2', '\x2', '\x2', '\x402', '\x400', '\x3', '\x2', '\x2', '\x2', + '\x403', '\x405', '\x3', '\x2', '\x2', '\x2', '\x404', '\x406', '\a', + '\x7F', '\x2', '\x2', '\x405', '\x404', '\x3', '\x2', '\x2', '\x2', '\x405', + '\x406', '\x3', '\x2', '\x2', '\x2', '\x406', '\x407', '\x3', '\x2', '\x2', + '\x2', '\x407', '\x413', '\x5', 'z', '>', '\x2', '\x408', '\x409', '\a', + '\x7F', '\x2', '\x2', '\x409', '\x40A', '\a', 'S', '\x2', '\x2', '\x40A', + '\x40B', '\a', '\x7F', '\x2', '\x2', '\x40B', '\x413', '\a', 'T', '\x2', + '\x2', '\x40C', '\x40D', '\a', '\x7F', '\x2', '\x2', '\x40D', '\x40E', + '\a', 'S', '\x2', '\x2', '\x40E', '\x40F', '\a', '\x7F', '\x2', '\x2', + '\x40F', '\x410', '\a', 'N', '\x2', '\x2', '\x410', '\x411', '\a', '\x7F', + '\x2', '\x2', '\x411', '\x413', '\a', 'T', '\x2', '\x2', '\x412', '\x3E4', + '\x3', '\x2', '\x2', '\x2', '\x412', '\x3EB', '\x3', '\x2', '\x2', '\x2', + '\x412', '\x402', '\x3', '\x2', '\x2', '\x2', '\x412', '\x408', '\x3', + '\x2', '\x2', '\x2', '\x412', '\x40C', '\x3', '\x2', '\x2', '\x2', '\x413', + '\x416', '\x3', '\x2', '\x2', '\x2', '\x414', '\x412', '\x3', '\x2', '\x2', + '\x2', '\x414', '\x415', '\x3', '\x2', '\x2', '\x2', '\x415', 'y', '\x3', + '\x2', '\x2', '\x2', '\x416', '\x414', '\x3', '\x2', '\x2', '\x2', '\x417', + '\x41E', '\x5', '|', '?', '\x2', '\x418', '\x41A', '\a', '\x7F', '\x2', + '\x2', '\x419', '\x418', '\x3', '\x2', '\x2', '\x2', '\x419', '\x41A', + '\x3', '\x2', '\x2', '\x2', '\x41A', '\x41B', '\x3', '\x2', '\x2', '\x2', + '\x41B', '\x41D', '\x5', '\xA0', 'Q', '\x2', '\x41C', '\x419', '\x3', + '\x2', '\x2', '\x2', '\x41D', '\x420', '\x3', '\x2', '\x2', '\x2', '\x41E', + '\x41C', '\x3', '\x2', '\x2', '\x2', '\x41E', '\x41F', '\x3', '\x2', '\x2', + '\x2', '\x41F', '\x425', '\x3', '\x2', '\x2', '\x2', '\x420', '\x41E', + '\x3', '\x2', '\x2', '\x2', '\x421', '\x423', '\a', '\x7F', '\x2', '\x2', + '\x422', '\x421', '\x3', '\x2', '\x2', '\x2', '\x422', '\x423', '\x3', + '\x2', '\x2', '\x2', '\x423', '\x424', '\x3', '\x2', '\x2', '\x2', '\x424', + '\x426', '\x5', 'Z', '.', '\x2', '\x425', '\x422', '\x3', '\x2', '\x2', + '\x2', '\x425', '\x426', '\x3', '\x2', '\x2', '\x2', '\x426', '{', '\x3', + '\x2', '\x2', '\x2', '\x427', '\x499', '\x5', '~', '@', '\x2', '\x428', + '\x499', '\x5', '\xAC', 'W', '\x2', '\x429', '\x499', '\x5', '\xA2', 'R', + '\x2', '\x42A', '\x42C', '\a', 'U', '\x2', '\x2', '\x42B', '\x42D', '\a', + '\x7F', '\x2', '\x2', '\x42C', '\x42B', '\x3', '\x2', '\x2', '\x2', '\x42C', + '\x42D', '\x3', '\x2', '\x2', '\x2', '\x42D', '\x42E', '\x3', '\x2', '\x2', + '\x2', '\x42E', '\x430', '\a', '\t', '\x2', '\x2', '\x42F', '\x431', '\a', + '\x7F', '\x2', '\x2', '\x430', '\x42F', '\x3', '\x2', '\x2', '\x2', '\x430', + '\x431', '\x3', '\x2', '\x2', '\x2', '\x431', '\x432', '\x3', '\x2', '\x2', + '\x2', '\x432', '\x434', '\a', '\b', '\x2', '\x2', '\x433', '\x435', '\a', + '\x7F', '\x2', '\x2', '\x434', '\x433', '\x3', '\x2', '\x2', '\x2', '\x434', + '\x435', '\x3', '\x2', '\x2', '\x2', '\x435', '\x436', '\x3', '\x2', '\x2', + '\x2', '\x436', '\x499', '\a', '\n', '\x2', '\x2', '\x437', '\x499', '\x5', + '\x9C', 'O', '\x2', '\x438', '\x499', '\x5', '\x9E', 'P', '\x2', '\x439', + '\x43B', '\a', 'V', '\x2', '\x2', '\x43A', '\x43C', '\a', '\x7F', '\x2', + '\x2', '\x43B', '\x43A', '\x3', '\x2', '\x2', '\x2', '\x43B', '\x43C', + '\x3', '\x2', '\x2', '\x2', '\x43C', '\x43D', '\x3', '\x2', '\x2', '\x2', + '\x43D', '\x43F', '\a', '\t', '\x2', '\x2', '\x43E', '\x440', '\a', '\x7F', + '\x2', '\x2', '\x43F', '\x43E', '\x3', '\x2', '\x2', '\x2', '\x43F', '\x440', + '\x3', '\x2', '\x2', '\x2', '\x440', '\x441', '\x3', '\x2', '\x2', '\x2', + '\x441', '\x443', '\x5', '\x8A', '\x46', '\x2', '\x442', '\x444', '\a', + '\x7F', '\x2', '\x2', '\x443', '\x442', '\x3', '\x2', '\x2', '\x2', '\x443', + '\x444', '\x3', '\x2', '\x2', '\x2', '\x444', '\x445', '\x3', '\x2', '\x2', + '\x2', '\x445', '\x446', '\a', '\n', '\x2', '\x2', '\x446', '\x499', '\x3', + '\x2', '\x2', '\x2', '\x447', '\x449', '\a', 'W', '\x2', '\x2', '\x448', + '\x44A', '\a', '\x7F', '\x2', '\x2', '\x449', '\x448', '\x3', '\x2', '\x2', + '\x2', '\x449', '\x44A', '\x3', '\x2', '\x2', '\x2', '\x44A', '\x44B', + '\x3', '\x2', '\x2', '\x2', '\x44B', '\x44D', '\a', '\t', '\x2', '\x2', + '\x44C', '\x44E', '\a', '\x7F', '\x2', '\x2', '\x44D', '\x44C', '\x3', + '\x2', '\x2', '\x2', '\x44D', '\x44E', '\x3', '\x2', '\x2', '\x2', '\x44E', + '\x44F', '\x3', '\x2', '\x2', '\x2', '\x44F', '\x451', '\x5', '\x8A', + '\x46', '\x2', '\x450', '\x452', '\a', '\x7F', '\x2', '\x2', '\x451', + '\x450', '\x3', '\x2', '\x2', '\x2', '\x451', '\x452', '\x3', '\x2', '\x2', + '\x2', '\x452', '\x458', '\x3', '\x2', '\x2', '\x2', '\x453', '\x455', + '\a', '\x7F', '\x2', '\x2', '\x454', '\x453', '\x3', '\x2', '\x2', '\x2', + '\x454', '\x455', '\x3', '\x2', '\x2', '\x2', '\x455', '\x456', '\x3', + '\x2', '\x2', '\x2', '\x456', '\x457', '\a', '\xE', '\x2', '\x2', '\x457', + '\x459', '\x5', '\x64', '\x33', '\x2', '\x458', '\x454', '\x3', '\x2', + '\x2', '\x2', '\x458', '\x459', '\x3', '\x2', '\x2', '\x2', '\x459', '\x45A', + '\x3', '\x2', '\x2', '\x2', '\x45A', '\x45B', '\a', '\n', '\x2', '\x2', + '\x45B', '\x499', '\x3', '\x2', '\x2', '\x2', '\x45C', '\x45E', '\a', + '\x31', '\x2', '\x2', '\x45D', '\x45F', '\a', '\x7F', '\x2', '\x2', '\x45E', + '\x45D', '\x3', '\x2', '\x2', '\x2', '\x45E', '\x45F', '\x3', '\x2', '\x2', + '\x2', '\x45F', '\x460', '\x3', '\x2', '\x2', '\x2', '\x460', '\x462', + '\a', '\t', '\x2', '\x2', '\x461', '\x463', '\a', '\x7F', '\x2', '\x2', + '\x462', '\x461', '\x3', '\x2', '\x2', '\x2', '\x462', '\x463', '\x3', + '\x2', '\x2', '\x2', '\x463', '\x464', '\x3', '\x2', '\x2', '\x2', '\x464', + '\x466', '\x5', '\x8A', '\x46', '\x2', '\x465', '\x467', '\a', '\x7F', + '\x2', '\x2', '\x466', '\x465', '\x3', '\x2', '\x2', '\x2', '\x466', '\x467', + '\x3', '\x2', '\x2', '\x2', '\x467', '\x468', '\x3', '\x2', '\x2', '\x2', + '\x468', '\x469', '\a', '\n', '\x2', '\x2', '\x469', '\x499', '\x3', '\x2', + '\x2', '\x2', '\x46A', '\x46C', '\a', 'X', '\x2', '\x2', '\x46B', '\x46D', + '\a', '\x7F', '\x2', '\x2', '\x46C', '\x46B', '\x3', '\x2', '\x2', '\x2', + '\x46C', '\x46D', '\x3', '\x2', '\x2', '\x2', '\x46D', '\x46E', '\x3', + '\x2', '\x2', '\x2', '\x46E', '\x470', '\a', '\t', '\x2', '\x2', '\x46F', + '\x471', '\a', '\x7F', '\x2', '\x2', '\x470', '\x46F', '\x3', '\x2', '\x2', + '\x2', '\x470', '\x471', '\x3', '\x2', '\x2', '\x2', '\x471', '\x472', + '\x3', '\x2', '\x2', '\x2', '\x472', '\x474', '\x5', '\x8A', '\x46', '\x2', + '\x473', '\x475', '\a', '\x7F', '\x2', '\x2', '\x474', '\x473', '\x3', + '\x2', '\x2', '\x2', '\x474', '\x475', '\x3', '\x2', '\x2', '\x2', '\x475', + '\x476', '\x3', '\x2', '\x2', '\x2', '\x476', '\x477', '\a', '\n', '\x2', + '\x2', '\x477', '\x499', '\x3', '\x2', '\x2', '\x2', '\x478', '\x47A', + '\a', 'Y', '\x2', '\x2', '\x479', '\x47B', '\a', '\x7F', '\x2', '\x2', + '\x47A', '\x479', '\x3', '\x2', '\x2', '\x2', '\x47A', '\x47B', '\x3', + '\x2', '\x2', '\x2', '\x47B', '\x47C', '\x3', '\x2', '\x2', '\x2', '\x47C', + '\x47E', '\a', '\t', '\x2', '\x2', '\x47D', '\x47F', '\a', '\x7F', '\x2', + '\x2', '\x47E', '\x47D', '\x3', '\x2', '\x2', '\x2', '\x47E', '\x47F', + '\x3', '\x2', '\x2', '\x2', '\x47F', '\x480', '\x3', '\x2', '\x2', '\x2', + '\x480', '\x482', '\x5', '\x8A', '\x46', '\x2', '\x481', '\x483', '\a', + '\x7F', '\x2', '\x2', '\x482', '\x481', '\x3', '\x2', '\x2', '\x2', '\x482', + '\x483', '\x3', '\x2', '\x2', '\x2', '\x483', '\x484', '\x3', '\x2', '\x2', + '\x2', '\x484', '\x485', '\a', '\n', '\x2', '\x2', '\x485', '\x499', '\x3', + '\x2', '\x2', '\x2', '\x486', '\x488', '\a', 'Z', '\x2', '\x2', '\x487', + '\x489', '\a', '\x7F', '\x2', '\x2', '\x488', '\x487', '\x3', '\x2', '\x2', + '\x2', '\x488', '\x489', '\x3', '\x2', '\x2', '\x2', '\x489', '\x48A', + '\x3', '\x2', '\x2', '\x2', '\x48A', '\x48C', '\a', '\t', '\x2', '\x2', + '\x48B', '\x48D', '\a', '\x7F', '\x2', '\x2', '\x48C', '\x48B', '\x3', + '\x2', '\x2', '\x2', '\x48C', '\x48D', '\x3', '\x2', '\x2', '\x2', '\x48D', + '\x48E', '\x3', '\x2', '\x2', '\x2', '\x48E', '\x490', '\x5', '\x8A', + '\x46', '\x2', '\x48F', '\x491', '\a', '\x7F', '\x2', '\x2', '\x490', + '\x48F', '\x3', '\x2', '\x2', '\x2', '\x490', '\x491', '\x3', '\x2', '\x2', + '\x2', '\x491', '\x492', '\x3', '\x2', '\x2', '\x2', '\x492', '\x493', + '\a', '\n', '\x2', '\x2', '\x493', '\x499', '\x3', '\x2', '\x2', '\x2', + '\x494', '\x499', '\x5', '\x88', '\x45', '\x2', '\x495', '\x499', '\x5', + '\x86', '\x44', '\x2', '\x496', '\x499', '\x5', '\x8E', 'H', '\x2', '\x497', + '\x499', '\x5', '\xA6', 'T', '\x2', '\x498', '\x427', '\x3', '\x2', '\x2', + '\x2', '\x498', '\x428', '\x3', '\x2', '\x2', '\x2', '\x498', '\x429', + '\x3', '\x2', '\x2', '\x2', '\x498', '\x42A', '\x3', '\x2', '\x2', '\x2', + '\x498', '\x437', '\x3', '\x2', '\x2', '\x2', '\x498', '\x438', '\x3', + '\x2', '\x2', '\x2', '\x498', '\x439', '\x3', '\x2', '\x2', '\x2', '\x498', + '\x447', '\x3', '\x2', '\x2', '\x2', '\x498', '\x45C', '\x3', '\x2', '\x2', + '\x2', '\x498', '\x46A', '\x3', '\x2', '\x2', '\x2', '\x498', '\x478', + '\x3', '\x2', '\x2', '\x2', '\x498', '\x486', '\x3', '\x2', '\x2', '\x2', + '\x498', '\x494', '\x3', '\x2', '\x2', '\x2', '\x498', '\x495', '\x3', + '\x2', '\x2', '\x2', '\x498', '\x496', '\x3', '\x2', '\x2', '\x2', '\x498', + '\x497', '\x3', '\x2', '\x2', '\x2', '\x499', '}', '\x3', '\x2', '\x2', + '\x2', '\x49A', '\x4A1', '\x5', '\xA8', 'U', '\x2', '\x49B', '\x4A1', + '\a', '\x63', '\x2', '\x2', '\x49C', '\x4A1', '\x5', '\x80', '\x41', '\x2', + '\x49D', '\x4A1', '\a', 'T', '\x2', '\x2', '\x49E', '\x4A1', '\x5', '\xAA', + 'V', '\x2', '\x49F', '\x4A1', '\x5', '\x82', '\x42', '\x2', '\x4A0', '\x49A', + '\x3', '\x2', '\x2', '\x2', '\x4A0', '\x49B', '\x3', '\x2', '\x2', '\x2', + '\x4A0', '\x49C', '\x3', '\x2', '\x2', '\x2', '\x4A0', '\x49D', '\x3', + '\x2', '\x2', '\x2', '\x4A0', '\x49E', '\x3', '\x2', '\x2', '\x2', '\x4A0', + '\x49F', '\x3', '\x2', '\x2', '\x2', '\x4A1', '\x7F', '\x3', '\x2', '\x2', + '\x2', '\x4A2', '\x4A3', '\t', '\x4', '\x2', '\x2', '\x4A3', '\x81', '\x3', + '\x2', '\x2', '\x2', '\x4A4', '\x4A6', '\a', '\v', '\x2', '\x2', '\x4A5', + '\x4A7', '\a', '\x7F', '\x2', '\x2', '\x4A6', '\x4A5', '\x3', '\x2', '\x2', + '\x2', '\x4A6', '\x4A7', '\x3', '\x2', '\x2', '\x2', '\x4A7', '\x4B9', + '\x3', '\x2', '\x2', '\x2', '\x4A8', '\x4AA', '\x5', '\x64', '\x33', '\x2', + '\x4A9', '\x4AB', '\a', '\x7F', '\x2', '\x2', '\x4AA', '\x4A9', '\x3', + '\x2', '\x2', '\x2', '\x4AA', '\x4AB', '\x3', '\x2', '\x2', '\x2', '\x4AB', + '\x4B6', '\x3', '\x2', '\x2', '\x2', '\x4AC', '\x4AE', '\a', '\x4', '\x2', + '\x2', '\x4AD', '\x4AF', '\a', '\x7F', '\x2', '\x2', '\x4AE', '\x4AD', + '\x3', '\x2', '\x2', '\x2', '\x4AE', '\x4AF', '\x3', '\x2', '\x2', '\x2', + '\x4AF', '\x4B0', '\x3', '\x2', '\x2', '\x2', '\x4B0', '\x4B2', '\x5', + '\x64', '\x33', '\x2', '\x4B1', '\x4B3', '\a', '\x7F', '\x2', '\x2', '\x4B2', + '\x4B1', '\x3', '\x2', '\x2', '\x2', '\x4B2', '\x4B3', '\x3', '\x2', '\x2', + '\x2', '\x4B3', '\x4B5', '\x3', '\x2', '\x2', '\x2', '\x4B4', '\x4AC', + '\x3', '\x2', '\x2', '\x2', '\x4B5', '\x4B8', '\x3', '\x2', '\x2', '\x2', + '\x4B6', '\x4B4', '\x3', '\x2', '\x2', '\x2', '\x4B6', '\x4B7', '\x3', + '\x2', '\x2', '\x2', '\x4B7', '\x4BA', '\x3', '\x2', '\x2', '\x2', '\x4B8', + '\x4B6', '\x3', '\x2', '\x2', '\x2', '\x4B9', '\x4A8', '\x3', '\x2', '\x2', + '\x2', '\x4B9', '\x4BA', '\x3', '\x2', '\x2', '\x2', '\x4BA', '\x4BB', + '\x3', '\x2', '\x2', '\x2', '\x4BB', '\x4BC', '\a', '\f', '\x2', '\x2', + '\x4BC', '\x83', '\x3', '\x2', '\x2', '\x2', '\x4BD', '\x4BF', '\a', '\x5', + '\x2', '\x2', '\x4BE', '\x4C0', '\a', '\x7F', '\x2', '\x2', '\x4BF', '\x4BE', + '\x3', '\x2', '\x2', '\x2', '\x4BF', '\x4C0', '\x3', '\x2', '\x2', '\x2', + '\x4C0', '\x4C1', '\x3', '\x2', '\x2', '\x2', '\x4C1', '\x4DC', '\x5', + 'p', '\x39', '\x2', '\x4C2', '\x4C4', '\a', '\x14', '\x2', '\x2', '\x4C3', + '\x4C5', '\a', '\x7F', '\x2', '\x2', '\x4C4', '\x4C3', '\x3', '\x2', '\x2', + '\x2', '\x4C4', '\x4C5', '\x3', '\x2', '\x2', '\x2', '\x4C5', '\x4C6', + '\x3', '\x2', '\x2', '\x2', '\x4C6', '\x4DC', '\x5', 'p', '\x39', '\x2', + '\x4C7', '\x4C9', '\a', '\x15', '\x2', '\x2', '\x4C8', '\x4CA', '\a', + '\x7F', '\x2', '\x2', '\x4C9', '\x4C8', '\x3', '\x2', '\x2', '\x2', '\x4C9', + '\x4CA', '\x3', '\x2', '\x2', '\x2', '\x4CA', '\x4CB', '\x3', '\x2', '\x2', + '\x2', '\x4CB', '\x4DC', '\x5', 'p', '\x39', '\x2', '\x4CC', '\x4CE', + '\a', '\x16', '\x2', '\x2', '\x4CD', '\x4CF', '\a', '\x7F', '\x2', '\x2', + '\x4CE', '\x4CD', '\x3', '\x2', '\x2', '\x2', '\x4CE', '\x4CF', '\x3', + '\x2', '\x2', '\x2', '\x4CF', '\x4D0', '\x3', '\x2', '\x2', '\x2', '\x4D0', + '\x4DC', '\x5', 'p', '\x39', '\x2', '\x4D1', '\x4D3', '\a', '\x17', '\x2', + '\x2', '\x4D2', '\x4D4', '\a', '\x7F', '\x2', '\x2', '\x4D3', '\x4D2', + '\x3', '\x2', '\x2', '\x2', '\x4D3', '\x4D4', '\x3', '\x2', '\x2', '\x2', + '\x4D4', '\x4D5', '\x3', '\x2', '\x2', '\x2', '\x4D5', '\x4DC', '\x5', + 'p', '\x39', '\x2', '\x4D6', '\x4D8', '\a', '\x18', '\x2', '\x2', '\x4D7', + '\x4D9', '\a', '\x7F', '\x2', '\x2', '\x4D8', '\x4D7', '\x3', '\x2', '\x2', + '\x2', '\x4D8', '\x4D9', '\x3', '\x2', '\x2', '\x2', '\x4D9', '\x4DA', + '\x3', '\x2', '\x2', '\x2', '\x4DA', '\x4DC', '\x5', 'p', '\x39', '\x2', + '\x4DB', '\x4BD', '\x3', '\x2', '\x2', '\x2', '\x4DB', '\x4C2', '\x3', + '\x2', '\x2', '\x2', '\x4DB', '\x4C7', '\x3', '\x2', '\x2', '\x2', '\x4DB', + '\x4CC', '\x3', '\x2', '\x2', '\x2', '\x4DB', '\x4D1', '\x3', '\x2', '\x2', + '\x2', '\x4DB', '\x4D6', '\x3', '\x2', '\x2', '\x2', '\x4DC', '\x85', + '\x3', '\x2', '\x2', '\x2', '\x4DD', '\x4DF', '\a', '\t', '\x2', '\x2', + '\x4DE', '\x4E0', '\a', '\x7F', '\x2', '\x2', '\x4DF', '\x4DE', '\x3', + '\x2', '\x2', '\x2', '\x4DF', '\x4E0', '\x3', '\x2', '\x2', '\x2', '\x4E0', + '\x4E1', '\x3', '\x2', '\x2', '\x2', '\x4E1', '\x4E3', '\x5', '\x64', + '\x33', '\x2', '\x4E2', '\x4E4', '\a', '\x7F', '\x2', '\x2', '\x4E3', + '\x4E2', '\x3', '\x2', '\x2', '\x2', '\x4E3', '\x4E4', '\x3', '\x2', '\x2', + '\x2', '\x4E4', '\x4E5', '\x3', '\x2', '\x2', '\x2', '\x4E5', '\x4E6', + '\a', '\n', '\x2', '\x2', '\x4E6', '\x87', '\x3', '\x2', '\x2', '\x2', + '\x4E7', '\x4EC', '\x5', 'N', '(', '\x2', '\x4E8', '\x4EA', '\a', '\x7F', + '\x2', '\x2', '\x4E9', '\x4E8', '\x3', '\x2', '\x2', '\x2', '\x4E9', '\x4EA', + '\x3', '\x2', '\x2', '\x2', '\x4EA', '\x4EB', '\x3', '\x2', '\x2', '\x2', + '\x4EB', '\x4ED', '\x5', 'P', ')', '\x2', '\x4EC', '\x4E9', '\x3', '\x2', + '\x2', '\x2', '\x4ED', '\x4EE', '\x3', '\x2', '\x2', '\x2', '\x4EE', '\x4EC', + '\x3', '\x2', '\x2', '\x2', '\x4EE', '\x4EF', '\x3', '\x2', '\x2', '\x2', + '\x4EF', '\x89', '\x3', '\x2', '\x2', '\x2', '\x4F0', '\x4F5', '\x5', + '\x8C', 'G', '\x2', '\x4F1', '\x4F3', '\a', '\x7F', '\x2', '\x2', '\x4F2', + '\x4F1', '\x3', '\x2', '\x2', '\x2', '\x4F2', '\x4F3', '\x3', '\x2', '\x2', + '\x2', '\x4F3', '\x4F4', '\x3', '\x2', '\x2', '\x2', '\x4F4', '\x4F6', + '\x5', '\x44', '#', '\x2', '\x4F5', '\x4F2', '\x3', '\x2', '\x2', '\x2', + '\x4F5', '\x4F6', '\x3', '\x2', '\x2', '\x2', '\x4F6', '\x8B', '\x3', + '\x2', '\x2', '\x2', '\x4F7', '\x4F8', '\x5', '\xA6', 'T', '\x2', '\x4F8', + '\x4F9', '\a', '\x7F', '\x2', '\x2', '\x4F9', '\x4FA', '\a', 'O', '\x2', + '\x2', '\x4FA', '\x4FB', '\a', '\x7F', '\x2', '\x2', '\x4FB', '\x4FC', + '\x5', '\x64', '\x33', '\x2', '\x4FC', '\x8D', '\x3', '\x2', '\x2', '\x2', + '\x4FD', '\x4FF', '\x5', '\x90', 'I', '\x2', '\x4FE', '\x500', '\a', '\x7F', + '\x2', '\x2', '\x4FF', '\x4FE', '\x3', '\x2', '\x2', '\x2', '\x4FF', '\x500', + '\x3', '\x2', '\x2', '\x2', '\x500', '\x501', '\x3', '\x2', '\x2', '\x2', + '\x501', '\x503', '\a', '\t', '\x2', '\x2', '\x502', '\x504', '\a', '\x7F', + '\x2', '\x2', '\x503', '\x502', '\x3', '\x2', '\x2', '\x2', '\x503', '\x504', + '\x3', '\x2', '\x2', '\x2', '\x504', '\x509', '\x3', '\x2', '\x2', '\x2', + '\x505', '\x507', '\a', '@', '\x2', '\x2', '\x506', '\x508', '\a', '\x7F', + '\x2', '\x2', '\x507', '\x506', '\x3', '\x2', '\x2', '\x2', '\x507', '\x508', + '\x3', '\x2', '\x2', '\x2', '\x508', '\x50A', '\x3', '\x2', '\x2', '\x2', + '\x509', '\x505', '\x3', '\x2', '\x2', '\x2', '\x509', '\x50A', '\x3', + '\x2', '\x2', '\x2', '\x50A', '\x51C', '\x3', '\x2', '\x2', '\x2', '\x50B', + '\x50D', '\x5', '\x64', '\x33', '\x2', '\x50C', '\x50E', '\a', '\x7F', + '\x2', '\x2', '\x50D', '\x50C', '\x3', '\x2', '\x2', '\x2', '\x50D', '\x50E', + '\x3', '\x2', '\x2', '\x2', '\x50E', '\x519', '\x3', '\x2', '\x2', '\x2', + '\x50F', '\x511', '\a', '\x4', '\x2', '\x2', '\x510', '\x512', '\a', '\x7F', + '\x2', '\x2', '\x511', '\x510', '\x3', '\x2', '\x2', '\x2', '\x511', '\x512', + '\x3', '\x2', '\x2', '\x2', '\x512', '\x513', '\x3', '\x2', '\x2', '\x2', + '\x513', '\x515', '\x5', '\x64', '\x33', '\x2', '\x514', '\x516', '\a', + '\x7F', '\x2', '\x2', '\x515', '\x514', '\x3', '\x2', '\x2', '\x2', '\x515', + '\x516', '\x3', '\x2', '\x2', '\x2', '\x516', '\x518', '\x3', '\x2', '\x2', + '\x2', '\x517', '\x50F', '\x3', '\x2', '\x2', '\x2', '\x518', '\x51B', + '\x3', '\x2', '\x2', '\x2', '\x519', '\x517', '\x3', '\x2', '\x2', '\x2', + '\x519', '\x51A', '\x3', '\x2', '\x2', '\x2', '\x51A', '\x51D', '\x3', + '\x2', '\x2', '\x2', '\x51B', '\x519', '\x3', '\x2', '\x2', '\x2', '\x51C', + '\x50B', '\x3', '\x2', '\x2', '\x2', '\x51C', '\x51D', '\x3', '\x2', '\x2', + '\x2', '\x51D', '\x51E', '\x3', '\x2', '\x2', '\x2', '\x51E', '\x51F', + '\a', '\n', '\x2', '\x2', '\x51F', '\x8F', '\x3', '\x2', '\x2', '\x2', + '\x520', '\x523', '\x5', '\xBA', '^', '\x2', '\x521', '\x523', '\a', ']', + '\x2', '\x2', '\x522', '\x520', '\x3', '\x2', '\x2', '\x2', '\x522', '\x521', + '\x3', '\x2', '\x2', '\x2', '\x523', '\x91', '\x3', '\x2', '\x2', '\x2', + '\x524', '\x526', '\x5', '\x98', 'M', '\x2', '\x525', '\x527', '\a', '\x7F', + '\x2', '\x2', '\x526', '\x525', '\x3', '\x2', '\x2', '\x2', '\x526', '\x527', + '\x3', '\x2', '\x2', '\x2', '\x527', '\x528', '\x3', '\x2', '\x2', '\x2', + '\x528', '\x52A', '\a', '\t', '\x2', '\x2', '\x529', '\x52B', '\a', '\x7F', + '\x2', '\x2', '\x52A', '\x529', '\x3', '\x2', '\x2', '\x2', '\x52A', '\x52B', + '\x3', '\x2', '\x2', '\x2', '\x52B', '\x53D', '\x3', '\x2', '\x2', '\x2', + '\x52C', '\x52E', '\x5', '\x64', '\x33', '\x2', '\x52D', '\x52F', '\a', + '\x7F', '\x2', '\x2', '\x52E', '\x52D', '\x3', '\x2', '\x2', '\x2', '\x52E', + '\x52F', '\x3', '\x2', '\x2', '\x2', '\x52F', '\x53A', '\x3', '\x2', '\x2', + '\x2', '\x530', '\x532', '\a', '\x4', '\x2', '\x2', '\x531', '\x533', + '\a', '\x7F', '\x2', '\x2', '\x532', '\x531', '\x3', '\x2', '\x2', '\x2', + '\x532', '\x533', '\x3', '\x2', '\x2', '\x2', '\x533', '\x534', '\x3', + '\x2', '\x2', '\x2', '\x534', '\x536', '\x5', '\x64', '\x33', '\x2', '\x535', + '\x537', '\a', '\x7F', '\x2', '\x2', '\x536', '\x535', '\x3', '\x2', '\x2', + '\x2', '\x536', '\x537', '\x3', '\x2', '\x2', '\x2', '\x537', '\x539', + '\x3', '\x2', '\x2', '\x2', '\x538', '\x530', '\x3', '\x2', '\x2', '\x2', + '\x539', '\x53C', '\x3', '\x2', '\x2', '\x2', '\x53A', '\x538', '\x3', + '\x2', '\x2', '\x2', '\x53A', '\x53B', '\x3', '\x2', '\x2', '\x2', '\x53B', + '\x53E', '\x3', '\x2', '\x2', '\x2', '\x53C', '\x53A', '\x3', '\x2', '\x2', + '\x2', '\x53D', '\x52C', '\x3', '\x2', '\x2', '\x2', '\x53D', '\x53E', + '\x3', '\x2', '\x2', '\x2', '\x53E', '\x53F', '\x3', '\x2', '\x2', '\x2', + '\x53F', '\x540', '\a', '\n', '\x2', '\x2', '\x540', '\x93', '\x3', '\x2', + '\x2', '\x2', '\x541', '\x542', '\x5', '\x98', 'M', '\x2', '\x542', '\x95', + '\x3', '\x2', '\x2', '\x2', '\x543', '\x544', '\x5', '\xBA', '^', '\x2', + '\x544', '\x97', '\x3', '\x2', '\x2', '\x2', '\x545', '\x546', '\x5', + '\x9A', 'N', '\x2', '\x546', '\x547', '\x5', '\xBA', '^', '\x2', '\x547', + '\x99', '\x3', '\x2', '\x2', '\x2', '\x548', '\x549', '\x5', '\xBA', '^', + '\x2', '\x549', '\x54A', '\a', '\x19', '\x2', '\x2', '\x54A', '\x54C', + '\x3', '\x2', '\x2', '\x2', '\x54B', '\x548', '\x3', '\x2', '\x2', '\x2', + '\x54C', '\x54F', '\x3', '\x2', '\x2', '\x2', '\x54D', '\x54B', '\x3', + '\x2', '\x2', '\x2', '\x54D', '\x54E', '\x3', '\x2', '\x2', '\x2', '\x54E', + '\x9B', '\x3', '\x2', '\x2', '\x2', '\x54F', '\x54D', '\x3', '\x2', '\x2', + '\x2', '\x550', '\x552', '\a', '\v', '\x2', '\x2', '\x551', '\x553', '\a', + '\x7F', '\x2', '\x2', '\x552', '\x551', '\x3', '\x2', '\x2', '\x2', '\x552', + '\x553', '\x3', '\x2', '\x2', '\x2', '\x553', '\x554', '\x3', '\x2', '\x2', + '\x2', '\x554', '\x55D', '\x5', '\x8A', '\x46', '\x2', '\x555', '\x557', + '\a', '\x7F', '\x2', '\x2', '\x556', '\x555', '\x3', '\x2', '\x2', '\x2', + '\x556', '\x557', '\x3', '\x2', '\x2', '\x2', '\x557', '\x558', '\x3', + '\x2', '\x2', '\x2', '\x558', '\x55A', '\a', '\xE', '\x2', '\x2', '\x559', + '\x55B', '\a', '\x7F', '\x2', '\x2', '\x55A', '\x559', '\x3', '\x2', '\x2', + '\x2', '\x55A', '\x55B', '\x3', '\x2', '\x2', '\x2', '\x55B', '\x55C', + '\x3', '\x2', '\x2', '\x2', '\x55C', '\x55E', '\x5', '\x64', '\x33', '\x2', + '\x55D', '\x556', '\x3', '\x2', '\x2', '\x2', '\x55D', '\x55E', '\x3', + '\x2', '\x2', '\x2', '\x55E', '\x560', '\x3', '\x2', '\x2', '\x2', '\x55F', + '\x561', '\a', '\x7F', '\x2', '\x2', '\x560', '\x55F', '\x3', '\x2', '\x2', + '\x2', '\x560', '\x561', '\x3', '\x2', '\x2', '\x2', '\x561', '\x562', + '\x3', '\x2', '\x2', '\x2', '\x562', '\x563', '\a', '\f', '\x2', '\x2', + '\x563', '\x9D', '\x3', '\x2', '\x2', '\x2', '\x564', '\x566', '\a', '\v', + '\x2', '\x2', '\x565', '\x567', '\a', '\x7F', '\x2', '\x2', '\x566', '\x565', + '\x3', '\x2', '\x2', '\x2', '\x566', '\x567', '\x3', '\x2', '\x2', '\x2', + '\x567', '\x570', '\x3', '\x2', '\x2', '\x2', '\x568', '\x56A', '\x5', + '\xA6', 'T', '\x2', '\x569', '\x56B', '\a', '\x7F', '\x2', '\x2', '\x56A', + '\x569', '\x3', '\x2', '\x2', '\x2', '\x56A', '\x56B', '\x3', '\x2', '\x2', + '\x2', '\x56B', '\x56C', '\x3', '\x2', '\x2', '\x2', '\x56C', '\x56E', + '\a', '\x5', '\x2', '\x2', '\x56D', '\x56F', '\a', '\x7F', '\x2', '\x2', + '\x56E', '\x56D', '\x3', '\x2', '\x2', '\x2', '\x56E', '\x56F', '\x3', + '\x2', '\x2', '\x2', '\x56F', '\x571', '\x3', '\x2', '\x2', '\x2', '\x570', + '\x568', '\x3', '\x2', '\x2', '\x2', '\x570', '\x571', '\x3', '\x2', '\x2', + '\x2', '\x571', '\x572', '\x3', '\x2', '\x2', '\x2', '\x572', '\x574', + '\x5', '\x88', '\x45', '\x2', '\x573', '\x575', '\a', '\x7F', '\x2', '\x2', + '\x574', '\x573', '\x3', '\x2', '\x2', '\x2', '\x574', '\x575', '\x3', + '\x2', '\x2', '\x2', '\x575', '\x57E', '\x3', '\x2', '\x2', '\x2', '\x576', + '\x578', '\a', 'J', '\x2', '\x2', '\x577', '\x579', '\a', '\x7F', '\x2', + '\x2', '\x578', '\x577', '\x3', '\x2', '\x2', '\x2', '\x578', '\x579', + '\x3', '\x2', '\x2', '\x2', '\x579', '\x57A', '\x3', '\x2', '\x2', '\x2', + '\x57A', '\x57C', '\x5', '\x64', '\x33', '\x2', '\x57B', '\x57D', '\a', + '\x7F', '\x2', '\x2', '\x57C', '\x57B', '\x3', '\x2', '\x2', '\x2', '\x57C', + '\x57D', '\x3', '\x2', '\x2', '\x2', '\x57D', '\x57F', '\x3', '\x2', '\x2', + '\x2', '\x57E', '\x576', '\x3', '\x2', '\x2', '\x2', '\x57E', '\x57F', + '\x3', '\x2', '\x2', '\x2', '\x57F', '\x580', '\x3', '\x2', '\x2', '\x2', + '\x580', '\x582', '\a', '\xE', '\x2', '\x2', '\x581', '\x583', '\a', '\x7F', + '\x2', '\x2', '\x582', '\x581', '\x3', '\x2', '\x2', '\x2', '\x582', '\x583', + '\x3', '\x2', '\x2', '\x2', '\x583', '\x584', '\x3', '\x2', '\x2', '\x2', + '\x584', '\x586', '\x5', '\x64', '\x33', '\x2', '\x585', '\x587', '\a', + '\x7F', '\x2', '\x2', '\x586', '\x585', '\x3', '\x2', '\x2', '\x2', '\x586', + '\x587', '\x3', '\x2', '\x2', '\x2', '\x587', '\x588', '\x3', '\x2', '\x2', + '\x2', '\x588', '\x589', '\a', '\f', '\x2', '\x2', '\x589', '\x9F', '\x3', + '\x2', '\x2', '\x2', '\x58A', '\x58C', '\a', '\x19', '\x2', '\x2', '\x58B', + '\x58D', '\a', '\x7F', '\x2', '\x2', '\x58C', '\x58B', '\x3', '\x2', '\x2', + '\x2', '\x58C', '\x58D', '\x3', '\x2', '\x2', '\x2', '\x58D', '\x58E', + '\x3', '\x2', '\x2', '\x2', '\x58E', '\x58F', '\x5', '\xB0', 'Y', '\x2', + '\x58F', '\xA1', '\x3', '\x2', '\x2', '\x2', '\x590', '\x595', '\a', '^', + '\x2', '\x2', '\x591', '\x593', '\a', '\x7F', '\x2', '\x2', '\x592', '\x591', + '\x3', '\x2', '\x2', '\x2', '\x592', '\x593', '\x3', '\x2', '\x2', '\x2', + '\x593', '\x594', '\x3', '\x2', '\x2', '\x2', '\x594', '\x596', '\x5', + '\xA4', 'S', '\x2', '\x595', '\x592', '\x3', '\x2', '\x2', '\x2', '\x596', + '\x597', '\x3', '\x2', '\x2', '\x2', '\x597', '\x595', '\x3', '\x2', '\x2', + '\x2', '\x597', '\x598', '\x3', '\x2', '\x2', '\x2', '\x598', '\x5A7', + '\x3', '\x2', '\x2', '\x2', '\x599', '\x59B', '\a', '^', '\x2', '\x2', + '\x59A', '\x59C', '\a', '\x7F', '\x2', '\x2', '\x59B', '\x59A', '\x3', + '\x2', '\x2', '\x2', '\x59B', '\x59C', '\x3', '\x2', '\x2', '\x2', '\x59C', + '\x59D', '\x3', '\x2', '\x2', '\x2', '\x59D', '\x5A2', '\x5', '\x64', + '\x33', '\x2', '\x59E', '\x5A0', '\a', '\x7F', '\x2', '\x2', '\x59F', + '\x59E', '\x3', '\x2', '\x2', '\x2', '\x59F', '\x5A0', '\x3', '\x2', '\x2', + '\x2', '\x5A0', '\x5A1', '\x3', '\x2', '\x2', '\x2', '\x5A1', '\x5A3', + '\x5', '\xA4', 'S', '\x2', '\x5A2', '\x59F', '\x3', '\x2', '\x2', '\x2', + '\x5A3', '\x5A4', '\x3', '\x2', '\x2', '\x2', '\x5A4', '\x5A2', '\x3', + '\x2', '\x2', '\x2', '\x5A4', '\x5A5', '\x3', '\x2', '\x2', '\x2', '\x5A5', + '\x5A7', '\x3', '\x2', '\x2', '\x2', '\x5A6', '\x590', '\x3', '\x2', '\x2', + '\x2', '\x5A6', '\x599', '\x3', '\x2', '\x2', '\x2', '\x5A7', '\x5B0', + '\x3', '\x2', '\x2', '\x2', '\x5A8', '\x5AA', '\a', '\x7F', '\x2', '\x2', + '\x5A9', '\x5A8', '\x3', '\x2', '\x2', '\x2', '\x5A9', '\x5AA', '\x3', + '\x2', '\x2', '\x2', '\x5AA', '\x5AB', '\x3', '\x2', '\x2', '\x2', '\x5AB', + '\x5AD', '\a', '_', '\x2', '\x2', '\x5AC', '\x5AE', '\a', '\x7F', '\x2', + '\x2', '\x5AD', '\x5AC', '\x3', '\x2', '\x2', '\x2', '\x5AD', '\x5AE', + '\x3', '\x2', '\x2', '\x2', '\x5AE', '\x5AF', '\x3', '\x2', '\x2', '\x2', + '\x5AF', '\x5B1', '\x5', '\x64', '\x33', '\x2', '\x5B0', '\x5A9', '\x3', + '\x2', '\x2', '\x2', '\x5B0', '\x5B1', '\x3', '\x2', '\x2', '\x2', '\x5B1', + '\x5B3', '\x3', '\x2', '\x2', '\x2', '\x5B2', '\x5B4', '\a', '\x7F', '\x2', + '\x2', '\x5B3', '\x5B2', '\x3', '\x2', '\x2', '\x2', '\x5B3', '\x5B4', + '\x3', '\x2', '\x2', '\x2', '\x5B4', '\x5B5', '\x3', '\x2', '\x2', '\x2', + '\x5B5', '\x5B6', '\a', '`', '\x2', '\x2', '\x5B6', '\xA3', '\x3', '\x2', + '\x2', '\x2', '\x5B7', '\x5B9', '\a', '\x61', '\x2', '\x2', '\x5B8', '\x5BA', + '\a', '\x7F', '\x2', '\x2', '\x5B9', '\x5B8', '\x3', '\x2', '\x2', '\x2', + '\x5B9', '\x5BA', '\x3', '\x2', '\x2', '\x2', '\x5BA', '\x5BB', '\x3', + '\x2', '\x2', '\x2', '\x5BB', '\x5BD', '\x5', '\x64', '\x33', '\x2', '\x5BC', + '\x5BE', '\a', '\x7F', '\x2', '\x2', '\x5BD', '\x5BC', '\x3', '\x2', '\x2', + '\x2', '\x5BD', '\x5BE', '\x3', '\x2', '\x2', '\x2', '\x5BE', '\x5BF', + '\x3', '\x2', '\x2', '\x2', '\x5BF', '\x5C1', '\a', '\x62', '\x2', '\x2', + '\x5C0', '\x5C2', '\a', '\x7F', '\x2', '\x2', '\x5C1', '\x5C0', '\x3', + '\x2', '\x2', '\x2', '\x5C1', '\x5C2', '\x3', '\x2', '\x2', '\x2', '\x5C2', + '\x5C3', '\x3', '\x2', '\x2', '\x2', '\x5C3', '\x5C4', '\x5', '\x64', + '\x33', '\x2', '\x5C4', '\xA5', '\x3', '\x2', '\x2', '\x2', '\x5C5', '\x5C6', + '\x5', '\xBA', '^', '\x2', '\x5C6', '\xA7', '\x3', '\x2', '\x2', '\x2', + '\x5C7', '\x5CA', '\x5', '\xB4', '[', '\x2', '\x5C8', '\x5CA', '\x5', + '\xB2', 'Z', '\x2', '\x5C9', '\x5C7', '\x3', '\x2', '\x2', '\x2', '\x5C9', + '\x5C8', '\x3', '\x2', '\x2', '\x2', '\x5CA', '\xA9', '\x3', '\x2', '\x2', + '\x2', '\x5CB', '\x5CD', '\a', '\x1A', '\x2', '\x2', '\x5CC', '\x5CE', + '\a', '\x7F', '\x2', '\x2', '\x5CD', '\x5CC', '\x3', '\x2', '\x2', '\x2', + '\x5CD', '\x5CE', '\x3', '\x2', '\x2', '\x2', '\x5CE', '\x5F0', '\x3', + '\x2', '\x2', '\x2', '\x5CF', '\x5D1', '\x5', '\xB0', 'Y', '\x2', '\x5D0', + '\x5D2', '\a', '\x7F', '\x2', '\x2', '\x5D1', '\x5D0', '\x3', '\x2', '\x2', + '\x2', '\x5D1', '\x5D2', '\x3', '\x2', '\x2', '\x2', '\x5D2', '\x5D3', + '\x3', '\x2', '\x2', '\x2', '\x5D3', '\x5D5', '\a', '\r', '\x2', '\x2', + '\x5D4', '\x5D6', '\a', '\x7F', '\x2', '\x2', '\x5D5', '\x5D4', '\x3', + '\x2', '\x2', '\x2', '\x5D5', '\x5D6', '\x3', '\x2', '\x2', '\x2', '\x5D6', + '\x5D7', '\x3', '\x2', '\x2', '\x2', '\x5D7', '\x5D9', '\x5', '\x64', + '\x33', '\x2', '\x5D8', '\x5DA', '\a', '\x7F', '\x2', '\x2', '\x5D9', + '\x5D8', '\x3', '\x2', '\x2', '\x2', '\x5D9', '\x5DA', '\x3', '\x2', '\x2', + '\x2', '\x5DA', '\x5ED', '\x3', '\x2', '\x2', '\x2', '\x5DB', '\x5DD', + '\a', '\x4', '\x2', '\x2', '\x5DC', '\x5DE', '\a', '\x7F', '\x2', '\x2', + '\x5DD', '\x5DC', '\x3', '\x2', '\x2', '\x2', '\x5DD', '\x5DE', '\x3', + '\x2', '\x2', '\x2', '\x5DE', '\x5DF', '\x3', '\x2', '\x2', '\x2', '\x5DF', + '\x5E1', '\x5', '\xB0', 'Y', '\x2', '\x5E0', '\x5E2', '\a', '\x7F', '\x2', + '\x2', '\x5E1', '\x5E0', '\x3', '\x2', '\x2', '\x2', '\x5E1', '\x5E2', + '\x3', '\x2', '\x2', '\x2', '\x5E2', '\x5E3', '\x3', '\x2', '\x2', '\x2', + '\x5E3', '\x5E5', '\a', '\r', '\x2', '\x2', '\x5E4', '\x5E6', '\a', '\x7F', + '\x2', '\x2', '\x5E5', '\x5E4', '\x3', '\x2', '\x2', '\x2', '\x5E5', '\x5E6', + '\x3', '\x2', '\x2', '\x2', '\x5E6', '\x5E7', '\x3', '\x2', '\x2', '\x2', + '\x5E7', '\x5E9', '\x5', '\x64', '\x33', '\x2', '\x5E8', '\x5EA', '\a', + '\x7F', '\x2', '\x2', '\x5E9', '\x5E8', '\x3', '\x2', '\x2', '\x2', '\x5E9', + '\x5EA', '\x3', '\x2', '\x2', '\x2', '\x5EA', '\x5EC', '\x3', '\x2', '\x2', + '\x2', '\x5EB', '\x5DB', '\x3', '\x2', '\x2', '\x2', '\x5EC', '\x5EF', + '\x3', '\x2', '\x2', '\x2', '\x5ED', '\x5EB', '\x3', '\x2', '\x2', '\x2', + '\x5ED', '\x5EE', '\x3', '\x2', '\x2', '\x2', '\x5EE', '\x5F1', '\x3', + '\x2', '\x2', '\x2', '\x5EF', '\x5ED', '\x3', '\x2', '\x2', '\x2', '\x5F0', + '\x5CF', '\x3', '\x2', '\x2', '\x2', '\x5F0', '\x5F1', '\x3', '\x2', '\x2', + '\x2', '\x5F1', '\x5F2', '\x3', '\x2', '\x2', '\x2', '\x5F2', '\x5F3', + '\a', '\x1B', '\x2', '\x2', '\x5F3', '\xAB', '\x3', '\x2', '\x2', '\x2', + '\x5F4', '\x5F7', '\a', '\x1C', '\x2', '\x2', '\x5F5', '\x5F8', '\x5', + '\xBA', '^', '\x2', '\x5F6', '\x5F8', '\a', '\x66', '\x2', '\x2', '\x5F7', + '\x5F5', '\x3', '\x2', '\x2', '\x2', '\x5F7', '\x5F6', '\x3', '\x2', '\x2', + '\x2', '\x5F8', '\xAD', '\x3', '\x2', '\x2', '\x2', '\x5F9', '\x5FE', + '\x5', '|', '?', '\x2', '\x5FA', '\x5FC', '\a', '\x7F', '\x2', '\x2', + '\x5FB', '\x5FA', '\x3', '\x2', '\x2', '\x2', '\x5FB', '\x5FC', '\x3', + '\x2', '\x2', '\x2', '\x5FC', '\x5FD', '\x3', '\x2', '\x2', '\x2', '\x5FD', + '\x5FF', '\x5', '\xA0', 'Q', '\x2', '\x5FE', '\x5FB', '\x3', '\x2', '\x2', + '\x2', '\x5FF', '\x600', '\x3', '\x2', '\x2', '\x2', '\x600', '\x5FE', + '\x3', '\x2', '\x2', '\x2', '\x600', '\x601', '\x3', '\x2', '\x2', '\x2', + '\x601', '\xAF', '\x3', '\x2', '\x2', '\x2', '\x602', '\x603', '\x5', + '\xB6', '\\', '\x2', '\x603', '\xB1', '\x3', '\x2', '\x2', '\x2', '\x604', + '\x605', '\t', '\x5', '\x2', '\x2', '\x605', '\xB3', '\x3', '\x2', '\x2', + '\x2', '\x606', '\x607', '\t', '\x6', '\x2', '\x2', '\x607', '\xB5', '\x3', + '\x2', '\x2', '\x2', '\x608', '\x60B', '\x5', '\xBA', '^', '\x2', '\x609', + '\x60B', '\x5', '\xB8', ']', '\x2', '\x60A', '\x608', '\x3', '\x2', '\x2', + '\x2', '\x60A', '\x609', '\x3', '\x2', '\x2', '\x2', '\x60B', '\xB7', + '\x3', '\x2', '\x2', '\x2', '\x60C', '\x60D', '\t', '\a', '\x2', '\x2', + '\x60D', '\xB9', '\x3', '\x2', '\x2', '\x2', '\x60E', '\x60F', '\t', '\b', + '\x2', '\x2', '\x60F', '\xBB', '\x3', '\x2', '\x2', '\x2', '\x610', '\x611', + '\t', '\t', '\x2', '\x2', '\x611', '\xBD', '\x3', '\x2', '\x2', '\x2', + '\x612', '\x613', '\t', '\n', '\x2', '\x2', '\x613', '\xBF', '\x3', '\x2', + '\x2', '\x2', '\x614', '\x615', '\t', '\v', '\x2', '\x2', '\x615', '\xC1', + '\x3', '\x2', '\x2', '\x2', '\x122', '\xC3', '\xC7', '\xCA', '\xCD', '\xD5', + '\xD9', '\xDE', '\xE5', '\xEA', '\xED', '\xF1', '\xF5', '\xF9', '\xFF', + '\x103', '\x108', '\x10D', '\x111', '\x114', '\x116', '\x11A', '\x11E', + '\x123', '\x127', '\x12C', '\x130', '\x139', '\x13E', '\x142', '\x146', + '\x14A', '\x14D', '\x151', '\x15B', '\x162', '\x16F', '\x173', '\x179', + '\x180', '\x185', '\x189', '\x18F', '\x193', '\x199', '\x19D', '\x1A3', + '\x1A7', '\x1AB', '\x1AF', '\x1B3', '\x1B7', '\x1BC', '\x1C3', '\x1C7', + '\x1CC', '\x1D3', '\x1D9', '\x1DE', '\x1E4', '\x1EA', '\x1EE', '\x1F2', + '\x1F7', '\x1FB', '\x202', '\x208', '\x20B', '\x210', '\x213', '\x217', + '\x21A', '\x222', '\x226', '\x22A', '\x22E', '\x232', '\x237', '\x23C', + '\x240', '\x245', '\x248', '\x251', '\x25A', '\x25F', '\x26C', '\x26F', + '\x277', '\x27B', '\x280', '\x285', '\x289', '\x28E', '\x294', '\x299', + '\x2A0', '\x2A4', '\x2A8', '\x2AA', '\x2AE', '\x2B0', '\x2B4', '\x2B6', + '\x2BC', '\x2C2', '\x2C6', '\x2C9', '\x2CC', '\x2D0', '\x2D6', '\x2DA', + '\x2DD', '\x2E0', '\x2E6', '\x2E9', '\x2EC', '\x2F0', '\x2F6', '\x2F9', + '\x2FC', '\x300', '\x304', '\x308', '\x30A', '\x30E', '\x310', '\x313', + '\x317', '\x319', '\x31F', '\x323', '\x327', '\x32B', '\x32E', '\x333', + '\x338', '\x33D', '\x342', '\x348', '\x34C', '\x34E', '\x352', '\x356', + '\x358', '\x35A', '\x369', '\x373', '\x37D', '\x382', '\x386', '\x38D', + '\x392', '\x397', '\x39B', '\x39F', '\x3A3', '\x3A6', '\x3A8', '\x3AD', + '\x3B1', '\x3B5', '\x3B9', '\x3BD', '\x3C1', '\x3C4', '\x3C6', '\x3CB', + '\x3CF', '\x3D4', '\x3D9', '\x3DD', '\x3E4', '\x3EB', '\x3EF', '\x3F3', + '\x402', '\x405', '\x412', '\x414', '\x419', '\x41E', '\x422', '\x425', + '\x42C', '\x430', '\x434', '\x43B', '\x43F', '\x443', '\x449', '\x44D', + '\x451', '\x454', '\x458', '\x45E', '\x462', '\x466', '\x46C', '\x470', + '\x474', '\x47A', '\x47E', '\x482', '\x488', '\x48C', '\x490', '\x498', + '\x4A0', '\x4A6', '\x4AA', '\x4AE', '\x4B2', '\x4B6', '\x4B9', '\x4BF', + '\x4C4', '\x4C9', '\x4CE', '\x4D3', '\x4D8', '\x4DB', '\x4DF', '\x4E3', + '\x4E9', '\x4EE', '\x4F2', '\x4F5', '\x4FF', '\x503', '\x507', '\x509', + '\x50D', '\x511', '\x515', '\x519', '\x51C', '\x522', '\x526', '\x52A', + '\x52E', '\x532', '\x536', '\x53A', '\x53D', '\x54D', '\x552', '\x556', + '\x55A', '\x55D', '\x560', '\x566', '\x56A', '\x56E', '\x570', '\x574', + '\x578', '\x57C', '\x57E', '\x582', '\x586', '\x58C', '\x592', '\x597', + '\x59B', '\x59F', '\x5A4', '\x5A6', '\x5A9', '\x5AD', '\x5B0', '\x5B3', + '\x5B9', '\x5BD', '\x5C1', '\x5C9', '\x5CD', '\x5D1', '\x5D5', '\x5D9', + '\x5DD', '\x5E1', '\x5E5', '\x5E9', '\x5ED', '\x5F0', '\x5F7', '\x5FB', + '\x600', '\x60A', + }; + + public static readonly ATN _ATN = + new ATNDeserializer().Deserialize(_serializedATN); + + +} +} // namespace openCypherTranspiler.openCypherParser.ANTLR diff --git a/src/openCypherParser/Grammar/CypherVisitor.cs b/src/openCypherParser/Grammar/CypherVisitor.cs new file mode 100644 index 0000000..b84c8ca --- /dev/null +++ b/src/openCypherParser/Grammar/CypherVisitor.cs @@ -0,0 +1,612 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// ANTLR Version: 4.7.2 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +// Generated from Cypher.g4 by ANTLR 4.7.2 + +// Unreachable code detected +#pragma warning disable 0162 +// The variable '...' is assigned but its value is never used +#pragma warning disable 0219 +// Missing XML comment for publicly visible type or member '...' +#pragma warning disable 1591 +// Ambiguous reference in cref attribute +#pragma warning disable 419 + +namespace openCypherTranspiler.openCypherParser.ANTLR { +using Antlr4.Runtime.Misc; +using Antlr4.Runtime.Tree; +using IToken = Antlr4.Runtime.IToken; + +/// +/// This interface defines a complete generic visitor for a parse tree produced +/// by . +/// +/// The return type of the visit operation. +[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.7.2")] +[System.CLSCompliant(false)] +public interface ICypherVisitor : IParseTreeVisitor { + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Cypher([NotNull] CypherParser.OC_CypherContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Statement([NotNull] CypherParser.OC_StatementContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Query([NotNull] CypherParser.OC_QueryContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_RegularQuery([NotNull] CypherParser.OC_RegularQueryContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Union([NotNull] CypherParser.OC_UnionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_SingleQuery([NotNull] CypherParser.OC_SingleQueryContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_SinglePartQuery([NotNull] CypherParser.OC_SinglePartQueryContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_MultiPartQuery([NotNull] CypherParser.OC_MultiPartQueryContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_UpdatingClause([NotNull] CypherParser.OC_UpdatingClauseContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_ReadingClause([NotNull] CypherParser.OC_ReadingClauseContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Match([NotNull] CypherParser.OC_MatchContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Unwind([NotNull] CypherParser.OC_UnwindContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Merge([NotNull] CypherParser.OC_MergeContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_MergeAction([NotNull] CypherParser.OC_MergeActionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Create([NotNull] CypherParser.OC_CreateContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Set([NotNull] CypherParser.OC_SetContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_SetItem([NotNull] CypherParser.OC_SetItemContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Delete([NotNull] CypherParser.OC_DeleteContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Remove([NotNull] CypherParser.OC_RemoveContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_RemoveItem([NotNull] CypherParser.OC_RemoveItemContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_InQueryCall([NotNull] CypherParser.OC_InQueryCallContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_StandaloneCall([NotNull] CypherParser.OC_StandaloneCallContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_YieldItems([NotNull] CypherParser.OC_YieldItemsContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_YieldItem([NotNull] CypherParser.OC_YieldItemContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_With([NotNull] CypherParser.OC_WithContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Return([NotNull] CypherParser.OC_ReturnContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_ReturnBody([NotNull] CypherParser.OC_ReturnBodyContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_ReturnItems([NotNull] CypherParser.OC_ReturnItemsContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_ReturnItem([NotNull] CypherParser.OC_ReturnItemContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Order([NotNull] CypherParser.OC_OrderContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Skip([NotNull] CypherParser.OC_SkipContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Limit([NotNull] CypherParser.OC_LimitContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_SortItem([NotNull] CypherParser.OC_SortItemContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Where([NotNull] CypherParser.OC_WhereContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Pattern([NotNull] CypherParser.OC_PatternContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_PatternPart([NotNull] CypherParser.OC_PatternPartContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_AnonymousPatternPart([NotNull] CypherParser.OC_AnonymousPatternPartContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_PatternElement([NotNull] CypherParser.OC_PatternElementContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_NodePattern([NotNull] CypherParser.OC_NodePatternContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_PatternElementChain([NotNull] CypherParser.OC_PatternElementChainContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_RelationshipPattern([NotNull] CypherParser.OC_RelationshipPatternContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_RelationshipDetail([NotNull] CypherParser.OC_RelationshipDetailContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Properties([NotNull] CypherParser.OC_PropertiesContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_RelationshipTypes([NotNull] CypherParser.OC_RelationshipTypesContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_NodeLabels([NotNull] CypherParser.OC_NodeLabelsContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_NodeLabel([NotNull] CypherParser.OC_NodeLabelContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_RangeLiteral([NotNull] CypherParser.OC_RangeLiteralContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_LabelName([NotNull] CypherParser.OC_LabelNameContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_RelTypeName([NotNull] CypherParser.OC_RelTypeNameContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Expression([NotNull] CypherParser.OC_ExpressionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_OrExpression([NotNull] CypherParser.OC_OrExpressionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_XorExpression([NotNull] CypherParser.OC_XorExpressionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_AndExpression([NotNull] CypherParser.OC_AndExpressionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_NotExpression([NotNull] CypherParser.OC_NotExpressionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_ComparisonExpression([NotNull] CypherParser.OC_ComparisonExpressionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_AddOrSubtractExpression([NotNull] CypherParser.OC_AddOrSubtractExpressionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_MultiplyDivideModuloExpression([NotNull] CypherParser.OC_MultiplyDivideModuloExpressionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_PowerOfExpression([NotNull] CypherParser.OC_PowerOfExpressionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_UnaryAddOrSubtractExpression([NotNull] CypherParser.OC_UnaryAddOrSubtractExpressionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_StringListNullOperatorExpression([NotNull] CypherParser.OC_StringListNullOperatorExpressionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_PropertyOrLabelsExpression([NotNull] CypherParser.OC_PropertyOrLabelsExpressionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Atom([NotNull] CypherParser.OC_AtomContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Literal([NotNull] CypherParser.OC_LiteralContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_BooleanLiteral([NotNull] CypherParser.OC_BooleanLiteralContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_ListLiteral([NotNull] CypherParser.OC_ListLiteralContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_PartialComparisonExpression([NotNull] CypherParser.OC_PartialComparisonExpressionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_ParenthesizedExpression([NotNull] CypherParser.OC_ParenthesizedExpressionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_RelationshipsPattern([NotNull] CypherParser.OC_RelationshipsPatternContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_FilterExpression([NotNull] CypherParser.OC_FilterExpressionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_IdInColl([NotNull] CypherParser.OC_IdInCollContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_FunctionInvocation([NotNull] CypherParser.OC_FunctionInvocationContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_FunctionName([NotNull] CypherParser.OC_FunctionNameContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_ExplicitProcedureInvocation([NotNull] CypherParser.OC_ExplicitProcedureInvocationContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_ImplicitProcedureInvocation([NotNull] CypherParser.OC_ImplicitProcedureInvocationContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_ProcedureResultField([NotNull] CypherParser.OC_ProcedureResultFieldContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_ProcedureName([NotNull] CypherParser.OC_ProcedureNameContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Namespace([NotNull] CypherParser.OC_NamespaceContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_ListComprehension([NotNull] CypherParser.OC_ListComprehensionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_PatternComprehension([NotNull] CypherParser.OC_PatternComprehensionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_PropertyLookup([NotNull] CypherParser.OC_PropertyLookupContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_CaseExpression([NotNull] CypherParser.OC_CaseExpressionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_CaseAlternatives([NotNull] CypherParser.OC_CaseAlternativesContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Variable([NotNull] CypherParser.OC_VariableContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_NumberLiteral([NotNull] CypherParser.OC_NumberLiteralContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_MapLiteral([NotNull] CypherParser.OC_MapLiteralContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Parameter([NotNull] CypherParser.OC_ParameterContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_PropertyExpression([NotNull] CypherParser.OC_PropertyExpressionContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_PropertyKeyName([NotNull] CypherParser.OC_PropertyKeyNameContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_IntegerLiteral([NotNull] CypherParser.OC_IntegerLiteralContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_DoubleLiteral([NotNull] CypherParser.OC_DoubleLiteralContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_SchemaName([NotNull] CypherParser.OC_SchemaNameContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_ReservedWord([NotNull] CypherParser.OC_ReservedWordContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_SymbolicName([NotNull] CypherParser.OC_SymbolicNameContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_LeftArrowHead([NotNull] CypherParser.OC_LeftArrowHeadContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_RightArrowHead([NotNull] CypherParser.OC_RightArrowHeadContext context); + /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitOC_Dash([NotNull] CypherParser.OC_DashContext context); +} +} // namespace openCypherTranspiler.openCypherParser.ANTLR diff --git a/src/openCypherParser/Grammar/antlr4.cmd b/src/openCypherParser/Grammar/antlr4.cmd new file mode 100644 index 0000000..bfbae7b --- /dev/null +++ b/src/openCypherParser/Grammar/antlr4.cmd @@ -0,0 +1 @@ +java org.antlr.v4.Tool %* \ No newline at end of file diff --git a/src/openCypherParser/OpenCypherParser.cs b/src/openCypherParser/OpenCypherParser.cs new file mode 100644 index 0000000..fa9e232 --- /dev/null +++ b/src/openCypherParser/OpenCypherParser.cs @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using Antlr4.Runtime; +using openCypherTranspiler.Common.Logging; +using openCypherTranspiler.openCypherParser.ANTLR; +using openCypherTranspiler.openCypherParser.AST; + +namespace openCypherTranspiler.openCypherParser +{ + + public class OpenCypherParser + { + private OpenCypherParser() + { } + + public static QueryTreeNode Parse(string cypherQueryText, ILoggable logger = null) + { + var lexer = new CypherLexer(new AntlrInputStream(cypherQueryText)); + var tokens = new CommonTokenStream(lexer); + var parser = new CypherParser(tokens); + var visitor = new CypherVisitor(logger); + var result = visitor.Visit(parser.oC_Cypher()) as QueryTreeNode; + return result; + } + + } +} diff --git a/src/openCypherParser/README.md b/src/openCypherParser/README.md new file mode 100644 index 0000000..8bf27c0 --- /dev/null +++ b/src/openCypherParser/README.md @@ -0,0 +1,35 @@ +# openCypherParser + +The 'Grammar' sub-folder contains [ANTLR4](https://github.com/antlr) generated visitors using the g4 grammar file published by [openCypher project](http://www.opencypher.org/). + +To regenerate the grammar file in the event of openCypher specification updates, please follow the steps below. + +## Prerequisites + +Before building project, make sure you have: +* Java 8 SDK. E.g. on Windows +* Dotnet Core SDK 2.2 +* Latest ANTLR4 Tools (download and use [ANTLR4 tools](https://github.com/antlr/antlr4/blob/master/doc/getting-started.md)) + +E.g. on Windows: + +```batch +REM Download and install dependencies +choco install dotnetcore-sdk openjdk curl + +REM Get ANTLR4 tools +mkdir %USERPROFILE%\javalibs +cd /d %USERPROFILE%\javalibs +curl https://www.antlr.org/download/antlr-4.7.2-complete.jar --output antlr-4.7.2-complete.jar +SET CLASSPATH=%CLASSPATH%%USERPROFILE%\javalibs\antlr-4.7.2-complete.jar; +setx CLASSPATH %CLASSPATH% +``` + +## (Re)Build Cypher visitor base + +To rebuild the grammar classes do: + +```batch +cd \openCypherParser\Grammar +antlr4 -package openCypherTranspiler.openCypherParser.ANTLR -Dlanguage=CSharp -no-listener -visitor Cypher.g4 +``` diff --git a/src/openCypherParser/openCypherParser.csproj b/src/openCypherParser/openCypherParser.csproj new file mode 100644 index 0000000..0e684bb --- /dev/null +++ b/src/openCypherParser/openCypherParser.csproj @@ -0,0 +1,27 @@ + + + + netcoreapp2.1 + Microsoft.GraphPlatform.Transpiler.openCypherParser + CS3021 + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/CommonTest/CommonTest.csproj b/tests/CommonTest/CommonTest.csproj new file mode 100644 index 0000000..35df811 --- /dev/null +++ b/tests/CommonTest/CommonTest.csproj @@ -0,0 +1,16 @@ + + + + netcoreapp2.1 + Microsoft.GraphPlatform.Transpiler.CommonTest + + + + + + + + + + + diff --git a/tests/CommonTest/JSONGraphSchema.cs b/tests/CommonTest/JSONGraphSchema.cs new file mode 100644 index 0000000..632f5df --- /dev/null +++ b/tests/CommonTest/JSONGraphSchema.cs @@ -0,0 +1,108 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright(c) Microsoft Corporation.All rights reserved. + * Licensed under the MIT License.See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Newtonsoft.Json; +using openCypherTranspiler.Common.GraphSchema; + +namespace openCypherTranspiler.CommonTest +{ + public class JSONGraphSchema : IGraphSchemaProvider + { + private IList _allNodeDefinions; + private IList _allEdgeDefinions; + + public JSONGraphSchema(string file) + { + LoadFromFile(file); + } + + private void LoadFromFile(string file) + { + var res = JsonConvert.DeserializeObject(File.ReadAllText(file)); + + var allnodes = new Dictionary(); + foreach (var n in res.Nodes) + { + var nodeName = n.Name.ToString(); + var nodeDef = new NodeSchema() + { + Name = nodeName, + Properties = (n.Properties?.ToObject>() as List ?? Enumerable.Empty()) + .Select(s => (new EntityProperty() + { + PropertyName = s.PropertyName.ToString(), + DataType = Type.GetType(s.PropertyType.ToString()), + PropertyType = EntityProperty.PropertyDefinitionType.RegularProperty + })).ToList(), + NodeIdProperty = new EntityProperty() + { + PropertyName = n.IdProperty.PropertyName.ToString(), + DataType = Type.GetType(n.IdProperty.PropertyType.ToString()), + PropertyType = EntityProperty.PropertyDefinitionType.NodeJoinKey + }, + }; + allnodes.Add(nodeName, nodeDef); + } + _allNodeDefinions = allnodes.Values.ToList(); + + _allEdgeDefinions = new List(); + foreach (var e in res.Edges) + { + _allEdgeDefinions.Add(new EdgeSchema() + { + Name = e.Name.ToString(), + SourceNodeId= e.FromNode.ToString(), + SinkNodeId = e.ToNode.ToString(), + Properties = (e.Properties?.ToObject>() as List ?? Enumerable.Empty()) + .Select(s => (new EntityProperty() + { + PropertyName = s.PropertyName.ToString(), + DataType = Type.GetType(s.PropertyType.ToString()) + })).ToList(), + SourceIdProperty = new EntityProperty() + { + PropertyName = e.SourceIdProperty.PropertyName.ToString(), + DataType = Type.GetType(e.SourceIdProperty.PropertyType.ToString()), + PropertyType = EntityProperty.PropertyDefinitionType.NodeJoinKey + }, + SinkIdProperty = new EntityProperty() + { + PropertyName = e.SinkIdProperty.PropertyName.ToString(), + DataType = Type.GetType(e.SinkIdProperty.PropertyType.ToString()), + PropertyType = EntityProperty.PropertyDefinitionType.NodeJoinKey + }, + }); + } + } + + public EdgeSchema GetEdgeDefinition(string edgeVerb, string fromNodeName, string toNodeName) + { + var edge = _allEdgeDefinions?.Where(n => n.Name == edgeVerb && n.SourceNodeId == fromNodeName && n.SinkNodeId == toNodeName).FirstOrDefault(); + if (edge == null) + { + throw new KeyNotFoundException($"Edge with edgeverb = {edgeVerb}, fromNodeName = {fromNodeName} and toNodename = {toNodeName} not found!"); + } + return edge; + } + + public NodeSchema GetNodeDefinition(string nodeName) + { + var node = _allNodeDefinions?.Where(n => n.Name == nodeName).FirstOrDefault(); + if (node == null) + { + throw new KeyNotFoundException($"Node with name = {nodeName} not found!"); + } + return node; + } + + } + +} diff --git a/tests/CommonTest/TestLogger.cs b/tests/CommonTest/TestLogger.cs new file mode 100644 index 0000000..6187c22 --- /dev/null +++ b/tests/CommonTest/TestLogger.cs @@ -0,0 +1,29 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +using System; +using System.Diagnostics; +using openCypherTranspiler.Common.Logging; + + +namespace openCypherTranspiler.CommonTest +{ + public class TestLogger : BaseLogger, ILoggable + { + public TestLogger(LoggingLevel logLevel = LoggingLevel.Verbose) + { + SetLoggingLevel(logLevel); + } + + protected override void LogMessage(string msgFormat, params object[] msgArgs) + { + Console.WriteLine(msgFormat, msgArgs); +#if DEBUG + Debug.WriteLine(msgFormat, msgArgs); +#endif + } + } +} diff --git a/tests/LogicalPlanner.Test/LogicalPlanner.Test.csproj b/tests/LogicalPlanner.Test/LogicalPlanner.Test.csproj new file mode 100644 index 0000000..fd93103 --- /dev/null +++ b/tests/LogicalPlanner.Test/LogicalPlanner.Test.csproj @@ -0,0 +1,33 @@ + + + + netcoreapp2.1 + + false + + Microsoft.GraphPlatform.Transpiler.LogicalPlanner.Test + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/tests/LogicalPlanner.Test/LogicalPlannerTest.cs b/tests/LogicalPlanner.Test/LogicalPlannerTest.cs new file mode 100644 index 0000000..9d86dbc --- /dev/null +++ b/tests/LogicalPlanner.Test/LogicalPlannerTest.cs @@ -0,0 +1,419 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +using openCypherTranspiler.Common.Exceptions; +using openCypherTranspiler.Common.GraphSchema; +using openCypherTranspiler.Common.Logging; +using openCypherTranspiler.CommonTest; +using openCypherTranspiler.LogicalPlanner.Utils; +using openCypherTranspiler.openCypherParser; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Linq; +using JT = openCypherTranspiler.LogicalPlanner.JoinOperator.JoinType; + +namespace openCypherTranspiler.LogicalPlanner.Test +{ + /// + /// Test the logical planner (which turns parsed cypher statement into + /// relational algebra + /// + [TestClass] + public class LogicalPlannerTest + { + private ILoggable _logger = new TestLogger(); + + private bool MatrixEquals(T[,] data1, T[,] data2) + { + var equal = + data1.Rank == data2.Rank && + Enumerable.Range(0, data1.Rank).All(dimension => data1.GetLength(dimension) == data2.GetLength(dimension)) && + data1.Cast().SequenceEqual(data2.Cast()); + + return equal; + } + + private LogicalPlan RunQueryAndDumpTree(IGraphSchemaProvider graphDef, string cypherQueryText) + { + var queryNode = OpenCypherParser.Parse(cypherQueryText, _logger); + + var planner = LogicalPlan.ProcessQueryTree(queryNode, graphDef); + + Assert.IsNotNull(planner.StartingOperators); + Assert.IsNotNull(planner.TerminalOperators); + + // Dump both parse tree and logical plan + var tree = queryNode.DumpTree(); + var logical = planner.DumpGraph(); + + return planner; + } + + [TestMethod] + public void TestTransitiveClosureHelper() + { + { + // equivalent of MATCH (a)-[b]-(c), (d) + var startMat = new JT[4, 4] + { + { JT.Inner, JT.Inner, JT.Cross, JT.Cross }, + { JT.Inner, JT.Inner, JT.Inner, JT.Cross }, + { JT.Cross, JT.Inner, JT.Inner, JT.Cross }, + { JT.Cross, JT.Cross, JT.Cross, JT.Inner }, + }; + + var expectedMat = new JT[4, 4] + { + { JT.Inner, JT.Inner, JT.Inner, JT.Cross }, + { JT.Inner, JT.Inner, JT.Inner, JT.Cross }, + { JT.Inner, JT.Inner, JT.Inner, JT.Cross }, + { JT.Cross, JT.Cross, JT.Cross, JT.Inner }, + }; + + var actualMat = startMat.TransitiveClosure(); + Assert.IsTrue(MatrixEquals(expectedMat, actualMat)); + } + + { + // equivalent of MATCH (a)-[b]-(c), + // OPTIONAL MATCH (c)-[d]-(e) + var startMat = new JT[5, 5] + { + { JT.Inner, JT.Inner, JT.Cross, JT.Cross, JT.Cross }, + { JT.Inner, JT.Inner, JT.Inner, JT.Cross, JT.Cross }, + { JT.Cross, JT.Inner, JT.Inner, JT.Left, JT.Cross }, + { JT.Cross, JT.Cross, JT.Left, JT.Inner, JT.Left }, + { JT.Cross, JT.Cross, JT.Cross, JT.Left, JT.Inner }, + }; + + var expectedMat = new JT[5, 5] + { + { JT.Inner, JT.Inner, JT.Inner, JT.Left, JT.Left }, + { JT.Inner, JT.Inner, JT.Inner, JT.Left, JT.Left }, + { JT.Inner, JT.Inner, JT.Inner, JT.Left, JT.Left }, + { JT.Left, JT.Left, JT.Left, JT.Inner, JT.Left }, + { JT.Left, JT.Left, JT.Left, JT.Left, JT.Inner }, + }; + + var actualMat = startMat.TransitiveClosure(); + Assert.IsTrue(MatrixEquals(expectedMat, actualMat)); + } + + { + // equivalent of MATCH (a)-[b]-(c), + // MATCH (c)-[d]-(a) + // OPTIONAL MATCH (c)-[e]-(a) + var startMat = new JT[5, 5] + { + { JT.Inner, JT.Inner, JT.Cross, JT.Inner, JT.Left }, + { JT.Inner, JT.Inner, JT.Inner, JT.Cross, JT.Cross }, + { JT.Cross, JT.Inner, JT.Inner, JT.Inner, JT.Left }, + { JT.Inner, JT.Cross, JT.Inner, JT.Inner, JT.Cross }, + { JT.Left, JT.Cross, JT.Left, JT.Cross, JT.Inner }, + }; + + var expectedMat = new JT[5, 5] + { + { JT.Inner, JT.Inner, JT.Inner, JT.Inner, JT.Left }, + { JT.Inner, JT.Inner, JT.Inner, JT.Inner, JT.Left }, + { JT.Inner, JT.Inner, JT.Inner, JT.Inner, JT.Left }, + { JT.Inner, JT.Inner, JT.Inner, JT.Inner, JT.Left }, + { JT.Left, JT.Left, JT.Left, JT.Left, JT.Inner }, + }; + + var actualMat = startMat.TransitiveClosure(); + Assert.IsTrue(MatrixEquals(expectedMat, actualMat)); + } + } + + [TestMethod] + public void BasicTestLogicalPlanner() + { + IGraphSchemaProvider graphDef = new JSONGraphSchema(@"./TestData/MovieGraph.json"); + + // Basic test with no WITH and OPTIONAL + { + var lp = RunQueryAndDumpTree(graphDef, @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +RETURN p.Name, m.Title +" + ); + // TODO: structural verification + Assert.IsTrue(lp.StartingOperators.Count() > 0); + Assert.IsTrue(lp.TerminalOperators.Count() == 1); + } + + // Basic test with optional match + { + var lp = RunQueryAndDumpTree(graphDef, @" +MATCH (p:Person)-[r:REVIEWED]->(m:Movie) +OPTIONAL MATCH (p)<-[:FOLLOWS]-(p2:Person)-[r2:REVIEWED]->(m) +return p.Name as Name1, p2.Name as Name2, m.Title as Title, r.Rating as Rating1, r2.Rating as Rating2 +" + ); + // TODO: structural verification + Assert.IsTrue(lp.StartingOperators.Count() > 0); + Assert.IsTrue(lp.TerminalOperators.Count() == 1); + // nullable no change after optional match + Assert.IsTrue((lp.TerminalOperators.First().OutputSchema.First(f => f.FieldAlias == "Name1") as SingleField).FieldType == typeof(string)); + Assert.IsTrue((lp.TerminalOperators.First().OutputSchema.First(f => f.FieldAlias == "Name2") as SingleField).FieldType == typeof(string)); + // non nullable changed to nullable after optional match + Assert.IsTrue((lp.TerminalOperators.First().OutputSchema.First(f => f.FieldAlias == "Rating1") as SingleField).FieldType == typeof(int)); + Assert.IsTrue((lp.TerminalOperators.First().OutputSchema.First(f => f.FieldAlias == "Rating2") as SingleField).FieldType == typeof(int?)); + } + + // Basic test with WITH and OPTIONAL match + { + var lp = RunQueryAndDumpTree(graphDef, @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WITH p, m +OPTIONAL MATCH (p)-[d:DIRECTED]->(m) +RETURN p.Name, m.Title +" + ); + // TODO: structural verification + Assert.IsTrue(lp.StartingOperators.Count() > 0); + Assert.IsTrue(lp.TerminalOperators.Count() == 1); + } + + // Basic test with plan tree optimization that collapse pure MATCHes + { + var lp = RunQueryAndDumpTree(graphDef, @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +MATCH (p)-[p2:PRODUCED]->(m) +OPTIONAL MATCH (p)-[d:DIRECTED]->(m) +RETURN p.Name, m.Title +" + ); + // TODO: structural verification + Assert.IsTrue(lp.StartingOperators.Count() > 0); + Assert.IsTrue(lp.TerminalOperators.Count() == 1); + } + + // Duplicated match patterns + { + var lp = RunQueryAndDumpTree(graphDef, @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie), (p)-[p2:PRODUCED]->(m) +MATCH (p)-[p2:PRODUCED]->(m) +OPTIONAL MATCH (p)-[d:DIRECTED]->(m) +RETURN p.Name, m.Title +" + ); + // TODO: structural verification + Assert.IsTrue(lp.StartingOperators.Count() > 0); + Assert.IsTrue(lp.TerminalOperators.Count() == 1); + } + + // Functions and WITH with additional returns + { + var lp = RunQueryAndDumpTree(graphDef, @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie), (p)-[p2:PRODUCED]->(m) +WITH a.Roles as ActedRoles, p, m +OPTIONAL MATCH (p)-[d:REVIEWED]->(m) +WITH d.Summary as ReviewSummary, d.Rating as ReviewRating, p, m, ActedRoles +RETURN p.Name, m.Title, ActedRoles, ReviewRating, ReviewSummary +" + ); + // TODO: structural verification + Assert.IsTrue(lp.StartingOperators.Count() > 0); + Assert.IsTrue(lp.TerminalOperators.Count() == 1); + } + + // Twisted alias for with/return entities + { + var lp = RunQueryAndDumpTree(graphDef, @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WITH p as m, m as p +MATCH (m)-[a:DIRECTED]->(p) +RETURN m.Name, p.Title +" + ); + // TODO: structural verification + Assert.IsTrue(lp.StartingOperators.Count() > 0); + Assert.IsTrue(lp.TerminalOperators.Count() == 1); + } + + // Join two already joined patterns + { + var lp = RunQueryAndDumpTree(graphDef, @" +MATCH (p:Person)-[:REVIEWED]->(m:Movie) +MATCH (p2:Person)-[:REVIEWED]->(m2:Movie) +MATCH (p:Person)-[:FOLLOWS]->(p2:Person) +RETURN p.Name as Name1, m.Title as Title1, p2.Name as Name2, m2.Title as Title2 +" + ); + // TODO: structural verification + Assert.IsTrue(lp.StartingOperators.Count() > 0); + Assert.IsTrue(lp.TerminalOperators.Count() == 1); + } + + // basic WHERE test + { + var lp = RunQueryAndDumpTree(graphDef, @" +MATCH (p:Person)-[:REVIEWED]->(m:Movie) +WHERE p.Name = 'Tom Hanks' +RETURN p.Name as Name +" + ); + // TODO: structural verification + Assert.IsTrue(lp.StartingOperators.Count() > 0); + Assert.IsTrue(lp.TerminalOperators.Count() == 1); + } + + // WHERE attached to optional match + { + var lp = RunQueryAndDumpTree(graphDef, @" +MATCH (p:Person) +OPTIONAL MATCH (p:Person)-[:REVIEWED]->(m:Movie) +WHERE p.Name = 'Tom Hanks' +RETURN p.Name as Name +" + ); + // TODO: structural verification + Assert.IsTrue(lp.StartingOperators.Count() > 0); + Assert.IsTrue(lp.TerminalOperators.Count() == 1); + } + + // WHERE attached to WITH projection + { + var lp = RunQueryAndDumpTree(graphDef, @" +MATCH (p:Person) +OPTIONAL MATCH (p:Person)-[:REVIEWED]->(m:Movie) +WITH p, m +WHERE p.Name = 'Tom Hanks' +RETURN p.Name as Name +" + ); + // TODO: structural verification + Assert.IsTrue(lp.StartingOperators.Count() > 0); + Assert.IsTrue(lp.TerminalOperators.Count() == 1); + } + } + + [TestMethod] + public void AdvancedTestLogicalPlanner() + { + IGraphSchemaProvider graphDef = new JSONGraphSchema(@"./TestData/MovieGraph.json"); + + // Duplicate (or overlapping) match pattern across WITH barrier + { + // join is outter then upgraded to inner after WITH barrier + // Today, we have less optimized plan by not allow the join + // to propagate up past the WITH barrier. + var lp = RunQueryAndDumpTree(graphDef, @" +match (n: Person), (m: Movie) +where n.Name = 'Tom Hanks' +with n, m +optional match(n)-[:ACTED_IN]-(m) +with n, m +match(n)-[:ACTED_IN]-(m) +return distinct n.Name, m.Title +" + ); + // TODO: structural verification + Assert.IsTrue(lp.StartingOperators.Count() > 0); + Assert.IsTrue(lp.TerminalOperators.Count() == 1); + } + + // More complicated pattern in a single match clause that requires inequality conditions to be added + { + // implicit condition to be added is ACTED_IN should not be the same by its 2 key ids + var lp = RunQueryAndDumpTree(graphDef, @" +MATCH (p:Person)-[:ACTED_IN]->(m:Movie)<-[:ACTED_IN]-(p2:Person) +RETURN p.Name AS Name, p2.Name as CoStarName +" + ); + Assert.IsTrue(lp.StartingOperators.Count() > 0); + Assert.IsTrue(lp.TerminalOperators.Count() == 1); + // make sure that the selection condition is added + var conditionOpsAdded = lp.TerminalOperators.First().GetAllUpstreamOperatorsOfType(); + Assert.IsTrue(conditionOpsAdded.Count() == 1); + Assert.IsTrue(conditionOpsAdded.First().UnexpandedEntityInequalityConditions.Count() == 1); + Assert.IsTrue(conditionOpsAdded.First().FilterExpression != null); + } + } + + public void NegativeTestLogicalPlanner() + { + IGraphSchemaProvider graphDef = new JSONGraphSchema(@".\TestData\Movie\MovieGraph.json"); + + // Our implementation block of returning whole entity instead of its fields + // We don't support packing whole entity into JSON today, as JSON blob in Cosmos + // is not very useful for any further computations + { + try + { + var lp = RunQueryAndDumpTree(graphDef, @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie), (p)-[p2:PRODUCED]->(m) +MATCH (p)-[p2:PRODUCED]->(m) +OPTIONAL MATCH (p)-[d:DIRECTED]->(m) +RETURN p +" + ); + Assert.Fail("Didn't failed as expected."); + } + catch (TranspilerNotSupportedException e) + { + Assert.IsTrue(e.Message.Contains("Query final return body returns the whole entity")); + } + } + + // repeated relationship pattern on the same match statement + // NOTE: repeated relationship pattern not on the same match statement is still supported + { + try + { + var lp = RunQueryAndDumpTree(graphDef, @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie), (p2:Person)-[a:ACTED_IN]->(m2:Movie) +RETURN p.Name, m.Title +" + ); + Assert.Fail("Didn't failed as expected."); + } + catch (TranspilerNotSupportedException e) + { + Assert.IsTrue(e.Message.Contains("Cannot use the same relationship variable 'a'")); + } + + } + } + + public void NegativeTestLogicalPlannerSchemaBinding() + { + IGraphSchemaProvider graphDef = new JSONGraphSchema(@"./TestData/MovieGraph.json"); + + // Binding to non exist node + { + try + { + var lp = RunQueryAndDumpTree(graphDef, @" +MATCH (p:Actor) +RETURN p +" + ); + Assert.Fail("Didn't failed as expected."); + } + catch (TranspilerBindingException e) + { + Assert.IsTrue(e.Message.Contains("Actor")); + } + + try + { + var lp = RunQueryAndDumpTree(graphDef, @" +MATCH (p:Person)-[:Performed]-(m:Movie) +RETURN p +" + ); + Assert.Fail("Didn't failed as expected."); + } + catch (TranspilerBindingException e) + { + Assert.IsTrue(e.Message.Contains("Performed")); + } + } + } + } +} diff --git a/tests/LogicalPlanner.Test/TestData/MovieGraph.json b/tests/LogicalPlanner.Test/TestData/MovieGraph.json new file mode 100644 index 0000000..675c50f --- /dev/null +++ b/tests/LogicalPlanner.Test/TestData/MovieGraph.json @@ -0,0 +1,150 @@ +{ + "Nodes": [ + { + "Id": "Person", + "Name": "Person", + "IdProperty": { + "PropertyName": "id", + "PropertyType": "System.String" + }, + "Properties": [ + { + "PropertyName": "Name", + "PropertyType": "System.String" + }, + { + "PropertyName": "Born", + "PropertyType": "System.Nullable`1[System.Int32]" + } + ] + }, + { + "Id": "Movie", + "Name": "Movie", + "IdProperty": { + "PropertyName": "id", + "PropertyType": "System.String" + }, + "Properties": [ + { + "PropertyName": "Title", + "PropertyType": "System.String" + }, + { + "PropertyName": "Tagline", + "PropertyType": "System.String" + }, + { + "PropertyName": "Released", + "PropertyType": "System.Int32" + } + ] + } + ], + "Edges": [ + { + "Id": "Person@ACTED_IN@Movie", + "Name": "ACTED_IN", + "FromNode": "Person", + "ToNode": "Movie", + "SourceIdProperty": { + "PropertyName": "_vertexId", + "PropertyType": "System.String" + }, + "SinkIdProperty": { + "PropertyName": "_sink", + "PropertyType": "System.String" + }, + "Properties": [ + { + "PropertyName": "Roles", + "PropertyType": "System.String" + } + ] + }, + { + "Id": "Person@REVIEWED@Movie", + "Name": "REVIEWED", + "FromNode": "Person", + "ToNode": "Movie", + "SourceIdProperty": { + "PropertyName": "_vertexId", + "PropertyType": "System.String" + }, + "SinkIdProperty": { + "PropertyName": "_sink", + "PropertyType": "System.String" + }, + "Properties": [ + { + "PropertyName": "Summary", + "PropertyType": "System.String" + }, + { + "PropertyName": "Rating", + "PropertyType": "System.Int32" + } + ] + }, + { + "Id": "Person@DIRECTED@Movie", + "Name": "DIRECTED", + "FromNode": "Person", + "ToNode": "Movie", + "SourceIdProperty": { + "PropertyName": "_vertexId", + "PropertyType": "System.String" + }, + "SinkIdProperty": { + "PropertyName": "_sink", + "PropertyType": "System.String" + }, + "Properties": [] + }, + { + "Id": "Person@PRODUCED@Movie", + "Name": "PRODUCED", + "FromNode": "Person", + "ToNode": "Movie", + "SourceIdProperty": { + "PropertyName": "_vertexId", + "PropertyType": "System.String" + }, + "SinkIdProperty": { + "PropertyName": "_sink", + "PropertyType": "System.String" + }, + "Properties": [] + }, + { + "Id": "Person@WROTE@Movie", + "Name": "WROTE", + "FromNode": "Person", + "ToNode": "Movie", + "SourceIdProperty": { + "PropertyName": "_vertexId", + "PropertyType": "System.String" + }, + "SinkIdProperty": { + "PropertyName": "_sink", + "PropertyType": "System.String" + }, + "Properties": [] + }, + { + "Id": "Person@FOLLOWS@Person", + "Name": "FOLLOWS", + "FromNode": "Person", + "ToNode": "Person", + "SourceIdProperty": { + "PropertyName": "_vertexId", + "PropertyType": "System.String" + }, + "SinkIdProperty": { + "PropertyName": "_sink", + "PropertyType": "System.String" + }, + "Properties": [] + } + ] +} \ No newline at end of file diff --git a/tests/SQLRenderer.Test/DataTableComparisonHelper.cs b/tests/SQLRenderer.Test/DataTableComparisonHelper.cs new file mode 100644 index 0000000..668eff8 --- /dev/null +++ b/tests/SQLRenderer.Test/DataTableComparisonHelper.cs @@ -0,0 +1,183 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +using System; +using System.Collections.Generic; +using System.Data; +using System.Diagnostics; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace openCypherTranspiler.SQLRenderer.Test +{ + public class DataTableComparisonHelper + { + /// + /// Since Neo4j result is not strictly typed, hence we have an approximate comparer to match up columns + /// + class ApproximateColumnComparer : IEqualityComparer> + { + public static Dictionary EqualityGroups = new Dictionary() + { + { typeof(bool), typeof(bool) }, + { typeof(int), typeof(Int64) }, + { typeof(Int16), typeof(Int64) }, + { typeof(Int64), typeof(Int64) }, + { typeof(uint), typeof(Int64) }, + { typeof(UInt16), typeof(Int64) }, + { typeof(UInt64), typeof(Int64) }, + { typeof(string), typeof(string) }, + { typeof(float), typeof(double) }, + { typeof(double), typeof(double) }, + { typeof(object), typeof(object) }, + }; + + public bool Equals(Tuple x, Tuple y) + { + return x.Item1 == y.Item1 && EqualityGroups[x.Item2] == EqualityGroups[y.Item2]; + } + + public int GetHashCode(Tuple obj) + { + return obj.Item1.GetHashCode() ^ EqualityGroups[obj.Item2].GetHashCode(); + } + } + + private bool ApproximateValueComparer(object x, object y) + { + var eqTypes = ApproximateColumnComparer.EqualityGroups; + + if (x == DBNull.Value || y == DBNull.Value) + { + // special case for string as our test data creation tool cannot handle + // "" vs null for string case + if (x.GetType() == typeof(string) || y.GetType() == typeof(string)) + { + var isXEmptyOrNullStr = x == DBNull.Value ? true : string.IsNullOrEmpty((string)x); + var isYEmptyOrNullStr = y == DBNull.Value ? true : string.IsNullOrEmpty((string)y); + return isXEmptyOrNullStr == isYEmptyOrNullStr; + } + + return x == DBNull.Value && y == DBNull.Value; + } + + Assert.IsTrue(eqTypes[x.GetType()] == eqTypes[y.GetType()]); + var tarType = eqTypes[x.GetType()]; + + if (tarType == typeof(Int64)) + { + var x_c = Convert.ToInt64(x); + var y_c = Convert.ToInt64(y); + return x_c == y_c; + } + else if (tarType == typeof(bool)) + { + var x_c = Convert.ToBoolean(x); + var y_c = Convert.ToBoolean(y); + return x_c == y_c; + } + else if (tarType == typeof(double)) + { + var x_c = Convert.ToDouble(x); + var y_c = Convert.ToDouble(y); + return Math.Abs(x_c - y_c) / Math.Max(Math.Abs(x_c), Math.Abs(y_c)) < 0.0001; + } + else if (tarType == typeof(string)) + { + var x_c = x is string ? (string)x : x.ToString(); + var y_c = y is string ? (string)y : y.ToString(); + return x_c.Equals(y_c); + } + else + { + return x.Equals(y); + } + } + + public void CompareDataTables(DataTable leftTable, DataTable rightTable, bool compareOrder = false) + { + // Shallow test to ensure cardinatlity is the same at least + Assert.IsTrue(leftTable.Columns.Count == rightTable.Columns.Count && leftTable.Rows.Count == rightTable.Rows.Count); + + // Neo4j returns no data type at all if no result, if it happens, only compare record count + if (leftTable.Rows.Count > 0) + { + // Schema test + var leftSchema = leftTable.Columns.Cast().Select(c => new Tuple(c.ColumnName, c.DataType)).OrderBy(n => n.Item1).ToList(); + var rightSchema = rightTable.Columns.Cast().Select(c => new Tuple(c.ColumnName, c.DataType)).OrderBy(n => n.Item1).ToList(); + Assert.IsTrue(leftSchema.SequenceEqual(rightSchema, new ApproximateColumnComparer())); + + // Row by row comparison + if (compareOrder) + { + throw new NotImplementedException("Ordered comparison is not implemented"); + } + else + { + var leftSchemaColumns = leftSchema.Select(c => c.Item1).ToList(); + var orderBy = string.Join(", ", leftSchemaColumns); + DataView leftSorted = new DataView(leftTable); + leftSorted.Sort = orderBy; + DataView rightSorted = new DataView(rightTable); + rightSorted.Sort = orderBy; + + // change the order of columns + leftSorted.SetColumnsOrder(leftSchemaColumns); + rightSorted.SetColumnsOrder(leftSchemaColumns); + + for (int i = 0; i < leftSorted.Count; i++) + { + var leftRow = leftSorted[i]; + var rightRow = rightSorted[i]; + for (int j = 0; j < leftSchema.Count; j++) + { + var leftVal = leftRow[j]; + var rightVal = rightRow[j]; + if (leftVal == null || rightVal == null) + { + Assert.IsTrue(leftVal == rightVal); + } + else + { + var isValueSimilar = ApproximateValueComparer(leftRow[j], rightRow[j]); + if (!isValueSimilar) + { + Debug.WriteLine($"Comparison failed for row: {i} col {j}({leftSchema[j].Item1}):"); + Debug.WriteLine($" rightVal: {rightRow[j]}, leftVal: {leftRow[j]}"); + } + Assert.IsTrue(isValueSimilar); + } + } + } + } + } + else + { + Assert.IsTrue(rightTable.Rows.Count == 0); + } + + + } + + } + + + + public static class DataViewExtensions + { + public static void SetColumnsOrder(this DataView view, IList columnNames) + { + int columnIndex = 0; + foreach (var columnName in columnNames) + { + view.Table.Columns[columnName].SetOrdinal(columnIndex); + columnIndex++; + } + } + } + +} + diff --git a/tests/SQLRenderer.Test/DockerContainer.cs b/tests/SQLRenderer.Test/DockerContainer.cs new file mode 100644 index 0000000..6206689 --- /dev/null +++ b/tests/SQLRenderer.Test/DockerContainer.cs @@ -0,0 +1,256 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Threading.Tasks; +using Docker.DotNet; +using Docker.DotNet.Models; +using openCypherTranspiler.Common.Logging; + +namespace openCypherTranspiler.SQLRenderer.Test +{ + /// + /// Docker container helper class (mini docker-compose) + /// + public class DockerContainer + { + private DockerClient _client; + private ILoggable _logger; + private IDictionary _environmentVariables = new Dictionary(); + private IDictionary _tcpPortMapping = new Dictionary(); // + + class Progress : IProgress + { + private Action _onCalled; + private ILoggable _logger; + + public Progress(Action action = null, ILoggable logger = null) + { + _onCalled = action; + _logger = logger; + } + + void IProgress.Report(JSONMessage value) + { + _logger?.LogVerbose($"{value.Status}: {value.ProgressMessage}"); + _onCalled?.Invoke(value); + } + } + + protected DockerContainer(DockerClient client, ILoggable logger) + { + _client = client; + _logger = logger; + } + + public static DockerContainer On(DockerClient client, ILoggable logger = null) + { + return new DockerContainer(client, logger); + } + + public string Image { get; private set; } + public string Tag { get; private set; } = "latest"; + public DockerContainer UseImage(string image, string tag = "latest") + { + Image = image; + Tag = tag; + return this; + } + + public string Name { get; private set; } + public DockerContainer SetName(string name) + { + Name = name; + return this; + } + + public IReadOnlyCollection<(string, string)> Env { get { return _environmentVariables.Select(kv => (kv.Key, kv.Value)).ToList().AsReadOnly(); } } + public DockerContainer AddEnv(string key, string value) + { + _environmentVariables.Add(key, value); + return this; + } + + public IReadOnlyCollection<(string, string)> Port { get { return _tcpPortMapping.Select(kv => ($"{kv.Key}/tcp", $"{kv.Value}")).ToList().AsReadOnly(); } } + public DockerContainer AddTcpPort(int containerPort, int hostPort) + { + _tcpPortMapping.Add(containerPort, hostPort); + return this; + } + + public async Task Up(bool rebuildIfExists = false, bool waitForAllTcpPorts = false) + { + // parameter checks + if (string.IsNullOrEmpty(Image)) + { + throw new ArgumentException("Must provide Image"); + } + if (string.IsNullOrEmpty(Name)) + { + throw new ArgumentException("Must provide container name"); + } + + var imageNameWithTag = $"{Image}{(string.IsNullOrEmpty(Tag) ? "" : $":{Tag}")}"; + + // pull the specified image if not already + _logger?.LogVerbose($"Pulling {imageNameWithTag} ..."); + await _client.Images.CreateImageAsync( + new ImagesCreateParameters + { + FromImage = Image, + Tag = Tag, + }, + null, + new Progress(null, _logger) + ); + _logger?.LogVerbose($"Successfuly pulled {imageNameWithTag}."); + + // check if a matching container already exists + var containers = await _client.Containers.ListContainersAsync( + new ContainersListParameters() + { + All = true + }); + var matchingContainer = containers.FirstOrDefault(c => c.Names.Contains($"/{Name}")); + var mismatchInfo = new List(); + + if (matchingContainer != null) + { + // check exsitng matching container spec satisfy the requirements, if + // not, either fail, or delete it, depending on user's preference + if (matchingContainer.Image != $"{imageNameWithTag}") + { + mismatchInfo.Add($"Container {Name} does not have matching image: {matchingContainer.Image}, where {Image} is expected"); + } + if (_tcpPortMapping.Count > 0 && + !_tcpPortMapping.All(kv => matchingContainer.Ports + .Any(p => p.Type == "tcp" && p.PublicPort == kv.Value && p.PrivatePort == kv.Key))) + { + mismatchInfo.Add($"Container {Name} does not satisfy all port mappings: " + + $"{string.Join(",", matchingContainer.Ports.Select(p => $"{p.PublicPort}/{p.Type}:{p.PrivatePort}"))}, " + + $"where {string.Join(",", _tcpPortMapping.Select(p => $"{p.Value}/tcp:{p.Key}"))} is expected"); + } + + if (mismatchInfo.Count > 0) + { + if (rebuildIfExists) + { + if (matchingContainer.Status == "running") + { + await _client.Containers.StopContainerAsync(matchingContainer.ID, new ContainerStopParameters()); + } + await _client.Containers.RemoveContainerAsync(matchingContainer.ID, new ContainerRemoveParameters()); + matchingContainer = null; + } + else + { + throw new ArgumentException($"Conflicting container with same name '{Name}' already exists."); + } + } + } + + // create a new instance of the container if it does not exists or was destroyed + if (matchingContainer == null) + { + _logger?.LogVerbose($"Creating container {Name}..."); + await _client.Containers.CreateContainerAsync( + new CreateContainerParameters() + { + Image = imageNameWithTag, + Name = Name, + Env = _environmentVariables.Select(ev => $"{ev.Key}={ev.Value}").ToList(), + HostConfig = new HostConfig() + { + PortBindings = _tcpPortMapping.ToDictionary( + kv => $"{kv.Key}/tcp", + kv => new List() + { + new PortBinding() + { + HostPort = kv.Value.ToString() + } + } as IList) + } + } + ); + + // get the list of recently created containers and find the one we just created + containers = await _client.Containers.ListContainersAsync(new ContainersListParameters() + { + All = true, + Filters = new Dictionary>() + { + { + "status", new Dictionary() + { + { "created", true } + } + } + } + }); + matchingContainer = containers.FirstOrDefault(c => c.Names.Contains($"/{Name}")); + if (matchingContainer != null) + { + _logger?.LogVerbose($"Container {Name} created."); + } + else + { + throw new InvalidOperationException($"Failed to start container {Name}"); + } + } + + // start the created container + if (matchingContainer.State != "running") + { + _logger?.LogVerbose($"Starting container {Name}..."); + await _client.Containers.StartContainerAsync(Name, new ContainerStartParameters()); + _logger?.LogVerbose($"Container {Name} started."); + } + + // if requested, wait for container services is fully up + if (waitForAllTcpPorts) + { + _logger?.LogVerbose($"Checking for service ports ..."); + foreach (var port in _tcpPortMapping.Values) + { + TestPortConnection(port, TimeSpan.FromSeconds(300)); + } + _logger?.LogVerbose($"All service ports have responded."); + } + } + + private void TestPortConnection(int port, TimeSpan timeout) + { + DateTime startTime = DateTime.Now; + using (TcpClient tcpClient = new TcpClient()) + { + bool connected = false; + while (!connected) + { + try + { + tcpClient.Connect("127.0.0.1", port); + connected = true; + } + catch (Exception) + { + if (DateTime.Now - startTime < timeout) + { + Task.Delay(2000).Wait(1000); + } + else + { + throw new ApplicationException($"Timeout after trying to wait for port {port}"); + } + } + } + } + } + } +} diff --git a/tests/SQLRenderer.Test/JSONGraphSQLSchema.cs b/tests/SQLRenderer.Test/JSONGraphSQLSchema.cs new file mode 100644 index 0000000..5ec4c05 --- /dev/null +++ b/tests/SQLRenderer.Test/JSONGraphSQLSchema.cs @@ -0,0 +1,66 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using openCypherTranspiler.Common.GraphSchema; +using openCypherTranspiler.CommonTest; +using Newtonsoft.Json; + +namespace openCypherTranspiler.SQLRenderer.Test +{ + class JSONGraphSQLSchema : ISQLDBSchemaProvider + { + private JSONGraphSchema _schemaHelper; + private IDictionary _tableDescs; + + public JSONGraphSQLSchema(string jsonDefFile) + { + _schemaHelper = new JSONGraphSchema(jsonDefFile); + LoadFromFile(jsonDefFile); + } + + private (string Verb, string NodeFrom, string NodeTo) ParseEntityId(string entityId) + { + var splits = entityId.Split('@'); + return (Verb: splits[1], NodeFrom: splits[0], NodeTo: splits[2]); + } + + private void LoadFromFile(string jsonDefFile) + { + var res = JsonConvert.DeserializeObject(File.ReadAllText(jsonDefFile)); + var allnodes = ((IEnumerable)res.Nodes).Select(n => (string)n.Id.ToString()); + + var tableDescs = ((IEnumerable)res.TableDescriptors).Select(d => + new SQLTableDescriptor() + { + EntityId = d.EntityId.ToString(), + TableOrViewName = d.TableOrViewName.ToString() + }); + + _tableDescs = tableDescs.ToDictionary(kv => kv.EntityId, kv => kv); + } + + public EdgeSchema GetEdgeDefinition(string edgeVerb, string fromNodeName, string toNodeName) + { + return _schemaHelper.GetEdgeDefinition(edgeVerb, fromNodeName, toNodeName); + } + + public NodeSchema GetNodeDefinition(string nodeName) + { + return _schemaHelper.GetNodeDefinition(nodeName); + } + + public SQLTableDescriptor GetSQLTableDescriptors(string entityId) + { + return _tableDescs[entityId]; + } + } +} diff --git a/tests/SQLRenderer.Test/SQLRenderer.Test.csproj b/tests/SQLRenderer.Test/SQLRenderer.Test.csproj new file mode 100644 index 0000000..f8801ca --- /dev/null +++ b/tests/SQLRenderer.Test/SQLRenderer.Test.csproj @@ -0,0 +1,47 @@ + + + + netcoreapp2.1 + + false + + Microsoft.GraphPlatform.Transpiler.SQLRenderer.Test + + + + + + + + + + PreserveNewest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SQLRenderer.Test/SQLRendererTest.cs b/tests/SQLRenderer.Test/SQLRendererTest.cs new file mode 100644 index 0000000..e9c8bd1 --- /dev/null +++ b/tests/SQLRenderer.Test/SQLRendererTest.cs @@ -0,0 +1,801 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +using System; +using System.IO; +using System.Linq; +using System.Data; +using System.Data.SqlClient; +using System.Diagnostics; +using System.Threading.Tasks; +using System.Runtime.InteropServices; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo4j.Driver.V1; +using Docker.DotNet; +using Docker.DotNet.Models; +using openCypherTranspiler.Common.Exceptions; +using openCypherTranspiler.Common.Logging; +using openCypherTranspiler.CommonTest; +using openCypherTranspiler.openCypherParser; +using openCypherTranspiler.LogicalPlanner; +using Microsoft.Extensions.Configuration; + +namespace openCypherTranspiler.SQLRenderer.Test +{ + /// + /// Tests for SQLRenderer + /// + /// References: + /// - Docker.DotNet how to use PortBindings of HostConfig: + /// https://github.com/Microsoft/Docker-PowerShell/issues/174 + /// - Docker REST API doc: + /// https://docs.docker.com/engine/api/v1.39/ + /// - appsettings: + /// https://blog.bitscry.com/2017/05/30/appsettings-json-in-net-core-console-app/ + /// https://www.humankode.com/asp-net-core/asp-net-core-configuration-best-practices-for-keeping-secrets-out-of-source-control + /// + [TestClass] + public class SQLRendererTest + { + private ISQLDBSchemaProvider _graphDef; + private readonly ILoggable _logger = new TestLogger(LoggingLevel.Normal); + + private IDriver _driver; + private Func _conn; + private Func _conn_init; + + #region Test initialization and clean up + + // + // Use ClassInitialize to run code before running the first test in the class + [ClassInitialize()] + public static void MyClassInitialize(TestContext testContext) { } + + // + // Use ClassCleanup to run code after all tests in a class have run + // [ClassCleanup()] + public static void MyClassCleanup() { } + + // + // Use TestInitialize to run code before running each test + [TestInitialize()] + public void TestInitialize() + { + // load graph definition and connect to the servers + _graphDef = new JSONGraphSQLSchema(@"./TestData/MovieGraph.json"); + + // setup neo4j and sql drivers + var builder = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("./appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile("./appsettings.private.json", optional: true, reloadOnChange: true); + IConfigurationRoot configuration = builder.Build(); + + var useDocker = bool.Parse(configuration + .GetSection("appSettings") + .GetSection("createLocalDockerImages").Value); + var neo4jHost = configuration + .GetSection("appSettings") + .GetSection("neo4jHost").Value; + var neo4jPort = int.Parse(configuration + .GetSection("appSettings") + .GetSection("neo4jPort").Value); + var neo4jUser = configuration + .GetSection("appSettings") + .GetSection("neo4jUser").Value; + var neo4jPassword = configuration + .GetSection("appSettings") + .GetSection("neo4jPassword").Value; + var sqlHost = configuration + .GetSection("appSettings") + .GetSection("sqlHost").Value; + var sqlPort = int.Parse(configuration + .GetSection("appSettings") + .GetSection("sqlPort").Value); + var sqlPassword = configuration + .GetSection("appSettings") + .GetSection("sqlPassword").Value; + + var neo4jBoltUrl = $"bolt://{neo4jHost}:{neo4jPort}"; + var sqlConnStrInit = $"Data Source={sqlHost},{sqlPort};User id=SA;Password={sqlPassword};"; + var sqlConnStr = $"Data Source={sqlHost},{sqlPort};Initial Catalog=octestdb;User id=SA;Password={sqlPassword};"; + + _driver = GraphDatabase.Driver(neo4jBoltUrl, AuthTokens.Basic(neo4jUser, neo4jPassword)); + _conn = () => new SqlConnection(sqlConnStr); + _conn_init = () => new SqlConnection(sqlConnStrInit); + + // initialize test harness + if (!File.Exists("./TestInitDone.tmp")) + { + if (useDocker) + { + // create and start test harness containers containers + CreateTestHarnessContainers( + neo4jUser, + neo4jPassword, + neo4jPort, + sqlHost, + sqlPort, + sqlPassword + ).ConfigureAwait(false).GetAwaiter().GetResult(); + } + + // initialize neo4j db + InitializeNeo4jDB(); + + // initialize sql db + InitializeSQLDB(); + + Console.WriteLine("Test Initialization completed."); + File.WriteAllText("./TestInitDone.tmp", DateTime.UtcNow.ToString()); + } + else + { + // Depending the cached the initialization state to speed up unit test + Console.WriteLine("Test Initialization skipped. To redo test initialization, remove './TestInitDone.tmp'."); + } + } + + #endregion Test initialization and clean up + + private async Task PullDockerImage(DockerClient client, string imageName, string tagName = "") + { + await client.Images.CreateImageAsync( + new ImagesCreateParameters + { + FromImage = imageName, + Tag = tagName, + }, + null, + null); + } + + private async Task CreateTestHarnessContainers( + string neo4jUser, + string neo4jPassword, + int neo4jBoltPort, + string sqlHost, + int sqlPort, + string sqlPassword + ) + { + var dockerClient = new DockerClientConfiguration( + RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? + new Uri("npipe://./pipe/docker_engine") : + new Uri("unix:///var/run/docker.sock") + ).CreateClient(); + + // start Neo4j test instance + // Bolt: 10087 + // HTTP: 10074 + await DockerContainer.On(dockerClient, _logger) + .UseImage("neo4j") + .SetName("neo4j_unittest_1") + //.AddTcpPort(7474, 10074) + .AddTcpPort(7687, neo4jBoltPort) + .AddEnv("NEO4J_AUTH", $"{neo4jUser}/{neo4jPassword}") + .Up(rebuildIfExists: true, waitForAllTcpPorts: true); + + // start Microsoft SQL test instance + await DockerContainer.On(dockerClient, _logger) + .UseImage("mcr.microsoft.com/mssql/server", "2017-latest") + .SetName("mssql_unittest_1") + .AddTcpPort(1433, sqlPort) + .AddEnv("ACCEPT_EULA", "y") + .AddEnv("SA_PASSWORD", sqlPassword) + .Up(rebuildIfExists: true, waitForAllTcpPorts: true); + } + + private void InitializeNeo4jDB() + { + using (var session = _driver.Session()) + { + session.Run("MATCH (n) DETACH DELETE n"); + var movieDbCreationScript = File.ReadAllText(@"./TestData/MovieGraphNeo4jQuery.txt"); + session.Run(movieDbCreationScript); + } + } + + private void InitializeSQLDB() + { + var movieDbCreationScript = File.ReadAllLines(@"./TestData/MovieDBSQLCmds.sql"); + var goLines = movieDbCreationScript.Select( + (l, i) => string.Compare(l.Trim(), "go", true) == 0 || string.Compare(l.Trim(), "go;", true) == 0 ? + i : -1 + ).Where(idx => idx >= 0).Append(movieDbCreationScript.Length); + + using (var con = _conn_init()) + { + con.Open(); + var startIdx = 0; + foreach (var endIdx in goLines) + { + var cmdText = string.Join("\r\n", movieDbCreationScript.Skip(startIdx).Take(endIdx - startIdx)); + if (!string.IsNullOrWhiteSpace(cmdText.Trim())) + { + using (var command = new SqlCommand(cmdText, con)) + { + command.ExecuteNonQuery(); + } + } + startIdx = endIdx + 1; + } + con.Close(); + } + } + + private DataTable RunQueryInCypherAndGetResult(string cypherQueryText) + { + var dataTable = new DataTable(); + var typeOrder = new Type[] { typeof(bool), typeof(byte), typeof(char), typeof(int), typeof(DateTime), typeof(long), typeof(double), typeof(string), typeof(object) }; + var typeOrderDict = typeOrder.Select((t, i) => (t:t, i:i)).ToDictionary(kv => kv.t, kv => kv.i); + using (var session = _driver.Session()) + { + var result = session.Run(cypherQueryText).ToList(); + var resultFirstRec = result.FirstOrDefault(); + + // get type for each column + if (resultFirstRec != null) + { + // try to find most generous type that can accommodate the data + var colTypes = new Type[resultFirstRec.Keys.Count]; + foreach (var record in result) + { + foreach (var v in record.Values.Select((v, i) => (v:v, i:i))) + { + colTypes[v.i] = v.v.Value != null ? + typeOrder[Math.Max(typeOrderDict[v.v.Value.GetType()], typeOrderDict[colTypes[v.i] ?? typeOrder.First()])] : + colTypes[v.i]; + }; + } + foreach (var col in resultFirstRec.Keys.Select((v, i) => (v:v, i:i))) + { + dataTable.Columns.Add(col.v, colTypes[col.i] ?? typeof(object)); + } + foreach (var record in result) + { + var dataRow = dataTable.NewRow(); + foreach (var v in record.Values) + { + dataRow[v.Key] = v.Value ?? DBNull.Value; + }; + dataTable.Rows.Add(dataRow); + } + } + } + return dataTable; + } + + private DataTable RunQueryInSQLAndGetResult(string sqlQueryText) + { + var dataTable = new DataTable(); + using (var con = _conn()) + { + con.Open(); + Stopwatch sw = new Stopwatch(); + sw.Start(); + using (var command = new SqlCommand(sqlQueryText, con)) + { + var dataReader = command.ExecuteReader(); + dataTable.Load(dataReader); + } + sw.Stop(); + _logger?.Log("SQL Query elapsed={0}", sw.Elapsed); + if (sw.Elapsed.TotalSeconds > 5) + { + _logger?.LogCritical("Following generated query took a long time to run:"); + _logger?.LogCritical(sqlQueryText); + } + con.Close(); + } + return dataTable; + } + + private string TranspileToSQL(string cypherQueryText) + { + var plan = LogicalPlan.ProcessQueryTree( + OpenCypherParser.Parse(cypherQueryText, _logger), + _graphDef, + _logger); + var sqlRender = new SQLRenderer(_graphDef, _logger); + return sqlRender.RenderPlan(plan); + } + + private DataTable RunQueryTranspiledToSQLAndGetResult(string cypherQueryText) + { + var sqlQueryText = TranspileToSQL(cypherQueryText); + return RunQueryInSQLAndGetResult(sqlQueryText); + } + + private void RunQueryAndCompare(string cypherQueryText, bool compareOrder = false) + { + _logger?.Log($"----------------------------------------"); + _logger?.Log($"Running cypher query:\n{cypherQueryText}"); + var resultNeo4j = RunQueryInCypherAndGetResult(cypherQueryText); + var resultSQL = RunQueryTranspiledToSQLAndGetResult(cypherQueryText); + var comparisonHelper = new DataTableComparisonHelper(); + comparisonHelper.CompareDataTables(resultNeo4j, resultSQL, compareOrder); + _logger?.Log($"----------------------------------------"); + } + + [TestMethod] + public void SanityQueryTest() + { + // really basic sanity test + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WHERE p.Name = 'Tom Hanks' +RETURN p.Name as Name, m.Title as Title +"; + RunQueryAndCompare(queryText); + } + + [TestMethod] + public void AdvancedPatternMatchTest() + { + // Check if implicit inequality was added if same type of relationships are referred + // in a single match statement + { + var queryText = @" +MATCH (p:Person)-[:ACTED_IN]->(m:Movie), (p2:Person)-[:ACTED_IN]->(m:Movie) +WHERE p.Name = 'Tom Hanks' +RETURN p.Name as Name, m.Title as Title, p2.Name as CoStarName +"; + + RunQueryAndCompare(queryText); + } + } + + [TestMethod] + public void CaseWhenExpressionTest() + { + // basic test + { + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WITH p.Name as PersonName, m.Title as MovieTitle, CASE WHEN p.Name = 'Tom Hanks' THEN 1 WHEN p.Name starts with 'Tom' THEN 2 WHEN p.Name starts with 'T' THEN 3 ELSE 0 END as NameFlag +WHERE PersonName starts with 'T' +RETURN PersonName, MovieTitle,NameFlag, +CASE WHEN PersonName = 'Tom Hanks' THEN 1 WHEN PersonName starts with 'Tom' THEN 2 WHEN PersonName starts with 'T' THEN 3 ELSE 0 END as NameFlag2 +ORDER BY PersonName, MovieTitle +LIMIT 100 +"; + RunQueryAndCompare(queryText); + } + + // swiching entities aliases + { + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WITH p as m, m as p +MATCH (m)-[a:DIRECTED]->(p) +RETURN m.Name as Name, p.Title as Title, Case when m.Name = 'Tom Hanks' then 'This is Tom Hanks' else 'This is not Tom Hanks' end as Flag +"; + + RunQueryAndCompare(queryText); + } + + // type casting help for case when + { + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WITH p as m, m as p +MATCH (m)-[a:DIRECTED]->(p) +RETURN m.Name as Name, p.Title as Title, +Case when m.Name = 'Tom Hanks' then 1.1 else 'This is not Tom Hanks' end as Flags +"; + RunQueryAndCompare(queryText); + } + } + + [TestMethod] + public void OptionalMatchTest() + { + // optional match basic test + { + var queryText = @" +MATCH (p:Person)-[r:REVIEWED]->(m:Movie) +OPTIONAL MATCH (p)<-[:FOLLOWS]-(p2:Person)-[r2:REVIEWED]->(m) +return p.Name as Name1, p2.Name as Name2, m.Title as Title, r.Rating as Rating1, r2.Rating as Rating2 + "; + RunQueryAndCompare(queryText); + } + { + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +OPTIONAL MATCH (p)-[d:DIRECTED]->(m) +WITH p, a, m, d +WHERE p.Name = 'Tom Hanks' +RETURN p.Name as Name, m.Title as Title, count(d) > 0 as IsDirector +"; + RunQueryAndCompare(queryText); + } + + // optional match attached to optional match + // TODO: + // This query took long time to run on MS T-SQL w/ long RESOURCE_SEMAPHORE. Investigate. + { + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +OPTIONAL MATCH (p)-[d:DIRECTED]->(m) WHERE p.Name = 'Tom Hanks' +RETURN p.Name as Name, m.Title as Title, count(d) > 0 as IsDirector +"; + RunQueryAndCompare(queryText); + } + + // multiple optional matches + { + var queryText = @" +match (p:Person) where p.Name = 'Tom Hanks' or p.Name = 'Meg Ryan' +optional match (p:Person)-[:ACTED_IN]-(m:Movie) where p.Name = 'Meg Ryan' +optional match (p:Person)-[:ACTED_IN]->(m) where p.Name = 'Tom Hanks' +return p.Name as Name, m.Title as Title +"; + RunQueryAndCompare(queryText); + } + + // multiple optional matches (Var 2) + { + var queryText = @" +match (p:Person) where p.Name = 'Tom Hanks' or p.Name = 'Meg Ryan' +optional match (p:Person)-[:ACTED_IN]-(m1:Movie) where p.Name = 'Meg Ryan' +optional match (p:Person)-[:ACTED_IN]->(m2:Movie) where p.Name = 'Tom Hanks' +return p.Name as Name, m1.Title as Title1, m2.Title as Title2 +"; + RunQueryAndCompare(queryText); + } + } + + [TestMethod] + public void DistinctSanityTest() + { + // distinct test + { + // distinct fields + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +RETURN DISTINCT p.Name as Name +"; + + RunQueryAndCompare(queryText); + } + + { + // distinct entity + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WITH DISTINCT p +RETURN p.Name as Name +"; + + RunQueryAndCompare(queryText); + } + } + + [TestMethod] + public void DistinctAdvancedTest() + { + { + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +RETURN p.Name as Name, Count(Distinct m.Title) as TitleCount +ORDER BY Name +LIMIT 20 +"; + RunQueryAndCompare(queryText); + } + + { + // distinct properties under "WITH" + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WITH DISTINCT m.Title as Title, p.Name as Name +ORDER BY Title ASC, Name DESC +LIMIT 20 +WHERE Title <> 'A' +RETURN Title, Name + "; + + RunQueryAndCompare(queryText); + } + + { + // distinct properties under "RETURN" + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WITH m.Title as Title, p.Name as Name +WHERE Title <> 'A' +RETURN DISTINCT Title, Name +ORDER BY Title, Name DESC +LIMIT 20 + "; + RunQueryAndCompare(queryText); + } + + { + // negative test + // match where/order by clause field not listed in the data source + var expectedExceptionThrown = false; + try + { + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WITH DISTINCT m.Title as Title, p.Name as Name +WHERE a.Title <> 'A' +RETURN Title, Name + "; + TranspileToSQL(queryText); + } + catch (TranspilerSyntaxErrorException e) + { + Assert.IsTrue(e.Message.Contains("entity field: \"a\" not exsit")); + expectedExceptionThrown = true; + } + Assert.IsTrue(expectedExceptionThrown); + } + + { + // negative test + // match where/order by clause field not listed in the data source + var expectedExceptionThrown = false; + try + { + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WITH DISTINCT m.Title as Title, p.Name as Name +WHERE Titl <> 'A' +RETURN Title, Name + "; + TranspileToSQL(queryText); + } + catch (TranspilerSyntaxErrorException e) + { + Assert.IsTrue(e.Message.Contains("Titl not existed")); + expectedExceptionThrown = true; + } + Assert.IsTrue(expectedExceptionThrown); + } + } + + [TestMethod] + public void OperatorTest() + { + // Test various operators + // +, -, *, /, ^, IN + { + var queryText = @" +MATCH (p:Person)-[:ACTED_IN]-(m:Movie) +WHERE p.Name in ['Tom Hanks', 'Meg Ryan'] and m.Released >= 1990 +RETURN p.Name as Name, m.Title AS Title, m.Released % 100 as ReleasedYear2Digit, m.Released - 2000 as YearSinceY2k, m.Released * 1 / 1 ^ 1 AS TestReleasedYear +"; + + RunQueryAndCompare(queryText); + } + } + + [TestMethod] + public void StringFunctionTest() + { + // Basic string function test + // left + // right + // ltrim + // rtrim + // trim + // toLower + // toUpper + // contains + // size + { + var queryText = @" +MATCH (p:Person) +WHERE p.Name contains 'Tom' OR left(p.Name, 3) = 'Meg' OR right(p.Name, 3) = 'nks' +RETURN p.Name as Name, toLower(p.Name) as LName, toUpper(p.Name) as UName, size(p.Name) as NameSize, + trim(' ' + p.Name + ' ') AS TrimmedName, + ltrim(' ' + p.Name + ' ') AS LTrimmedName, + rtrim(' ' + p.Name + ' ') AS RTrimmedName +"; + + RunQueryAndCompare(queryText); + } + } + + [TestMethod] + public void AggregationFunctionTest() + { + // Currently supported + // avg + // sum + // max + // min + // count + + // test basic aggregates + { + var queryText = @" +MATCH (p:Person)-[r:REVIEWED]->(m:Movie) +return m.Title as Title, AVG(r.Rating) as AvgRating, MAX(r.Rating) as HighestRating, MIN(r.Rating) as LowestRating, COUNT(r.Rating) as NumberOfReviews, SUM(r.Rating) as TotalRating, COUNT(r.Rating) / SUM(r.Rating) as AvgRating2 +"; + + RunQueryAndCompare(queryText); + } + + // test count(distinct()) + { + var queryText = @" +MATCH (p:Person)-[r:REVIEWED]->(m:Movie) +return COUNT(r.Rating) as NumberOfRatings, COUNT(DISTINCT(r.Rating)) as NumberOfUniqueRatings, COUNT(DISTINCT(m)) as NumberOfUniqueMovies +"; + + RunQueryAndCompare(queryText); + } + + // test stdev/stdevp aggregates + // NOTE: neo4j returns 0 for STDEV for when popsize = 1, where SQL (correctly) return Null + // so for now, we skip comparing STDEV for this special case + { + var queryText = @" +MATCH (p:Person)-[r:REVIEWED]->(m:Movie) +WITH m.Title as Title, STDEV(r.Rating) as RatingStdDev, STDEVP(r.Rating) as RatingStdDevP, COUNT(DISTINCT(p)) AS PopSize +WHERE PopSize > 1 +RETURN Title, RatingStdDev, RatingStdDevP, PopSize +"; + + RunQueryAndCompare(queryText); + } + + + // negative test case: nested aggregations + { + var queryText = @" +MATCH (p:Person)-[r:REVIEWED]->(m:Movie) +return COUNT(MAX(r.Rating)) as CountOfMaxRatings +"; + try + { + TranspileToSQL(queryText); + Assert.Fail("Negative test case passed unexpectedly."); + } + catch (TranspilerNotSupportedException) + { } + } + + // TODO: following is not supported/tested yet + // - percentileCount + // - percentileDisc + } + + [TestMethod] + public void EdgeDirectionTest() + { + // forward + { + var queryText = @" +MATCH (p:Person)-[:FOLLOWS]->(p2:Person) +return p.Name as Name1, p2.Name as Name2 + "; + RunQueryAndCompare(queryText); + } + + // backward + { + var queryText = @" +MATCH (p:Person)<-[:FOLLOWS]-(p2:Person) +return p.Name as Name1, p2.Name as Name2 + "; + RunQueryAndCompare(queryText); + } + + // either direction (automatically inferred) + { + var queryText = @" +MATCH (p:Person)-[:DIRECTED]-(m:Movie) +return p.Name as Name, m.Title as Title + "; + RunQueryAndCompare(queryText); + } + + // negative test case (wrong direction) + { + var queryText = @" +MATCH (p:Person)<-[:DIRECTED]-(m:Movie) +return p.Name as Name, m.Title as Title + "; + try + { + TranspileToSQL(queryText); + Assert.Fail("Negative test case passed unexpectedly."); + } + catch (TranspilerBindingException) + { } + } + + // negative test case of both direction with same type of src/sink + { + // right now we block the case of ambiguity edges (while neo4j support it right now + // by union the match from either direction) + var queryText = @" +MATCH (p:Person)-[:FOLLOWS]-(p2:Person) +return p.Name as Name1, p2.Name as Name2 + "; + try + { + TranspileToSQL(queryText); + Assert.Fail("Negative test case passed unexpectedly."); + } + catch (TranspilerNotSupportedException) + { } + } + } + + [TestMethod] + public void OrderByLimitClauseTest() + { + // basic case 1 + { + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WITH p.Name as Name, m.Title as Title +ORDER BY Name +LIMIT 11 +RETURN Name +"; + RunQueryAndCompare(queryText); + } + + // basic case 2 + { + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +RETURN p.Name as Name, m.Title as Title +ORDER BY Name +LIMIT 11 +"; + RunQueryAndCompare(queryText); + } + + // order by nested under with statement + { + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WHERE p.Name = 'Tom Hanks' +WITH p.Name+""B"" AS Name2, m.Title AS Title +ORDER BY m.Tagline, Name2, m.Title ASC +LIMIT 10 +Where p.Name starts with 'T' and Name2 starts with 'T' +RETURN Name2, Title +"; + + RunQueryAndCompare(queryText); + } + + // order by nested undet return statement + { + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WHERE p.Name = 'Tom Hanks' +WITH p.Name AS Name2, m.Title AS Title +RETURN Name2, Title +ORDER BY Name2 +LIMIT 20 +"; + RunQueryAndCompare(queryText); + } + + // order by nested undet return statement + { + var queryText = @" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WHERE p.Name = 'Tom Hanks' +RETURN p.Name as Name2 ,m.Title as Title +ORDER BY Name2 +LIMIT 20 +"; + RunQueryAndCompare(queryText); + } + + } + } +} diff --git a/tests/SQLRenderer.Test/TestData/ConvertAllToSQLCmds.cmd b/tests/SQLRenderer.Test/TestData/ConvertAllToSQLCmds.cmd new file mode 100644 index 0000000..3f21ac6 --- /dev/null +++ b/tests/SQLRenderer.Test/TestData/ConvertAllToSQLCmds.cmd @@ -0,0 +1,32 @@ +@echo off + +del MovieDBSQLCmds.sql + +echo IF db_id('octestdb') is null CREATE DATABASE octestdb; > MovieDBSQLCmds.sql +echo GO >> MovieDBSQLCmds.sql +echo >> MovieDBSQLCmds.sql +echo USE octestdb; >> MovieDBSQLCmds.sql +echo GO >> MovieDBSQLCmds.sql +echo >> MovieDBSQLCmds.sql + +CALL :CONVERT_SQL person.csv Person MovieDBSQLCmds.sql +CALL :CONVERT_SQL movie.csv Movie MovieDBSQLCmds.sql +CALL :CONVERT_SQL acted_in.csv ActedIn MovieDBSQLCmds.sql +CALL :CONVERT_SQL produced.csv Produced MovieDBSQLCmds.sql +CALL :CONVERT_SQL directed.csv Directed MovieDBSQLCmds.sql +CALL :CONVERT_SQL wrote.csv Wrote MovieDBSQLCmds.sql +CALL :CONVERT_SQL reviewed.csv Reviewed MovieDBSQLCmds.sql +CALL :CONVERT_SQL follows.csv Follows MovieDBSQLCmds.sql + +GOTO :EOF + +REM %1 is CSV file +REM %2 is the table name +REM %3 is the resulting SQL file +:CONVERT_SQL +echo python ConvertToSQLCmds.py %1 true %2 %3 +python ConvertToSQLCmds.py %1 true %2 %3 + +GOTO :EOF + +:EOF \ No newline at end of file diff --git a/tests/SQLRenderer.Test/TestData/ConvertToSQLCmds.py b/tests/SQLRenderer.Test/TestData/ConvertToSQLCmds.py new file mode 100644 index 0000000..7fbbf23 --- /dev/null +++ b/tests/SQLRenderer.Test/TestData/ConvertToSQLCmds.py @@ -0,0 +1,319 @@ +import unicodedata, re +import sys +import operator +import csv +from datetime import datetime +from io import StringIO + + +# read file, determine if it is csv or tsv, then extract the data and automatically determine the best +# type for each field. Eventually output a .ss file that can be run with Cosmos run time to +# actually convert the csv/tsv file into .ss file + + +# parameters: +# [1]: file to read +# [2]: first row is header +# [3]: script file to generate + + +# Contants + +# supported delimiters and how to represent it in Scope code +delims = { + # (Delimiter, C# representation) + ',': ',', + '\t': '\\t' +} + +# supported type and represent it in Scope code +type_tests = { + # type name : (Test, DowngradeTo, StringTypeName, StringTypeNameIfNullable) + int: ([int], float, "int", "int"), + float: ([float], datetime, "float", "float"), + datetime: ( + [ + lambda value: datetime.strptime(value, "%m/%d/%Y"), + lambda value: datetime.strptime(value, "%Y-%m-%d"), + lambda value: datetime.strptime(value, "%m/%d/%Y %H:%M:%S"), + lambda value: datetime.strptime(value, "%Y-%m-%d %I:%M:%S.%f %p") + ], str, "datetime", "datetime"), + str: ([str], str, "varchar(MAX)", "varchar(100)") +} + +# default type that is most restrictive to start with +type_most_restrictive = int + + + +# read first 10 rows and use majority vote to determine the deliminator +def get_delim(content_file): + supported_delims = [k for k, v in delims.items()] + num_lines_hasSep = {k:0 for k, v in delims.items()} + total_hasSep = {k:0 for k, v in delims.items()} + is_header_row = True + total_rows_read = 0 + num_rows_to_test = 10 + + # collect sample rows + #with open(readFileName, 'r', encoding='utf8') as content_file: + line = content_file.readline() + while (line != ''): + #for line in content_file: + if (is_header_row) : + is_header_row = False + for c in supported_delims: + cnt = line.count(c) + num_lines_hasSep[c] += (1 if cnt > 0 else 0) + total_hasSep[c] += cnt + total_rows_read+=1 + #print(line) + if (total_rows_read >= num_rows_to_test) : + break + else: + line = content_file.readline() + + # determine delimiters + # first, each row should have the delim, if one doesn't filter it out + survive_delim = {key:value for key, value in num_lines_hasSep.items() if value >= total_rows_read} + #print(survive_delim) + if (len(survive_delim) <= 0): + # no deliminator? should be one row case. we use default as delimiter + return supported_delims[0] + else: + return sorted(survive_delim.items(), key=operator.itemgetter(1), reverse=True)[0][0] + + +def regulate_token(str): + # for now regulating column name means remove all splitter strings, and replace , with _ + return str.replace(" ", "").replace(",", "_") + +def get_mostprefered_type(curtype, value): + typ = curtype + while (typ != str): + typobj = type_tests[typ] + for typtest in typobj[0]: + try: + typtest(value) + return typ + except ValueError: + # try next + pass + typ = typobj[1] + return str + +def get_type_rep(type, isnullable, iskey): + if (iskey): + return f"""{type_tests[type][3]}{" NULL" if isnullable else ""}""" + else: + return f"""{type_tests[type][2]}{" NULL" if isnullable else ""}""" + + +# read a string file and extract columns and label it with types +# return (cols, rows) +def extract_from_csv(content_file, delim, has_header): + # read the csv file row by row + reader = csv.reader(content_file, delimiter=delim) + + num_cols = 0 + rowid = 0 + colmap = {} + rows = [] + + for row in reader: + rowid+=1 + if (num_cols == 0): + num_cols = len(row) + # seen first row, create column definitions + if (has_header): + for id, col in enumerate(row): + colmap[id] = {'colname':col, 'type':type_most_restrictive, 'nullable':False, 'confirmed':False} # col name, type, nullable?, confirmed? + # header read. move to next line + continue + else: + for id, col in enumerate(row): + regname = regulate_token(col) + colmap[id] = {'colname':("Column%d" % (id+1)), 'type':type_most_restrictive, 'nullable':False, 'confirmed':False} + elif len(row) == 0: + # skip empty rows + continue + elif num_cols != len(row): + #col inconsistent + raise ValueError('Line %d has inconsistent number of cols %d, expect %d. Line content:\n%s' % (rowid, len(row), num_cols, row)) + elif (row is not None): + # see normal row. Fall through to do the common processing + pass + else: + raise Exception("Unhandled situation") + + # the common processing: update column type for each column + for id, col in enumerate(row): + curT = colmap[id]['type'] + is_confirmed = colmap[id]['confirmed'] + if ( (not is_confirmed) or + (curT is not str) ): + # string cannot be downgraded anymore, other types can + # unless, we haven't seen the first confirmable data yet + if (col == ''): + # col is nullable + colmap[id]['nullable'] = True + else: + # check the type + colmap[id]['type'] = get_mostprefered_type(curT, col) + colmap[id]['confirmed'] = True + + rows.append(row) + + return colmap, rows + +# helper function to parse boolean +def parse_bool(s): + return (s in ['true', '1', 't', 'y', 'yes']) + + +def create_table_insert(table_name, colmap, pkcols): + script = f"DROP TABLE IF EXISTS dbo.{table_name};\nGO;\n" + script += f"CREATE TABLE dbo.{table_name}\n" + script += "(\n" + # construct the type string + cols = sorted(colmap.items(), key=operator.itemgetter(0)) + first = True + for col in cols: + script += f""" {"" if first else ", "}{col[1]['colname']} {get_type_rep(col[1]['type'], col[1]['nullable'], col[1]['colname'] in pkcols)}\n""" + first = False + pkcols_exists = [ pkcol for pkcol in pkcols if pkcol in [col[1]['colname'] for col in cols] ] + if len(pkcols_exists) > 0: + script += f""" , CONSTRAINT PK_{table_name.upper()}\n""" + script += f""" PRIMARY KEY CLUSTERED ({", ".join(pkcols_exists)})\n""" + script += f""" WITH (IGNORE_DUP_KEY = OFF)\n""" + script += ");\nGO;\n" + return script + +def formatvalue(val, coltype): + if coltype is str: + return f"""'{val.replace("'", "''")}'""" + else: + return "NULL" if val is None or val == "" else val + +def create_insert(table_name, colmap, rows): + script = "" + cols = sorted(colmap.items(), key=operator.itemgetter(0)) + for row in rows: + script += f"""INSERT INTO {table_name} ({", ".join([col[1]['colname'] for col in cols])})\n""" + row_quoted = [ formatvalue(row[i], cols[i][1]['type']) for i in range(len(cols)) ] + script += f""" VALUES ({", ".join(row_quoted)})\n""" + script += "GO;\n" + return script + +# Test code +def run_test() : + # expect , + testFile = "A,B,C\n1,str,str2\n2,str3,str4" + testFileDummy = StringIO(testFile) + testres = get_delim(testFileDummy) + print("delimiter is %s" % testres) + assert(testres == ',') + + # expect + testFile = "A\tB\tC\n1\tstr\tstr2\n2\tstr3\tstr4" + testFileDummy = StringIO(testFile) + testres = get_delim(testFileDummy) + print("delimiter is %s" % '<\\t>' if testres == '\t' else get_delim(testFileDummy)) + assert(testres == '\t') + + # expect + testFile = "A\tB,C\tD\n1\tstr\tstr2\n2\tstr3,str4\tstr5" + testFileDummy = StringIO(testFile) + testres = get_delim(testFileDummy) + print("delimiter is %s" % '<\\t>' if testres == '\t' else get_delim(testFileDummy)) + assert(testres == '\t') + + +def run_test2() : + testStr = "my col name" + testres = regulate_token(testStr) + print("%s --> %s" % (testStr, testres)) + assert(testres == 'mycolname') + + testStr = "my col name, name2" + testres = regulate_token(testStr) + print("%s --> %s" % (testStr, testres)) + assert(testres == 'mycolname_name2') + + +def run_test3() : + + #expect: A:int, B:str, C:str + testFile = "A,B,C\n1,str,str2\n2,str3,str4" + testFileDummy = StringIO(testFile) + testres, testrows = extract_from_csv(testFileDummy, ',', True) + print(testres) + assert(len(testres.items()) == 3) + # TODO: more asserts + + #expect: Column1:int, Column2:str, Column3:str + testFile = "1,str,str2\n2,str3,str4" + testFileDummy = StringIO(testFile) + testres, testrows = extract_from_csv(testFileDummy, ',', False) + print(testres) + assert(len(testres.items()) == 3) + # TODO: more asserts + + +# read a file, filter out the bad chars in memory, write the cleaned file back +def process(csv_file, has_header, outtable, outfile): + print(f"Reading {csv_file} ...") + print(f"""The CSV file should{"" if has_header else " not"} contain header""") + + # peek the csv file and mine the column type + colmap = {} + with open(csv_file, 'r', encoding='utf8') as content_file: + delim = get_delim(content_file) + + # TODO: this is not optimal, we can do one pass instead of 2 pass here + with open(csv_file, 'r', encoding='utf8') as content_file: + colmap, rows = extract_from_csv(content_file, delim, has_header) + + # Generate table creation statement + table_name = outtable + full_script = create_table_insert(table_name, colmap, ["id", "_vertexId", "_sink"]) + full_script += create_insert(table_name, colmap, rows) + + with open(outfile, 'a', encoding='utf8') as target_file: + target_file.write(full_script) + + print("Done") + + +def main(): + + if len(sys.argv) < 2 : + print("Error: must provide the csv/tsv file name to peek at") + return + + if len(sys.argv) < 3 : + print("Error: must provide true or false that the csv file contains header") + return + + if len(sys.argv) < 4 : + print("Error: must provide a table name file to write to") + return + + if len(sys.argv) < 5 : + print("Error: must provide a script file to write to (or append to)") + return + + csv_file = sys.argv[1] + has_header = parse_bool(sys.argv[2]) + out_table = sys.argv[3] + out_file = sys.argv[4] + + process(csv_file, has_header, out_table, out_file) + + +# main operations + +#run_test() +#run_test2() +#run_test3() +main() diff --git a/tests/SQLRenderer.Test/TestData/DownloadMovieDB.cmd b/tests/SQLRenderer.Test/TestData/DownloadMovieDB.cmd new file mode 100644 index 0000000..19d61dd --- /dev/null +++ b/tests/SQLRenderer.Test/TestData/DownloadMovieDB.cmd @@ -0,0 +1,45 @@ +set NEODB=https://jerrylia-home-2-wifi:7473 +set USER=neo4j +set PW=neo4jtest +Setlocal + +CALL :DOWNLOAD_AS_CSV "match (p:Person) return p.id as id, p.Name as Name, p.Born as Born" person.csv +CALL :DOWNLOAD_AS_CSV "match (m:Movie) return m.id as id, m.Title as Title, m.Tagline as Tagline, m.Released as Released" movie.csv + +CALL :DOWNLOAD_AS_CSV_CUSTOMJQ "match (m:Person)-[r:ACTED_IN]->(n:Movie) return m.id as _vertexId, n.id as _sink, r.Roles as Roles" acted_in.csv acted_in.jq.txt +CALL :DOWNLOAD_AS_CSV "match (m:Person)-[r:PRODUCED]->(n:Movie) return m.id as _vertexId, n.id as _sink" produced.csv +CALL :DOWNLOAD_AS_CSV "match (m:Person)-[r:DIRECTED]->(n:Movie) return m.id as _vertexId, n.id as _sink" directed.csv +CALL :DOWNLOAD_AS_CSV "match (m:Person)-[r:WROTE]->(n:Movie) return m.id as _vertexId, n.id as _sink" wrote.csv +CALL :DOWNLOAD_AS_CSV "match (m:Person)-[r:REVIEWED]->(n:Movie) return m.id as _vertexId, n.id as _sink, r.Summary as Summary, r.Rating as Rating" reviewed.csv +CALL :DOWNLOAD_AS_CSV "match (m:Person)-[r:FOLLOWS]->(n:Person) return m.id as _vertexId, n.id as _sink" follows.csv + +goto :EOF + +REM %1 is the cypher command +REM %2 is the output file +:DOWNLOAD_AS_CSV +echo {"statements":[{"statement":"%~1"}]} > dn.req.temp.txt +curl --insecure -u %USER%:%PW% ^ + -H accept:application/json -H content-type:application/json ^ + -d @dn.req.temp.txt ^ + %NEODB%/db/data/transaction/commit ^ + | jq -r "(.results[0]) | .columns,.data[].row | @csv" ^ + > %~2 + + GOTO:EOF + +REM %1 is the cypher command +REM %2 is the output file +REM %3 is the JQ command file when the command doesn't work well over command line interface + :DOWNLOAD_AS_CSV_CUSTOMJQ +echo {"statements":[{"statement":"%~1"}]} > dn.req.temp.txt +curl --insecure -u %USER%:%PW% ^ + -H accept:application/json -H content-type:application/json ^ + -d @dn.req.temp.txt ^ + %NEODB%/db/data/transaction/commit ^ + | jq -f %~3 -r ^ + > %~2 + + GOTO:EOF + +:EOF \ No newline at end of file diff --git a/tests/SQLRenderer.Test/TestData/MovieDBSQLCmds.sql b/tests/SQLRenderer.Test/TestData/MovieDBSQLCmds.sql new file mode 100644 index 0000000..68e4cd6 --- /dev/null +++ b/tests/SQLRenderer.Test/TestData/MovieDBSQLCmds.sql @@ -0,0 +1,932 @@ +IF db_id('octestdb') is null CREATE DATABASE octestdb; +GO + +USE octestdb; +GO + +DROP TABLE IF EXISTS dbo.Person +CREATE TABLE dbo.Person +( + id varchar(100) + , Name varchar(MAX) + , Born int NULL + , CONSTRAINT PK_PERSON + PRIMARY KEY CLUSTERED (id) + WITH (IGNORE_DUP_KEY = OFF) +) +INSERT INTO Person (id, Name, Born) + VALUES ('Keanu Reeves', 'Keanu Reeves', 1964) +INSERT INTO Person (id, Name, Born) + VALUES ('Carrie-Anne Moss', 'Carrie-Anne Moss', 1967) +INSERT INTO Person (id, Name, Born) + VALUES ('Laurence Fishburne', 'Laurence Fishburne', 1961) +INSERT INTO Person (id, Name, Born) + VALUES ('Hugo Weaving', 'Hugo Weaving', 1960) +INSERT INTO Person (id, Name, Born) + VALUES ('Lilly Wachowski', 'Lilly Wachowski', 1967) +INSERT INTO Person (id, Name, Born) + VALUES ('Lana Wachowski', 'Lana Wachowski', 1965) +INSERT INTO Person (id, Name, Born) + VALUES ('Joel Silver', 'Joel Silver', 1952) +INSERT INTO Person (id, Name, Born) + VALUES ('Emil Eifrem', 'Emil Eifrem', 1978) +INSERT INTO Person (id, Name, Born) + VALUES ('Charlize Theron', 'Charlize Theron', 1975) +INSERT INTO Person (id, Name, Born) + VALUES ('Al Pacino', 'Al Pacino', 1940) +INSERT INTO Person (id, Name, Born) + VALUES ('Taylor Hackford', 'Taylor Hackford', 1944) +INSERT INTO Person (id, Name, Born) + VALUES ('Tom Cruise', 'Tom Cruise', 1962) +INSERT INTO Person (id, Name, Born) + VALUES ('Jack Nicholson', 'Jack Nicholson', 1937) +INSERT INTO Person (id, Name, Born) + VALUES ('Demi Moore', 'Demi Moore', 1962) +INSERT INTO Person (id, Name, Born) + VALUES ('Kevin Bacon', 'Kevin Bacon', 1958) +INSERT INTO Person (id, Name, Born) + VALUES ('Kiefer Sutherland', 'Kiefer Sutherland', 1966) +INSERT INTO Person (id, Name, Born) + VALUES ('Noah Wyle', 'Noah Wyle', 1971) +INSERT INTO Person (id, Name, Born) + VALUES ('Cuba Gooding Jr.', 'Cuba Gooding Jr.', 1968) +INSERT INTO Person (id, Name, Born) + VALUES ('Kevin Pollak', 'Kevin Pollak', 1957) +INSERT INTO Person (id, Name, Born) + VALUES ('J.T. Walsh', 'J.T. Walsh', 1943) +INSERT INTO Person (id, Name, Born) + VALUES ('James Marshall', 'James Marshall', 1967) +INSERT INTO Person (id, Name, Born) + VALUES ('Christopher Guest', 'Christopher Guest', 1948) +INSERT INTO Person (id, Name, Born) + VALUES ('Rob Reiner', 'Rob Reiner', 1947) +INSERT INTO Person (id, Name, Born) + VALUES ('Aaron Sorkin', 'Aaron Sorkin', 1961) +INSERT INTO Person (id, Name, Born) + VALUES ('Kelly McGillis', 'Kelly McGillis', 1957) +INSERT INTO Person (id, Name, Born) + VALUES ('Val Kilmer', 'Val Kilmer', 1959) +INSERT INTO Person (id, Name, Born) + VALUES ('Anthony Edwards', 'Anthony Edwards', 1962) +INSERT INTO Person (id, Name, Born) + VALUES ('Tom Skerritt', 'Tom Skerritt', 1933) +INSERT INTO Person (id, Name, Born) + VALUES ('Meg Ryan', 'Meg Ryan', 1961) +INSERT INTO Person (id, Name, Born) + VALUES ('Tony Scott', 'Tony Scott', 1944) +INSERT INTO Person (id, Name, Born) + VALUES ('Jim Cash', 'Jim Cash', 1941) +INSERT INTO Person (id, Name, Born) + VALUES ('Renee Zellweger', 'Renee Zellweger', 1969) +INSERT INTO Person (id, Name, Born) + VALUES ('Kelly Preston', 'Kelly Preston', 1962) +INSERT INTO Person (id, Name, Born) + VALUES ('Jerry O''Connell', 'Jerry O''Connell', 1974) +INSERT INTO Person (id, Name, Born) + VALUES ('Jay Mohr', 'Jay Mohr', 1970) +INSERT INTO Person (id, Name, Born) + VALUES ('Bonnie Hunt', 'Bonnie Hunt', 1961) +INSERT INTO Person (id, Name, Born) + VALUES ('Regina King', 'Regina King', 1971) +INSERT INTO Person (id, Name, Born) + VALUES ('Jonathan Lipnicki', 'Jonathan Lipnicki', 1996) +INSERT INTO Person (id, Name, Born) + VALUES ('Cameron Crowe', 'Cameron Crowe', 1957) +INSERT INTO Person (id, Name, Born) + VALUES ('River Phoenix', 'River Phoenix', 1970) +INSERT INTO Person (id, Name, Born) + VALUES ('Corey Feldman', 'Corey Feldman', 1971) +INSERT INTO Person (id, Name, Born) + VALUES ('Wil Wheaton', 'Wil Wheaton', 1972) +INSERT INTO Person (id, Name, Born) + VALUES ('John Cusack', 'John Cusack', 1966) +INSERT INTO Person (id, Name, Born) + VALUES ('Marshall Bell', 'Marshall Bell', 1942) +INSERT INTO Person (id, Name, Born) + VALUES ('Helen Hunt', 'Helen Hunt', 1963) +INSERT INTO Person (id, Name, Born) + VALUES ('Greg Kinnear', 'Greg Kinnear', 1963) +INSERT INTO Person (id, Name, Born) + VALUES ('James L. Brooks', 'James L. Brooks', 1940) +INSERT INTO Person (id, Name, Born) + VALUES ('Annabella Sciorra', 'Annabella Sciorra', 1960) +INSERT INTO Person (id, Name, Born) + VALUES ('Max von Sydow', 'Max von Sydow', 1929) +INSERT INTO Person (id, Name, Born) + VALUES ('Werner Herzog', 'Werner Herzog', 1942) +INSERT INTO Person (id, Name, Born) + VALUES ('Robin Williams', 'Robin Williams', 1951) +INSERT INTO Person (id, Name, Born) + VALUES ('Vincent Ward', 'Vincent Ward', 1956) +INSERT INTO Person (id, Name, Born) + VALUES ('Ethan Hawke', 'Ethan Hawke', 1970) +INSERT INTO Person (id, Name, Born) + VALUES ('Rick Yune', 'Rick Yune', 1971) +INSERT INTO Person (id, Name, Born) + VALUES ('James Cromwell', 'James Cromwell', 1940) +INSERT INTO Person (id, Name, Born) + VALUES ('Scott Hicks', 'Scott Hicks', 1953) +INSERT INTO Person (id, Name, Born) + VALUES ('Parker Posey', 'Parker Posey', 1968) +INSERT INTO Person (id, Name, Born) + VALUES ('Dave Chappelle', 'Dave Chappelle', 1973) +INSERT INTO Person (id, Name, Born) + VALUES ('Steve Zahn', 'Steve Zahn', 1967) +INSERT INTO Person (id, Name, Born) + VALUES ('Tom Hanks', 'Tom Hanks', 1956) +INSERT INTO Person (id, Name, Born) + VALUES ('Nora Ephron', 'Nora Ephron', 1941) +INSERT INTO Person (id, Name, Born) + VALUES ('Rita Wilson', 'Rita Wilson', 1956) +INSERT INTO Person (id, Name, Born) + VALUES ('Bill Pullman', 'Bill Pullman', 1953) +INSERT INTO Person (id, Name, Born) + VALUES ('Victor Garber', 'Victor Garber', 1949) +INSERT INTO Person (id, Name, Born) + VALUES ('Rosie O''Donnell', 'Rosie O''Donnell', 1962) +INSERT INTO Person (id, Name, Born) + VALUES ('John Patrick Stanley', 'John Patrick Stanley', 1950) +INSERT INTO Person (id, Name, Born) + VALUES ('Nathan Lane', 'Nathan Lane', 1956) +INSERT INTO Person (id, Name, Born) + VALUES ('Billy Crystal', 'Billy Crystal', 1948) +INSERT INTO Person (id, Name, Born) + VALUES ('Carrie Fisher', 'Carrie Fisher', 1956) +INSERT INTO Person (id, Name, Born) + VALUES ('Bruno Kirby', 'Bruno Kirby', 1949) +INSERT INTO Person (id, Name, Born) + VALUES ('Liv Tyler', 'Liv Tyler', 1977) +INSERT INTO Person (id, Name, Born) + VALUES ('Brooke Langton', 'Brooke Langton', 1970) +INSERT INTO Person (id, Name, Born) + VALUES ('Gene Hackman', 'Gene Hackman', 1930) +INSERT INTO Person (id, Name, Born) + VALUES ('Orlando Jones', 'Orlando Jones', 1968) +INSERT INTO Person (id, Name, Born) + VALUES ('Howard Deutch', 'Howard Deutch', 1950) +INSERT INTO Person (id, Name, Born) + VALUES ('Christian Bale', 'Christian Bale', 1974) +INSERT INTO Person (id, Name, Born) + VALUES ('Zach Grenier', 'Zach Grenier', 1954) +INSERT INTO Person (id, Name, Born) + VALUES ('Mike Nichols', 'Mike Nichols', 1931) +INSERT INTO Person (id, Name, Born) + VALUES ('Richard Harris', 'Richard Harris', 1930) +INSERT INTO Person (id, Name, Born) + VALUES ('Clint Eastwood', 'Clint Eastwood', 1930) +INSERT INTO Person (id, Name, Born) + VALUES ('Takeshi Kitano', 'Takeshi Kitano', 1947) +INSERT INTO Person (id, Name, Born) + VALUES ('Dina Meyer', 'Dina Meyer', 1968) +INSERT INTO Person (id, Name, Born) + VALUES ('Ice-T', 'Ice-T', 1958) +INSERT INTO Person (id, Name, Born) + VALUES ('Robert Longo', 'Robert Longo', 1953) +INSERT INTO Person (id, Name, Born) + VALUES ('Halle Berry', 'Halle Berry', 1966) +INSERT INTO Person (id, Name, Born) + VALUES ('Jim Broadbent', 'Jim Broadbent', 1949) +INSERT INTO Person (id, Name, Born) + VALUES ('Tom Tykwer', 'Tom Tykwer', 1965) +INSERT INTO Person (id, Name, Born) + VALUES ('David Mitchell', 'David Mitchell', 1969) +INSERT INTO Person (id, Name, Born) + VALUES ('Stefan Arndt', 'Stefan Arndt', 1961) +INSERT INTO Person (id, Name, Born) + VALUES ('Ian McKellen', 'Ian McKellen', 1939) +INSERT INTO Person (id, Name, Born) + VALUES ('Audrey Tautou', 'Audrey Tautou', 1976) +INSERT INTO Person (id, Name, Born) + VALUES ('Paul Bettany', 'Paul Bettany', 1971) +INSERT INTO Person (id, Name, Born) + VALUES ('Ron Howard', 'Ron Howard', 1954) +INSERT INTO Person (id, Name, Born) + VALUES ('Natalie Portman', 'Natalie Portman', 1981) +INSERT INTO Person (id, Name, Born) + VALUES ('Stephen Rea', 'Stephen Rea', 1946) +INSERT INTO Person (id, Name, Born) + VALUES ('John Hurt', 'John Hurt', 1940) +INSERT INTO Person (id, Name, Born) + VALUES ('', 'Ben Miles', 1967) +INSERT INTO Person (id, Name, Born) + VALUES ('Emile Hirsch', 'Emile Hirsch', 1985) +INSERT INTO Person (id, Name, Born) + VALUES ('John Goodman', 'John Goodman', 1960) +INSERT INTO Person (id, Name, Born) + VALUES ('Susan Sarandon', 'Susan Sarandon', 1946) +INSERT INTO Person (id, Name, Born) + VALUES ('Matthew Fox', 'Matthew Fox', 1966) +INSERT INTO Person (id, Name, Born) + VALUES ('Christina Ricci', 'Christina Ricci', 1980) +INSERT INTO Person (id, Name, Born) + VALUES ('Rain', 'Rain', 1982) +INSERT INTO Person (id, Name, Born) + VALUES ('Naomie Harris', 'Naomie Harris', NULL) +INSERT INTO Person (id, Name, Born) + VALUES ('Michael Clarke Duncan', 'Michael Clarke Duncan', 1957) +INSERT INTO Person (id, Name, Born) + VALUES ('David Morse', 'David Morse', 1953) +INSERT INTO Person (id, Name, Born) + VALUES ('Sam Rockwell', 'Sam Rockwell', 1968) +INSERT INTO Person (id, Name, Born) + VALUES ('Gary Sinise', 'Gary Sinise', 1955) +INSERT INTO Person (id, Name, Born) + VALUES ('Patricia Clarkson', 'Patricia Clarkson', 1959) +INSERT INTO Person (id, Name, Born) + VALUES ('Frank Darabont', 'Frank Darabont', 1959) +INSERT INTO Person (id, Name, Born) + VALUES ('Frank Langella', 'Frank Langella', 1938) +INSERT INTO Person (id, Name, Born) + VALUES ('Michael Sheen', 'Michael Sheen', 1969) +INSERT INTO Person (id, Name, Born) + VALUES ('Oliver Platt', 'Oliver Platt', 1960) +INSERT INTO Person (id, Name, Born) + VALUES ('Danny DeVito', 'Danny DeVito', 1944) +INSERT INTO Person (id, Name, Born) + VALUES ('John C. Reilly', 'John C. Reilly', 1965) +INSERT INTO Person (id, Name, Born) + VALUES ('Ed Harris', 'Ed Harris', 1950) +INSERT INTO Person (id, Name, Born) + VALUES ('Bill Paxton', 'Bill Paxton', 1955) +INSERT INTO Person (id, Name, Born) + VALUES ('Philip Seymour Hoffman', 'Philip Seymour Hoffman', 1967) +INSERT INTO Person (id, Name, Born) + VALUES ('Jan de Bont', 'Jan de Bont', 1943) +INSERT INTO Person (id, Name, Born) + VALUES ('Robert Zemeckis', 'Robert Zemeckis', 1951) +INSERT INTO Person (id, Name, Born) + VALUES ('Milos Forman', 'Milos Forman', 1932) +INSERT INTO Person (id, Name, Born) + VALUES ('Diane Keaton', 'Diane Keaton', 1946) +INSERT INTO Person (id, Name, Born) + VALUES ('Nancy Meyers', 'Nancy Meyers', 1949) +INSERT INTO Person (id, Name, Born) + VALUES ('Chris Columbus', 'Chris Columbus', 1958) +INSERT INTO Person (id, Name, Born) + VALUES ('Julia Roberts', 'Julia Roberts', 1967) +INSERT INTO Person (id, Name, Born) + VALUES ('Madonna', 'Madonna', 1954) +INSERT INTO Person (id, Name, Born) + VALUES ('Geena Davis', 'Geena Davis', 1956) +INSERT INTO Person (id, Name, Born) + VALUES ('Lori Petty', 'Lori Petty', 1963) +INSERT INTO Person (id, Name, Born) + VALUES ('Penny Marshall', 'Penny Marshall', 1943) +INSERT INTO Person (id, Name, Born) + VALUES ('Paul Blythe', 'Paul Blythe', NULL) +INSERT INTO Person (id, Name, Born) + VALUES ('Angela Scope', 'Angela Scope', NULL) +INSERT INTO Person (id, Name, Born) + VALUES ('Jessica Thompson', 'Jessica Thompson', NULL) +INSERT INTO Person (id, Name, Born) + VALUES ('James Thompson', 'James Thompson', NULL) +DROP TABLE IF EXISTS dbo.Movie +CREATE TABLE dbo.Movie +( + id varchar(100) + , Title varchar(MAX) + , Tagline varchar(MAX) + , Released int + , CONSTRAINT PK_MOVIE + PRIMARY KEY CLUSTERED (id) + WITH (IGNORE_DUP_KEY = OFF) +) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('The Matrix', 'The Matrix', 'Welcome to the Real World', 1999) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('The Matrix Reloaded', 'The Matrix Reloaded', 'Free your mind', 2003) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('The Matrix Revolutions', 'The Matrix Revolutions', 'Everything that has a beginning has an end', 2003) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('The Devil''s Advocate', 'The Devil''s Advocate', 'Evil has its winning ways', 1997) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('A Few Good Men', 'A Few Good Men', 'In the heart of the nation''s capital, in a courthouse of the U.S. government, one man will stop at nothing to keep his honor, and one will stop at nothing to find the truth.', 1992) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Top Gun', 'Top Gun', 'I feel the need, the need for speed.', 1986) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Jerry Maguire', 'Jerry Maguire', 'The rest of his life begins now.', 2000) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Stand By Me', 'Stand By Me', 'For some, it''s the last real taste of innocence, and the first real taste of life. But for everyone, it''s the time that memories are made of.', 1986) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('As Good as It Gets', 'As Good as It Gets', 'A comedy from the heart that goes for the throat.', 1997) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('What Dreams May Come', 'What Dreams May Come', 'After life there is more. The end is just the beginning.', 1998) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Snow Falling on Cedars', 'Snow Falling on Cedars', 'First loves last. Forever.', 1999) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('You''ve Got Mail', 'You''ve Got Mail', 'At odds in life... in love on-line.', 1998) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Sleepless in Seattle', 'Sleepless in Seattle', 'What if someone you never met, someone you never saw, someone you never knew was the only someone for you?', 1993) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Joe Versus the Volcano', 'Joe Versus the Volcano', 'A story of love, lava and burning desire.', 1990) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('When Harry Met Sally', 'When Harry Met Sally', 'At odds in life... in love on-line.', 1998) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('That Thing You Do', 'That Thing You Do', 'In every life there comes a time when that thing you dream becomes that thing you do', 1996) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('The Replacements', 'The Replacements', 'Pain heals, Chicks dig scars... Glory lasts forever', 2000) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('RescueDawn', 'RescueDawn', 'Based on the extraordinary true story of one man''s fight for freedom', 2006) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('The Birdcage', 'The Birdcage', 'Come as you are', 1996) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Unforgiven', 'Unforgiven', 'It''s a hell of a thing, killing a man', 1992) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Johnny Mnemonic', 'Johnny Mnemonic', 'The hottest data on earth. In the coolest head in town', 1995) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Cloud Atlas', 'Cloud Atlas', 'Everything is connected', 2012) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('The Da Vinci Code', 'The Da Vinci Code', 'Break The Codes', 2006) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('V for Vendetta', 'V for Vendetta', 'Freedom! Forever!', 2006) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Speed Racer', 'Speed Racer', 'Speed has no limits', 2008) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Ninja Assassin', 'Ninja Assassin', 'Prepare to enter a secret world of assassins', 2009) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('The Green Mile', 'The Green Mile', 'Walk a mile you''ll never forget.', 1999) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Frost/Nixon', 'Frost/Nixon', '400 million people were waiting for the truth.', 2008) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Hoffa', 'Hoffa', 'He didn''t want law. He wanted justice.', 1992) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Apollo 13', 'Apollo 13', 'Houston, we have a problem.', 1995) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Twister', 'Twister', 'Don''t Breathe. Don''t Look Back.', 1996) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Cast Away', 'Cast Away', 'At the edge of the world, his journey begins.', 2000) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('One Flew Over the Cuckoo''s Nest', 'One Flew Over the Cuckoo''s Nest', 'If he''s crazy, what does that make you?', 1975) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Something''s Gotta Give', 'Something''s Gotta Give', '', 2003) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Bicentennial Man', 'Bicentennial Man', 'One robot''s 200 year journey to become an ordinary man.', 1999) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('Charlie Wilson''s War', 'Charlie Wilson''s War', 'A stiff drink. A little mascara. A lot of nerve. Who said they couldn''t bring down the Soviet empire.', 2007) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('The Polar Express', 'The Polar Express', 'This Holiday Season… Believe', 2004) +INSERT INTO Movie (id, Title, Tagline, Released) + VALUES ('A League of Their Own', 'A League of Their Own', 'Once in a lifetime you get a chance to do something different.', 1992) +DROP TABLE IF EXISTS dbo.ActedIn +CREATE TABLE dbo.ActedIn +( + _vertexId varchar(100) + , _sink varchar(100) + , Roles varchar(MAX) + , CONSTRAINT PK_ACTEDIN + PRIMARY KEY CLUSTERED (_vertexId, _sink) + WITH (IGNORE_DUP_KEY = OFF) +) +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Emil Eifrem', 'The Matrix', 'Emil') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Hugo Weaving', 'The Matrix', 'Agent Smith') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Laurence Fishburne', 'The Matrix', 'Morpheus') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Carrie-Anne Moss', 'The Matrix', 'Trinity') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Keanu Reeves', 'The Matrix', 'Neo') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Hugo Weaving', 'The Matrix Reloaded', 'Agent Smith') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Laurence Fishburne', 'The Matrix Reloaded', 'Morpheus') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Carrie-Anne Moss', 'The Matrix Reloaded', 'Trinity') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Keanu Reeves', 'The Matrix Reloaded', 'Neo') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Hugo Weaving', 'The Matrix Revolutions', 'Agent Smith') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Laurence Fishburne', 'The Matrix Revolutions', 'Morpheus') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Carrie-Anne Moss', 'The Matrix Revolutions', 'Trinity') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Keanu Reeves', 'The Matrix Revolutions', 'Neo') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Al Pacino', 'The Devil''s Advocate', 'John Milton') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Charlize Theron', 'The Devil''s Advocate', 'Mary Ann Lomax') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Keanu Reeves', 'The Devil''s Advocate', 'Kevin Lomax') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('James Marshall', 'A Few Good Men', 'Pfc. Louden Downey') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Kevin Pollak', 'A Few Good Men', 'Lt. Sam Weinberg') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('J.T. Walsh', 'A Few Good Men', 'Lt. Col. Matthew Andrew Markinson') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Aaron Sorkin', 'A Few Good Men', 'Man in Bar') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Cuba Gooding Jr.', 'A Few Good Men', 'Cpl. Carl Hammaker') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Christopher Guest', 'A Few Good Men', 'Dr. Stone') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Noah Wyle', 'A Few Good Men', 'Cpl. Jeffrey Barnes') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Kiefer Sutherland', 'A Few Good Men', 'Lt. Jonathan Kendrick') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Kevin Bacon', 'A Few Good Men', 'Capt. Jack Ross') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Demi Moore', 'A Few Good Men', 'Lt. Cdr. JoAnne Galloway') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Jack Nicholson', 'A Few Good Men', 'Col. Nathan R. Jessup') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Tom Cruise', 'A Few Good Men', 'Lt. Daniel Kaffee') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Val Kilmer', 'Top Gun', 'Iceman') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Meg Ryan', 'Top Gun', 'Carole') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Tom Skerritt', 'Top Gun', 'Viper') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Kelly McGillis', 'Top Gun', 'Charlie') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Tom Cruise', 'Top Gun', 'Maverick') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Anthony Edwards', 'Top Gun', 'Goose') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Jerry O''Connell', 'Jerry Maguire', 'Frank Cushman') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Bonnie Hunt', 'Jerry Maguire', 'Laurel Boyd') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Jay Mohr', 'Jerry Maguire', 'Bob Sugar') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Cuba Gooding Jr.', 'Jerry Maguire', 'Rod Tidwell') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Jonathan Lipnicki', 'Jerry Maguire', 'Ray Boyd') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Renee Zellweger', 'Jerry Maguire', 'Dorothy Boyd') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Kelly Preston', 'Jerry Maguire', 'Avery Bishop') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Regina King', 'Jerry Maguire', 'Marcee Tidwell') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Tom Cruise', 'Jerry Maguire', 'Jerry Maguire') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Jerry O''Connell', 'Stand By Me', 'Vern Tessio') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('River Phoenix', 'Stand By Me', 'Chris Chambers') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Marshall Bell', 'Stand By Me', 'Mr. Lachance') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Wil Wheaton', 'Stand By Me', 'Gordie Lachance') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Kiefer Sutherland', 'Stand By Me', 'Ace Merrill') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('John Cusack', 'Stand By Me', 'Denny Lachance') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Corey Feldman', 'Stand By Me', 'Teddy Duchamp') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Helen Hunt', 'As Good as It Gets', 'Carol Connelly') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Jack Nicholson', 'As Good as It Gets', 'Melvin Udall') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Cuba Gooding Jr.', 'As Good as It Gets', 'Frank Sachs') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Greg Kinnear', 'As Good as It Gets', 'Simon Bishop') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Robin Williams', 'What Dreams May Come', 'Chris Nielsen') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Cuba Gooding Jr.', 'What Dreams May Come', 'Albert Lewis') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Max von Sydow', 'What Dreams May Come', 'The Tracker') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Werner Herzog', 'What Dreams May Come', 'The Face') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Annabella Sciorra', 'What Dreams May Come', 'Annie Collins-Nielsen') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Ethan Hawke', 'Snow Falling on Cedars', 'Ishmael Chambers') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Rick Yune', 'Snow Falling on Cedars', 'Kazuo Miyamoto') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Max von Sydow', 'Snow Falling on Cedars', 'Nels Gudmundsson') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('James Cromwell', 'Snow Falling on Cedars', 'Judge Fielding') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Tom Hanks', 'You''ve Got Mail', 'Joe Fox') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Parker Posey', 'You''ve Got Mail', 'Patricia Eden') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Greg Kinnear', 'You''ve Got Mail', 'Frank Navasky') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Meg Ryan', 'You''ve Got Mail', 'Kathleen Kelly') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Steve Zahn', 'You''ve Got Mail', 'George Pappas') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Dave Chappelle', 'You''ve Got Mail', 'Kevin Jackson') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Meg Ryan', 'Sleepless in Seattle', 'Annie Reed') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Victor Garber', 'Sleepless in Seattle', 'Greg') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Tom Hanks', 'Sleepless in Seattle', 'Sam Baldwin') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Bill Pullman', 'Sleepless in Seattle', 'Walter') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Rita Wilson', 'Sleepless in Seattle', 'Suzy') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Rosie O''Donnell', 'Sleepless in Seattle', 'Becky') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Tom Hanks', 'Joe Versus the Volcano', 'Joe Banks') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Nathan Lane', 'Joe Versus the Volcano', 'Baw') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Meg Ryan', 'Joe Versus the Volcano', 'DeDe|Angelica Graynamore|Patricia Graynamore') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Carrie Fisher', 'When Harry Met Sally', 'Marie') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Billy Crystal', 'When Harry Met Sally', 'Harry Burns') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Bruno Kirby', 'When Harry Met Sally', 'Jess') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Meg Ryan', 'When Harry Met Sally', 'Sally Albright') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Tom Hanks', 'That Thing You Do', 'Mr. White') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Liv Tyler', 'That Thing You Do', 'Faye Dolan') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Charlize Theron', 'That Thing You Do', 'Tina') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Brooke Langton', 'The Replacements', 'Annabelle Farrell') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Keanu Reeves', 'The Replacements', 'Shane Falco') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Orlando Jones', 'The Replacements', 'Clifford Franklin') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Gene Hackman', 'The Replacements', 'Jimmy McGinty') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Zach Grenier', 'RescueDawn', 'Squad Leader') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Steve Zahn', 'RescueDawn', 'Duane') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Christian Bale', 'RescueDawn', 'Dieter Dengler') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Marshall Bell', 'RescueDawn', 'Admiral') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Robin Williams', 'The Birdcage', 'Armand Goldman') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Nathan Lane', 'The Birdcage', 'Albert Goldman') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Gene Hackman', 'The Birdcage', 'Sen. Kevin Keeley') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Clint Eastwood', 'Unforgiven', 'Bill Munny') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Gene Hackman', 'Unforgiven', 'Little Bill Daggett') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Richard Harris', 'Unforgiven', 'English Bob') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Ice-T', 'Johnny Mnemonic', 'J-Bone') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Dina Meyer', 'Johnny Mnemonic', 'Jane') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Keanu Reeves', 'Johnny Mnemonic', 'Johnny Mnemonic') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Takeshi Kitano', 'Johnny Mnemonic', 'Takahashi') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Tom Hanks', 'Cloud Atlas', 'Zachry|Dr. Henry Goose|Isaac Sachs|Dermot Hoggins') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Jim Broadbent', 'Cloud Atlas', 'Vyvyan Ayrs|Captain Molyneux|Timothy Cavendish') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Halle Berry', 'Cloud Atlas', 'Luisa Rey|Jocasta Ayrs|Ovid|Meronym') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Hugo Weaving', 'Cloud Atlas', 'Bill Smoke|Haskell Moore|Tadeusz Kesselring|Nurse Noakes|Boardman Mephi|Old Georgie') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Tom Hanks', 'The Da Vinci Code', 'Dr. Robert Langdon') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Ian McKellen', 'The Da Vinci Code', 'Sir Leight Teabing') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Audrey Tautou', 'The Da Vinci Code', 'Sophie Neveu') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Paul Bettany', 'The Da Vinci Code', 'Silas') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('John Hurt', 'V for Vendetta', 'High Chancellor Adam Sutler') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Stephen Rea', 'V for Vendetta', 'Eric Finch') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Natalie Portman', 'V for Vendetta', 'Evey Hammond') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Hugo Weaving', 'V for Vendetta', 'V') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('', 'V for Vendetta', 'Dascomb') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Emile Hirsch', 'Speed Racer', 'Speed Racer') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Rain', 'Speed Racer', 'Taejo Togokahn') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Christina Ricci', 'Speed Racer', 'Trixie') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('', 'Speed Racer', 'Cass Jones') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Susan Sarandon', 'Speed Racer', 'Mom') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('John Goodman', 'Speed Racer', 'Pops') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Matthew Fox', 'Speed Racer', 'Racer X') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Rain', 'Ninja Assassin', 'Raizo') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('', 'Ninja Assassin', 'Ryan Maslow') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Rick Yune', 'Ninja Assassin', 'Takeshi') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Naomie Harris', 'Ninja Assassin', 'Mika Coretti') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Sam Rockwell', 'The Green Mile', '"Wild Bill" Wharton') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Bonnie Hunt', 'The Green Mile', 'Jan Edgecomb') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Patricia Clarkson', 'The Green Mile', 'Melinda Moores') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('James Cromwell', 'The Green Mile', 'Warden Hal Moores') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Tom Hanks', 'The Green Mile', 'Paul Edgecomb') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Michael Clarke Duncan', 'The Green Mile', 'John Coffey') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('David Morse', 'The Green Mile', 'Brutus "Brutal" Howell') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Gary Sinise', 'The Green Mile', 'Burt Hammersmith') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Sam Rockwell', 'Frost/Nixon', 'James Reston, Jr.') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Michael Sheen', 'Frost/Nixon', 'David Frost') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Frank Langella', 'Frost/Nixon', 'Richard Nixon') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Oliver Platt', 'Frost/Nixon', 'Bob Zelnick') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Kevin Bacon', 'Frost/Nixon', 'Jack Brennan') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('John C. Reilly', 'Hoffa', 'Peter "Pete" Connelly') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Danny DeVito', 'Hoffa', 'Robert "Bobby" Ciaro') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('J.T. Walsh', 'Hoffa', 'Frank Fitzsimmons') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Jack Nicholson', 'Hoffa', 'Hoffa') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Tom Hanks', 'Apollo 13', 'Jim Lovell') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Ed Harris', 'Apollo 13', 'Gene Kranz') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Gary Sinise', 'Apollo 13', 'Ken Mattingly') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Kevin Bacon', 'Apollo 13', 'Jack Swigert') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Bill Paxton', 'Apollo 13', 'Fred Haise') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Helen Hunt', 'Twister', 'Dr. Jo Harding') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Bill Paxton', 'Twister', 'Bill Harding') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Philip Seymour Hoffman', 'Twister', 'Dustin "Dusty" Davis') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Zach Grenier', 'Twister', 'Eddie') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Helen Hunt', 'Cast Away', 'Kelly Frears') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Tom Hanks', 'Cast Away', 'Chuck Noland') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Danny DeVito', 'One Flew Over the Cuckoo''s Nest', 'Martini') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Jack Nicholson', 'One Flew Over the Cuckoo''s Nest', 'Randle McMurphy') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Keanu Reeves', 'Something''s Gotta Give', 'Julian Mercer') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Diane Keaton', 'Something''s Gotta Give', 'Erica Barry') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Jack Nicholson', 'Something''s Gotta Give', 'Harry Sanborn') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Robin Williams', 'Bicentennial Man', 'Andrew Marin') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Oliver Platt', 'Bicentennial Man', 'Rupert Burns') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Julia Roberts', 'Charlie Wilson''s War', 'Joanne Herring') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Tom Hanks', 'Charlie Wilson''s War', 'Rep. Charlie Wilson') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Philip Seymour Hoffman', 'Charlie Wilson''s War', 'Gust Avrakotos') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Tom Hanks', 'The Polar Express', 'Hero Boy|Father|Conductor|Hobo|Scrooge|Santa Claus') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Tom Hanks', 'A League of Their Own', 'Jimmy Dugan') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Madonna', 'A League of Their Own', '"All the Way" Mae Mordabito') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Rosie O''Donnell', 'A League of Their Own', 'Doris Murphy') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Geena Davis', 'A League of Their Own', 'Dottie Hinson') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Bill Paxton', 'A League of Their Own', 'Bob Hinson') +INSERT INTO ActedIn (_vertexId, _sink, Roles) + VALUES ('Lori Petty', 'A League of Their Own', 'Kit Keller') +DROP TABLE IF EXISTS dbo.Produced +CREATE TABLE dbo.Produced +( + _vertexId varchar(100) + , _sink varchar(100) + , CONSTRAINT PK_PRODUCED + PRIMARY KEY CLUSTERED (_vertexId, _sink) + WITH (IGNORE_DUP_KEY = OFF) +) +INSERT INTO Produced (_vertexId, _sink) + VALUES ('Joel Silver', 'The Matrix') +INSERT INTO Produced (_vertexId, _sink) + VALUES ('Joel Silver', 'The Matrix Reloaded') +INSERT INTO Produced (_vertexId, _sink) + VALUES ('Joel Silver', 'The Matrix Revolutions') +INSERT INTO Produced (_vertexId, _sink) + VALUES ('Cameron Crowe', 'Jerry Maguire') +INSERT INTO Produced (_vertexId, _sink) + VALUES ('Nora Ephron', 'When Harry Met Sally') +INSERT INTO Produced (_vertexId, _sink) + VALUES ('Rob Reiner', 'When Harry Met Sally') +INSERT INTO Produced (_vertexId, _sink) + VALUES ('Stefan Arndt', 'Cloud Atlas') +INSERT INTO Produced (_vertexId, _sink) + VALUES ('Lana Wachowski', 'V for Vendetta') +INSERT INTO Produced (_vertexId, _sink) + VALUES ('Lilly Wachowski', 'V for Vendetta') +INSERT INTO Produced (_vertexId, _sink) + VALUES ('Joel Silver', 'V for Vendetta') +INSERT INTO Produced (_vertexId, _sink) + VALUES ('Joel Silver', 'Speed Racer') +INSERT INTO Produced (_vertexId, _sink) + VALUES ('Lana Wachowski', 'Ninja Assassin') +INSERT INTO Produced (_vertexId, _sink) + VALUES ('Joel Silver', 'Ninja Assassin') +INSERT INTO Produced (_vertexId, _sink) + VALUES ('Lilly Wachowski', 'Ninja Assassin') +INSERT INTO Produced (_vertexId, _sink) + VALUES ('Nancy Meyers', 'Something''s Gotta Give') +DROP TABLE IF EXISTS dbo.Directed +CREATE TABLE dbo.Directed +( + _vertexId varchar(100) + , _sink varchar(100) + , CONSTRAINT PK_DIRECTED + PRIMARY KEY CLUSTERED (_vertexId, _sink) + WITH (IGNORE_DUP_KEY = OFF) +) +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Lana Wachowski', 'The Matrix') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Lilly Wachowski', 'The Matrix') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Lana Wachowski', 'The Matrix Reloaded') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Lilly Wachowski', 'The Matrix Reloaded') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Lana Wachowski', 'The Matrix Revolutions') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Lilly Wachowski', 'The Matrix Revolutions') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Taylor Hackford', 'The Devil''s Advocate') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Rob Reiner', 'A Few Good Men') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Tony Scott', 'Top Gun') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Cameron Crowe', 'Jerry Maguire') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Rob Reiner', 'Stand By Me') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('James L. Brooks', 'As Good as It Gets') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Vincent Ward', 'What Dreams May Come') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Scott Hicks', 'Snow Falling on Cedars') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Nora Ephron', 'You''ve Got Mail') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Nora Ephron', 'Sleepless in Seattle') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('John Patrick Stanley', 'Joe Versus the Volcano') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Rob Reiner', 'When Harry Met Sally') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Tom Hanks', 'That Thing You Do') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Howard Deutch', 'The Replacements') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Werner Herzog', 'RescueDawn') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Mike Nichols', 'The Birdcage') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Clint Eastwood', 'Unforgiven') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Robert Longo', 'Johnny Mnemonic') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Tom Tykwer', 'Cloud Atlas') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Lana Wachowski', 'Cloud Atlas') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Lilly Wachowski', 'Cloud Atlas') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Ron Howard', 'The Da Vinci Code') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('James Marshall', 'V for Vendetta') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Lana Wachowski', 'Speed Racer') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Lilly Wachowski', 'Speed Racer') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('James Marshall', 'Ninja Assassin') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Frank Darabont', 'The Green Mile') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Ron Howard', 'Frost/Nixon') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Danny DeVito', 'Hoffa') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Ron Howard', 'Apollo 13') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Jan de Bont', 'Twister') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Robert Zemeckis', 'Cast Away') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Milos Forman', 'One Flew Over the Cuckoo''s Nest') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Nancy Meyers', 'Something''s Gotta Give') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Chris Columbus', 'Bicentennial Man') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Mike Nichols', 'Charlie Wilson''s War') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Robert Zemeckis', 'The Polar Express') +INSERT INTO Directed (_vertexId, _sink) + VALUES ('Penny Marshall', 'A League of Their Own') +DROP TABLE IF EXISTS dbo.Wrote +CREATE TABLE dbo.Wrote +( + _vertexId varchar(100) + , _sink varchar(100) + , CONSTRAINT PK_WROTE + PRIMARY KEY CLUSTERED (_vertexId, _sink) + WITH (IGNORE_DUP_KEY = OFF) +) +INSERT INTO Wrote (_vertexId, _sink) + VALUES ('Aaron Sorkin', 'A Few Good Men') +INSERT INTO Wrote (_vertexId, _sink) + VALUES ('Jim Cash', 'Top Gun') +INSERT INTO Wrote (_vertexId, _sink) + VALUES ('Cameron Crowe', 'Jerry Maguire') +INSERT INTO Wrote (_vertexId, _sink) + VALUES ('Nora Ephron', 'When Harry Met Sally') +INSERT INTO Wrote (_vertexId, _sink) + VALUES ('David Mitchell', 'Cloud Atlas') +INSERT INTO Wrote (_vertexId, _sink) + VALUES ('Lana Wachowski', 'V for Vendetta') +INSERT INTO Wrote (_vertexId, _sink) + VALUES ('Lilly Wachowski', 'V for Vendetta') +INSERT INTO Wrote (_vertexId, _sink) + VALUES ('Lana Wachowski', 'Speed Racer') +INSERT INTO Wrote (_vertexId, _sink) + VALUES ('Lilly Wachowski', 'Speed Racer') +INSERT INTO Wrote (_vertexId, _sink) + VALUES ('Nancy Meyers', 'Something''s Gotta Give') +DROP TABLE IF EXISTS dbo.Reviewed +CREATE TABLE dbo.Reviewed +( + _vertexId varchar(100) + , _sink varchar(100) + , Summary varchar(MAX) + , Rating int + , CONSTRAINT PK_REVIEWED + PRIMARY KEY CLUSTERED (_vertexId, _sink) + WITH (IGNORE_DUP_KEY = OFF) +) +INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating) + VALUES ('Jessica Thompson', 'Jerry Maguire', 'You had me at Jerry', 92) +INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating) + VALUES ('James Thompson', 'The Replacements', 'The coolest football movie ever', 100) +INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating) + VALUES ('Angela Scope', 'The Replacements', 'Pretty funny at times', 62) +INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating) + VALUES ('Jessica Thompson', 'The Replacements', 'Silly, but fun', 65) +INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating) + VALUES ('Jessica Thompson', 'The Birdcage', 'Slapstick redeemed only by the Robin Williams and Gene Hackman''s stellar performances', 45) +INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating) + VALUES ('Jessica Thompson', 'Unforgiven', 'Dark, but compelling', 85) +INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating) + VALUES ('Jessica Thompson', 'Cloud Atlas', 'An amazing journey', 95) +INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating) + VALUES ('Jessica Thompson', 'The Da Vinci Code', 'A solid romp', 68) +INSERT INTO Reviewed (_vertexId, _sink, Summary, Rating) + VALUES ('James Thompson', 'The Da Vinci Code', 'Fun, but a little far fetched', 65) +DROP TABLE IF EXISTS dbo.Follows +CREATE TABLE dbo.Follows +( + _vertexId varchar(100) + , _sink varchar(100) + , CONSTRAINT PK_FOLLOWS + PRIMARY KEY CLUSTERED (_vertexId, _sink) + WITH (IGNORE_DUP_KEY = OFF) +) +INSERT INTO Follows (_vertexId, _sink) + VALUES ('Paul Blythe', 'Angela Scope') +INSERT INTO Follows (_vertexId, _sink) + VALUES ('Angela Scope', 'Jessica Thompson') +INSERT INTO Follows (_vertexId, _sink) + VALUES ('James Thompson', 'Jessica Thompson') diff --git a/tests/SQLRenderer.Test/TestData/MovieGraph.json b/tests/SQLRenderer.Test/TestData/MovieGraph.json new file mode 100644 index 0000000..d5ae7c8 --- /dev/null +++ b/tests/SQLRenderer.Test/TestData/MovieGraph.json @@ -0,0 +1,202 @@ +{ + "Nodes": [ + { + "Id": "Person", + "Name": "Person", + "IdProperty": { + "PropertyName": "id", + "PropertyType": "System.String" + }, + "Properties": [ + { + "PropertyName": "Name", + "PropertyType": "System.String" + }, + { + "PropertyName": "Born", + "PropertyType": "System.Nullable`1[System.Int32]" + } + ] + }, + { + "Id": "Movie", + "Name": "Movie", + "IdProperty": { + "PropertyName": "id", + "PropertyType": "System.String" + }, + "Properties": [ + { + "PropertyName": "Title", + "PropertyType": "System.String" + }, + { + "PropertyName": "Tagline", + "PropertyType": "System.String" + }, + { + "PropertyName": "Released", + "PropertyType": "System.Int32" + } + ] + } + ], + "Edges": [ + { + "Id": "Person@ACTED_IN@Movie", + "Name": "ACTED_IN", + "FromNode": "Person", + "ToNode": "Movie", + "SourceIdProperty": { + "PropertyName": "_vertexId", + "PropertyType": "System.String" + }, + "SinkIdProperty": { + "PropertyName": "_sink", + "PropertyType": "System.String" + }, + "Properties": [ + { + "PropertyName": "Roles", + "PropertyType": "System.String" + } + ] + }, + { + "Id": "Person@REVIEWED@Movie", + "Name": "REVIEWED", + "FromNode": "Person", + "ToNode": "Movie", + "SourceIdProperty": { + "PropertyName": "_vertexId", + "PropertyType": "System.String" + }, + "SinkIdProperty": { + "PropertyName": "_sink", + "PropertyType": "System.String" + }, + "Properties": [ + { + "PropertyName": "Summary", + "PropertyType": "System.String" + }, + { + "PropertyName": "Rating", + "PropertyType": "System.Int32" + } + ] + }, + { + "Id": "Person@DIRECTED@Movie", + "Name": "DIRECTED", + "FromNode": "Person", + "ToNode": "Movie", + "SourceIdProperty": { + "PropertyName": "_vertexId", + "PropertyType": "System.String" + }, + "SinkIdProperty": { + "PropertyName": "_sink", + "PropertyType": "System.String" + }, + "Properties": [] + }, + { + "Id": "Person@PRODUCED@Movie", + "Name": "PRODUCED", + "FromNode": "Person", + "ToNode": "Movie", + "SourceIdProperty": { + "PropertyName": "_vertexId", + "PropertyType": "System.String" + }, + "SinkIdProperty": { + "PropertyName": "_sink", + "PropertyType": "System.String" + }, + "Properties": [] + }, + { + "Id": "Person@WROTE@Movie", + "Name": "WROTE", + "FromNode": "Person", + "ToNode": "Movie", + "SourceIdProperty": { + "PropertyName": "_vertexId", + "PropertyType": "System.String" + }, + "SinkIdProperty": { + "PropertyName": "_sink", + "PropertyType": "System.String" + }, + "Properties": [] + }, + { + "Id": "Person@FOLLOWS@Person", + "Name": "FOLLOWS", + "FromNode": "Person", + "ToNode": "Person", + "SourceIdProperty": { + "PropertyName": "_vertexId", + "PropertyType": "System.String" + }, + "SinkIdProperty": { + "PropertyName": "_sink", + "PropertyType": "System.String" + }, + "Properties": [] + } + ], + "TableDescriptors": [ + { + "EntityId": "Person", + "Properties": [ + "Name", + "Born" + ], + "TableOrViewName": "[dbo].[Person]" + }, + { + "EntityId": "Movie", + "Properties": [ + "Title", + "Tagline", + "Released" + ], + "TableOrViewName": "[dbo].[Movie]" + }, + { + "EntityId": "Person@ACTED_IN@Movie", + "Properties": [], + "TableOrViewName": "[dbo].[ActedIn]" + }, + { + "EntityId": "Person@REVIEWED@Movie", + "Properties": [ + "Summary", + "Rating" + ], + "TableOrViewName": "[dbo].[Reviewed]" + }, + { + "EntityId": "Person@DIRECTED@Movie", + "Properties": [], + "TableOrViewName": "[dbo].[Directed]" + }, + { + "EntityId": "Person@PRODUCED@Movie", + "Properties": [], + "TableOrViewName": "[dbo].[Produced]" + }, + { + "EntityId": "Person@WROTE@Movie", + "Properties": [], + "TableOrViewName": "[dbo].[Wrote]" + }, + { + "EntityId": "Person@FOLLOWS@Person", + "Properties": [], + "TableOrViewName": "[dbo].[Follows]" + } + ] +} \ No newline at end of file diff --git a/tests/SQLRenderer.Test/TestData/MovieGraphNeo4jQuery.txt b/tests/SQLRenderer.Test/TestData/MovieGraphNeo4jQuery.txt new file mode 100644 index 0000000..3384b21 --- /dev/null +++ b/tests/SQLRenderer.Test/TestData/MovieGraphNeo4jQuery.txt @@ -0,0 +1,509 @@ +CREATE (TheMatrix:Movie {id:'The Matrix', Title:'The Matrix', Released:1999, Tagline:'Welcome to the Real World'}) +CREATE (Keanu:Person {id:'Keanu Reeves', Name:'Keanu Reeves', Born:1964}) +CREATE (Carrie:Person {id:'Carrie-Anne Moss', Name:'Carrie-Anne Moss', Born:1967}) +CREATE (Laurence:Person {id:'Laurence Fishburne', Name:'Laurence Fishburne', Born:1961}) +CREATE (Hugo:Person {id:'Hugo Weaving', Name:'Hugo Weaving', Born:1960}) +CREATE (LillyW:Person {id:'Lilly Wachowski', Name:'Lilly Wachowski', Born:1967}) +CREATE (LanaW:Person {id:'Lana Wachowski', Name:'Lana Wachowski', Born:1965}) +CREATE (JoelS:Person {id:'Joel Silver', Name:'Joel Silver', Born:1952}) +CREATE + (Keanu)-[:ACTED_IN {Roles:['Neo']}]->(TheMatrix), + (Carrie)-[:ACTED_IN {Roles:['Trinity']}]->(TheMatrix), + (Laurence)-[:ACTED_IN {Roles:['Morpheus']}]->(TheMatrix), + (Hugo)-[:ACTED_IN {Roles:['Agent Smith']}]->(TheMatrix), + (LillyW)-[:DIRECTED]->(TheMatrix), + (LanaW)-[:DIRECTED]->(TheMatrix), + (JoelS)-[:PRODUCED]->(TheMatrix) + +CREATE (Emil:Person {id:"Emil Eifrem", Name:"Emil Eifrem", Born:1978}) +CREATE (Emil)-[:ACTED_IN {Roles:["Emil"]}]->(TheMatrix) + +CREATE (TheMatrixReloaded:Movie {id:'The Matrix Reloaded', Title:'The Matrix Reloaded', Released:2003, Tagline:'Free your mind'}) +CREATE + (Keanu)-[:ACTED_IN {Roles:['Neo']}]->(TheMatrixReloaded), + (Carrie)-[:ACTED_IN {Roles:['Trinity']}]->(TheMatrixReloaded), + (Laurence)-[:ACTED_IN {Roles:['Morpheus']}]->(TheMatrixReloaded), + (Hugo)-[:ACTED_IN {Roles:['Agent Smith']}]->(TheMatrixReloaded), + (LillyW)-[:DIRECTED]->(TheMatrixReloaded), + (LanaW)-[:DIRECTED]->(TheMatrixReloaded), + (JoelS)-[:PRODUCED]->(TheMatrixReloaded) + +CREATE (TheMatrixRevolutions:Movie {id:'The Matrix Revolutions', Title:'The Matrix Revolutions', Released:2003, Tagline:'Everything that has a beginning has an end'}) +CREATE + (Keanu)-[:ACTED_IN {Roles:['Neo']}]->(TheMatrixRevolutions), + (Carrie)-[:ACTED_IN {Roles:['Trinity']}]->(TheMatrixRevolutions), + (Laurence)-[:ACTED_IN {Roles:['Morpheus']}]->(TheMatrixRevolutions), + (Hugo)-[:ACTED_IN {Roles:['Agent Smith']}]->(TheMatrixRevolutions), + (LillyW)-[:DIRECTED]->(TheMatrixRevolutions), + (LanaW)-[:DIRECTED]->(TheMatrixRevolutions), + (JoelS)-[:PRODUCED]->(TheMatrixRevolutions) + +CREATE (TheDevilsAdvocate:Movie {id:"The Devil's Advocate", Title:"The Devil's Advocate", Released:1997, Tagline:'Evil has its winning ways'}) +CREATE (Charlize:Person {id:'Charlize Theron', Name:'Charlize Theron', Born:1975}) +CREATE (Al:Person {id:'Al Pacino', Name:'Al Pacino', Born:1940}) +CREATE (Taylor:Person {id:'Taylor Hackford', Name:'Taylor Hackford', Born:1944}) +CREATE + (Keanu)-[:ACTED_IN {Roles:['Kevin Lomax']}]->(TheDevilsAdvocate), + (Charlize)-[:ACTED_IN {Roles:['Mary Ann Lomax']}]->(TheDevilsAdvocate), + (Al)-[:ACTED_IN {Roles:['John Milton']}]->(TheDevilsAdvocate), + (Taylor)-[:DIRECTED]->(TheDevilsAdvocate) + +CREATE (AFewGoodMen:Movie {id:"A Few Good Men", Title:"A Few Good Men", Released:1992, Tagline:"In the heart of the nation's capital, in a courthouse of the U.S. government, one man will stop at nothing to keep his honor, and one will stop at nothing to find the truth."}) +CREATE (TomC:Person {id:'Tom Cruise', Name:'Tom Cruise', Born:1962}) +CREATE (JackN:Person {id:'Jack Nicholson', Name:'Jack Nicholson', Born:1937}) +CREATE (DemiM:Person {id:'Demi Moore', Name:'Demi Moore', Born:1962}) +CREATE (KevinB:Person {id:'Kevin Bacon', Name:'Kevin Bacon', Born:1958}) +CREATE (KieferS:Person {id:'Kiefer Sutherland', Name:'Kiefer Sutherland', Born:1966}) +CREATE (NoahW:Person {id:'Noah Wyle', Name:'Noah Wyle', Born:1971}) +CREATE (CubaG:Person {id:'Cuba Gooding Jr.', Name:'Cuba Gooding Jr.', Born:1968}) +CREATE (KevinP:Person {id:'Kevin Pollak', Name:'Kevin Pollak', Born:1957}) +CREATE (JTW:Person {id:'J.T. Walsh', Name:'J.T. Walsh', Born:1943}) +CREATE (JamesM:Person {id:'James Marshall', Name:'James Marshall', Born:1967}) +CREATE (ChristopherG:Person {id:'Christopher Guest', Name:'Christopher Guest', Born:1948}) +CREATE (RobR:Person {id:'Rob Reiner', Name:'Rob Reiner', Born:1947}) +CREATE (AaronS:Person {id:'Aaron Sorkin', Name:'Aaron Sorkin', Born:1961}) +CREATE + (TomC)-[:ACTED_IN {Roles:['Lt. Daniel Kaffee']}]->(AFewGoodMen), + (JackN)-[:ACTED_IN {Roles:['Col. Nathan R. Jessup']}]->(AFewGoodMen), + (DemiM)-[:ACTED_IN {Roles:['Lt. Cdr. JoAnne Galloway']}]->(AFewGoodMen), + (KevinB)-[:ACTED_IN {Roles:['Capt. Jack Ross']}]->(AFewGoodMen), + (KieferS)-[:ACTED_IN {Roles:['Lt. Jonathan Kendrick']}]->(AFewGoodMen), + (NoahW)-[:ACTED_IN {Roles:['Cpl. Jeffrey Barnes']}]->(AFewGoodMen), + (CubaG)-[:ACTED_IN {Roles:['Cpl. Carl Hammaker']}]->(AFewGoodMen), + (KevinP)-[:ACTED_IN {Roles:['Lt. Sam Weinberg']}]->(AFewGoodMen), + (JTW)-[:ACTED_IN {Roles:['Lt. Col. Matthew Andrew Markinson']}]->(AFewGoodMen), + (JamesM)-[:ACTED_IN {Roles:['Pfc. Louden Downey']}]->(AFewGoodMen), + (ChristopherG)-[:ACTED_IN {Roles:['Dr. Stone']}]->(AFewGoodMen), + (AaronS)-[:ACTED_IN {Roles:['Man in Bar']}]->(AFewGoodMen), + (RobR)-[:DIRECTED]->(AFewGoodMen), + (AaronS)-[:WROTE]->(AFewGoodMen) + +CREATE (TopGun:Movie {id:"Top Gun", Title:"Top Gun", Released:1986, Tagline:'I feel the need, the need for speed.'}) +CREATE (KellyM:Person {id:'Kelly McGillis', Name:'Kelly McGillis', Born:1957}) +CREATE (ValK:Person {id:'Val Kilmer', Name:'Val Kilmer', Born:1959}) +CREATE (AnthonyE:Person {id:'Anthony Edwards', Name:'Anthony Edwards', Born:1962}) +CREATE (TomS:Person {id:'Tom Skerritt', Name:'Tom Skerritt', Born:1933}) +CREATE (MegR:Person {id:'Meg Ryan', Name:'Meg Ryan', Born:1961}) +CREATE (TonyS:Person {id:'Tony Scott', Name:'Tony Scott', Born:1944}) +CREATE (JimC:Person {id:'Jim Cash', Name:'Jim Cash', Born:1941}) +CREATE + (TomC)-[:ACTED_IN {Roles:['Maverick']}]->(TopGun), + (KellyM)-[:ACTED_IN {Roles:['Charlie']}]->(TopGun), + (ValK)-[:ACTED_IN {Roles:['Iceman']}]->(TopGun), + (AnthonyE)-[:ACTED_IN {Roles:['Goose']}]->(TopGun), + (TomS)-[:ACTED_IN {Roles:['Viper']}]->(TopGun), + (MegR)-[:ACTED_IN {Roles:['Carole']}]->(TopGun), + (TonyS)-[:DIRECTED]->(TopGun), + (JimC)-[:WROTE]->(TopGun) + +CREATE (JerryMaguire:Movie {id:'Jerry Maguire', Title:'Jerry Maguire', Released:2000, Tagline:'The rest of his life begins now.'}) +CREATE (ReneeZ:Person {id:'Renee Zellweger', Name:'Renee Zellweger', Born:1969}) +CREATE (KellyP:Person {id:'Kelly Preston', Name:'Kelly Preston', Born:1962}) +CREATE (JerryO:Person {id:"Jerry O'Connell", Name:"Jerry O'Connell", Born:1974}) +CREATE (JayM:Person {id:'Jay Mohr', Name:'Jay Mohr', Born:1970}) +CREATE (BonnieH:Person {id:'Bonnie Hunt', Name:'Bonnie Hunt', Born:1961}) +CREATE (ReginaK:Person {id:'Regina King', Name:'Regina King', Born:1971}) +CREATE (JonathanL:Person {id:'Jonathan Lipnicki', Name:'Jonathan Lipnicki', Born:1996}) +CREATE (CameronC:Person {id:'Cameron Crowe', Name:'Cameron Crowe', Born:1957}) +CREATE + (TomC)-[:ACTED_IN {Roles:['Jerry Maguire']}]->(JerryMaguire), + (CubaG)-[:ACTED_IN {Roles:['Rod Tidwell']}]->(JerryMaguire), + (ReneeZ)-[:ACTED_IN {Roles:['Dorothy Boyd']}]->(JerryMaguire), + (KellyP)-[:ACTED_IN {Roles:['Avery Bishop']}]->(JerryMaguire), + (JerryO)-[:ACTED_IN {Roles:['Frank Cushman']}]->(JerryMaguire), + (JayM)-[:ACTED_IN {Roles:['Bob Sugar']}]->(JerryMaguire), + (BonnieH)-[:ACTED_IN {Roles:['Laurel Boyd']}]->(JerryMaguire), + (ReginaK)-[:ACTED_IN {Roles:['Marcee Tidwell']}]->(JerryMaguire), + (JonathanL)-[:ACTED_IN {Roles:['Ray Boyd']}]->(JerryMaguire), + (CameronC)-[:DIRECTED]->(JerryMaguire), + (CameronC)-[:PRODUCED]->(JerryMaguire), + (CameronC)-[:WROTE]->(JerryMaguire) + +CREATE (StandByMe:Movie {id:"Stand By Me", Title:"Stand By Me", Released:1986, Tagline:"For some, it's the last real taste of innocence, and the first real taste of life. But for everyone, it's the time that memories are made of."}) +CREATE (RiverP:Person {id:'River Phoenix', Name:'River Phoenix', Born:1970}) +CREATE (CoreyF:Person {id:'Corey Feldman', Name:'Corey Feldman', Born:1971}) +CREATE (WilW:Person {id:'Wil Wheaton', Name:'Wil Wheaton', Born:1972}) +CREATE (JohnC:Person {id:'John Cusack', Name:'John Cusack', Born:1966}) +CREATE (MarshallB:Person {id:'Marshall Bell', Name:'Marshall Bell', Born:1942}) +CREATE + (WilW)-[:ACTED_IN {Roles:['Gordie Lachance']}]->(StandByMe), + (RiverP)-[:ACTED_IN {Roles:['Chris Chambers']}]->(StandByMe), + (JerryO)-[:ACTED_IN {Roles:['Vern Tessio']}]->(StandByMe), + (CoreyF)-[:ACTED_IN {Roles:['Teddy Duchamp']}]->(StandByMe), + (JohnC)-[:ACTED_IN {Roles:['Denny Lachance']}]->(StandByMe), + (KieferS)-[:ACTED_IN {Roles:['Ace Merrill']}]->(StandByMe), + (MarshallB)-[:ACTED_IN {Roles:['Mr. Lachance']}]->(StandByMe), + (RobR)-[:DIRECTED]->(StandByMe) + +CREATE (AsGoodAsItGets:Movie {id:'As Good as It Gets', Title:'As Good as It Gets', Released:1997, Tagline:'A comedy from the heart that goes for the throat.'}) +CREATE (HelenH:Person {id:'Helen Hunt', Name:'Helen Hunt', Born:1963}) +CREATE (GregK:Person {id:'Greg Kinnear', Name:'Greg Kinnear', Born:1963}) +CREATE (JamesB:Person {id:'James L. Brooks', Name:'James L. Brooks', Born:1940}) +CREATE + (JackN)-[:ACTED_IN {Roles:['Melvin Udall']}]->(AsGoodAsItGets), + (HelenH)-[:ACTED_IN {Roles:['Carol Connelly']}]->(AsGoodAsItGets), + (GregK)-[:ACTED_IN {Roles:['Simon Bishop']}]->(AsGoodAsItGets), + (CubaG)-[:ACTED_IN {Roles:['Frank Sachs']}]->(AsGoodAsItGets), + (JamesB)-[:DIRECTED]->(AsGoodAsItGets) + +CREATE (WhatDreamsMayCome:Movie {id:'What Dreams May Come', Title:'What Dreams May Come', Released:1998, Tagline:'After life there is more. The end is just the beginning.'}) +CREATE (AnnabellaS:Person {id:'Annabella Sciorra', Name:'Annabella Sciorra', Born:1960}) +CREATE (MaxS:Person {id:'Max von Sydow', Name:'Max von Sydow', Born:1929}) +CREATE (WernerH:Person {id:'Werner Herzog', Name:'Werner Herzog', Born:1942}) +CREATE (Robin:Person {id:'Robin Williams', Name:'Robin Williams', Born:1951}) +CREATE (VincentW:Person {id:'Vincent Ward', Name:'Vincent Ward', Born:1956}) +CREATE + (Robin)-[:ACTED_IN {Roles:['Chris Nielsen']}]->(WhatDreamsMayCome), + (CubaG)-[:ACTED_IN {Roles:['Albert Lewis']}]->(WhatDreamsMayCome), + (AnnabellaS)-[:ACTED_IN {Roles:['Annie Collins-Nielsen']}]->(WhatDreamsMayCome), + (MaxS)-[:ACTED_IN {Roles:['The Tracker']}]->(WhatDreamsMayCome), + (WernerH)-[:ACTED_IN {Roles:['The Face']}]->(WhatDreamsMayCome), + (VincentW)-[:DIRECTED]->(WhatDreamsMayCome) + +CREATE (SnowFallingonCedars:Movie {id:'Snow Falling on Cedars', Title:'Snow Falling on Cedars', Released:1999, Tagline:'First loves last. Forever.'}) +CREATE (EthanH:Person {id:'Ethan Hawke', Name:'Ethan Hawke', Born:1970}) +CREATE (RickY:Person {id:'Rick Yune', Name:'Rick Yune', Born:1971}) +CREATE (JamesC:Person {id:'James Cromwell', Name:'James Cromwell', Born:1940}) +CREATE (ScottH:Person {id:'Scott Hicks', Name:'Scott Hicks', Born:1953}) +CREATE + (EthanH)-[:ACTED_IN {Roles:['Ishmael Chambers']}]->(SnowFallingonCedars), + (RickY)-[:ACTED_IN {Roles:['Kazuo Miyamoto']}]->(SnowFallingonCedars), + (MaxS)-[:ACTED_IN {Roles:['Nels Gudmundsson']}]->(SnowFallingonCedars), + (JamesC)-[:ACTED_IN {Roles:['Judge Fielding']}]->(SnowFallingonCedars), + (ScottH)-[:DIRECTED]->(SnowFallingonCedars) + +CREATE (YouveGotMail:Movie {id:"You've Got Mail", Title:"You've Got Mail", Released:1998, Tagline:'At odds in life... in love on-line.'}) +CREATE (ParkerP:Person {id:'Parker Posey', Name:'Parker Posey', Born:1968}) +CREATE (DaveC:Person {id:'Dave Chappelle', Name:'Dave Chappelle', Born:1973}) +CREATE (SteveZ:Person {id:'Steve Zahn', Name:'Steve Zahn', Born:1967}) +CREATE (TomH:Person {id:'Tom Hanks', Name:'Tom Hanks', Born:1956}) +CREATE (NoraE:Person {id:'Nora Ephron', Name:'Nora Ephron', Born:1941}) +CREATE + (TomH)-[:ACTED_IN {Roles:['Joe Fox']}]->(YouveGotMail), + (MegR)-[:ACTED_IN {Roles:['Kathleen Kelly']}]->(YouveGotMail), + (GregK)-[:ACTED_IN {Roles:['Frank Navasky']}]->(YouveGotMail), + (ParkerP)-[:ACTED_IN {Roles:['Patricia Eden']}]->(YouveGotMail), + (DaveC)-[:ACTED_IN {Roles:['Kevin Jackson']}]->(YouveGotMail), + (SteveZ)-[:ACTED_IN {Roles:['George Pappas']}]->(YouveGotMail), + (NoraE)-[:DIRECTED]->(YouveGotMail) + +CREATE (SleeplessInSeattle:Movie {id:'Sleepless in Seattle', Title:'Sleepless in Seattle', Released:1993, Tagline:'What if someone you never met, someone you never saw, someone you never knew was the only someone for you?'}) +CREATE (RitaW:Person {id:'Rita Wilson', Name:'Rita Wilson', Born:1956}) +CREATE (BillPull:Person {id:'Bill Pullman', Name:'Bill Pullman', Born:1953}) +CREATE (VictorG:Person {id:'Victor Garber', Name:'Victor Garber', Born:1949}) +CREATE (RosieO:Person {id:"Rosie O'Donnell", Name:"Rosie O'Donnell", Born:1962}) +CREATE + (TomH)-[:ACTED_IN {Roles:['Sam Baldwin']}]->(SleeplessInSeattle), + (MegR)-[:ACTED_IN {Roles:['Annie Reed']}]->(SleeplessInSeattle), + (RitaW)-[:ACTED_IN {Roles:['Suzy']}]->(SleeplessInSeattle), + (BillPull)-[:ACTED_IN {Roles:['Walter']}]->(SleeplessInSeattle), + (VictorG)-[:ACTED_IN {Roles:['Greg']}]->(SleeplessInSeattle), + (RosieO)-[:ACTED_IN {Roles:['Becky']}]->(SleeplessInSeattle), + (NoraE)-[:DIRECTED]->(SleeplessInSeattle) + +CREATE (JoeVersustheVolcano:Movie {id:'Joe Versus the Volcano', Title:'Joe Versus the Volcano', Released:1990, Tagline:'A story of love, lava and burning desire.'}) +CREATE (JohnS:Person {id:'John Patrick Stanley', Name:'John Patrick Stanley', Born:1950}) +CREATE (Nathan:Person {id:'Nathan Lane', Name:'Nathan Lane', Born:1956}) +CREATE + (TomH)-[:ACTED_IN {Roles:['Joe Banks']}]->(JoeVersustheVolcano), + (MegR)-[:ACTED_IN {Roles:['DeDe', 'Angelica Graynamore', 'Patricia Graynamore']}]->(JoeVersustheVolcano), + (Nathan)-[:ACTED_IN {Roles:['Baw']}]->(JoeVersustheVolcano), + (JohnS)-[:DIRECTED]->(JoeVersustheVolcano) + +CREATE (WhenHarryMetSally:Movie {id:'When Harry Met Sally', Title:'When Harry Met Sally', Released:1998, Tagline:'At odds in life... in love on-line.'}) +CREATE (BillyC:Person {id:'Billy Crystal', Name:'Billy Crystal', Born:1948}) +CREATE (CarrieF:Person {id:'Carrie Fisher', Name:'Carrie Fisher', Born:1956}) +CREATE (BrunoK:Person {id:'Bruno Kirby', Name:'Bruno Kirby', Born:1949}) +CREATE + (BillyC)-[:ACTED_IN {Roles:['Harry Burns']}]->(WhenHarryMetSally), + (MegR)-[:ACTED_IN {Roles:['Sally Albright']}]->(WhenHarryMetSally), + (CarrieF)-[:ACTED_IN {Roles:['Marie']}]->(WhenHarryMetSally), + (BrunoK)-[:ACTED_IN {Roles:['Jess']}]->(WhenHarryMetSally), + (RobR)-[:DIRECTED]->(WhenHarryMetSally), + (RobR)-[:PRODUCED]->(WhenHarryMetSally), + (NoraE)-[:PRODUCED]->(WhenHarryMetSally), + (NoraE)-[:WROTE]->(WhenHarryMetSally) + +CREATE (ThatThingYouDo:Movie {id:'That Thing You Do', Title:'That Thing You Do', Released:1996, Tagline:'In every life there comes a time when that thing you dream becomes that thing you do'}) +CREATE (LivT:Person {id:'Liv Tyler', Name:'Liv Tyler', Born:1977}) +CREATE + (TomH)-[:ACTED_IN {Roles:['Mr. White']}]->(ThatThingYouDo), + (LivT)-[:ACTED_IN {Roles:['Faye Dolan']}]->(ThatThingYouDo), + (Charlize)-[:ACTED_IN {Roles:['Tina']}]->(ThatThingYouDo), + (TomH)-[:DIRECTED]->(ThatThingYouDo) + +CREATE (TheReplacements:Movie {id:'The Replacements', Title:'The Replacements', Released:2000, Tagline:'Pain heals, Chicks dig scars... Glory lasts forever'}) +CREATE (Brooke:Person {id:'Brooke Langton', Name:'Brooke Langton', Born:1970}) +CREATE (Gene:Person {id:'Gene Hackman', Name:'Gene Hackman', Born:1930}) +CREATE (Orlando:Person {id:'Orlando Jones', Name:'Orlando Jones', Born:1968}) +CREATE (Howard:Person {id:'Howard Deutch', Name:'Howard Deutch', Born:1950}) +CREATE + (Keanu)-[:ACTED_IN {Roles:['Shane Falco']}]->(TheReplacements), + (Brooke)-[:ACTED_IN {Roles:['Annabelle Farrell']}]->(TheReplacements), + (Gene)-[:ACTED_IN {Roles:['Jimmy McGinty']}]->(TheReplacements), + (Orlando)-[:ACTED_IN {Roles:['Clifford Franklin']}]->(TheReplacements), + (Howard)-[:DIRECTED]->(TheReplacements) + +CREATE (RescueDawn:Movie {id:'RescueDawn', Title:'RescueDawn', Released:2006, Tagline:"Based on the extraordinary true story of one man's fight for freedom"}) +CREATE (ChristianB:Person {id:'Christian Bale', Name:'Christian Bale', Born:1974}) +CREATE (ZachG:Person {id:'Zach Grenier', Name:'Zach Grenier', Born:1954}) +CREATE + (MarshallB)-[:ACTED_IN {Roles:['Admiral']}]->(RescueDawn), + (ChristianB)-[:ACTED_IN {Roles:['Dieter Dengler']}]->(RescueDawn), + (ZachG)-[:ACTED_IN {Roles:['Squad Leader']}]->(RescueDawn), + (SteveZ)-[:ACTED_IN {Roles:['Duane']}]->(RescueDawn), + (WernerH)-[:DIRECTED]->(RescueDawn) + +CREATE (TheBirdcage:Movie {id:'The Birdcage', Title:'The Birdcage', Released:1996, Tagline:'Come as you are'}) +CREATE (MikeN:Person {id:'Mike Nichols', Name:'Mike Nichols', Born:1931}) +CREATE + (Robin)-[:ACTED_IN {Roles:['Armand Goldman']}]->(TheBirdcage), + (Nathan)-[:ACTED_IN {Roles:['Albert Goldman']}]->(TheBirdcage), + (Gene)-[:ACTED_IN {Roles:['Sen. Kevin Keeley']}]->(TheBirdcage), + (MikeN)-[:DIRECTED]->(TheBirdcage) + +CREATE (Unforgiven:Movie {id:'Unforgiven', Title:'Unforgiven', Released:1992, Tagline:"It's a hell of a thing, killing a man"}) +CREATE (RichardH:Person {id:'Richard Harris', Name:'Richard Harris', Born:1930}) +CREATE (ClintE:Person {id:'Clint Eastwood', Name:'Clint Eastwood', Born:1930}) +CREATE + (RichardH)-[:ACTED_IN {Roles:['English Bob']}]->(Unforgiven), + (ClintE)-[:ACTED_IN {Roles:['Bill Munny']}]->(Unforgiven), + (Gene)-[:ACTED_IN {Roles:['Little Bill Daggett']}]->(Unforgiven), + (ClintE)-[:DIRECTED]->(Unforgiven) + +CREATE (JohnnyMnemonic:Movie {id:'Johnny Mnemonic', Title:'Johnny Mnemonic', Released:1995, Tagline:'The hottest data on earth. In the coolest head in town'}) +CREATE (Takeshi:Person {id:'Takeshi Kitano', Name:'Takeshi Kitano', Born:1947}) +CREATE (Dina:Person {id:'Dina Meyer', Name:'Dina Meyer', Born:1968}) +CREATE (IceT:Person {id:'Ice-T', Name:'Ice-T', Born:1958}) +CREATE (RobertL:Person {id:'Robert Longo', Name:'Robert Longo', Born:1953}) +CREATE + (Keanu)-[:ACTED_IN {Roles:['Johnny Mnemonic']}]->(JohnnyMnemonic), + (Takeshi)-[:ACTED_IN {Roles:['Takahashi']}]->(JohnnyMnemonic), + (Dina)-[:ACTED_IN {Roles:['Jane']}]->(JohnnyMnemonic), + (IceT)-[:ACTED_IN {Roles:['J-Bone']}]->(JohnnyMnemonic), + (RobertL)-[:DIRECTED]->(JohnnyMnemonic) + +CREATE (CloudAtlas:Movie {id:'Cloud Atlas', Title:'Cloud Atlas', Released:2012, Tagline:'Everything is connected'}) +CREATE (HalleB:Person {id:'Halle Berry', Name:'Halle Berry', Born:1966}) +CREATE (JimB:Person {id:'Jim Broadbent', Name:'Jim Broadbent', Born:1949}) +CREATE (TomT:Person {id:'Tom Tykwer', Name:'Tom Tykwer', Born:1965}) +CREATE (DavidMitchell:Person {id:'David Mitchell', Name:'David Mitchell', Born:1969}) +CREATE (StefanArndt:Person {id:'Stefan Arndt', Name:'Stefan Arndt', Born:1961}) +CREATE + (TomH)-[:ACTED_IN {Roles:['Zachry', 'Dr. Henry Goose', 'Isaac Sachs', 'Dermot Hoggins']}]->(CloudAtlas), + (Hugo)-[:ACTED_IN {Roles:['Bill Smoke', 'Haskell Moore', 'Tadeusz Kesselring', 'Nurse Noakes', 'Boardman Mephi', 'Old Georgie']}]->(CloudAtlas), + (HalleB)-[:ACTED_IN {Roles:['Luisa Rey', 'Jocasta Ayrs', 'Ovid', 'Meronym']}]->(CloudAtlas), + (JimB)-[:ACTED_IN {Roles:['Vyvyan Ayrs', 'Captain Molyneux', 'Timothy Cavendish']}]->(CloudAtlas), + (TomT)-[:DIRECTED]->(CloudAtlas), + (LillyW)-[:DIRECTED]->(CloudAtlas), + (LanaW)-[:DIRECTED]->(CloudAtlas), + (DavidMitchell)-[:WROTE]->(CloudAtlas), + (StefanArndt)-[:PRODUCED]->(CloudAtlas) + +CREATE (TheDaVinciCode:Movie {id:'The Da Vinci Code', Title:'The Da Vinci Code', Released:2006, Tagline:'Break The Codes'}) +CREATE (IanM:Person {id:'Ian McKellen', Name:'Ian McKellen', Born:1939}) +CREATE (AudreyT:Person {id:'Audrey Tautou', Name:'Audrey Tautou', Born:1976}) +CREATE (PaulB:Person {id:'Paul Bettany', Name:'Paul Bettany', Born:1971}) +CREATE (RonH:Person {id:'Ron Howard', Name:'Ron Howard', Born:1954}) +CREATE + (TomH)-[:ACTED_IN {Roles:['Dr. Robert Langdon']}]->(TheDaVinciCode), + (IanM)-[:ACTED_IN {Roles:['Sir Leight Teabing']}]->(TheDaVinciCode), + (AudreyT)-[:ACTED_IN {Roles:['Sophie Neveu']}]->(TheDaVinciCode), + (PaulB)-[:ACTED_IN {Roles:['Silas']}]->(TheDaVinciCode), + (RonH)-[:DIRECTED]->(TheDaVinciCode) + +CREATE (VforVendetta:Movie {id:'V for Vendetta', Title:'V for Vendetta', Released:2006, Tagline:'Freedom! Forever!'}) +CREATE (NatalieP:Person {id:'Natalie Portman', Name:'Natalie Portman', Born:1981}) +CREATE (StephenR:Person {id:'Stephen Rea', Name:'Stephen Rea', Born:1946}) +CREATE (JohnH:Person {id:'John Hurt', Name:'John Hurt', Born:1940}) +CREATE (BenM:Person {Name: 'Ben Miles', Born:1967}) +CREATE + (Hugo)-[:ACTED_IN {Roles:['V']}]->(VforVendetta), + (NatalieP)-[:ACTED_IN {Roles:['Evey Hammond']}]->(VforVendetta), + (StephenR)-[:ACTED_IN {Roles:['Eric Finch']}]->(VforVendetta), + (JohnH)-[:ACTED_IN {Roles:['High Chancellor Adam Sutler']}]->(VforVendetta), + (BenM)-[:ACTED_IN {Roles:['Dascomb']}]->(VforVendetta), + (JamesM)-[:DIRECTED]->(VforVendetta), + (LillyW)-[:PRODUCED]->(VforVendetta), + (LanaW)-[:PRODUCED]->(VforVendetta), + (JoelS)-[:PRODUCED]->(VforVendetta), + (LillyW)-[:WROTE]->(VforVendetta), + (LanaW)-[:WROTE]->(VforVendetta) + +CREATE (SpeedRacer:Movie {id:'Speed Racer', Title:'Speed Racer', Released:2008, Tagline:'Speed has no limits'}) +CREATE (EmileH:Person {id:'Emile Hirsch', Name:'Emile Hirsch', Born:1985}) +CREATE (JohnG:Person {id:'John Goodman', Name:'John Goodman', Born:1960}) +CREATE (SusanS:Person {id:'Susan Sarandon', Name:'Susan Sarandon', Born:1946}) +CREATE (MatthewF:Person {id:'Matthew Fox', Name:'Matthew Fox', Born:1966}) +CREATE (ChristinaR:Person {id:'Christina Ricci', Name:'Christina Ricci', Born:1980}) +CREATE (Rain:Person {id:'Rain', Name:'Rain', Born:1982}) +CREATE + (EmileH)-[:ACTED_IN {Roles:['Speed Racer']}]->(SpeedRacer), + (JohnG)-[:ACTED_IN {Roles:['Pops']}]->(SpeedRacer), + (SusanS)-[:ACTED_IN {Roles:['Mom']}]->(SpeedRacer), + (MatthewF)-[:ACTED_IN {Roles:['Racer X']}]->(SpeedRacer), + (ChristinaR)-[:ACTED_IN {Roles:['Trixie']}]->(SpeedRacer), + (Rain)-[:ACTED_IN {Roles:['Taejo Togokahn']}]->(SpeedRacer), + (BenM)-[:ACTED_IN {Roles:['Cass Jones']}]->(SpeedRacer), + (LillyW)-[:DIRECTED]->(SpeedRacer), + (LanaW)-[:DIRECTED]->(SpeedRacer), + (LillyW)-[:WROTE]->(SpeedRacer), + (LanaW)-[:WROTE]->(SpeedRacer), + (JoelS)-[:PRODUCED]->(SpeedRacer) + +CREATE (NinjaAssassin:Movie {id:'Ninja Assassin', Title:'Ninja Assassin', Released:2009, Tagline:'Prepare to enter a secret world of assassins'}) +CREATE (NaomieH:Person {id:'Naomie Harris', Name:'Naomie Harris'}) +CREATE + (Rain)-[:ACTED_IN {Roles:['Raizo']}]->(NinjaAssassin), + (NaomieH)-[:ACTED_IN {Roles:['Mika Coretti']}]->(NinjaAssassin), + (RickY)-[:ACTED_IN {Roles:['Takeshi']}]->(NinjaAssassin), + (BenM)-[:ACTED_IN {Roles:['Ryan Maslow']}]->(NinjaAssassin), + (JamesM)-[:DIRECTED]->(NinjaAssassin), + (LillyW)-[:PRODUCED]->(NinjaAssassin), + (LanaW)-[:PRODUCED]->(NinjaAssassin), + (JoelS)-[:PRODUCED]->(NinjaAssassin) + +CREATE (TheGreenMile:Movie {id:'The Green Mile', Title:'The Green Mile', Released:1999, Tagline:"Walk a mile you'll never forget."}) +CREATE (MichaelD:Person {id:'Michael Clarke Duncan', Name:'Michael Clarke Duncan', Born:1957}) +CREATE (DavidM:Person {id:'David Morse', Name:'David Morse', Born:1953}) +CREATE (SamR:Person {id:'Sam Rockwell', Name:'Sam Rockwell', Born:1968}) +CREATE (GaryS:Person {id:'Gary Sinise', Name:'Gary Sinise', Born:1955}) +CREATE (PatriciaC:Person {id:'Patricia Clarkson', Name:'Patricia Clarkson', Born:1959}) +CREATE (FrankD:Person {id:'Frank Darabont', Name:'Frank Darabont', Born:1959}) +CREATE + (TomH)-[:ACTED_IN {Roles:['Paul Edgecomb']}]->(TheGreenMile), + (MichaelD)-[:ACTED_IN {Roles:['John Coffey']}]->(TheGreenMile), + (DavidM)-[:ACTED_IN {Roles:['Brutus "Brutal" Howell']}]->(TheGreenMile), + (BonnieH)-[:ACTED_IN {Roles:['Jan Edgecomb']}]->(TheGreenMile), + (JamesC)-[:ACTED_IN {Roles:['Warden Hal Moores']}]->(TheGreenMile), + (SamR)-[:ACTED_IN {Roles:['"Wild Bill" Wharton']}]->(TheGreenMile), + (GaryS)-[:ACTED_IN {Roles:['Burt Hammersmith']}]->(TheGreenMile), + (PatriciaC)-[:ACTED_IN {Roles:['Melinda Moores']}]->(TheGreenMile), + (FrankD)-[:DIRECTED]->(TheGreenMile) + +CREATE (FrostNixon:Movie {id:'Frost/Nixon', Title:'Frost/Nixon', Released:2008, Tagline:'400 million people were waiting for the truth.'}) +CREATE (FrankL:Person {id:'Frank Langella', Name:'Frank Langella', Born:1938}) +CREATE (MichaelS:Person {id:'Michael Sheen', Name:'Michael Sheen', Born:1969}) +CREATE (OliverP:Person {id:'Oliver Platt', Name:'Oliver Platt', Born:1960}) +CREATE + (FrankL)-[:ACTED_IN {Roles:['Richard Nixon']}]->(FrostNixon), + (MichaelS)-[:ACTED_IN {Roles:['David Frost']}]->(FrostNixon), + (KevinB)-[:ACTED_IN {Roles:['Jack Brennan']}]->(FrostNixon), + (OliverP)-[:ACTED_IN {Roles:['Bob Zelnick']}]->(FrostNixon), + (SamR)-[:ACTED_IN {Roles:['James Reston, Jr.']}]->(FrostNixon), + (RonH)-[:DIRECTED]->(FrostNixon) + +CREATE (Hoffa:Movie {id:'Hoffa', Title:'Hoffa', Released:1992, Tagline:"He didn't want law. He wanted justice."}) +CREATE (DannyD:Person {id:'Danny DeVito', Name:'Danny DeVito', Born:1944}) +CREATE (JohnR:Person {id:'John C. Reilly', Name:'John C. Reilly', Born:1965}) +CREATE + (JackN)-[:ACTED_IN {Roles:['Hoffa']}]->(Hoffa), + (DannyD)-[:ACTED_IN {Roles:['Robert "Bobby" Ciaro']}]->(Hoffa), + (JTW)-[:ACTED_IN {Roles:['Frank Fitzsimmons']}]->(Hoffa), + (JohnR)-[:ACTED_IN {Roles:['Peter "Pete" Connelly']}]->(Hoffa), + (DannyD)-[:DIRECTED]->(Hoffa) + +CREATE (Apollo13:Movie {id:'Apollo 13', Title:'Apollo 13', Released:1995, Tagline:'Houston, we have a problem.'}) +CREATE (EdH:Person {id:'Ed Harris', Name:'Ed Harris', Born:1950}) +CREATE (BillPax:Person {id:'Bill Paxton', Name:'Bill Paxton', Born:1955}) +CREATE + (TomH)-[:ACTED_IN {Roles:['Jim Lovell']}]->(Apollo13), + (KevinB)-[:ACTED_IN {Roles:['Jack Swigert']}]->(Apollo13), + (EdH)-[:ACTED_IN {Roles:['Gene Kranz']}]->(Apollo13), + (BillPax)-[:ACTED_IN {Roles:['Fred Haise']}]->(Apollo13), + (GaryS)-[:ACTED_IN {Roles:['Ken Mattingly']}]->(Apollo13), + (RonH)-[:DIRECTED]->(Apollo13) + +CREATE (Twister:Movie {id:'Twister', Title:'Twister', Released:1996, Tagline:"Don't Breathe. Don't Look Back."}) +CREATE (PhilipH:Person {id:'Philip Seymour Hoffman', Name:'Philip Seymour Hoffman', Born:1967}) +CREATE (JanB:Person {id:'Jan de Bont', Name:'Jan de Bont', Born:1943}) +CREATE + (BillPax)-[:ACTED_IN {Roles:['Bill Harding']}]->(Twister), + (HelenH)-[:ACTED_IN {Roles:['Dr. Jo Harding']}]->(Twister), + (ZachG)-[:ACTED_IN {Roles:['Eddie']}]->(Twister), + (PhilipH)-[:ACTED_IN {Roles:['Dustin "Dusty" Davis']}]->(Twister), + (JanB)-[:DIRECTED]->(Twister) + +CREATE (CastAway:Movie {id:'Cast Away', Title:'Cast Away', Released:2000, Tagline:'At the edge of the world, his journey begins.'}) +CREATE (RobertZ:Person {id:'Robert Zemeckis', Name:'Robert Zemeckis', Born:1951}) +CREATE + (TomH)-[:ACTED_IN {Roles:['Chuck Noland']}]->(CastAway), + (HelenH)-[:ACTED_IN {Roles:['Kelly Frears']}]->(CastAway), + (RobertZ)-[:DIRECTED]->(CastAway) + +CREATE (OneFlewOvertheCuckoosNest:Movie {id:"One Flew Over the Cuckoo's Nest", Title:"One Flew Over the Cuckoo's Nest", Released:1975, Tagline:"If he's crazy, what does that make you?"}) +CREATE (MilosF:Person {id:'Milos Forman', Name:'Milos Forman', Born:1932}) +CREATE + (JackN)-[:ACTED_IN {Roles:['Randle McMurphy']}]->(OneFlewOvertheCuckoosNest), + (DannyD)-[:ACTED_IN {Roles:['Martini']}]->(OneFlewOvertheCuckoosNest), + (MilosF)-[:DIRECTED]->(OneFlewOvertheCuckoosNest) + +CREATE (SomethingsGottaGive:Movie {id:"Something's Gotta Give", Title:"Something's Gotta Give", Released:2003}) +CREATE (DianeK:Person {id:'Diane Keaton', Name:'Diane Keaton', Born:1946}) +CREATE (NancyM:Person {id:'Nancy Meyers', Name:'Nancy Meyers', Born:1949}) +CREATE + (JackN)-[:ACTED_IN {Roles:['Harry Sanborn']}]->(SomethingsGottaGive), + (DianeK)-[:ACTED_IN {Roles:['Erica Barry']}]->(SomethingsGottaGive), + (Keanu)-[:ACTED_IN {Roles:['Julian Mercer']}]->(SomethingsGottaGive), + (NancyM)-[:DIRECTED]->(SomethingsGottaGive), + (NancyM)-[:PRODUCED]->(SomethingsGottaGive), + (NancyM)-[:WROTE]->(SomethingsGottaGive) + +CREATE (BicentennialMan:Movie {id:'Bicentennial Man', Title:'Bicentennial Man', Released:1999, Tagline:"One robot's 200 year journey to become an ordinary man."}) +CREATE (ChrisC:Person {id:'Chris Columbus', Name:'Chris Columbus', Born:1958}) +CREATE + (Robin)-[:ACTED_IN {Roles:['Andrew Marin']}]->(BicentennialMan), + (OliverP)-[:ACTED_IN {Roles:['Rupert Burns']}]->(BicentennialMan), + (ChrisC)-[:DIRECTED]->(BicentennialMan) + +CREATE (CharlieWilsonsWar:Movie {id:"Charlie Wilson's War", Title:"Charlie Wilson's War", Released:2007, Tagline:"A stiff drink. A little mascara. A lot of nerve. Who said they couldn't bring down the Soviet empire."}) +CREATE (JuliaR:Person {id:'Julia Roberts', Name:'Julia Roberts', Born:1967}) +CREATE + (TomH)-[:ACTED_IN {Roles:['Rep. Charlie Wilson']}]->(CharlieWilsonsWar), + (JuliaR)-[:ACTED_IN {Roles:['Joanne Herring']}]->(CharlieWilsonsWar), + (PhilipH)-[:ACTED_IN {Roles:['Gust Avrakotos']}]->(CharlieWilsonsWar), + (MikeN)-[:DIRECTED]->(CharlieWilsonsWar) + +CREATE (ThePolarExpress:Movie {id:'The Polar Express', Title:'The Polar Express', Released:2004, Tagline:'This Holiday Season… Believe'}) +CREATE + (TomH)-[:ACTED_IN {Roles:['Hero Boy', 'Father', 'Conductor', 'Hobo', 'Scrooge', 'Santa Claus']}]->(ThePolarExpress), + (RobertZ)-[:DIRECTED]->(ThePolarExpress) + +CREATE (ALeagueofTheirOwn:Movie {id:'A League of Their Own', Title:'A League of Their Own', Released:1992, Tagline:'Once in a lifetime you get a chance to do something different.'}) +CREATE (Madonna:Person {id:'Madonna', Name:'Madonna', Born:1954}) +CREATE (GeenaD:Person {id:'Geena Davis', Name:'Geena Davis', Born:1956}) +CREATE (LoriP:Person {id:'Lori Petty', Name:'Lori Petty', Born:1963}) +CREATE (PennyM:Person {id:'Penny Marshall', Name:'Penny Marshall', Born:1943}) +CREATE + (TomH)-[:ACTED_IN {Roles:['Jimmy Dugan']}]->(ALeagueofTheirOwn), + (GeenaD)-[:ACTED_IN {Roles:['Dottie Hinson']}]->(ALeagueofTheirOwn), + (LoriP)-[:ACTED_IN {Roles:['Kit Keller']}]->(ALeagueofTheirOwn), + (RosieO)-[:ACTED_IN {Roles:['Doris Murphy']}]->(ALeagueofTheirOwn), + (Madonna)-[:ACTED_IN {Roles:['"All the Way" Mae Mordabito']}]->(ALeagueofTheirOwn), + (BillPax)-[:ACTED_IN {Roles:['Bob Hinson']}]->(ALeagueofTheirOwn), + (PennyM)-[:DIRECTED]->(ALeagueofTheirOwn) + +CREATE (PaulBlythe:Person {id:'Paul Blythe', Name:'Paul Blythe'}) +CREATE (AngelaScope:Person {id:'Angela Scope', Name:'Angela Scope'}) +CREATE (JessicaThompson:Person {id:'Jessica Thompson', Name:'Jessica Thompson'}) +CREATE (JamesThompson:Person {id:'James Thompson', Name:'James Thompson'}) + +CREATE + (JamesThompson)-[:FOLLOWS]->(JessicaThompson), + (AngelaScope)-[:FOLLOWS]->(JessicaThompson), + (PaulBlythe)-[:FOLLOWS]->(AngelaScope) + +CREATE + (JessicaThompson)-[:REVIEWED {Summary:'An amazing journey', Rating:95}]->(CloudAtlas), + (JessicaThompson)-[:REVIEWED {Summary:'Silly, but fun', Rating:65}]->(TheReplacements), + (JamesThompson)-[:REVIEWED {Summary:'The coolest football movie ever', Rating:100}]->(TheReplacements), + (AngelaScope)-[:REVIEWED {Summary:'Pretty funny at times', Rating:62}]->(TheReplacements), + (JessicaThompson)-[:REVIEWED {Summary:'Dark, but compelling', Rating:85}]->(Unforgiven), + (JessicaThompson)-[:REVIEWED {Summary:"Slapstick redeemed only by the Robin Williams and Gene Hackman's stellar performances", Rating:45}]->(TheBirdcage), + (JessicaThompson)-[:REVIEWED {Summary:'A solid romp', Rating:68}]->(TheDaVinciCode), + (JamesThompson)-[:REVIEWED {Summary:'Fun, but a little far fetched', Rating:65}]->(TheDaVinciCode), + (JessicaThompson)-[:REVIEWED {Summary:'You had me at Jerry', Rating:92}]->(JerryMaguire) + +WITH TomH as a +MATCH (a)-[:ACTED_IN]->(m)<-[:DIRECTED]-(d) RETURN a,m,d LIMIT 10 +; diff --git a/tests/SQLRenderer.Test/TestData/acted_in.jq.txt b/tests/SQLRenderer.Test/TestData/acted_in.jq.txt new file mode 100644 index 0000000..9e95f8c --- /dev/null +++ b/tests/SQLRenderer.Test/TestData/acted_in.jq.txt @@ -0,0 +1 @@ +.results[0] | { cols: .columns, rows: [.data[].row | {a: .[0], b: .[1], c: .[2] | join("|")} ] } | {cols: .cols, rows: [.rows[] | [.a, .b, .c]]} | .cols, .rows[] | @csv \ No newline at end of file diff --git a/tests/SQLRenderer.Test/appsettings.json b/tests/SQLRenderer.Test/appsettings.json new file mode 100644 index 0000000..c101de5 --- /dev/null +++ b/tests/SQLRenderer.Test/appsettings.json @@ -0,0 +1,12 @@ +{ + "appSettings": { + "createLocalDockerImages": true, + "neo4jHost": "localhost", + "neo4jPort": 10087, + "neo4jUser": "neo4j", + "neo4jPassword": "test", + "sqlHost": "localhost", + "sqlPort": 10033, + "sqlPassword": "AVeryStrong!123TestPassword" + } +} \ No newline at end of file diff --git a/tests/openCypherParser.Test/OpenCypherParserTest.cs b/tests/openCypherParser.Test/OpenCypherParserTest.cs new file mode 100644 index 0000000..54a61e6 --- /dev/null +++ b/tests/openCypherParser.Test/OpenCypherParserTest.cs @@ -0,0 +1,271 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +using System.Diagnostics; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using openCypherTranspiler.Common.Logging; +using openCypherTranspiler.openCypherParser.Common; +using openCypherTranspiler.openCypherParser.AST; +using openCypherTranspiler.CommonTest; +using openCypherTranspiler.Common.Exceptions; + +namespace openCypherTranspiler.openCypherParser.Test +{ + + /// + /// Tests for OpenCypherParser (openCypher ANTLR4 Parser + AST builder) + /// + [TestClass] + public class OpenCypherParserTest + { + private readonly ILoggable _logger = new TestLogger(); + + private QueryTreeNode RunQueryAndDumpTree(string cypherQueryText) + { + var queryNode = OpenCypherParser.Parse(cypherQueryText, _logger); + var tree = queryNode.DumpTree(); + Debug.WriteLine(tree); + return queryNode; + } + + [TestMethod] + public void BasicParsingTest() + { + var tree = RunQueryAndDumpTree(@" +MATCH (person:Person)-[r:KNOWS]->(friend:Person) +WITH toFloat(r.score + r.score_delta) AS score2, friend.Name, person.level AS number +WHERE friend.Name='bnitta' OR (person.number >= 1 AND person.number <= 10) +RETURN sum(score2), avg(score2+1) AS scoreShift1 +" + ); + // TODO: structural verifications + Assert.IsNotNull(tree); + } + + [TestMethod] + public void BasicExpressionParsingTest() + { + var tree = RunQueryAndDumpTree(@" +MATCH (p:Person)-[:ACTED_IN]->(m:Movie) +WHERE (p.Name = 'Meg Ryan' OR p.Name = 'Tom Hanks') AND m.Title = 'Apollo 13' +RETURN m.Title AS Title, p.Name AS Name +" + ); + + var expressionParsed = tree.GetChildrenOfType(); + Assert.IsNotNull(tree.GetChildrenOfType().Count() == 2); + Assert.IsNotNull(tree.GetChildrenOfType().Any(expr => expr.StringValue == "Meg Ryan")); + Assert.IsNotNull(tree.GetChildrenOfType().Any(expr => expr.StringValue == "Tom Hanks")); + Assert.IsNotNull(tree.GetChildrenOfType().Any(expr => expr.StringValue == "Apollo 13")); + } + + [TestMethod] + public void MatchPatternAdvancedTest() + { + { + // multiple matches + var tree = RunQueryAndDumpTree(@" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +MATCH (p)-[d:DIRECTED]->(m) +MATCH (p)-[a]->(m2:Movie) +RETURN p.Name, m.Title +" + ); + // TODO: structural verifications + Assert.IsNotNull(tree); + } + + { + // piped queries + var tree = RunQueryAndDumpTree(@" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WITH p, m +MATCH (p)-[d:DIRECTED]->(m) +RETURN p.Name, m.Title +" + ); + // TODO: structural verifications + Assert.IsNotNull(tree); + } + + { + // optional match + var tree = RunQueryAndDumpTree(@" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +OPTIONAL MATCH (p)-[d:DIRECTED]->(m) +RETURN p.Name, m.Title +" + ); + // TODO: structural verifications + Assert.IsNotNull(tree); + } + + { + // match followed by local where + var tree = RunQueryAndDumpTree(@" +match (p:Person) +where p.Name = 'Tom Hanks' +optional match (p)-[:ACTED_IN]-(m:Movie) +with p, m +where p.Name = 'Tom Hanks' +return p.Name, m.Title +" + ); + // TODO: structural verifications + Assert.IsNotNull(tree); + } + + { + // optional match case 2: the second subquery is optional + var tree = RunQueryAndDumpTree(@" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WITH p, m +OPTIONAL MATCH (p)-[d:DIRECTED]->(m) +RETURN p.Name, m.Title +" + ); + // TODO: structural verifications + Assert.IsNotNull(tree); + } + + } + + [TestMethod] + public void OperatorTest() + { + var tree = RunQueryAndDumpTree(@" +MATCH (p:Person) +WHERE p.Name in ['Tom Hanks', 'Meg Ryan'] +RETURN p.Name as Name +" + ); + + Assert.IsNotNull(tree); + var expressionParsed = tree.GetChildrenOfType(); + Assert.IsTrue(expressionParsed.Any(expr => expr.Operator.Name == BinaryOperator.IN)); + Assert.IsTrue(tree.GetChildrenOfType().Any(expr => expr.ExpressionList.Count == 2)); + } + + [TestMethod] + public void StringFunctionTest() + { + var tree = RunQueryAndDumpTree(@" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WHERE p.Name STARTS WITH 'Tom' AND (m.Title CONTAINS '13' OR m.Title ENDS WITH 'Mail') +RETURN toUpper(p.Name) as NameCapital, toLower(m.Title) as TitleLC +" + ); + + Assert.IsNotNull(tree); + Assert.IsTrue(tree.GetChildrenOfType().Count() == 5); + Assert.IsTrue(tree.GetChildrenOfType().Any(expr => expr.Function.FunctionName == Function.StringContains)); + Assert.IsTrue(tree.GetChildrenOfType().Any(expr => expr.Function.FunctionName == Function.StringStartsWith)); + Assert.IsTrue(tree.GetChildrenOfType().Any(expr => expr.Function.FunctionName == Function.StringEndsWith)); + Assert.IsTrue(tree.GetChildrenOfType().Any(expr => expr.Function.FunctionName == Function.StringToUpper)); + Assert.IsTrue(tree.GetChildrenOfType().Any(expr => expr.Function.FunctionName == Function.StringToLower)); + } + + [TestMethod] + public void OtherWeirdSyntaxTest() + { + { + // reuse the same alias in piped query. the second alias is a new alias + // in below case, m in first match is not the m in second match due to WITH in between + // the query will return all folks who acted in any movie and directed any movie as well, but + // not necessarily the same movie + var tree = RunQueryAndDumpTree(@" +MATCH (p:Person)-[a:ACTED_IN]->(m:Movie) +WITH p, m.Title as ActedMovieTitle +MATCH (p)-[d:DIRECTED]->(m:Movie) +RETURN p.Name, m.Title AS DirectedMovieTitle, ActedMovieTitle +" + ); + // TODO: structural verifications + Assert.IsNotNull(tree); + } + } + + [TestMethod] + public void NegativeTest() + { + { + // duplicate returned names + var expectedExceptionThrown = false; + try + { + var tree = RunQueryAndDumpTree(@" +MATCH (p:Person) +RETURN p.Name, p.Name +" + ); + } + catch (TranspilerSyntaxErrorException) + { + expectedExceptionThrown = true; + } + Assert.IsTrue(expectedExceptionThrown); + } + + { + //Node/Edge attached with properties. Not supported + var expectedExceptionThrown = false; + try + { + var tree = RunQueryAndDumpTree(@" +MATCH (person:Person {name:'jerrylia'})-[r:KNOWS]->(friend:Person) +WITH toFloat(r.score + r.score_delta) AS score2 +WHERE friend.Name='bnitta' +RETURN sum(score2), avg(score2+1) AS scoreShift1 +" + ); + } + catch (TranspilerNotSupportedException) + { + expectedExceptionThrown = true; + } + Assert.IsTrue(expectedExceptionThrown); + } + + { + // match after optional match + var expectedExceptionThrown = false; + try + { + var tree = RunQueryAndDumpTree(@" +match (p:Person), (m:Movie) +optional match (p)-[:ACTED_IN]->(m) +match (p)-[:ACTED_IN]->(m) +return p.Name, m.Title +" + ); + } + catch (TranspilerSyntaxErrorException e) + { + Assert.IsTrue(e.Message.Contains("MATCH cannot follow OPTIONAL MATCH")); + expectedExceptionThrown = true; + } + Assert.IsTrue(expectedExceptionThrown); + } + } + + + [TestMethod] + public void CaseExpressionParsingTest() + { + var tree = RunQueryAndDumpTree(@" +MATCH (person:Person)-[r:KNOWS]->(friend:Person) +WITH toFloat(r.score + r.score_delta) AS score2, friend.Name, person.level AS number +WHERE friend.Name='bnitta' OR (person.number >= 1 AND person.number <= 10) +RETURN sum(score2), avg(score2+1) AS scoreShift1, + case when friend.Name = 'bnitta' then 1 else 0 end as friendFlag +" + ); + // TODO: structural verifications + Assert.IsNotNull(tree); + } + } +} diff --git a/tests/openCypherParser.Test/openCypherParser.Test.csproj b/tests/openCypherParser.Test/openCypherParser.Test.csproj new file mode 100644 index 0000000..62ef50b --- /dev/null +++ b/tests/openCypherParser.Test/openCypherParser.Test.csproj @@ -0,0 +1,22 @@ + + + + netcoreapp2.1 + + false + + openCypherTranspiler.openCypherParser.Test + + + + + + + + + + + + + +