FParsec возврат в вложенном парсере - PullRequest
0 голосов
/ 28 июня 2018

Я хочу разобрать выражения, которые сконструированы следующим образом: a is x or y or z or b is z or w, поэтому в основном у меня есть один и тот же разделитель для разных правил в моей грамматике.

Я уже преуспел в разборе таких выражений с помощью Antlr, так как он вполне может вернуться назад. Но теперь я хочу разобрать его с помощью FParsec и не получаю, чтобы внутренний анализатор не был жадным. Мои текущие парсеры выглядят так:

let variable = // matches a,b,c,...

// variables ::= variable { "or" variable }+ ;
let variables =
    variable .>>? keyword "or" .>>.? (sepBy1 variable (keyword "or"))

let operation =
    variable .>>? keyword "is" .>>.? variables

// expression ::= operation { "or" operation }+ ;
let expression =
    operation .>>? keyword "or" .>>.? (sepBy1 variable (keyword "or"))

В моем примере парсер переменных потребляет x or y or z or b, и все это терпит неудачу при is. Это означает, что мне нужно сделать этот variables синтаксический анализатор менее жадным или вернуть его правильно.

Я нашел похожий вопрос , где они делают версию для обратного отслеживания sepBy1, но использование этой проблемы все еще не решает мою проблему. Я думаю, это потому, что я хочу вернуться к вложенному парсеру.

Так, как правильно заставить FParsec принимать мой ввод?

1 Ответ

0 голосов
/ 29 июня 2018

Помимо переключения одного из значений or на |, как я упоминал в комментарии, вы также можете использовать notFollowedBy (keyword "is") следующим образом:

let variables =
    variable .>>? keyword "or" .>>.? (sepBy1 (variable .>> (notFollowedBy (keyword "is"))) (keyword "or"))

Мне не очень нравится это решение, потому что оно не легко обобщается. Есть ли другие ключевые слова, кроме is, которые могут появляться после переменной? Например, у вас есть синтаксис типа b matches x or y или что-то подобное? Если так, то вам нужно написать что-то вроде (notFollowedBy ((keyword "is") <|> (keyword "matches"))), и это может быстро усложниться. Но до тех пор, пока ключевое слово is является единственным, которое отбрасывает ваш анализатор, использование (notFollowedBy (keyword "is")), вероятно, будет лучшим выбором.

...