Синтаксический анализатор combinator не завершающийся - как зарегистрировать то, что продолжается?

Я экспериментирую с синтаксическим анализатором combinators, и я часто сталкиваюсь с тем, что походит на бесконечные рекурсии. Вот первый, с которым я столкнулся:

import util.parsing.combinator.Parsers
import util.parsing.input.CharSequenceReader

class CombinatorParserTest extends Parsers {

  type Elem = Char

  def notComma = elem("not comma", _ != ',')

  def notEndLine = elem("not end line", x => x != '\r' && x != '\n')

  def text = rep(notComma | notEndLine)

}

object CombinatorParserTest {

  def main(args:Array[String]): Unit = {
    val p = new CombinatorParserTest()
    val r = p.text(new CharSequenceReader(","))
    // does not get here
    println(r)
  }

}

Как я могу распечатать то, что продолжается? И почему это не заканчивается?

7
задан huynhjl 5 March 2010 в 15:37
поделиться

2 ответа

Регистрация попыток синтаксического анализа notComma и notEndLine показывает, что это конец файла (отображается как CTRL-Z в вывод журнала (...) ("mesg")), который повторно анализируется. Вот как я модифицировал ваш синтаксический анализатор для этой цели:

def text = rep(log(notComma)("notComma") | log(notEndLine)("notEndLine"))

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

4
ответ дан 7 December 2019 в 10:00
поделиться

Хорошо, я думаю, что разобрался. CharSequenceReader возвращает '\ 032' в качестве маркера конца ввода. Итак, если я изменю свой ввод таким образом, он будет работать:

import util.parsing.combinator.Parsers
import util.parsing.input.CharSequenceReader

class CombinatorParserTest extends Parsers {

  type Elem = Char

  import CharSequenceReader.EofCh

  def notComma = elem("not comma", x => x != ',' && x!=EofCh)

  def notEndLine = elem("not end line", x => x != '\r' && x != '\n' && x!=EofCh)

  //def text = rep(notComma | notEndLine)
  def text = rep(log(notComma)("notComma") | log(notEndLine)("notEndLine"))

}

object CombinatorParserTest {

  def main(args:Array[String]): Unit = {
    val p = new CombinatorParserTest()
    val r = p.text(new CharSequenceReader(","))
    println(r)
  }

}

См. Исходный код для CharSequenceReader здесь . Если бы скаладок упомянул об этом, это сэкономило бы мне много времени.

2
ответ дан 7 December 2019 в 10:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: