PegKit: грамматический синтаксис, который по-разному обрабатывает одну и ту же работу
Я работаю над кодом, который использует PegKit, и я наткнулся на что-то, я не уверен, как это выяснить. У меня есть синтаксис, который выглядит следующим образом (упрощенно):
expr = runtimeExpr | objectExpr;
runtimeExpr = is? runtimeObject;
objectExpr = runtimeObject keyPath;
runtimeObject = '[' string ']';
is = 'is';
keyPath = string;
Я ищу следующие результаты:
[abc] -> runtime expr.
is [abc] -> runtime expr.
[abc].def -> object expr.
Однако то, что происходит, - то, что сгенерированный код парсера выглядит следующим образом:
if ([self predicts:STLOGEXPRESSIONPARSER_TOKEN_KIND_IS, 0]) {
[self runtimeExpr_];
} else if ([self predicts:STLOGEXPRESSIONPARSER_TOKEN_KIND_OPEN_BRACKET, 0]) {
[self objectExpr_];
}
Это говорит о том, что для анализа выражения во время выполнения он должен начинаться с "is". Который означает, что [abc]
вместо этого передается как объект expr.
Так что мне нужна помощь в понимании того, как выразить эту логику в синтаксисе грамматики:
Если строка начинается с "is", за которым следует runtimeObject, или является только runtimeObject, обработайте ее как runtimeExpr.
В противном случае обработайте его как objectExpr.
1 ответ
Создатель PEGKit здесь.
Я считаю, что проблема здесь является ведущим необязательным is?
, Любое правило, которое начинается с необязательного префикса, подобного этому, а затем впоследствии соответствует чему-то похожему или идентичному другому правилу (runtimeObject
в этом случае) может вызвать проблемы.
Но решение легко. Просто измените порядок вещей. PEGKit является детерминированным, что означает, что он будет пытаться использовать альтернативы OR в порядке, указанном в грамматике. Так что в этом случае просто поместите более длинное альтернативное правило (objectExpr
) сначала (до runtimeExpr
в expr
правило).
Попробуйте это, я верю, что все получится
expr = objectExpr | runtimeExpr;
objectExpr = runtimeObject keyPath;
runtimeExpr = is runtimeObject | runtimeObject;
runtimeObject = '[' string ']';
is = 'is';
keyPath = string;
Обратите внимание на изменения, которые я внес в оба expr
а также runtimeExpr
правила. Я подозреваю только изменение в expr
необходимо решить эту проблему, но изменение на runtimeExpr
безвреден Эксперимент должен сказать вам, является ли runtimeExpr
изменение действительно необходимо.