29 个版本 (19 个重大更新)
0.19.0 | 2024年5月21日 |
---|---|
0.18.0 | 2023年10月4日 |
0.17.0 | 2023年9月28日 |
0.11.0 | 2023年7月25日 |
0.0.0 | 2021年9月1日 |
#371 在 解析器实现
每月188 次下载
用于 3 个crate(2 个直接使用)
1MB
19K SLoC
fea-rs
解析和编译 Adobe OpenType 特征 文件。
状态:我们应该能够编译大多数输入。一些生成的表可能不是最优的,但应该是正确的。一些晦涩的语法可能不受支持。请报告错误。
快速入门
要使用此工具从 UFO 文件编译 OpenType 特征
$ cargo run PATH_TO_FONT.ufo -o my_generated_font.ttf
或者,您可以直接提供 FEA 文件的路径,在这种情况下,您还需要提供包含字形顺序的文件的路径:每行一个字形,使用 utf-8 编码。
$ cargo run features.fea --glyph-order glyph_order.txt -o my_font.ttf
测试
此 crate 使用多种测试策略,尽管所有测试都可以通过 cargo test
运行。
除了单元测试之外,我们还有一个自定义的属性测试系统来测试解析和编译。这涉及到存储在 test-data
目录中的数据。这些测试通过获取一些输入,生成一些输出,然后将该输出与测试数据中包含的预期输出进行比较来完成。这有三种不同的格式
- 解析测试:这些确保我们为各种输入生成预期的抽象语法树或错误。有关概述,请参阅
test-data/parse-tests/README.md
。 - 编译测试:这些测试确保我们为各种输入生成预期的TTX输出或错误。请参阅
test-data/compile-tests/README.md
以获取概述。 - fonttools测试:与编译测试非常相似,但不同之处在于,我们不是自己定义用例,而是重用fonttools feaLib中的属性测试。这确保我们生成的输出与feaLib相同。
架构草图
这个crate的整体设计在很大程度上受到rust analyzer的设计的启发。在非常高的层次上,给定一些源代码,我们
- 词法分析源文件到原始标记(src/parse/lexer.rs)
- 解析这些标记到一个抽象语法树(src/parse/parser.rs)
- 验证这个树,确保它符合规范(src/compile/validate.rs)
- 编译验证后的树到OpenType表中(src/compile/compile_ctx.rs)
解析
解析被分为词法分析和解析步骤。词法分析识别标记(数字、字符串、标识符、符号、关键字)但没有关于FEA语言语法的知识。解析接收一个标记流,并从中构建一个语法树。
解析器是“错误恢复”的:当解析失败时,解析器跳过标记直到找到可能在当前上下文中开始有效语句的东西,然后再次尝试。错误被收集,并在最后报告。
AST
AST设计是从rust analyzer的一部分AST in rowan中借鉴的。基本思想是,在构建AST节点时,我们确保该节点内容的一些事情是真的。然后我们可以使用该节点的类型(由我们分配)将该节点转换为知道如何解释该节点内容的具体类型。
验证
在构建AST之后,我们执行验证过程。这检查树中的语句是否符合规范:例如,它检查引用的名称是否存在,或者给定的语句是否允许在特定的表块中。验证也是“错误恢复”的;如果某些东西无法验证,我们将继续检查树的其余部分,并在最后报告所有错误。
如果验证成功,则编译应该总是成功。
编译
在验证之后,我们进行最后的编译过程,该过程遍历树并组装各种表和查找。这使用fontations生成表,然后可以将它们添加到字体中。
一些通用设计概念
- 在给定的“阶段”,收集遇到的错误并在最后报告它们。例如,在解析过程中,即使发生错误,我们也会继续解析,并在解析完成后报告所有解析错误。
依赖关系
~9–13MB
~245K SLoC