Рекурсивный анализ в красном
Я хочу проанализировать-пропустить Forth-стиль, если это из ввода, Forth-стиль означает каждый, если начинается с if
и заканчивается then
при условии, что все данные введены правильно, обработка несоответствий не требуется.
Проблема в каждой части if
может рекурсивно содержать любое количество других if
"S.
Вот мое лучшее решение с тестовыми примерами:
Red []
skip-nested-ifs: [skip to ['if | 'then] skip-nested-ifs-helper]
skip-nested-ifs-helper: ['then | skip-nested-ifs skip-nested-ifs-helper ]
rules: skip-nested-ifs
test-cases: [
[if a then]
[if a else b then]
[if a if b then then]
[if a if b then 5 then]
[if a if b then 5 if c then then]
[if a else if b then then]
[if a else if b then 5 then]
[if a else if b then if c then then]
[if a if b if c then if d then then then]
]
forall test-cases [
prin [mold test-cases/1 ""]
print either parse test-cases/1 rules [ "OK" ] [ "FAIL" ]
]
Выход:
[if a then] OK
[if a else b then] OK
[if a if b then then] OK
[if a if b then 5 then] FAIL
[if a if b then 5 if c then then] FAIL
[if a else if b then then] OK
[if a else if b then 5 then] FAIL
[if a else if b then if c then then] OK
[if a if b if c then if d then then then] OK
Так что три из них терпят неудачу, потому что они содержат что-то (5
в этом случае) между одним then
и другой.
Возможно, это очень простое и очевидное решение, но сейчас я его не вижу. Не могли бы вы помочь мне исправить приведенное выше правило, если это возможно, или показать другое, которое проходит все тесты?
1 ответ
Я не уверен, исправимо ли ваше правило или нет, так как оно сильно зависит от рекурсии, но не может обеспечить поддержку итерации, которая необходима для теста № 5. Я не смог это исправить, так как skip
используется для использования как терминальных, так и нетерминальных токенов (включая if
), поэтому мне трудно следовать.
Я придумал другое решение. Это длиннее, но проходит все ваши тесты (используя красный):
rules: [
'if skip
opt ['else [some rules | skip]]
opt some rules
'then
opt [some rules | ahead 'then | skip]
]
Заметки:
- Я попытался сделать правила грамматики как можно более явными.
- Обратите внимание на использование
some
итеративно потреблять подвыражения. ahead 'then
охранное правило, есть, чтобы предотвратитьskip
от потребления дополнительногоthen
который будет частью родительского выражения (в случае рекурсивного вызова).- Оно использует
skip
передать через терминал значение следующегоthen
или жеelse
хотя из вашего описания не ясно, может ли там быть более одного значения. В любом случае, его легко расширить для соответствия более сложным шаблонам, если это необходимо.
Если вы хотите использовать такое правило для пропуска ввода, вы можете вызвать его следующим образом:
skip-ifs: [to 'if rules]
Надеюсь это поможет.