Добавление номеров строк к ошибкам синтаксического анализа без непосредственного расширения Positional

Я (наконец) завершил синтаксический анализатор, который обрабатывает мой DSL и переводит его в объекты моего домена. Теперь я хочу добавить правильную обработку ошибок и добавить номера строк к ошибкам, о которых сообщает синтаксический анализатор.

Примеры и ответы я нашел здесь и здесь кажется, указывает, что я должны изменить мои объекты домена, чтобы расширить scala.util.parsing.input.Positional. Пример слишком упрощен для моего случая, и (из-за моей неопытности) кажется, что мой случай не совсем соответствует этой парадигме.

Основная проблема, с которой я столкнулся, заключается в том, что я не хочу, чтобы мои объекты домена напрямую расширяли Positional. Они используются в других местах программы, которые не имеют ничего общего с синтаксическим анализом (парсер — это просто расширение программы для создания другого способа ввода данных). Кроме того, я не знаю, как обрабатывать случаи, которые выводят String (или другие классы, над которыми я не контролирую). Существует также проблема, что мои объекты домена уже расширяют другие объекты программы, я не могу просто изменить иерархию таким образом.

Есть ли какой-либо альтернативный способ справиться с этим чисто, без изменения объектов домена и связывания их с Positional? (Извините, если я спрашиваю что-то тривиальное, связанное с реализацией трейтов и т. д., потому что я все еще новичок в Scala)


person jbx    schedule 04.01.2014    source источник


Ответы (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)
}
person SpiderPig    schedule 04.01.2014
comment
Как мне использовать это в моем парсере? У меня есть парсер около 300 строк (довольно сложный BNF). Что мне изменить, чтобы интегрировать это? - person jbx; 07.01.2014