【问题标题】:Does Pyparsing Support Context-Sensitive Grammars?Pyparsing 是否支持上下文相关语法?
【发布时间】:2013-02-27 02:23:52
【问题描述】:

如果我有不正确的术语,请原谅我;也许只是用“正确”的词来描述我想要的东西就足以让我自己找到答案。

我正在开发 ODL(对象描述语言)的解析器,据我所知,这是一种神秘的语言,现在只有 NASA PDS(行星数据系统;这是 NASA 向公众提供数据的方式) .幸运的是,PDS 终于转向 XML,但我仍然需要为在截止日期前落下的任务编写软件。

ODL 以如下方式定义对象:

OBJECT              = TABLE
  ROWS              = 128
  ROW_BYTES         = 512 
END_OBJECT          = TABLE

我正在尝试使用pyparsing 编写解析器,并且在完成上述构造之前我做得很好。

我必须创建一些规则,以确保 OBJECT 行的右侧值与 END_OBJECT 的 RHV 相同。但我似乎无法将其放入pyparsing 规则中。我可以确保两者都是语法上有效的值,但我不能采取额外的步骤来确保值相同。

  1. 我的直觉是否正确,这是一种上下文相关的语法?这是我应该用来描述这个问题的短语吗?
  2. 无论这是理论上的哪种语法,pyparsing 是否能够处理这种结构?
  3. 如果pyparsing 无法处理,是否还有其他 Python 工具可以处理? plylex/yacc的Python实现)怎么样?

【问题讨论】:

    标签: python parsing pyparsing ply


    【解决方案1】:

    它实际上是上下文相关语言的语法,经典抽象为 wcw 其中 w 在 (a|b)* 中(注意 wcw' ,其中 ' 表示反转,是上下文无关的)。

    解析表达式语法能够通过使用语义谓词来解析 wcw 类型的语言。 PyParsing 为此目的提供了matchPreviousExpr()matchPreviousLiteral() 辅助方法,例如

    w = Word("ab")
    s = w + "c" + matchPreviousExpr(w)
    

    所以在你的情况下,你可能会做类似的事情

    table_name = Word(alphas, alphanums)
    object = Literal("OBJECT") + "=" + table_name + ... +
      Literal("END_OBJECT") + "=" +matchPreviousExpr(table_name)
    

    【讨论】:

      【解决方案2】:

      作为一般规则,解析器构建为上下文无关的解析引擎。如果存在上下文敏感性,则在解析后(或至少在相关解析步骤完成后)进行嫁接。

      在你的情况下,你想编写上下文无关的语法规则:

        head = 'OBJECT' '=' IDENTIFIER ;
        tail = 'END_OBJECT'  '=' IDENTIFIER ;
        element = IDENTIFIER '=' value ;
        element_list = element ;
        element_list = element_list element ;
        block = head element_list tail ;
      

      从技术上讲,解析器不会检查头部和尾部构造是否具有匹配的标识符。

      然而,许多解析器允许在识别句法元素时发生语义动作,通常是为了构建树节点。在你的情况下,你想要 使用它来启用额外的检查。对于 element,您要确保 IDENTIFIER 不是块中已有内容的副本;这意味着对于遇到的每个 element,您都需要捕获相应的 IDENTIFIER 并制作一个特定于块的列表以启用重复检查。对于块,您要捕获 head *IDENTIFIER*,并检查它是否与 tail *IDENTIFIER* 匹配。

      如果您在进行过程中构建一个表示解析的树,并将各种上下文相关的值挂在树上的各个位置(例如,将实际的 IDENTIFIER 值附加到head 子句的树节点)。在您为 tail 构造构建树节点的位置,应该很简单地沿着树向上走,找到 head 树,然后比较标识符。

      如果您想象首先构建整个树,然后对树进行后处理传递来进行此检查,则更容易考虑。懒惰的人实际上是这样做的:-} 我们所做的只是将可以在后处理步骤中完成的工作推到附加到语义操作的树构建步骤中。

      这些概念都不是特定于 python 的,PyParsing 的细节会有所不同。

      【讨论】:

      • 在pyparsing中,你可以在block对应的表达式上附加一个解析时回调(我们称之为“解析动作”),它可以验证head和@987654324 @值同意,或提出ParseException。所以你不必做很多“树行走”。
      • 所以这正是我讨论的语义动作。它会自己构建树吗?如何?如果没有,你如何检查终端的值?
      • pyparsing 将解析后的结构传递给回调,在这种情况下,回调将查看第一个和最后一个元素以比较对象值字符串。所以我猜有 some tree-walking,但只是在被解析的当前对象上。通过添加一些标签(类似于在正则表达式中命名组),解析操作可以直接查看 tokens.head.identifiertokens.tail.identifier 以验证它们是否匹配。
      • 发布此问题后,我决定使用上述策略。我的直觉告诉我,由于对象从不交错,只是嵌套,简单的语法会正确解析,我可以断言这些值与事后的想法相同。但我不确定我能证明这一点。 (我想这更有动力回到学校。)
      猜你喜欢
      • 2012-01-04
      • 2017-08-03
      • 1970-01-01
      • 2014-02-28
      • 2018-02-17
      • 2012-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多