Yoho 🔥 是一个用 Mojo 🔥 制作的玩具编译器,旨在生成 RISC-V 汇编语言。
开源地址:https://github.com/YichengDWu/yoho
阶段
该项目目前正在积极开发中。请参阅test.sh当前版本的编译器支持的示例程序。
概述
标记器
这个编译器的标记器是相当手动实现的。它re2在底层调用 Python 库进行正则表达式操作。
解析器
该解析器基于解析表达式语法 (PEG)。它能够从 .gram 文件自动生成解析器。以下是用于定义语法的元语法:
start: grammar ENDMARKER { grammar }
grammar: rules=rule+ { Grammar(rules) }
rule:
| NAME ':' NEWLINE INDENT rhs NL DEDENT { Rule(name.text, rhs)}
| NAME ':' rhs NL { Rule(name.text, rhs)}
rhs:
| '|' alt NEWLINE rhs { Rhs(List(alt) + rhs.args)}
| '|' alt NEWLINE { Rhs(List(alt)) }
| alt NEWLINE { Rhs(List(alt)) }
alt:
| items action { Alt(items, action) }
| items { Alt(items) }
items: items=named_item+ { Items(items) }
named_item:
| NAME '=' item { NamedItem(item, name.text)}
| item { NamedItem(item) }
item:
| atom '*' { Repeat0(atom) }
| atom '+' { Repeat1(atom) }
| sep=atom '.' node=atom '+' { Gather(sep.text, node) }
| atom
atom:
| '(' items ')' { Group(items.args) }
| NAME { Atom(name.text) }
| STRING { Atom(string.text) }
action: '{' target '}' { target }
target:
| NAME target_atoms { Action(target_atoms, name)}
| target_atom { Action(target_atom) }
target_atoms:
| target_atom target_atoms { String(target_atom + ' ' + target_atoms) }
| target_atom
target_atom:
| NAME { String(name.text) }
| NUMBER { String(number.text) }
| ',' { String(', ') }
| '+' { String(' + ') }
| '(' { String('(') }
| ')' { String(')') }
| '.' { String('.')}
该元语法提供了一种灵活而强大的方法来定义和生成解析器。
解析树可以很好地打印出来:
0:12 ┃ ┃ BinOp
0:1 ┃ '1' ┃ NUMBER ✔
1:2 ┃ '-' ┃ MINUS ✔
3:12 ┃ ┃ BinOp
3:8 ┃ ┃ BinOp
3:4 ┃ '2' ┃ NUMBER ✔
4:5 ┃ '+' ┃ PLUS ✔
5:8 ┃ ┃ BinOp
5:6 ┃ '3' ┃ NUMBER ✔
6:7 ┃ '*' ┃ STAR ✔
7:8 ┃ '2' ┃ NUMBER ✔
8:9 ┃ '-' ┃ MINUS ✔
9:12 ┃ ┃ BinOp
9:10 ┃ '3' ┃ NUMBER ✔
10:11 ┃ '/' ┃ SLASH ✔
11:12 ┃ '2' ┃ NUMBER ✔
代码生成
代码生成器只是读取 ast 并发出 RISC-V 汇编。是的,有些源代码可能看起来很傻,这在某种程度上是故意的。对于初次阅读的人来说,简单易读是我的首要任务。yoho 中没有 IR 或 LLVM/MLIR。
参考
该编译器的开发受到了以下项目的启发和参考:
chibicc:一个小型 C 编译器。
pegen:基于 PEG 的解析器生成器。
安装
先决条件
确保已安装以下软件:
Mojo 夜间版本。访问Mojo Lang 网站并按照说明下载并安装 Mojo 夜间版本。
RISC-V 工具链。访问本指南以安装 RISC-V 工具链。
安装编译器的步骤
克隆存储库。
构建编译器:
make yoho
运行测试:
make test
清理:
make clean
示例输出
以下是输出 RISC-V 汇编代码‘1 2+ 4 5-(4-3>2)’的示例:
.global main
main:
li t0, 1
li t1, 2
mul t0, t0, t1
li t1, 4
li t2, 5
mul t1, t1, t2
add t0, t0, t1
li t1, 4
li t2, 3
sub t1, t1, t2
li t2, 2
slt t1, t2, t1
sub t0, t0, t1
mv a0, t0
ret
test.sh更多示例程序请参阅。
贡献
受到chibicc维护干净提交历史的方法的启发,我们采用了类似的风格来处理贡献。
当在这个编译器中发现错误时,我会追溯到导致错误的原始提交,并重写提交历史,就好像这个错误从未存在过一样。这种方法虽然非常规,但可以确保每次提交都没有错误,这对于项目的完整性至关重要。
该存储库致力于“每次提交均无错误”。如果您发现错误并提交问题,我将通过重写历史记录将必要的更改应用于相关的先前提交。
执照
该项目采用 MIT 许可证。有关详细信息,请参阅LICENSE文件。