python左右解析器


pyleri的Python项目详细描述

python左右解析器

pyleri是为siridb创建的一个易于使用的解析器。我们首先使用了lrparsinglrparsing,并在我们的web控制台中编写了jslerijsleri,用于自动完成和建议。后来,我们在lrparsing模块中发现了一些小问题,并且在所有项目中都很难保持语言相同。当我们决定创建Pyleri时,可以将创建的语法导出到JavaScript、C、Python、Go和Java.<



相关项目

  • jsleri:javascript解析器
  • libcleri:c解析器
  • goleri:go parser
  • = HRFF="HTTPS://GITHUBCOM/TyrPopeTeReTeaTys/JLeRI"Re="NoFoLoLo>"JLeRi :Java解析器

安装

最简单的方法是使用pypi:

sudo pip3 install pyleri

快速使用

# Imports, note that we skip the imports in other examples...
from pyleri import (
    Grammar,
    Keyword,
    Regex,
    Sequence)

# Create a Grammar Class to define your language
class MyGrammar(Grammar):
    r_name = Regex('(?:"(?:[^"]*)")+')
    k_hi = Keyword('hi')
    START = Sequence(k_hi, r_name)

# Compile your grammar by creating an instance of the Grammar Class.
my_grammar = MyGrammar()

# Use the compiled grammar to parse 'strings'
print(my_grammar.parse('hi "Iris"').is_valid) # => True
print(my_grammar.parse('bye "Iris"').is_valid) # => False
print(my_grammar.parse('bye "Iris"').as_str()) # => error at position 0, expecting: hi

语法

当你写语法的时候,你应该把语法分类。语法要求至少有一个start属性,这样解析器就知道从哪里开始解析。语法有一些默认属性,可以覆盖,如re_keywords,稍后将对其进行解释。语法也有一个解析方法:parse(),还有一些导出方法:export嫒js()export嫒c()export嫒py()export懔u java()如下所述。

解析

语法:

Grammar().parse(string)

parse()方法返回一个result对象,该对象具有以下属性,这些属性将在result中进一步解释:

  • 需要
  • 是否有效
  • pos

导出j

语法:

Grammar().export_js(
    js_module_name='jsleri',
    js_template=Grammar.JS_TEMPLATE,
    js_indent=' ' * 4)

可选关键字参数:

    代码> JSXMeimeEngEng/<代码>:Java的名称脚本模块。(默认值:"jsleri")
  • js_template:用于导出的模板字符串。您可能需要查看grammar.js_模板中的默认字符串。
  • js_indent:在javascript文件中使用的缩进。(默认值:4个空格)

例如,当使用快速用法语法时,这是运行my_grammar.export_js()时的输出:

/* jshint newcap: false */

/*
 * This grammar is generated using the Grammar.export_js() method and
 * should be used with the jsleri JavaScript module.
 *
 * Source class: MyGrammar
 * Created at: 2015-11-04 10:06:06
 */

'use strict';

(function (
            Regex,
            Sequence,
            Keyword,
            Grammar
        ) {
    var r_name = Regex('^(?:"(?:[^"]*)")+');
    var k_hi = Keyword('hi');
    var START = Sequence(
        k_hi,
        r_name
    );

    window.MyGrammar = Grammar(START, '^\w+');

})(
    window.jsleri.Regex,
    window.jsleri.Sequence,
    window.jsleri.Keyword,
    window.jsleri.Grammar
);

出口C

语法:

Grammar().export_c(
    target=Grammar.C_TARGET,
    c_indent=' ' * 4)

可选关键字参数:

  • 目标:C模块的名称。(默认:"语法")
  • c_indent:在c文件中使用的缩进。(默认值:4个空格)

返回值是包含源(C)文件和头(H)文件的元组。

例如,当使用快速用法语法时,这是运行my_grammar.export_c()时的输出:

/*
 * grammar.c
 *
 * This grammar is generated using the Grammar.export_c() method and
 * should be used with the libcleri module.
 *
 * Source class: MyGrammar
 * Created at: 2016-05-09 12:16:49
 */

#include "grammar.h"
#include <stdio.h>

#define CLERI_CASE_SENSITIVE 0
#define CLERI_CASE_INSENSITIVE 1

#define CLERI_FIRST_MATCH 0
#define CLERI_MOST_GREEDY 1

cleri_grammar_t * compile_grammar(void)
{
    cleri_t * r_name = cleri_regex(CLERI_GID_R_NAME, "^(?:\"(?:[^\"]*)\")+");
    cleri_t * k_hi = cleri_keyword(CLERI_GID_K_HI, "hi", CLERI_CASE_INSENSITIVE);
    cleri_t * START = cleri_sequence(
        CLERI_GID_START,
        2,
        k_hi,
        r_name
    );

    cleri_grammar_t * grammar = cleri_grammar(START, "^\\w+");

    return grammar;
}

还有头文件…

/*
 * grammar.h
 *
 * This grammar is generated using the Grammar.export_c() method and
 * should be used with the libcleri module.
 *
 * Source class: MyGrammar
 * Created at: 2016-05-09 12:16:49
 */
#ifndef CLERI_EXPORT_GRAMMAR_H_
#define CLERI_EXPORT_GRAMMAR_H_

#include <grammar.h>
#include <cleri/cleri.h>

cleri_grammar_t * compile_grammar(void);

enum cleri_grammar_ids {
    CLERI_NONE,   // used for objects with no name
    CLERI_GID_K_HI,
    CLERI_GID_R_NAME,
    CLERI_GID_START,
    CLERI_END // can be used to get the enum length
};

#endif /* CLERI_EXPORT_GRAMMAR_H_ */

导出'u go

语法:

Grammar().export_go(
    go_template=Grammar.GO_TEMPLATE,
    go_indent='\t',
    go_package='grammar')

可选关键字参数:

  • 转到模板:用于导出的模板字符串。您可能需要查看语法中的默认字符串。请使用模板。
  • 执行缩进:执行文件中使用的缩进。(默认:一个选项卡)
  • go_package:go package的名称。(默认:"语法")

例如,当使用快速用法语法时,这是运行my_grammar.export_go()时的输出:

sudo pip3 install pyleri
0

导出Java

语法:

sudo pip3 install pyleri
1

可选关键字参数:

  • java_template:用于导出的模板字符串。您可能需要查看grammar.java_模板中的默认字符串。
  • >代码> javaj-DutoNo./C> >:Java文件中使用的缩进。(默认值:四个空格) >代码JavaAuths:Java包的名称或在没有指定包时是不存在的。(默认值:无)
  • 是公共的:当为true时,类和构造函数被定义为公共的,否则它们将被定义为包私有的。

例如,当使用快速用法语法时,这是运行my_grammar.export_java()时的输出:

sudo pip3 install pyleri
2

导出py

语法:

sudo pip3 install pyleri
3

可选关键字参数:

  • py_module_name:pyleri模块的名称。(默认值:"pyleri")
  • py_template:用于导出的模板字符串。您可能需要查看grammar.py_模板中的默认字符串。
  • py_indent:python文件中使用的缩进。(默认值:4个空格)

例如,当使用快速用法语法时,这是运行my_grammar.export_py()时的输出:

sudo pip3 install pyleri
4

结果

parse()方法的结果包含4个属性,下面将解释这些属性。还提供了一个函数as_str(translate=none),它将 将结果显示为字符串。translate参数应该是接受元素作为参数的函数。此函数可用于 返回某些元素的自定义字符串。如果translate的返回值为none则函数将失败,尝试生成字符串值。如果 返回值为空字符串,将忽略该值。

翻译函数示例:

sudo pip3 install pyleri
5

有效吗

是有效的返回一个布尔值,真的根据给定的语法,给定的字符串有效时,假的无效时。

让我们以快速使用为例。

sudo pip3 install pyleri
6

位置

pos返回解析器必须停止的位置。(当有效时真时该值将等于应用str.rstrip()的给定字符串的长度)

让我们以快速使用为例。

sudo pip3 install pyleri
7

包含解析树。即使有效也会返回解析树,但仅在解析成功时才包含结果。树是根节点,它可以包含几个子节点节点。下面的示例将进一步阐明该结构,该示例解释了可视化解析树的方法。

示例:

sudo pip3 install pyleri
8

部分输出如下所示。

sudo pip3 install pyleri
9

一个节点包含5个属性,下面将解释这些属性:

  • 开始属性返回节点对象的开始。
  • end属性返回节点对象的结尾。
  • 元素返回元素的类型(例如repeat、sequence、keyword等)。可以将元素分配给变量;例如,在上面的示例中,keyword('hi')被分配给了khi。使用element.name将返回指定的名称k_hi。请注意,并不是给定元素是命名的;在我们的示例中,序列没有赋值,因此在这种情况下,元素没有属性名称
  • 字符串返回已分析的字符串。
  • 子节点可以返回包含更深层节点的节点对象,前提是存在任何节点。在我们的示例中,根节点有一个元素类型repeat(),从0开始,到24结束,它有两个子节点。这些子节点对象都具有元素类型序列,分别从0和12开始,依此类推。

期望

需要返回一个python set(),其中包含pyleri在pos处需要的元素。即使是有效的也是真的,这个集合中也可能有元素,例如,当可以向字符串中添加optional()元素时。如果要实现自动完成、语法错误处理、自动语法更正等功能,expecting非常有用。下面的示例将演示一种实现方法。

示例:

# Imports, note that we skip the imports in other examples...
from pyleri import (
    Grammar,
    Keyword,
    Regex,
    Sequence)

# Create a Grammar Class to define your language
class MyGrammar(Grammar):
    r_name = Regex('(?:"(?:[^"]*)")+')
    k_hi = Keyword('hi')
    START = Sequence(k_hi, r_name)

# Compile your grammar by creating an instance of the Grammar Class.
my_grammar = MyGrammar()

# Use the compiled grammar to parse 'strings'
print(my_grammar.parse('hi "Iris"').is_valid) # => True
print(my_grammar.parse('bye "Iris"').is_valid) # => False
print(my_grammar.parse('bye "Iris"').as_str()) # => error at position 0, expecting: hi
0

输出:

# Imports, note that we skip the imports in other examples...
from pyleri import (
    Grammar,
    Keyword,
    Regex,
    Sequence)

# Create a Grammar Class to define your language
class MyGrammar(Grammar):
    r_name = Regex('(?:"(?:[^"]*)")+')
    k_hi = Keyword('hi')
    START = Sequence(k_hi, r_name)

# Compile your grammar by creating an instance of the Grammar Class.
my_grammar = MyGrammar()

# Use the compiled grammar to parse 'strings'
print(my_grammar.parse('hi "Iris"').is_valid) # => True
print(my_grammar.parse('bye "Iris"').is_valid) # => False
print(my_grammar.parse('bye "Iris"').as_str()) # => error at position 0, expecting: hi
1

在上面的例子中,我们根据语法类分析了一个无效字符串。我们为本例构建的auto-correction()方法结合了parse()中的所有属性来创建有效的字符串。输出显示auto-correction()方法的每个递归,并连续打印期望的元素集。它随机抽取一个并将其添加到字符串中。当字符串与语法对应时,属性有效将返回。值得注意的是,预期的属性仍然包含元素,即使是有效的返回了真的。本例中的原因是因为repeat元素。

元素

pyleri有几个元素,它们都是元素的子类,可以用来创建语法。

关键字

语法:

# Imports, note that we skip the imports in other examples...
from pyleri import (
    Grammar,
    Keyword,
    Regex,
    Sequence)

# Create a Grammar Class to define your language
class MyGrammar(Grammar):
    r_name = Regex('(?:"(?:[^"]*)")+')
    k_hi = Keyword('hi')
    START = Sequence(k_hi, r_name)

# Compile your grammar by creating an instance of the Grammar Class.
my_grammar = MyGrammar()

# Use the compiled grammar to parse 'strings'
print(my_grammar.parse('hi "Iris"').is_valid) # => True
print(my_grammar.parse('bye "Iris"').is_valid) # => False
print(my_grammar.parse('bye "Iris"').as_str()) # => error at position 0, expecting: hi
2

解析器需要匹配只是一个字符串的关键字。当匹配关键字时,我们需要告诉解析器关键字中允许哪些字符。默认情况下,pyleri使用的^\w+在python和javascript中都等于^[a-za-z0-9++。我们可以通过在语法中设置re_keywords来覆盖默认值。keyword()接受一个keyword参数ign_case来告诉解析器是否应该匹配不区分大小写。

示例:

# Imports, note that we skip the imports in other examples...
from pyleri import (
    Grammar,
    Keyword,
    Regex,
    Sequence)

# Create a Grammar Class to define your language
class MyGrammar(Grammar):
    r_name = Regex('(?:"(?:[^"]*)")+')
    k_hi = Keyword('hi')
    START = Sequence(k_hi, r_name)

# Compile your grammar by creating an instance of the Grammar Class.
my_grammar = MyGrammar()

# Use the compiled grammar to parse 'strings'
print(my_grammar.parse('hi "Iris"').is_valid) # => True
print(my_grammar.parse('bye "Iris"').is_valid) # => False
print(my_grammar.parse('bye "Iris"').as_str()) # => error at position 0, expecting: hi
3

正则表达式

语法:

# Imports, note that we skip the imports in other examples...
from pyleri import (
    Grammar,
    Keyword,
    Regex,
    Sequence)

# Create a Grammar Class to define your language
class MyGrammar(Grammar):
    r_name = Regex('(?:"(?:[^"]*)")+')
    k_hi = Keyword('hi')
    START = Sequence(k_hi, r_name)

# Compile your grammar by creating an instance of the Grammar Class.
my_grammar = MyGrammar()

# Use the compiled grammar to parse 'strings'
print(my_grammar.parse('hi "Iris"').is_valid) # => True
print(my_grammar.parse('bye "Iris"').is_valid) # => False
print(my_grammar.parse('bye "Iris"').as_str()) # => error at position 0, expecting: hi
4

解析器使用re模块编译正则表达式。当前版本的pyleri只支持re.ignorecase标志。 有关如何使用regex的示例,请参见快速使用示例。

代币

语法:

# Imports, note that we skip the imports in other examples...
from pyleri import (
    Grammar,
    Keyword,
    Regex,
    Sequence)

# Create a Grammar Class to define your language
class MyGrammar(Grammar):
    r_name = Regex('(?:"(?:[^"]*)")+')
    k_hi = Keyword('hi')
    START = Sequence(k_hi, r_name)

# Compile your grammar by creating an instance of the Grammar Class.
my_grammar = MyGrammar()

# Use the compiled grammar to parse 'strings'
print(my_grammar.parse('hi "Iris"').is_valid) # => True
print(my_grammar.parse('bye "Iris"').is_valid) # => False
print(my_grammar.parse('bye "Iris"').as_str()) # => error at position 0, expecting: hi
5

代币可以是一个或多个字符,通常用于匹配+-//等运算符。当我们在pyleri需要元素的地方解析字符串对象时,它将自动转换为token()对象。

示例:

# Imports, note that we skip the imports in other examples...
from pyleri import (
    Grammar,
    Keyword,
    Regex,
    Sequence)

# Create a Grammar Class to define your language
class MyGrammar(Grammar):
    r_name = Regex('(?:"(?:[^"]*)")+')
    k_hi = Keyword('hi')
    START = Sequence(k_hi, r_name)

# Compile your grammar by creating an instance of the Grammar Class.
my_grammar = MyGrammar()

# Use the compiled grammar to parse 'strings'
print(my_grammar.parse('hi "Iris"').is_valid) # => True
print(my_grammar.parse('bye "Iris"').is_valid) # => False
print(my_grammar.parse('bye "Iris"').as_str()) # => error at position 0, expecting: hi
6

代币

语法:

# Imports, note that we skip the imports in other examples...
from pyleri import (
    Grammar,
    Keyword,
    Regex,
    Sequence)

# Create a Grammar Class to define your language
class MyGrammar(Grammar):
    r_name = Regex('(?:"(?:[^"]*)")+')
    k_hi = Keyword('hi')
    START = Sequence(k_hi, r_name)

# Compile your grammar by creating an instance of the Grammar Class.
my_grammar = MyGrammar()

# Use the compiled grammar to parse 'strings'
print(my_grammar.parse('hi "Iris"').is_valid) # => True
print(my_grammar.parse('bye "Iris"').is_valid) # => False
print(my_grammar.parse('bye "Iris"').as_str()) # => error at position 0, expecting: hi
7

可用于同时注册多个令牌。tokens参数应该是一个由空格分隔的标记字符串。如果给定的标记大小不同,解析器将首先尝试匹配最长的标记。

示例:

# Imports, note that we skip the imports in other examples...
from pyleri import (
    Grammar,
    Keyword,
    Regex,
    Sequence)

# Create a Grammar Class to define your language
class MyGrammar(Grammar):
    r_name = Regex('(?:"(?:[^"]*)")+')
    k_hi = Keyword('hi')
    START = Sequence(k_hi, r_name)

# Compile your grammar by creating an instance of the Grammar Class.
my_grammar = MyGrammar()

# Use the compiled grammar to parse 'strings'
print(my_grammar.parse('hi "Iris"').is_valid) # => True
print(my_grammar.parse('bye "Iris"').is_valid) # => False
print(my_grammar.parse('bye "Iris"').as_str()) # => error at position 0, expecting: hi
8

顺序

语法:

# Imports, note that we skip the imports in other examples...
from pyleri import (
    Grammar,
    Keyword,
    Regex,
    Sequence)

# Create a Grammar Class to define your language
class MyGrammar(Grammar):
    r_name = Regex('(?:"(?:[^"]*)")+')
    k_hi = Keyword('hi')
    START = Sequence(k_hi, r_name)

# Compile your grammar by creating an instance of the Grammar Class.
my_grammar = MyGrammar()

# Use the compiled grammar to parse 'strings'
print(my_grammar.parse('hi "Iris"').is_valid) # => True
print(my_grammar.parse('bye "Iris"').is_valid) # => False
print(my_grammar.parse('bye "Iris"').as_str()) # => error at position 0, expecting: hi
9

解析器需要匹配序列中的每个元素。

示例:

Grammar().parse(string)
0

选择

语法:

Grammar().parse(string)
1

解析器需要在给定的元素中进行选择。choice接受一个关键字参数最贪婪的默认为。当most_greedy设置为false时,解析器将在第一次匹配时停止。当true时,解析器将尝试每个元素并返回最长的匹配。将most_greedy设置为false可以提供一些额外的性能。请注意,解析器将尝试以完全相同的顺序匹配每个元素,这些元素将按照选择的顺序进行解析。

示例:让我们使用选项修改快速使用示例,以允许字符串'bye"iris'

Grammar().parse(string)
2

重复

语法:

Grammar().parse(string)
3

解析器至少需要mi元素,最多需要ma元素。当ma设置为none时,我们允许无限数量的元素。mi可以是任何等于或大于0但不大于ma的整数值

示例:

Grammar().parse(string)
4

不允许将名称绑定到同一个元素两次,而repeat(element,1,1)是将元素绑定到第二个(或更多)时间的常见解决方案。

例如,请考虑以下内容:

Grammar().parse(string)
5

列表

语法:

Grammar().parse(string)
6

list类似于repeat,但带有分隔符。逗号用作默认分隔符,但允许使用任何元素。当字符串用作分隔符时,它将转换为标记元素。mima的工作方式与repeat完全相同。可选的关键字参数opt可以设置为true以允许列表以分隔符结尾。默认设置为false这意味着列表必须以元素结尾。

示例:

Grammar().parse(string)
7

可选

语法:

Grammar().parse(string)
8

解析器寻找一个可选元素。这就像使用repeat(element,0,1)但是我们鼓励使用可选的,因为它更具可读性。(稍微快一点)

示例:

Grammar().parse(string)
9

REF

语法:

Grammar().export_js(
    js_module_name='jsleri',
    js_template=Grammar.JS_TEMPLATE,
    js_indent=' ' * 4)
0

语法可以使前向引用成为可能,从而使递归成为可能。在下面的示例中,我们创建了一个forward引用以开始,但请注意 可以引用任何元素。

< Buff行情>

警告:引用不受在中测试同一位置的保护 一个字符串。这可能会导致无限循环。 例如:

Grammar().export_js(
    js_module_name='jsleri',
    js_template=Grammar.JS_TEMPLATE,
    js_indent=' ' * 4)
1

如果需要这种递归构造,请使用prio。

示例:

Grammar().export_js(
    js_module_name='jsleri',
    js_template=Grammar.JS_TEMPLATE,
    js_indent=' ' * 4)
2

优先级

语法:

Grammar().export_js(
    js_module_name='jsleri',
    js_template=Grammar.JS_TEMPLATE,
    js_indent=' ' * 4)
3

从prio元素中选择第一个匹配项,并允许this用于递归操作。使用这个我们指向prio元素。可能下面的示例解释了如何使用priothis

< Buff行情>

注意:如有可能,请使用aref。 当字符串中的同一位置可能是 检查了不止一次。

示例:

Grammar().export_js(
    js_module_name='jsleri',
    js_template=Grammar.JS_TEMPLATE,
    js_indent=' ' * 4)
4

推荐PyPI第三方库


热门话题
elasticsearchdsl 差异 presence zanata 列车 discriminator 环境噪声 tsbx util themer comparing scrapbook friedman cwe 装卸工 p3 geopython simd marionette dest gcd cassiopeia pyavatax mdx 下单 xlwt 扭矩 loremipsum unittests 离合器 field2 lomb tsfresh nomadblue audiences vivarium firewall res2 mrjob githubcom supernova mycache craigslist 高空 hewlett vitroid blinky 国际标准 outputfilters winxp