【问题标题】:Recursive parsing based on level numbers基于层数的递归解析
【发布时间】:2011-12-30 09:54:56
【问题描述】:

我有一个棘手的问题(至少在我看来),关于 Scalas 解析器组合器和递归解析。我目前正在构建一个小型解析器,它应该能够解析这样的 PL/1 结构:

  dcl 1 data,
    3 subData,
      5 tmp char(15),
      5 tmp1 char(15),
    3 subData2,
      5 tmp2 char(10),
      5 tmp3 char(5);

在这种情况下,我想按如下方式构建 AST:

Record(data)  -> (Record(subData),Record(subData2))

  Record(subData) -> (Char(tmp),Char(tmp1))

  Record(subData2) -> (Char(tmp2),Char(tmp3))  

意味着父元素应该连接到它的子元素。在我的世界中,这应该以某种方式导致递归解析器,但是我的问题是如何控制何时停止在子级别中下降。例如,在解析“3 subdata”记录结构时,它应该在遇到本身不低的级别编号时停止,在本例中为“3 subData2”行。

有人可以帮助解决这个问题,或者指出一个好的方向。 我目前的解决方案是在解析一个未连接的结构后解决这个问题。

提前致谢。

问候斯特凡

【问题讨论】:

  • 你怎么知道一个记录结构在什么级别?在您的示例中,它可以是标识或记录类型(tmp 与 subData)。无论哪种方式,解析器对我来说都是直截了当的,所以我希望您能更具体地说明您尝试过的无效操作。

标签: parsing scala abstract-syntax-tree parser-combinators


【解决方案1】:

基本上你只需要Parser.into(它有一个别名>>),它会创建一个基于当前结果的解析器组合器。

我为你准备了一个简单的 REPLable 示例

import util.parsing.combinator.RegexParsers

case class Record(data: String, children: List[Record])

object RecordParser extends RegexParsers {
  override def skipWhitespace = false

  def ws = "\\s*".r
  def numberGT(min: Int) = "\\d+".r ^^ {  _.toInt } ^? {
    case i if i > min => i
  }

  def subData(n: Int): Parser[Record] = ws ~> numberGT(n) ~ ws ~ ".*".r <~ "\n" >> {
    case sub ~ _ ~ data => rep(subData(sub)) ^^ { new Record(data, _) }
  }
}

val testData = """
1 data
 2 subdata
  3 child1
  3 child2
 2 sub2
"""

RecordParser.parse(RecordParser.subData(0),test)
res7: RecordParser.ParseResult[Record] = [7.1] parsed: Record(data,List(Record(subdata,List(Record(child1,List()), Record(child2,List()))), Record(sub2,List())))

【讨论】:

    猜你喜欢
    • 2017-07-31
    • 1970-01-01
    • 2011-05-05
    • 2015-08-03
    • 2011-10-10
    • 2016-03-08
    • 2018-05-16
    • 2014-01-05
    • 1970-01-01
    相关资源
    最近更新 更多