#parser-generator #lexer #grammar #regex-parser #lexing #earley #run-time

bin+lib beans

基于 Earley 解析器的解析器生成库

19 个稳定版本 (6 个主要)

8.0.0 2023年4月20日
7.0.0 2023年4月13日
6.6.0 2022年12月5日
6.5.0 2022年11月25日
2.6.0 2022年11月2日

编程语言 中排名第 230

Download history 177/week @ 2024-03-30 25/week @ 2024-04-06

每月下载量 86

MIT 或 GPL-3.0 或更新版

270KB
7K SLoC

 _                                  
| |__     ___    __ _   _ __    ___ 
| '_ \   / _ \  / _` | | '_ \  / __|
| |_) | |  __/ | (_| | | | | | \__ \
|_.__/   \___|  \__,_| |_| |_| |___/
                                    

Beans 是一个词法和解析库。它允许编译语法,并在运行时加载它们,这使得它既适用于具有固定语法的语言,也适用于在其编译阶段语法可能变化的语言。

安装

Beans 目前没有正确打包,除非你有 Nix,否则安装是手动的。

手动安装

依赖项

Beans 是用纯 Rust 编写的,因此它的唯一依赖项是(最新稳定版)Rust 和几个 crate。这意味着,要构建 Beans,你只需要在你的机器上安装最新稳定的 Rust 编译器和 cargo(如果你不想手动做所有事情,还需要 make)。

下载 Beans 源代码

如果你已安装 git,则可以简单地运行 git clone https://github.com/jthulhu/beans。否则,你可以下载 zip 存档

构建 Beans

使用 make 构建 Beans

如果你也使用 make 安装 Beans,则可以跳过此步骤,因为它是在 install 规则的依赖项中。

$ make RELEASE=1 build

二进制文件位于 out/beans

手动构建 Beans

$ cargo build --release

二进制文件位于 target/release/beans

安装 Beans

使用 make 安装 Beans

$ make install

这将把 beans 安装在 /usr/local/bin/beans。如果你想更改安装目录,可以设置环境变量 DESTDIRPREFIX。默认情况下,它使用 DESTDIR=PREFIX=/usr/local

手动安装 Beans

$ install -D -m755 target/release/beans /usr/local/bin/beans

请确保将target/release/beans替换为二进制文件生成的目录,以及将/usr/local/bin/beans替换为您希望安装beans的位置。

卸载Beans

无论使用何种安装方法,Beans都是一个单一、自包含的二进制文件,不会创建任何配置文件。只需删除您安装它的二进制文件即可。

Nix Flake安装

Beans以github:jthulhu/beans#${system}.defaultPackage作为软件包,以github:jthulhu/beans#${system}.defaultApp作为应用程序提供,其中${system}可以是aarch64-darwinaarch64-linuxx86_64-darwinx86_64-linux

用法

Beans可以用作库,也可以用作应用程序。如果您想编译词法分析和解析语法,则使用应用程序。应用程序还可以进行词法分析和解析,这可能有助于调试。

编译

使用Beans的第一步是编写词法分析语法和解析语法,并按此顺序编译它们。这是因为解析语法依赖于终端的定义,这些定义可以在词法分析语法中找到。假设您有两个名为lexer.lxparser.gr的文件,请运行

$ beans compile lexer lexer.lx
# Will produce a file `lexer.clx`
$ beans compile parser --lexer lexer.clx parser.gr
# Will produce a file `lexer.cgr`
$ 

这两个文件现在可以在Rust代码中使用,如下所示

use beans::include_parser;

let (lexer, parser) = include_parser!(
    lexer => compiled "path/to/lexer.clx",
	parser => compiled "path/to/parser.cgr",
).unwrap();

这将把这两个blob打包到最终的二进制文件中。有关如何使用lexerparser来解析输入的更多详细信息,请参阅库文档

请注意,编译步骤实际上是可选的。您可以使用未编译的语法。当您希望在编译程序时允许用户修改语法时,这很有用。目前,此功能可能已损坏。

词法分析

Beans可以根据适当的语法在标准输出中生成一个标记流。例如,在文件input.c中显示

void f() {
  int x;
  int y;
  y = x = 0;
}

以及与C编程语言对应的词法分析语法,词法分析将显示以下结果

$ beans lex --lexer c.clx input.c
VOID { }
IDENT { 0: f, }
LPAR { }
RPAR { }
LBRACE { }
INTTY { }
IDENT { 0: x, }
SEMICOLON { }
INTTY { }
IDENT { 0: y, }
SEMICOLON { }
IDENT { 0: y, }
EQUAL { }
IDENT { 0: x, }
EQUAL { }
INT { 0: 0, }
SEMICOLON { }
RBRACE { }

由于输出目前相当难看,预计在可预见的未来将会改变。

解析

Beans可以根据适当的语法在标准输出中生成AST。例如,在之前显示的同一input.c中,结果将是

$ beans parse --lexer c.clx --parser c.cgr input.c
AST
└─ decls
   └─ value
      ├─ value
        ├─ variant
        │  └─ Nil
        └─ head
           ├─ name
           │  └─ f
           ├─ block
           │  └─ stmts
           │     └─ value
           │        ├─ value
           │        │  ├─ variant
           │        │  │  └─ Cons
           │        │  ├─ head
           │        │  │  ├─ declaration
           │        │  │  │  ├─ type
           │        │  │  │  │  └─ variant
           │        │  │  │  │     └─ Int
           │        │  │  │  ├─ value
           │        │  │  │  │  └─ variant
           │        │  │  │  │     └─ None
           │        │  │  │  └─ name
           │        │  │  │     └─ x
           │        │  │  └─ variant
           │        │  │     └─ Declaration
           │        │  └─ tail
           │        │     ├─ variant
           │        │     │  └─ Cons
           │        │     ├─ head
           │        │     │  ├─ variant
           │        │     │  │  └─ Declaration
           │        │     │  └─ declaration
           │        │     │     ├─ name
           │        │     │     │  └─ y
           │        │     │     ├─ value
           │        │     │     │  └─ variant
           │        │     │     │     └─ None
           │        │     │     └─ type
           │        │     │        └─ variant
           │        │     │           └─ Int
           │        │     └─ tail
           │        │        ├─ head
           │        │        │  ├─ stmt
           │        │        │  │  ├─ stmt
           │        │        │  │  │  ├─ key
           │        │        │  │  │  │  ├─ value
           │        │        │  │  │  │  │  └─ y
           │        │        │  │  │  │  └─ variant
           │        │        │  │  │  │     └─ Ident
           │        │        │  │  │  ├─ value
           │        │        │  │  │  │  ├─ value
           │        │        │  │  │  │  │  ├─ variant
           │        │        │  │  │  │  │  │  └─ Int
           │        │        │  │  │  │  │  └─ value
           │        │        │  │  │  │  │     ├─ variant
           │        │        │  │  │  │  │     │  └─ Int
           │        │        │  │  │  │  │     └─ value
           │        │        │  │  │  │  │        └─ 0
           │        │        │  │  │  │  ├─ key
           │        │        │  │  │  │  │  ├─ variant
           │        │        │  │  │  │  │  │  └─ Ident
           │        │        │  │  │  │  │  └─ value
           │        │        │  │  │  │  │     └─ x
           │        │        │  │  │  │  └─ variant
           │        │        │  │  │  │     └─ Assign
           │        │        │  │  │  └─ variant
           │        │        │  │  │     └─ Assign
           │        │        │  │  └─ variant
           │        │        │  │     └─ Regular
           │        │        │  └─ variant
           │        │        │     └─ Statement
           │        │        └─ variant
           │        │           └─ Nil
           │        └─ variant
           │           └─ Some
           ├─ rettype
           │  └─ variant
           │     └─ Void
           └─ args
              └─ value
                 └─ variant
                    └─ None
      └─ variant
         └─ Some
$

结果非常冗长,所以预计在可预见的未来会进行更改。

依赖项

~6.5MB
~110K SLoC