Parsing 解析嵌套括号中包含的值

Parsing 解析嵌套括号中包含的值,parsing,scala,Parsing,Scala,我只是在开玩笑,奇怪的是,我发现在一个简单的递归函数中解析嵌套括号有点棘手 例如,如果程序的目的是查找用户详细信息,则它可能从{{name names}age}到{Bob Builder age},然后到Bob Builder 20 下面是一个小程序,用于对花括号中的总数进行求和,演示了这个概念 // Parses string recursively by eliminating brackets def parse(s: String): String = { if (!s.

我只是在开玩笑,奇怪的是,我发现在一个简单的递归函数中解析嵌套括号有点棘手

例如,如果程序的目的是查找用户详细信息,则它可能从
{{name names}age}
{Bob Builder age}
,然后到
Bob Builder 20

下面是一个小程序,用于对花括号中的总数进行求和,演示了这个概念

  // Parses string recursively by eliminating brackets
  def parse(s: String): String = {
    if (!s.contains("{")) s
    else {
      parse(resolvePair(s))
    }
  }

  // Sums one pair and returns the string, starting at deepest nested pair
  // e.g.
  // {2+10} lollies and {3+{4+5}} peanuts
  // should return:
  // {2+10} lollies and {3+9} peanuts
  def resolvePair(s: String): String = {
    ??? // Replace the deepest nested pair with it's sumString result
  }

  // Sums values in a string, returning the result as a string
  // e.g. sumString("3+8") returns "11"
  def sumString(s: String): String = {
    val v = s.split("\\+")
    v.foldLeft(0)(_.toInt + _.toInt).toString
  }

  // Should return "12 lollies and 12 peanuts"
  parse("{2+10} lollies and {3+{4+5}} peanuts")
任何可以取代
的干净代码的想法都是非常好的。主要是出于好奇,我正在寻找一个优雅的解决方案来解决这个问题。

怎么样

def resolvePair(s: String): String = {
val open = s.lastIndexOf('{')
val close = s.indexOf('}', open)
if((open >= 0) && (close > open)) {
    val (a,b) = s.splitAt(open+1)
    val (c,d) = b.splitAt(close-open-1)
    resolvePair(a.dropRight(1)+sumString(c).toString+d.drop(1))
} else
    s
}   

我知道它很难看,但我认为它工作得很好。

解析器组合器可以处理这种情况:

import scala.util.parsing.combinator.RegexParsers
object BraceParser extends RegexParsers {
  override def skipWhitespace = false
  def number = """\d+""".r ^^ { _.toInt }
  def sum: Parser[Int] = "{" ~> (number | sum) ~ "+" ~ (number | sum) <~ "}" ^^ {
    case x ~ "+" ~ y => x + y
  }
  def text = """[^{}]+""".r
  def chunk = sum ^^ {_.toString } | text
  def chunks = rep1(chunk) ^^ {_.mkString} | ""
  def apply(input: String): String = parseAll(chunks, input) match {
    case Success(result, _) => result
    case failure: NoSuccess => scala.sys.error(failure.msg)
  }
}
在熟悉解析器组合器之前,需要进行一些投资,但我认为这是值得的

要帮助您解读上述语法,请执行以下操作:

  • 正则表达式和字符串具有隐式转换以创建具有字符串结果的基本解析器,它们具有类型
    Parser[String]
  • ^
    运算符允许将函数应用于已解析的元素
    • 它可以通过执行
      ^{uu.toInt}
    • 解析器是一个单元组,
      Parser[T]。^^(f)
      相当于
      Parser[T]。map(f)

  • ~
    ~>
    f(a,b)}
    相当于
    ,因为(a+1它并不难看;-)把它全部切碎,然后重新组合起来,这正是我通常解决字符串替换代码的方式。但是,我希望能找到一个更有效或更另类的答案来扩展我对这类问题的思考方式(因为我经常这样做,有时是在长而复杂的字符串上)。例如,使用正则表达式查找内部花括号对并将其替换为sumString结果,或者以某种好的或有效的方式使用Scala解析器组合器。感谢您的解决方案和完整的代码布局。是的,我真的应该投入一点时间,更好地了解解析器组合器。这个答案非常有用!谢谢
    
    BraceParser("{2+10} lollies and {3+{4+5}} peanuts")
    //> res0: String = 12 lollies and 12 peanuts