【问题标题】:How to describe scopes in EBNF?如何在 EBNF 中描述作用域?
【发布时间】:2016-10-03 14:22:30
【问题描述】:

我正在尝试使用 Grako 和 Python 为 Cisco IOS 和 ASA 配置编写解析器。我试图弄清楚如何在 EBNF 中表示“范围”关键字 - 例如,“描述”关键字必须出现在 interface 范围内,但 interface 有多个选项,它们都是可选的(并且我相信顺序可以在设备之间改变):

interface Vlan1435
 nameif untrust
 description the outside interface for customer X
 bridge-group 1
 security-level 0

我找到的最接近示例的是一个名为 Farly 的 Perl 应用程序,该应用程序使用 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 或解析器提供任何东西)

【问题讨论】:

    标签: python ebnf cisco-ios grako ciscoconfparse


    【解决方案1】:

    我在这些情况下使用的一个技巧是使用重复,即使选项只能出现一次:

    interface_options
        =
        { @+:(if_name | sec_level | if_addr | if_bridgegroup)  NEWLINE}*
        ;
    

    如有必要,您可以使用语义操作来验证选项是否重复。

    【讨论】:

    • 谢谢!我认为这一点,再加上一个替换 grako Buffer 类来发现缩进(如 Python)就可以解决问题......只需从文档中的单行提及扩展到一个功能性的东西 :-)
    • 我认为缩进不需要Buffer。您可以将缩进定义为语法中的标记,并使用语义规则来跟踪深度/级别。请记住,您可以使用“空”规则来激活语义操作(在您的情况下为unindent = ();)。
    • 好的,我试试看!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-22
    • 2012-10-23
    • 2018-06-08
    相关资源
    最近更新 更多