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

com.codecommit.gll.RegexParsers.scala Maven / Gradle / Ivy

The newest version!
package com.codecommit.gll

import com.codecommit.util._

import scala.util.matching.Regex

trait RegexParsers extends Parsers {
  import SetSyntax._

  protected val whitespace = """\s+"""r
  protected val skipWhitespace = true

  override implicit def literal(str: String): LiteralParser = {
    if (skipWhitespace) {
      new LiteralParser(str) {
        override def computeFirst(seen: Set[Parser[Any]]) = {
          val wsFirst = if (skipWhitespace) RegexUtils.first(whitespace) else Set[Option[Char]]()
          Some((wsFirst - None) ++ (super.computeFirst(seen) getOrElse Set[Option[Char]]()))
        }
      }
    } else super.literal(str)
  }

  implicit def regex(r: Regex): RegexParser =
    new RegexParser(r)

  override implicit def disjunctiveLiterals(left: String): RichRegexParser =
    new RichRegexParser(regex(new Regex(escapeRegex(left))))

  implicit def disjunctiveRegex(left: Regex): RichRegexParser =
    new RichRegexParser(left)

  implicit def funRegexSyntax(p: Regex) = new RichSyntax1(regex(p))

  private def escapeRegex(str: String) = {
    val specialChars = Set('[', ']', '{', '}', '\\', '|', '*', '+', '?', '^', '$', '(', ')')

    augmentString(str).foldLeft("") { (str, c) =>
      if (specialChars contains c)
        str + '\\' + c
      else
        str + c
    }
  }

  override protected def handleWhitespace(s: LineStream) =
    if (skipWhitespace)
      s.drop(whitespace findPrefixOf s map { _.length } getOrElse 0)
    else
      s


  class RichRegexParser(left: RegexParser) extends RichParser(left) {
    def |(right: Regex) = new RegexParser(new Regex("(" + left.regex.toString + ")|(" + right.regex.toString + ")"))

    def |(right: String) = new RegexParser(new Regex("(" + left.regex.toString + ")|(" + escapeRegex(right) + ")"))
  }

  case class RegexParser(val regex: Regex) extends TerminalParser[String] {
    if (regex == null)
      throw new NullPointerException("Cannot parse a null regular expression")

    lazy val constFirst = {
      val wsFirst = if (skipWhitespace) RegexUtils.first(whitespace) else Set[Option[Char]]()
      val regexFirst = RegexUtils.first(regex)

      if (wsFirst.isComplement)
        Some((wsFirst - None) ++ regexFirst)
      else
        Some(regexFirst ++ (wsFirst - None))
    }

    def computeFirst(s: Set[Parser[Any]]) = constFirst

    def parse(in: LineStream) = {
      val res = regex findPrefixOf in map { str => Success(str, in drop str.length) }
      res getOrElse Failure(ExpectedRegex(regex), in)
    }

    override def equals(other: Any) = other match {
      case that: RegexParser => this.regex.toString == that.regex.toString
      case _ => false
    }

    override def hashCode = regex.toString.hashCode

    override def toString = "/%s/".format(regex)
  }
}

object RegexParsers extends RegexParsers




© 2015 - 2024 Weber Informatics LLC | Privacy Policy