Pyparsing是否支持上下文敏感的语法?

时间:2013-02-27 02:23:53

标签: python parsing pyparsing ply

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

我正在研究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实现)?

2 个答案:

答案 0 :(得分:6)

实际上它是上下文敏感语言的语法,经典地抽象为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)

答案 1 :(得分:3)

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

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

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

头部和尾部构造具有匹配标识符的检查在技术上不是由解析器完成的。

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

如果您在构建表示解析的树时这是最简单的,并在树上的各个位置挂起各种上下文相关值(例如,将实际的 IDENTIFIER 值附加到 head 子句的树节点)。在为 tail 构造构建树节点时,应该直接向上走树,找到 head 树,然后比较标识符。

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

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