pyparsing module ——定义和执行语法分析的类和方法
相对于传统的Lex/Yacc方法或者正则表达式,Pyparsing提供了一个创建和执行简单的语法的替代方案。有了Pyarsing,你不需要学习新的句法来定义语法或者匹配表达式。你可以直接在Python环境中使用Pyparsing提供的类库来构造语法。
下面是一段用来解析 “Hello, World!” (或任何类似形式 "<招呼语>,<招呼对象>!"
)的程序。这个段程序使用了Word
, Literal
, 和And
元素 ('+'
操作符创建 And
表达式, 字符串被自动地转换成 Literal
表达式):
from pyparsing import Word, alphas
# define grammar of a greeting
greet = Word(alphas) + "," + Word(alphas) + "!"
hello = "Hello, World!"
print(hello, "->", greet.parseString(hello))
程序输出下面的结果:
Hello, World! -> ['Hello', ',', 'World', '!']
得益于自解释性的类名,以及使用‘+’, ‘|’ 和 ‘^’ 之类的操作符,用Pyparsing构造的语法表示具有很好的可读性。
从 ParserElement.parseString
返回的ParseResults
对象可以通过嵌套列表,字典或者命名的对象来访问。
Pyarsing模块内部已经处理了下面几个问题,这些都是在开发文本解释器时会碰到的令人恼火的典型问题:
- 多了或者少了空格(上面的程序可以处理 “Hello,World!”, “Hello , World !”, 等等。)
- 引用的字符串
- 内嵌的注释行
开始使用 Pyparsing —
ParserElement
和 ParseResults
是Pyparsing的两个基类,其他大部分子类都是从这两个基类继承来的。我们使用后续的例子来理解这两个基类的功能:
- 使用
Literal
和CaselessLiteral
classes构造字面表达式- 使用
Word
类构造字符word-group表达式- 使用
ZeroOrMore
和OneOrMore
创建可重复的表达式- 使用
'+'
,'|'
,'^'
, 和'&'
这些操作符把简单表达式组合成复杂表达式- 使用
ParserElement.setResultsName
给解析的结果命名- 通过返回的
ParseResults
对象来访问解析出的数据- 演示一些有帮助的表达式快捷方式,比如
delimitedList
和oneOf
- 在
pyparsing_common
名字空间类中找到更多有用的通用表达式
class pyparsing.And
(exprs, savelist=True)
Bases: pyparsing.core.ParseExpression
要求按照给定的顺序找出给定的 ParseExpression
表达式。表达式之间可以被空格分隔。相同的构造可以使用'+'
操作符来实现。也可以使用'-'
来构造,这个操作符抑制回溯。???
例子:
integer = Word(nums)
name_expr = OneOrMore(Word(alphas))
expr = And([integer("id"), name_expr("name"), integer("age")])
# more easily written as:
expr = integer("id") + name_expr("name") + integer("age")
checkRecursion
(parseElementList)
parseImpl
(instring, loc, doActions=True)
streamline
()
class pyparsing.CaselessKeyword
(matchString, identChars=None)
Bases: pyparsing.core.Keyword
关键字类 Keyword
的不关心大小写的版本.
例子:
OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD']
(对照 CaselessLiteral
.)
class pyparsing.CaselessLiteral
(matchString)
Bases: pyparsing.core.Literal
配置特定的字符串,忽略字母大小写格式。注意:匹配结果跟给定的匹配图样大小写一致,跟被匹配的字符串大小写无关。
例子:
OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD']
(对照 CaselessKeyword
.)
parseImpl
(instring, loc, doActions=True)
class pyparsing.CharsNotIn
(notChars, min=1, max=0, exact=0)
Bases: pyparsing.core.Token
Token for matching words composed of characters not in a given set (will include whitespace in matched characters if not listed in the provided exclusion set - see example). Defined with string containing all disallowed characters, and an optional minimum, maximum, and/or exact length.
构造一个令牌,用于匹配特定的单词。这些单词由不在给定集合中的字符组成。由这些单词组成的字符串包含所有不允许字符,字符串可选指定最小,最大和确定长度选项。min
的默认值是 1 小于 1 的值非法);max
和 exact
的默认值是 0,表示没有最大和确定的长度限制。
(如果空格符不在给定的例外集合里面,在匹配的字符中会包含空格符。参考下面的例子。)
例子:
# define a comma-separated-value as anything that is not a ','
csv_value = CharsNotIn(',')
print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213"))
输出结果:
['dkls', 'lsdkjf', 's12 34', '@!#', '213']
parseImpl
(instring, loc, doActions=True)
class pyparsing.Combine
(expr, joinString='', adjacent=True)
Bases: pyparsing.core.TokenConverter
用来把所有匹配的令牌连接成单一字符串的转换器。默认情况下,匹配图样在输入字符串中也必须是相邻的。可以在构造器中指定'adjacent=False'
来关闭这个默认特性。
例子:
real = Word(nums) + '.' + Word(nums)
print(real.parseString('3.1416')) # -> ['3', '.', '1416']
# will also erroneously match the following
print(real.parseString('3. 1416')) # -> ['3', '.', '1416']
real = Combine(Word(nums) + '.' + Word(nums))
print(real.parseString('3.1416')) # -> ['3.1416']
# no match when there are internal spaces
print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...)
ignore
(other)[]
Define expression to be ignored (e.g., comments) while doing pattern matching; may be called repeatedly, to define multiple comment or other ignorable patterns.
例子:
patt = OneOrMore(Word(alphas))
patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj']
patt.ignore(cStyleComment)
patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd']
postParse
(instring, loc, tokenlist)
class pyparsing.Dict
(expr)
Bases: pyparsing.core.TokenConverter
转换器,用于把一个多次重复的表达式匹配结果返回成一个列表和字典。每一个元素可以使用表达式中的第一个令牌作为Key来访问。
例子:
data_word = Word(alphas)
label = data_word + FollowedBy(':')
attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join))
text = "shape: SQUARE posn: upper left color: light blue texture: burlap"
attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join))
# print attributes as plain groups
print(OneOrMore(attr_expr).parseString(text).dump())
# instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names
result = Dict(OneOrMore(Group(attr_expr))).parseString(text)
print(result.dump())
# access named fields as dict entries, or output as dict
print(result['shape'])
print(result.asDict())
输出结果:
['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap']
[['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']]
- color: light blue
- posn: upper left
- shape: SQUARE
- texture: burlap
SQUARE
{'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'}
未完待续,请参考下一节 Pyparsing学习笔记(二)