Как еще больше улучшить сообщения об ошибках в парсерах-комбинаторах Scala? - PullRequest
7 голосов
/ 25 мая 2010

Я кодировал парсер на основе комбинаторов парсера Scala:

class SxmlParser extends RegexParsers with ImplicitConversions with PackratParsers {
    [...]
    lazy val document: PackratParser[AstNodeDocument] =
        ((procinst | element | comment | cdata | whitespace | text)*) ^^ {
            AstNodeDocument(_)
        }
    [...]
}
object SxmlParser {
    def parse(text: String): AstNodeDocument = {
        var ast = AstNodeDocument()
        val parser = new SxmlParser()
        val result = parser.parseAll(parser.document, new CharArrayReader(text.toArray))
        result match {
            case parser.Success(x, _) => ast = x
            case parser.NoSuccess(err, next) => {
                tool.die("failed to parse SXML input " +
                    "(line " + next.pos.line + ", column " + next.pos.column + "):\n" +
                    err + "\n" +
                    next.pos.longString)
            }
        }
        ast
    }
}

Обычно получающиеся сообщения об ошибках разбора довольно хороши. Но иногда это становится просто

sxml: ERROR: failed to parse SXML input (line 32, column 1):
`"' expected but `' found
^

Это происходит, если символы кавычки не закрыты и парсер достигает EOT. Я хотел бы видеть здесь: (1) в каком производстве находился парсер, когда он ожидал '' '(у меня их несколько) и (2) где во входных данных это производство начало анализироваться (что является показателем того, что открывающая кавычка во входных данных. Кто-нибудь знает, как я могу улучшить сообщения об ошибках и включить больше информации о фактическом внутреннем состоянии анализа при возникновении ошибки (возможно, что-то вроде трассировки стека производственного правила или чего-либо еще, что может быть дано здесь разумно для лучшей идентификации местоположение ошибки). Кстати, вышеуказанная «строка 32, столбец 1» фактически является позицией EOT и, следовательно, здесь, конечно, бесполезна.

Ответы [ 2 ]

3 голосов
/ 25 июня 2010

Я пока не знаю, что делать с (1), но я также искал (2), когда нашел эту веб-страницу:

https://wiki.scala -lang.org / плагины / ViewSource / viewpagesrc.action? PageId = 917624

Я просто копирую информацию:

Полезным улучшением является запись входной позиции (номер строки и номер столбца) значимых токенов. Для этого нужно сделать три вещи:

  • Расширение каждого типа вывода scala.util.parsing.input.Positional
  • вызывает комбинатор Parsers.positioned ()
  • Использовать источник текста, который записывает позиции строк и столбцов

и

Наконец, убедитесь, что источник отслеживает позиции. Для потоков вы можете просто использовать scala.util.parsing.input.StreamReader; для строк используйте scala.util.parsing.input.CharArrayReader.

Сейчас я играю с ним, поэтому постараюсь добавить простой пример позже

1 голос
/ 26 мая 2010

В таких случаях вы можете использовать err, failure и ~! с правилами производства, специально разработанными для соответствия ошибке.

...