regex - 解析 scala 中的 case 语句

标签 regex scala parser-combinators

解析 scala 中的 case 语句

CASE WHEN col1 <> 0 AND col2 <> 0 THEN 'COL1 & COL2 IS NOT ZERO' ELSE 'COL1 & COL2 IS ZERO'

这里的挑战是给出 case 语句可以出现的所有场景,例如它可以出现在函数内部。 case 语句/函数等也可以出现在另一个必须处理的 case 语句中。

最佳答案

这个问题可以用scala解析器组合器来解决

首先定义映射表达式所需的类

sealed trait Exp {
  def asStr: String

  override def toString: String = asStr
}
case class OperationExp(a: Exp, op: String, b: Exp, c: Option[String]) extends Exp { override def asStr = s"$a $op $b ${c.getOrElse("")}" }
case class CaseConditions(conditionValue: List[(String, String)] , elseValue: String, asAlias: Option[Exp]) extends Exp {
  override def asStr = "CASE " + conditionValue.map(c => s"WHEN ${c._1} THEN ${c._2}").mkString(" ") + s" ELSE ${elseValue} END ${asAlias.getOrElse("")}"
}

现在是解决方案

case class OperationExp(a: Exp, op: String, b: Exp, c: Option[String]) extends Exp { override def asStr = s"$a $op $b ${c.getOrElse("")}" }

case class CaseConditions(conditionValue: List[(String, String)] , elseValue: String, asAlias: Option[Exp]) extends Exp {
  override def asStr = "CASE " + conditionValue.map(c => s"WHEN ${c._1} THEN ${c._2}").mkString(" ") + s" ELSE ${elseValue} END ${asAlias.getOrElse("")}"
}
val identifiers: Parser[String]     = "[a-zA-Z0-9_~\\|,'\\-\\+:.()]+".r
      val operatorTokens: Parser[String]  = "[<>=!]+".r | ("IS NOT" | "IN" | "IS")
  val conditionJoiner: Parser[String] = ( "AND" | "OR" )

  val excludeKeywords = List("CASE","WHEN", "THEN", "ELSE", "END")


  val identifierWithoutCaseKw: Parser[Exp] = Parser(input =>
    identifiers(input).filterWithError(
      !excludeKeywords.contains(_),
      reservedWord => s"$reservedWord encountered",
      input
    )
  ) ^^ StrExp

  val anyStrExp: Parser[Exp]     = "[^()]*".r  ^^ StrExp




  val funcIdentifier: Parser[Exp] = name ~ ("(" ~> (caseConditionExpresionParser | funcIdentifier | anyStrExp) <~ ")") ^^ {case func ~ param => FunCallExp(func, Seq(param))}

  val identifierOrFunctions =  funcIdentifier | identifierWithoutCaseKw

  val conditionParser: Parser[String] =
    identifierOrFunctions ~ operatorTokens ~ identifierOrFunctions ~ opt(conditionJoiner) ^^ {
      case a ~ op ~ b ~ c => s"$a $op $b ${c.getOrElse("")}"
    }

  def caseConditionExpresionParser: Parser[CaseConditions]  = "CASE" ~ rep1("WHEN" ~ rep(conditionParser) ~ "THEN" ~ rep(identifierWithoutCaseKw)) ~ "ELSE" ~ rep(identifierWithoutCaseKw) ~ "END" ~ opt("AS" ~> identifierWithoutCaseKw)^^ {
    case "CASE" ~ conditionValuePair ~ "ELSE" ~ falseValue ~ "END" ~ asName =>
      CaseConditions(
        conditionValuePair.map(cv => (
          cv._1._1._2.mkString(" "),
          parsePipes(cv._2.mkString(" ")).isRight match {
            case true => parsePipes(cv._2.mkString(" ")).right.get
            case _    => cv._2.mkString(" ")
          }
        )),
        parsePipes(falseValue.mkString("")).isRight match {
          case true => parsePipes(falseValue.mkString(" ")).right.get
          case _    => falseValue.mkString("")
        }, asName)
  }
//this parser can be used to get the results
  val caseExpression = caseConditionExpresionParser | funcIdentifier

def parsePipes(input: String): Either[Seq[ParsingError], String] = {
    parse(caseExpression, input) match {
      case Success(parsed, _) => Right(parsed.asStr)
      case Failure(msg, next) => Left(Seq(ParsingError(s"Failed to parse $pipedStr: $msg, next: ${next.source}.")))
      case Error(msg, next)   => Left(Seq(ParsingError(s"Error in $pipedStr parse: $msg, next: ${next.source}.")))
    }
  }

关于regex - 解析 scala 中的 case 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51869502/

相关文章:

java - 当我在 Ubuntu 14.04 中运行 make-distribution.sh 时,Spark 1.3.1 在 MLlib 中安装失败

parsing - 使用 Trifecta 的布局解析器

匹配 {0} 的 JavaScript 正则表达式

scala - ScalaFX TableView 中的可编辑 bool 列

regex - 排除 vim 语法高亮的模式

scala - Specs2 和 scalacheck - 必须通过问题

scala - 使用 scala-parser-combinators 的递归定义

scala - 如何避免 Fastparse 中的左递归无限循环?

regex - 如何在 Visual Studio Code 中替换文档中的每一个换行符,而不是每两个换行符(或更多)?

regex - 在正则表达式中重用字符类