Как описать области применения в EBNF?
Я пытаюсь написать парсер для конфигураций Cisco IOS и ASA, используя Grako и Python. Я пытаюсь понять, как представлять ключевые слова с "областью видимости" в EBNF - например, ключевое слово "описание" должно появляться внутри interface
сфера, но есть несколько вариантов interface
и все они необязательны (и порядок может меняться между устройствами, я считаю):
interface Vlan1435
nameif untrust
description the outside interface for customer X
bridge-group 1
security-level 0
Ближайший пример, который я нашел, находится в приложении Perl под названием Farly, которое использует модуль perl Parse::Recdescent, который, похоже, похож на Grako.
Оттуда у меня есть этот тип рекурсивного определения:
@@eol_comments :: /!([^\n]*?)\n/
@@whitespace :: /[\t ]+/
start
=
file_input $
;
file_input
=
{NEWLINE | asa_line}
;
asa_line
=
'names' NEWLINE
| interface NEWLINE
;
interface
=
'interface' string NEWLINE interface_options
;
interface_options
=
if_name | sec_level | if_addr | if_bridgegroup | NEWLINE
;
if_bridgegroup
=
'bridge-group' digit NEWLINE interface_options
;
if_name
=
'nameif' string NEWLINE interface_options
;
sec_level
=
'security-level' digit NEWLINE interface_options
;
но он производит странное вложенное AST и не "сбрасывается", чтобы обнаружить второй интерфейс или что-либо еще в конфигурации, которая следует.
Как эти виды областей обычно определяются в EBNF? (есть ли полезный учебник для этого типа вещей тоже? Мой google-fu ничего не показал для Grako или парсеров вообще)
1 ответ
Уловка, которую я использую в этих ситуациях, состоит в том, чтобы использовать повторение, даже если параметры могут появиться только один раз:
interface_options
=
{ @+:(if_name | sec_level | if_addr | if_bridgegroup) NEWLINE}*
;
При необходимости вы можете использовать семантическое действие для проверки того, что параметры не повторяются.