В Parsec есть ли способ предотвратить использование новой строки в лексеме? - PullRequest
13 голосов
/ 15 апреля 2011

Все парсеры в Text.Parsec.Token вежливо используют lexeme, чтобы съесть пробел после токена. К сожалению для меня, пробел включает в себя новые строки, которые я хочу использовать как терминаторы выражений. Есть ли способ убедить lexeme покинуть новую строку?

Ответы [ 4 ]

6 голосов
/ 17 апреля 2011

Нет, это не так.Вот соответствующий код.

Из Text.Parsec.Token :

lexeme p
    = do{ x <- p; whiteSpace; return x  }


--whiteSpace
whiteSpace
    | noLine && noMulti  = skipMany (simpleSpace <?> "")
    | noLine             = skipMany (simpleSpace <|> multiLineComment <?> "")
    | noMulti            = skipMany (simpleSpace <|> oneLineComment <?> "")
    | otherwise          = skipMany (simpleSpace <|> oneLineComment <|> multiLineComment <?> "")
    where
      noLine  = null (commentLine languageDef)
      noMulti = null (commentStart languageDef)

В предложении where в whitespace можно заметить, что только единственные опциипосмотрел на сделку с комментариями.Функция lexeme использует whitespace и широко используется в остальной части parsec.token.


Обновление 28 сентября 2015 г.

Окончательное решение для меня заключалось в том, чтобыиспользуйте подходящий лексический анализатор ( alex ).Parsec отлично справляется с работой библиотеки разбора, и это заслуга дизайна в том, что его можно использовать для проведения лексического анализа, но для всех проектов, кроме небольших и простых, он быстро станет громоздким.Теперь я использую alex для создания линейного набора токенов, а затем Parsec превращает их в AST.

3 голосов
/ 15 апреля 2011

Если новые строки являются вашими терминаторами выражения, возможно, имеет смысл разделить ввод по каждой новой строке и проанализировать каждую строку самостоятельно.

2 голосов
/ 25 сентября 2015

Ну, не все парсеры в Text.Parsec.Token используют lexeme, хотя все их должны . Хуже всего не задокументировано, кто из них потребляет белый пространство, а какие из них нет. Некоторые парсеры в Text.Parsec.Token после лексемы потребляют пробелы, некоторые из них этого не делают. Некоторые из них потреблять ведущие пробелы, а также. Вы должны прочитать существующие проблемы на GitHub средство отслеживания ошибок, если вы хотите полностью контролировать ситуацию.

В частности:

  • decimal, hexadecimal и octal парсеры не не используют трейлинг пустое пространство, см источник , и этот выпуск ;

  • integer также занимает лидирующие пробелы, см. этот номер ;

  • остальные из них вероятно потребляют конечные пробелы и, следовательно, переводы строк, однако это трудно сказать наверняка, потому что код Parsec особенно волосатые (ИМХО) и в проекте нет ни одного набора тестов (кроме 3 тесты, которые проверяют, что уже исправленные ошибки не появляются снова, однако этого недостаточно для предотвращения регрессий, и каждое изменение в источнике может сломайте ваш код в следующей версии Parsec .)

Существуют различные предложения, как сделать его настраиваемым (что должно быть считается пустым пространством), ни один из них по каким-либо причинам не объединен или не прокомментирован.

Но настоящая проблема скорее в дизайне Text.Parsec.Token, который блокирует пользователь в решениях, построенных makeTokenParser. Этот дизайн особенно негибкий. Есть много случаев, когда единственным решением является копирование весь модуль и отредактируйте его при необходимости.

Но если вы хотите современный и неповторимый Parsec, есть возможность переключиться на Мегапарсек где это (и многие другие) проблема не существует.


Раскрытие информации : Я один из авторов Мегапарсек.

1 голос
/ 06 декабря 2012

Хотя другие ответы о невозможности этого являются правильными, я хотел бы отметить, что синтаксические анализаторы не используют синтаксический анализатор лексемы.
Я использую parsec для анализа некоторых HTML-шаблонов усов.Пробелы важны в этом анализе.Я просто проанализировал строки ">" и "}}" с Text.Parsec.Char.string.
Поскольку меня интересуют пробелы между тегами, а не внутри них, я все еще могу использовать зарезервированные операторы для анализа "<" и"{{" и т. д., поскольку синтаксический анализатор лексемы использует только конечные пробелы. </p>

...