最小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下获得许可。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
空字符串检查在java中未按预期工作   JavaSpringWebClient:自动计算主体的HMAC签名并将其作为头传递   foreach是否有一个Java等效的foreach循环和一个引用变量?   java如何在Eclipse中导入jar   使用特定第三方或java时lombok触发错误。*方法或构造函数   安卓 java将对象数组转换为int数组   java使一定百分比的JUnit测试通过   java Android:将Seekbar的一个值与另一个值进行比较   java将int数组(图像数据)写入文件的最佳方式是什么   java取代了系统。yml的构造函数内的getProperty   sqlite Java将公钥和私钥转换为字符串,然后再转换回字符串   安卓获取白色像素并将其保存到java opencv中的数组中   java为什么是ServerSocket。setSocketFactory静态?   Java数组似乎在不直接修改的情况下更改值