【问题标题】:Adding line numbers to parsing errors without extending Positional directly在不直接扩展 Positional 的情况下将行号添加到解析错误
【发布时间】:2014-01-04 17:40:43
【问题描述】:

我(终于)完成了一个解析器,它处理我的 DSL 并将其转换为我的域对象。现在我想添加一些适当的错误处理,并且我希望将行号添加到解析器报告的错误中。

我找到的示例和答案herehere 似乎表明我必须修改我的域对象以扩展scala.util.parsing.input.Positional。这个例子对我的案例来说有点过于简单了,而且(由于我的经验不足)我的案例似乎不太适合这个范式。

我的主要问题是我不希望我的域对象直接扩展Positional。它们在程序中与解析没有任何关系的其他地方使用(解析器只是程序的扩展,用于创建不同的数据输入方式)。另外,我不知道如何处理输出String(或我无法控制的其他类)的情况。还有一个问题是我的领域对象已经扩展了程序的其他对象,我不能简单地改变层次结构。

是否有任何替代方法可以干净地处理此问题,而无需修改域对象并将它们与Positional 耦合? (抱歉,如果我问一些与实现特征等有关的琐碎事情,因为我还是 Scala 的新手)

【问题讨论】:

    标签: scala parsing line-numbers parser-combinators


    【解决方案1】:

    你可以使用 scala.util.matching.Regex.MatchIterator 来构建这样的东西

    type Token = String
    
    trait TokenIterator extends Iterator[Token] {
      def next: Token
      def hasNext: Boolean
      def pos: Int
    }
    
    class Tokenizer(regexStr: String, input: String) {
      val regex = regexStr.r
    
      def iterator: TokenIterator = new TokenIterator {
        val iter = regex.findAllIn(input)
        var pos = 0
        def next = {
          val n = iter.next
          pos = iter.start
          n
        }
        def hasNext = iter.hasNext
      }
    }
    
    val str = "3 + 4 - 5"
    val iter = new Tokenizer("""d+|\S+?""", str).iterator
    
    while(iter.hasNext) {
      val token = iter.next
      val pos = iter.pos
      println(pos + ": " + token)
    }
    

    【讨论】:

    • 我如何在我的解析器中使用它?我有一个大约 300 行的解析器(相当复杂的 BNF)。我要改变什么来整合它?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-09
    • 1970-01-01
    • 2013-06-23
    • 2020-01-14
    • 2016-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多