最小peg解析器
parsik的Python项目详细描述
帕西克
一个简单的peg(解析表达式语法)解析器。
您为您的语言提供了语法,这个模块为您提供了一个解析器 用于识别文档(字符串)是否与语法匹配。你 可以在语法的各个部分匹配时附加回调函数,以及 帮助构造解析的一些“输出”(例如解析树)。
图书馆在时间和空间上都很简单,没有优化。和语法 左递归可以将解析器放入无限循环中。但是 实现非常简单,并且有大量的日志记录 帮助分析解析器的行为。
如果你想找更复杂或优雅的东西,我 推荐欧芹(https://github.com/python-parsy/parsy)。
示例
fromparsikimportParser,ParseFailure,\ Any,Char,EOF,Fail,OneOrMore,Optional,R,\ Regex,Sequence,Times,ZeroOrMore,silent# A grammar for 7- or 10-digit phone numbers.grammar={'PHONENUM':Sequence(Optional('AREACODE'),'THREE',silent(Char('-')),'FOUR'),'AREACODE':Sequence(silent(Char('(')),'THREE',silent(Regex(r'\) ')),on_match=lambdax:x[0]),'THREE':Regex(r'\d{3}'),# three digits'FOUR':Regex(r'\d{4}'),# four digits}parser=Parser(grammar,"Phone numbers")output=parser.parse("PHONENUM","123-4567")assertoutput==['123','4567']output=parser.parse("PHONENUM","(555) 123-4567")assertoutput==['555','123','4567']try:parser.parse("PHONENUM","123-456")exceptParseFailure:passelse:assertFalse
匹配器
Parsik提供了几个“matcher”,您可以使用它们来表达语法: 诸如sequence、optional、zeroormore、regex等组件。这些匹配器可以 能够组合并引用语法中的其他规则;即使是递归的,因此 只要它们不是“左递归”的,就可能导致无限循环。
包括的匹配者是:
- char:匹配单个字符。
- regex:匹配正则表达式。
- eof:匹配输入字符串的结尾。
- R:匹配语法中其他地方定义的规则。
- 但通常您可以使用字符串按名称引用规则。
- 可选:可选匹配项。
- 任何:匹配多个可能项目中的任何一个。
- 序列:按特定顺序匹配项序列。
- 次数:匹配一个项目的特定次数或次数范围。
- 零或更多:匹配一个项目零或更多次。
- 一次或多次:匹配一个项目一次或多次。
- 失败:如果项目匹配,则中止分析。
你也可以自己做火柴。
没有任何特殊的语法或运算符重载来表示 语法。它只是一个字典,其中的键是规则名和值 是媒人。有些匹配者,如sequence,是由其他匹配者或 规则。他们只是在构造器中获取子匹配器的列表。你 也可以按名称引用其他语法规则,即使它形成一个循环。
日志记录
parsik使用python的标准日志。如果在调试级别启用它:
logging.basicConfig(level=logging.DEBUG, format='%(message)s')
然后您将得到对任何解析尝试的详细分析。例如:
grammar={'MAIN':Sequence('FIRST','SECOND','THIRD'),'FIRST':ZeroOrMore(Regex(r'ab')),'SECOND':Any(Char('x'),Char('y')),'THIRD':'FIRST',}p=Parser(grammar,"Quick example")p.parse("MAIN","ababy")
这将记录:
Parsing Quick example {MAIN} against input string 'ababy'.
pos input output ✓|✕ rule rule details
------- ---------- ------------------- --- --------------- -------------------------
0 'a' MAIN [[{FIRST},{SECOND},{THIRD}]]
0 'a' {FIRST}
0 'a' FIRST *(r'ab')
0 'a' r'ab'
0-2 'ab' 'ab' ✓ r'ab'
2 'a' r'ab'
2-4 'ab' 'ab' ✓ r'ab'
4 'y' r'ab'
4 '' ✕ r'ab'
0-4 'abab' '[ab, ab]' ✓ FIRST *(r'ab')
0-4 'abab' '[ab, ab]' ✓ {FIRST}
4 'y' {SECOND}
4 'y' SECOND any(['x', 'y'])
4 'y' 'x'
4 '' ✕ 'x'
4 'y' 'y'
4-$ 'y' 'y' ✓ 'y'
4-$ 'y' 'y' ✓ SECOND any(['x', 'y'])
4-$ 'y' 'y' ✓ {SECOND}
5 '$' {THIRD}
5 '$' THIRD {FIRST}
5 '$' FIRST *(r'ab')
5 '$' r'ab'
5-$ '$' ✕ r'ab'
5-$ '$' '[]' ✓ FIRST *(r'ab')
5-$ '$' '[]' ✓ THIRD {FIRST}
5-$ '$' '[]' ✓ {THIRD}
0-$ 'a' '[[ab, ab], y, []]' ✓ MAIN [[{FIRST},{SECOND},{THIRD}]]
Parse success: '[[ab, ab], y, []]'.
每行显示递归下降解析尝试中的一个步骤。媒人会 在尝试匹配之前和之后立即记录行。所以, 其中一行中的列为空,另一行中的结果为空。
列为:
- 位置:在视图下输入文档中的位置(字符)。
$
表示已到达终点。
- 输入:输入文件在这些位置的文本。
- 输出:如果匹配器成功,这是它的输出。
- :
- 空白表示匹配者将尝试匹配。
- 也就是说比赛成功了。
- 表示比赛失败。
- 规则:规则的名称,如果匹配器是语法中的命名规则。
- 规则详细信息:匹配者将尝试执行的操作的简明表示
承认。它们显示为:
- 字符:
'x'
- 正则表达式:
r'pattern'
- eof:
EOF
- r:
{rule name}
- 可选:
?(...)
- 任何:
any(...)
- 序列:
[...]
- 次数:
X{min,max}(...)
- 零或更多:
*(...)
- 一个或多个:
+(...)
- 失败:
Fail(...)
- 字符:
许可证
此软件包在GNU GPL v3下获得许可。