跳转到主要内容

基于函数组合子的递归下降解析库

项目描述

Funcparserlib

基于函数组合子的Python递归下降解析库。

PyPI PyPI - Downloads

描述

funcparserlib的主要重点是解析小语言或外部DSL(领域特定语言)。

使用funcparserlib制作的解析器是纯Python LL(*)解析器。这意味着可以很容易地编写解析器,而不必考虑前瞻和其他核心解析内容。然而,与LL(k)或LR(k)算法相比,递归下降解析是一种相对较慢的方法。尽管如此,使用funcparserlib进行解析至少比PyParsing快两倍,PyParsing是Python中一个非常流行的库。

funcparserlib的源代码只有1.2K行代码,注释很多。它的API完全有类型提示。它具有最长解析前缀错误报告,以及一个用于跟踪令牌位置的微小词法分析器生成器。

funcparserlib中使用的解析器组合器的想法来自函数式编程导论课程。我们将它从ML转换为Python。

安装

您可以从PyPI安装funcparserlib

$ pip install funcparserlib

没有对其他库的依赖。

文档

  • 入门
    • 使用 funcparserlib 的起始点
  • API 参考
    • 了解 API 的详细信息

tests/ 目录中提供了几个示例

另请参阅变更日志

示例

让我们考虑一个小型的与 Python 表达式语法相似的 数值表达式 语言。以下是该语言中的一些表达式字符串

0
1 + 2 + 3
-1 + 2 ** 32
3.1415926 * (2 + 7.18281828e-1) * 42

以下是使用 funcparserlib 编写的此语言的词法分析和解析器的 完整源代码

from typing import List, Tuple, Union
from dataclasses import dataclass

from funcparserlib.lexer import make_tokenizer, TokenSpec, Token
from funcparserlib.parser import tok, Parser, many, forward_decl, finished


@dataclass
class BinaryExpr:
    op: str
    left: "Expr"
    right: "Expr"


Expr = Union[BinaryExpr, int, float]


def tokenize(s: str) -> List[Token]:
    specs = [
        TokenSpec("whitespace", r"\s+"),
        TokenSpec("float", r"[+\-]?\d+\.\d*([Ee][+\-]?\d+)*"),
        TokenSpec("int", r"[+\-]?\d+"),
        TokenSpec("op", r"(\*\*)|[+\-*/()]"),
    ]
    tokenizer = make_tokenizer(specs)
    return [t for t in tokenizer(s) if t.type != "whitespace"]


def parse(tokens: List[Token]) -> Expr:
    int_num = tok("int") >> int
    float_num = tok("float") >> float
    number = int_num | float_num

    expr: Parser[Token, Expr] = forward_decl()
    parenthesized = -op("(") + expr + -op(")")
    primary = number | parenthesized
    power = primary + many(op("**") + primary) >> to_expr
    term = power + many((op("*") | op("/")) + power) >> to_expr
    sum = term + many((op("+") | op("-")) + term) >> to_expr
    expr.define(sum)

    document = expr + -finished

    return document.parse(tokens)


def op(name: str) -> Parser[Token, str]:
    return tok("op", name)


def to_expr(args: Tuple[Expr, List[Tuple[str, Expr]]]) -> Expr:
    first, rest = args
    result = first
    for op, expr in rest:
        result = BinaryExpr(op, result, expr)
    return result

现在,考虑这个数值表达式:3.1415926 * (2 + 7.18281828e-1) * 42

让我们使用我们用 funcparserlib.lexer 创建的词法分析器来 tokenize() 它。

[
    Token('float', '3.1415926'),
    Token('op', '*'),
    Token('op', '('),
    Token('int', '2'),
    Token('op', '+'),
    Token('float', '7.18281828e-1'),
    Token('op', ')'),
    Token('op', '*'),
    Token('int', '42'),
]

让我们使用我们用 funcparserlib.parser 创建的解析器将这些标记解析成一个表达式树。

BinaryExpr(
    op='*',
    left=BinaryExpr(
        op='*',
        left=3.1415926,
        right=BinaryExpr(op='+', left=2, right=0.718281828),
    ),
    right=42,
)

入门指南中学习如何使用 funcparserlib 编写此解析器!

使用情况

一些使用 funcparserlib 作为显式依赖项的开源项目

  • Hy,一种嵌入到 Python 中的 Lisp 方言
    • 4.2K 星,版本 >= 1.0.0a0,Python 3.7+
  • Splash,由 Scrapinghub 提供的具有 HTTP API 的 JavaScript 渲染服务
    • 3.6K 星,版本 *。Python 3 在 Docker 中
  • graphite-beacon,Graphite 指标的一个简单警报系统
    • 459 星,版本 ==0.3.6,Python 2 和 3
  • blockdiag,从 spec-text 文件生成块图图像文件
    • 148 星,版本 >= 1.0.0a0,Python 3.7+
  • kll,键盘布局语言 (KLL) 编译器
    • 109 星,复制源代码,Python 3.5+

下一步

阅读入门指南开始学习 funcparserlib

项目详情


下载文件

下载适用于您的平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源代码分发

funcparserlib-1.0.1.tar.gz (17.2 kB 查看散列)

上传时间 源代码

构建分发

funcparserlib-1.0.1-py2.py3-none-any.whl (17.8 kB 查看散列)

上传时间 Python 2 Python 3

由以下提供支持