PEGKit Продолжай пробовать правила
Предположим, у меня есть правило:
myCoolRule:
Word
| 'myCoolToken' Word otherRule
Я поставляю как вход myCoolToken something else now
он пытается разобрать его, жадно сопоставляет myCoolToken как слово, а затем нажимает something
и говорит, э-э-э, я ожидал EOF, если я устрою правила, чтобы он пытался соответствовать myCoolToken
сначала все хорошо и отлично разбирается, для такого ввода.
Я задаюсь вопросом, возможно ли, чтобы это продолжало пробовать все правила в том утверждении, чтобы видеть, работает ли какой-либо. Таким образом, это соответствует Word терпит неудачу, возвращается и затем пытается следующее правило.
Вот фактические правила грамматики, вызывающие проблемы:
columnName = Word;
typeName = Word;
//accepts CAST and cast
cast = { MATCHES_IGNORE_CASE(LS(1), @"CAST") }? Word ;
checkConstraint = 'CHECK' '('! expr ')'!;
expr = requiredExp optionalExp*;
requiredExp = (columnName
| cast '(' expr as typeName ')'
... more but not important
optionalExp ...not important
Вход CHECK( CAST( abcd as defy) )
вызывает его сбой, даже если он действителен
Есть ли конструкт или как-то иначе заставить его проверить все правила, прежде чем сдаться.
1 ответ
Создатель PEGKit здесь.
Если я понимаю ваш вопрос, Нет, это невозможно. Но это особенность PEGKit, а не ошибка.
Ваш вопрос связан с "определенностью" против "неопределенности". PEGKit - это "детерминированный" инструментарий (который широко считается желательной функцией для синтаксического анализа языков программирования).
Кажется, вы ищете более "недетерминированное" поведение в этом случае, но я не думаю, что вы должны:).
PEGKit позволяет вам указать приоритет альтернативных опций в том порядке, в котором перечислены альтернативные опции. Так:
foo = highPriority
| lowerPriority
| lowestPriority
;
Если highPriority
опция соответствует текущему вводу, lowerPriority
а также lowestPriority
варианты не получат шанса на совпадение, даже если они как-то "лучше" совпадают (т. е. они сопоставляют больше токенов, чем highPriority
).
Опять же, это связано с "определенностью" (highPriority
гарантированно имеет приоритет) и широко считается желательной функцией при разборе языков программирования.
Так что если вы хотите, чтобы ваш cast()
выражения имеют более высокий приоритет, чем columnName
Просто перечисли cast()
Выражение как вариант перед columnName
вариант.
requiredExp = (cast '(' expr as typeName ')'
| columnName
... more but not important
ОК, так что позаботимся о синтаксических деталях. Однако, если у вас есть семантические ограничения более высокого уровня, которые могут повлиять на решения синтаксического анализа о том, какая альтернатива должна иметь наивысший приоритет, вы должны использовать семантический предикат, например:
foo = { shouldChooseOpt1() }? opt1
| { shouldChooseOpt2() }? opt2
| defaultOpt
;