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

org.neo4j.cypher.internal.parser.LikePatternParser.scala Maven / Gradle / Ivy

There is a newer version: 4.4.40
Show newest version
/*
 * Copyright (c) "Neo4j"
 * 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.neo4j.cypher.internal.parser

import org.parboiled.scala.ANY
import org.parboiled.scala.EOI
import org.parboiled.scala.Parser
import org.parboiled.scala.ReportingParseRunner
import org.parboiled.scala.Rule1

/**
 * Parser that parses a Like pattern into [[ParsedLikePattern]] which contains tokens of [[LikePatternOp]].
 *
 * A Like pattern can contain the special characters:
 *
 *  - % wildcard
 *  - _ matches exactly one character
 *
 */
case object LikePatternParser extends Parser {

  def apply(input: String): ParsedLikePattern =
    ReportingParseRunner(LikeRule).run(input).result.getOrElse(throw new IllegalArgumentException(s"$input is not valid to use with LIKE")).compact

  /** Base rule */
  def LikeRule: Rule1[ParsedLikePattern] = rule { zeroOrMore(MatchManyRule | MatchSingleRule | MatchTextRule | MatchEscapedCharRule) ~~> ParsedLikePattern ~ EOI }

  def MatchManyRule: Rule1[LikePatternOp] = rule { "%" ~ push(MatchMany) }

  def MatchSingleRule: Rule1[LikePatternOp] = rule { "_" ~ push(MatchSingle) }

  def MatchTextRule: Rule1[LikePatternOp]= oneOrMore(noneOf("%_\\")) ~> MatchText

  def MatchEscapedCharRule: Rule1[LikePatternOp] =  rule { "\\" ~ (ANY ~> MatchText) }
}

/** Contains a sequence of parsed LIKE tokens*/
case class ParsedLikePattern(ops: List[LikePatternOp]) {
 def compact: ParsedLikePattern = {
   val newOps = ops.foldLeft(List.empty[LikePatternOp]) {
     case (MatchText(fst) :: tl, MatchText(snd)) =>
       MatchText(fst ++ snd) :: tl

     case (acc, op) =>
       op :: acc
   }
   ParsedLikePattern(newOps.reverse)
 }
 override def toString = ops.mkString("\"","","\"")
}

sealed trait LikePatternOp

sealed trait WildcardLikePatternOp extends LikePatternOp

/** Contains a string that needs quoting for use in regular expression */
case class MatchText(text: String) extends LikePatternOp  {
  override def toString = text
}

/** Matches a % */
case object MatchMany extends WildcardLikePatternOp {
  override def toString = "%"
}

/** Matches a _*/
case object MatchSingle extends WildcardLikePatternOp {
  override def toString = "_"
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy