10 个版本

0.3.0-beta2022年7月22日
0.2.2 2022年1月10日
0.2.0 2021年1月4日
0.2.0-dev.22020年11月8日
0.1.1 2020年2月19日

#28 in 解析工具

Download history 565/week @ 2024-03-14 1044/week @ 2024-03-21 827/week @ 2024-03-28 825/week @ 2024-04-04 783/week @ 2024-04-11 699/week @ 2024-04-18 786/week @ 2024-04-25 854/week @ 2024-05-02 526/week @ 2024-05-09 1083/week @ 2024-05-16 850/week @ 2024-05-23 793/week @ 2024-05-30 860/week @ 2024-06-06 1078/week @ 2024-06-13 1260/week @ 2024-06-20 992/week @ 2024-06-27

4,305 每月下载量
用于 18 个 crate (12 个直接使用)

BSD-3-Clause

470KB
10K SLoC

antlr4rust

Crate docs ANTLR4 testsuite cargo test

ANTLR4 运行时库 for Rust 编程语言。

有关示例,请参阅 grammarstests/gen 对应生成的代码以及 tests/my_tests.rs 实际使用示例

ANTLR4 工具(解析生成器)

生成器部分目前位于我 ANTLR4 分支的 rust-target 中 rrevenantt/antlr4/tree/rust-target。最新版本将自动构建到本仓库的 releases 中。所以如果您只想生成解析器或只想为运行时部分做出贡献,您不需要自己构建。

但如果你想自己构建或修改生成器

  • git clone -b rust-target https://github.com/rrevenantt/antlr4 - 克隆我的 ANTLR4 分支
  • git submodule update --init --recursive - 更新 Rust 目标子模块
  • mvn -DskipTests install - 构建生成器

实现状态

目前开发正在进行此仓库中,但最终将合并到主 ANTLR4 仓库

自版本 0.3 起支持稳定 Rust。之前的版本不再维护,因此如果遇到夜间版本破坏,应升级到最新版本。

用法

您应使用 ANTLR4 "工具" 生成一个解析器,该解析器将使用此处定位的 ANTLR 运行时。您可以使用以下命令运行它

java -jar <path to ANTLR4 tool> -Dlanguage=Rust MyGrammar.g4

有关 antlr4 工具选项的完整列表,请访问 工具文档页面

您还可以将 build.rs 作为 build.rs 配置的示例,如果语法文件发生变化,可以自动重新构建解析器。

然后添加以下内容到将要使用生成的解析器的crate的 Cargo.toml 文件中

[dependencies]
antlr-rust = "0.3"

解析树结构

可以生成惯用的Rust语法树。为此,您需要使用ANTLR工具的标签功能。例如,您可以查看 Labels 语法。考虑以下规则

e   : a=e op='*' b=e   # mult
    | left=e '+' b=e   # add
		 

对于此类规则,ANTLR将生成包含 multadd 选择项的枚举 EContextAll,因此您可以在代码中匹配这些选择项。此外,每个选择项对应的相应结构将包含您标记的字段。例如,对于 MultContext 结构,它将包含包含子子树的 ab 字段,以及包含 TerminalNode 类型(对应于单个 Token)的 op 字段。还有可能通过 parser.build_parse_trees = false 禁用泛型解析树创建,以仅保留选定的子树,但遗憾的是,这会阻止访问者工作。

与Java的差异

尽管Rust运行时API被设计得尽可能接近Java,但由于Rust不是面向对象的编程语言并且更为明确,所以存在一些差异。

  • 如果您使用标记的选择项,为规则生成的结构是一个枚举,其中包含每个选择项的一个变体
  • 解析器需要拥有监听器的所有权,但可以通过 ListenerId 获取监听器,否则应使用 ParseTreeWalker
  • 在嵌入的动作中访问解析器时,应使用 recog 变量而不是 self/this。这是因为谓词必须插入到生成的解析器中两个语法上不同的位置,而在其中一个位置中,不可能有解析器作为 self
  • 基于str的 InputStream 在存在Unicode字符时具有不同的索引行为。如果您需要完全相同的行为,请使用基于 u32InputStream,或者实现自定义 CharStream
  • 在动作中,您必须在Rust生命周期中的 ' 前面添加转义字符 \,因为ANTLR将它们视为字符串,例如,Struct<\'lifetime>
  • 要创建自定义标记,应使用 @tokenfactory 自定义动作,而不是通常的 TokenLabelType 解析器选项。ANTLR解析器选项只能接受单个标识符,而Rust目标需要了解生命周期。此外,在Rust目标中,TokenFactory 是指定标记类型的方式。例如,您可以在 CSV 测试语法中查看示例。
  • 所有规则上下文变量(规则参数或规则返回值)应实现 Default + Clone

基准测试

以下是antlr生成的XML词法分析器和解析器(使用默认的XML语法,但带有自定义的最小Token/TokenFactory/InputStream/RuleContext)与Rust生态系统中的手写实现的比较。请注意,xmlparserquick_xml更接近于词法分析器而不是解析器,因此它们应该与antlr词法分析器进行比较。此外,虽然生成的词法分析器和解析器所使用的结构体已被自定义以跟踪所需的最小数据(这是antlr-rust的任何用户都可以做到的),但词法分析器的内部结构仍无法足够自定义,并且仍然跟踪大量可能在特定情况下未使用的数据。因此,仍有改进的空间。

lexers:
large/large_xmlparser        time:   [1.8598 ms 1.8607 ms 1.8619 ms]                                   
large/large_quick_xml        time:   [1.4623 ms 1.4645 ms 1.4675 ms]                                   
large/large_antlr_xml_lexer  time:   [5.7866 ms 5.7877 ms 5.7891 ms]
parsers:
large/large_xmlrs            time:   [16.734 ms 16.748 ms 16.766 ms]
large/large_minidom          time:   [7.0639 ms 7.0792 ms 7.0975 ms]                                
large/large_roxmltree        time:   [4.9341 ms 4.9360 ms 4.9380 ms]                                   
large/large_antlr_xml_full   time:   [10.243 ms 10.248 ms 10.252 ms]                                  

不安全

目前,仅用于向下转换(通过单独的crate)和通过get_mut_unchecked更新Rc中的数据(返回的可变引用被立即使用,且未存储在任何地方)

版本控制

除了常规的Rust语义版本控制之外,crate的补丁版本更改不应需要更新生成器部分

许可证

BSD 3条款。除非你明确声明,否则你提交给本项目包含在内的任何贡献都应按上述方式许可,不得附加任何额外条款或条件。

依赖关系

~1–1.4MB
~23K SLoC