org.opencypher.v9_0.parser.Clauses.scala Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) Neo4j Sweden AB (http://neo4j.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.opencypher.v9_0.parser
import org.opencypher.v9_0.ast
import org.opencypher.v9_0.ast.Yield
import org.opencypher.v9_0.expressions
import org.parboiled.scala.Parser
import org.parboiled.scala.Rule1
import org.parboiled.scala.Rule4
import org.parboiled.scala.Rule5
import org.parboiled.scala.group
trait Clauses extends Parser
with StartPoints
with Patterns
with Expressions
with Base
with ProcedureCalls
with GraphSelection {
self: Query =>
def Clause: Rule1[ast.Clause]
def LoadCSV: Rule1[ast.LoadCSV] = rule("LOAD CSV") {
keyword("LOAD CSV") ~~
group(keyword("WITH HEADERS") ~ push(true) | push(false)) ~~
keyword("FROM") ~~ Expression ~~
keyword("AS") ~~ Variable ~~
optional(keyword("FIELDTERMINATOR") ~~ StringLiteral) ~~>>
(ast.LoadCSV(_, _, _, _))
}
def ConstructGraph: Rule1[ast.ConstructGraph] = rule("CONSTRUCT") {
group(keyword("CONSTRUCT") ~~ optional(keyword("ON") ~~ oneOrMore(CatalogName, CommaSep)) ~~
zeroOrMore(WS ~ Clone) ~~
zeroOrMore(WS ~ ConstructCreate) ~~
zeroOrMore(WS ~ SetClause) ~~>> { (on, clones, news, sets) =>
ast.ConstructGraph(clones, news, on.getOrElse(List.empty), sets)
})
}
def Clone: Rule1[ast.Clone] = rule("CLONE (construct subclause)") {
group(keyword("CLONE") ~~ oneOrMore(ReturnItem, CommaSep)) ~~>> (ast.Clone(_))
}
def ConstructCreate: Rule1[ast.CreateInConstruct] = rule("NEW (construct subclause)") {
group(keyword("CREATE") ~~ Pattern) ~~>> (ast.CreateInConstruct(_))
}
def CatalogName: Rule1[ast.CatalogName] = rule("catalog name with parts; foo.bar.baz") {
group(SymbolicNameString ~~ zeroOrMore("." ~~ SymbolicNameString) ~~> (ast.CatalogName(_, _)))
}
def Start: Rule1[ast.Start] = rule("START") {
group(
keyword("START") ~~ oneOrMore(StartPoint, separator = CommaSep) ~~ optional(Where)
) ~~>> (ast.Start(_, _))
}
def Match: Rule1[ast.Match] = rule("MATCH") {
group((
keyword("OPTIONAL MATCH") ~ push(true)
| keyword("MATCH") ~ push(false)
) ~~ Pattern ~~ zeroOrMore(Hint, separator = WS) ~~ optional(Where)) ~~>> (ast.Match(_, _, _, _))
}
def Merge: Rule1[ast.Merge] = rule("MERGE") {
group(
group(keyword("MERGE") ~~ PatternPart) ~~>> (p => expressions.Pattern(Seq(p))) ~~ zeroOrMore(MergeAction,
separator = WS)
) ~~>> (ast.Merge(_, _))
}
def Create: Rule1[ast.Create] = rule("CREATE") {
group(keyword("CREATE") ~~ Pattern) ~~>> (ast.Create(_))
}
def CreateUnique: Rule1[ast.CreateUnique] = rule("CREATE UNIQUE") {
group(keyword("CREATE UNIQUE") ~~ Pattern) ~~>> (ast.CreateUnique(_))
}
def SetClause: Rule1[ast.SetClause] = rule("SET") {
group(keyword("SET") ~~ oneOrMore(SetItem, separator = CommaSep)) ~~>> (ast.SetClause(_))
}
def Delete: Rule1[ast.Delete] = rule("DELETE")(
group(keyword("DELETE") ~~ oneOrMore(Expression, separator = CommaSep)) ~~>> (ast.Delete(_, forced = false))
| group(keyword("DETACH DELETE") ~~ oneOrMore(Expression, separator = CommaSep)) ~~>> (ast.Delete(_, forced = true))
)
def Remove: Rule1[ast.Remove] = rule("REMOVE") {
group(keyword("REMOVE") ~~ oneOrMore(RemoveItem, separator = CommaSep)) ~~>> (ast.Remove(_))
}
def Foreach: Rule1[ast.Foreach] = rule("FOREACH") {
group(
keyword("FOREACH") ~~ "(" ~~ Variable ~~ keyword("IN") ~~ Expression ~~ "|" ~~
oneOrMore(Clause, separator = WS) ~~ ")") ~~>> (ast.Foreach(_, _, _))
}
def With: Rule1[ast.With] = rule("WITH")(
group(keyword("WITH DISTINCT") ~~ WithBody ~~ optional(Where)) ~~>> (ast.With(distinct = true, _, _, _, _, _))
| group(keyword("WITH") ~~ WithBody ~~ optional(Where)) ~~>> (ast.With(distinct = false, _, _, _, _, _))
)
def Unwind: Rule1[ast.Unwind] = rule("UNWIND")(
group(keyword("UNWIND") ~~ Expression ~~ keyword("AS") ~~ Variable) ~~>> (ast.Unwind(_, _))
)
def Return: Rule1[ast.Clause] = rule("RETURN")(
group(keyword("RETURN GRAPH")) ~ push(ast.ReturnGraph(None)(_))
| ReturnWithoutGraph
)
def ReturnWithoutGraph: Rule1[ast.Return] = rule("RETURN")(
group(keyword("RETURN DISTINCT") ~~ ReturnBody) ~~>> (ast.Return(distinct = true, _, _, _, _))
| group(keyword("RETURN") ~~ ReturnBody) ~~>> (ast.Return(distinct = false, _, _, _, _))
)
def Where: Rule1[ast.Where] = rule("WHERE") {
group(keyword("WHERE") ~~ Expression) ~~>> (ast.Where(_))
}
def PeriodicCommitHint: Rule1[ast.PeriodicCommitHint] = rule("USING PERIODIC COMMIT")(
group(keyword("USING PERIODIC COMMIT") ~~ optional(SignedIntegerLiteral)) ~~>> (ast.PeriodicCommitHint(_))
)
private def Hint: Rule1[ast.UsingHint] = rule("USING")(
group(keyword("USING INDEX SEEK") ~~ Variable ~~ NodeLabel ~~ "(" ~~ oneOrMore(PropertyKeyName, separator = CommaSep) ~~ ")") ~~>> (ast.UsingIndexHint(_, _, _, ast.SeekOnly))
| group(keyword("USING INDEX") ~~ Variable ~~ NodeLabel ~~ "(" ~~ oneOrMore(PropertyKeyName, separator = CommaSep) ~~ ")") ~~>> (ast.UsingIndexHint(_, _, _, ast.SeekOrScan))
| group(keyword("USING JOIN ON") ~~ oneOrMore(Variable, separator = CommaSep)) ~~>> (ast.UsingJoinHint(_))
| group(keyword("USING SCAN") ~~ Variable ~~ NodeLabel) ~~>> (ast.UsingScanHint(_, _))
)
private def MergeAction = rule("ON")(
group(keyword("ON MATCH") ~~ SetClause) ~~>> (ast.OnMatch(_))
| group(keyword("ON CREATE") ~~ SetClause) ~~>> (ast.OnCreate(_))
)
private def SetItem: Rule1[ast.SetItem] = rule(
PropertyExpression ~~ group(operator("=") ~~ Expression) ~~>> (ast.SetPropertyItem(_, _))
| Variable ~~ group(operator("=") ~~ Expression) ~~>> (ast.SetExactPropertiesFromMapItem(_, _))
| Variable ~~ group(operator("+=") ~~ Expression) ~~>> (ast.SetIncludingPropertiesFromMapItem(_, _))
| group(Variable ~~ NodeLabels) ~~>> (ast.SetLabelItem(_, _))
)
private def RemoveItem: Rule1[ast.RemoveItem] = rule(
group(Variable ~~ NodeLabels) ~~>> (ast.RemoveLabelItem(_, _))
| PropertyExpression ~~> ast.RemovePropertyItem
)
private def WithBody: Rule4[ast.ReturnItems, Option[ast.OrderBy], Option[ast.Skip], Option[ast.Limit]] = {
ReturnItems ~~
optional(Order) ~~
optional(Skip) ~~
optional(Limit)
}
def ReturnBody: Rule4[ast.ReturnItems, Option[ast.OrderBy], Option[ast.Skip], Option[ast.Limit]] = {
ReturnItems ~~
optional(Order) ~~
optional(Skip) ~~
optional(Limit)
}
private def ReturnItems: Rule1[ast.ReturnItems] = rule("'*', an expression")(
"*" ~ zeroOrMore(CommaSep ~ ReturnItem) ~~>> (ast.ReturnItems(includeExisting = true, _))
| oneOrMore(ReturnItem, separator = CommaSep) ~~>> (ast.ReturnItems(includeExisting = false, _))
)
private def ReturnItem: Rule1[ast.ReturnItem] = rule(
group(Expression ~~ keyword("AS") ~~ Variable) ~~>> (ast.AliasedReturnItem(_, _))
| group(Expression ~> (s => s)) ~~>> (ast.UnaliasedReturnItem(_, _))
)
def Yield: Rule1[Yield] = (keyword("YIELD") ~~ YieldBody) ~~>> (ast.Yield(_, _, _, _, _))
def YieldBody: Rule5[ast.ReturnItems, Option[ast.OrderBy], Option[ast.Skip], Option[ast.Limit], Option[ast.Where]] = {
YieldItems ~~
optional(Order) ~~
optional(group(keyword("SKIP") ~~ SignedIntegerLiteral) ~~>> (ast.Skip(_))) ~~
optional(group(keyword("LIMIT") ~~ SignedIntegerLiteral) ~~>> (ast.Limit(_))) ~~
optional(Where)
}
private def YieldItems: Rule1[ast.ReturnItems] = rule("'*', an expression")(
keyword("*") ~~~> ast.ReturnItems(includeExisting = true, List())
| oneOrMore(YieldItem, separator = CommaSep) ~~>> (ast.ReturnItems(includeExisting = false, _))
)
private def YieldItem: Rule1[ast.ReturnItem] = rule(
group(Variable ~~ keyword("AS") ~~ Variable) ~~>> (ast.AliasedReturnItem(_, _))
| group(Variable ~> (s => s)) ~~>> (ast.UnaliasedReturnItem(_, _))
)
def Order: Rule1[ast.OrderBy] = rule("ORDER") {
group(keyword("ORDER BY") ~~ oneOrMore(SortItem, separator = CommaSep)) ~~>> (ast.OrderBy(_))
}
private def SortItem: Rule1[ast.SortItem] = rule(
group(Expression ~~ (keyword("DESCENDING") | keyword("DESC"))) ~~>> (ast.DescSortItem(_))
| group(Expression ~~ optional(keyword("ASCENDING") | keyword("ASC"))) ~~>> (ast.AscSortItem(_))
)
private def Skip: Rule1[ast.Skip] = rule("SKIP") {
group(keyword("SKIP") ~~ Expression) ~~>> (ast.Skip(_))
}
private def Limit: Rule1[ast.Limit] = rule("LIMIT") {
group(keyword("LIMIT") ~~ Expression) ~~>> (ast.Limit(_))
}
def SubQuery: Rule1[ast.SubQuery] = rule("CALL") {
group(keyword("CALL") ~~ group("{" ~~ QueryPart ~~ "}")) ~~>> (part => ast.SubQuery(part))
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy