可爱的 Python: 使用 Spark 模块解析
2007-03-29 12:07:02 来源:WEB开发网我的 .p_para() 在其文档字符串中应该只包含一组语法规则(没有代码)。我决定专门用 .nonterminal() 方法来稍微对 AST 进行平铺。由一系列“plain”子树组成的“plain”节点将子树压缩为一个更长的字符串。同样,标记子树(即“emph”、“strong”、“module”、“code”和“title”)折叠为一个类型正确的单独节点,并包含一个复合字符串。
我们已经提到过,Spark 语法中显然缺少一样东西:没有计量符。通过下面这样的规则,
plain ::= plain plain
我们可以成对地聚集“plain“类型的子树。不过我更倾向于让 Spark 允许使用更类似于 EBNF 风格的语法表达式,如下所示:
plain ::= plain+
然后,我们就可以更简单地创建“plain 尽可能多”的 n-ary 子树了。既然这样,我们的树就更容易启动列,甚至不用在 .nonterminal() 中传送消息。
使用树
Spark 模块提供了几个使用 AST 的类。比起我的目的来说,这些责任比我需要的更大。如果您希望得到它们,GenericASTTraversal 和 GenericASTMatcher 提供了遍历树的方法,使用的继承协议类似于我们为扫描程序和解析器所提供的。
但是只用递归函数来遍历树并不十分困难。我在文章的压缩文件 prettyprint.py (请参阅 参考资料)中创建了一些这样的示例。其中的一个是 showtree() 。该函数将显示一个带有几个约定的 AST。
每行都显示下降深度
只有子节点(没有内容)的节点开头有破折号
节点类型用双层尖括号括起
让我们来看看上面示例中生成的 AST:
清单 7. 用 WordPlusScanner 向“智能 ASCII”赋予记号>>> from wordscanner import tokensFromFname
>>> from markupbuilder import treeFromTokens
>>> from prettyprint import showtree
>>> showtree(treeFromTokens(tokensFromFname('p.txt')))
0 <<para>>
1 - <<para>>
2 -- <<para>>
3 --- <<para>>
4 ---- <<para>>
5 ----- <<para>>
6 ------ <<para>>
7 ------- <<para>>
8 -------- <<plain>>
9 <<plain>> Text with
8 <<strong>> bold
7 ------- <<plain>>
8 <<plain>> , and
6 <<emph>> itals phrase
5 ----- <<plain>>
6 <<plain>> , and
4 <<module>> module
3 --- <<plain>>
4 <<plain>> --this should be a good
2 <<code>> practice run
1 - <<plain>>
2 <<plain>> .
更多精彩
赞助商链接