编译器在整个职业生涯中总是让我着迷。我想这是编译器采用高级代码并将其迅速转化为执行的内容的能力。我尝试过一次(对于我自己的编程语言)从头开始编写编译器,但它进展不顺利,但我能够从中学到很多东西。快进到今天,我终于编辑了“ OpenJDK17” /“ Corretto-17” Java编译器以添加自己的语法和功能。< / p>
通常用来将高级Java代码编译到.class文件或字节码的“ Javac”命令实际上是用Java编写的。这被称为Bootstrap编译器或“自我编译编译器”。这是用该语言编写的编译器。
Javac编译器在详细的层面上具有多个阶段,但是编译的主要步骤仍然遵守编译器理论 /编译器设计概念。他们是:
- 词汇分析(标记)
- 语法分析(解析)(生成一个解析树)
- 语义分析(类型检查,死亡代码分析等)
- 中级代码生成(可选)
- 目标代码生成(Bytecode)
- 代码优化
生成解析树后,每个其他阶段都是访客。它遵循访问者的设计模式。有一个流访问者(检查死亡代码),有一个Enter访问者(收集方法,类等符号)。有一个attr访问者可以键入检查。等。
要开始编辑Javac编译器,您需要首先在本地设置OpenJDK代码库。不幸的是,我找不到一组用于编译器开发的工具,但在这种情况下,我发现VSCODE是最简单的。 Intellij也有效,但我更喜欢VSCODE。 This page describes how to setup the codebase locally.
我要在此处添加的功能是“ JavaScript的选项链”操作员或“?”。操作员。在浏览了代码后,看来语法必须与三元操作员的语法代码一起编写。该代码在JavacParser.java
文件中存在。这是所有解析JCTree
发生的地方。
/** Expression1Rest = ["?" Expression ":" Expression1]
*/
JCExpression term1Rest(JCExpression t) {
if (token.kind == QUES) {
int pos = token.pos;
nextToken();
// option chaining
if (token.kind == DOT) {
accept(DOT);
var ident = ident();
JCExpression returnable = F.at(pos).Conditional(
F.at(pos).Parens(F.at(pos).Binary(optag(TokenKind.EQEQ), F.at(pos).Literal(TypeTag.BOT, null), t)),
F.at(pos).Literal(TypeTag.BOT, null), F.at(pos).Select(t, ident));
return term1Rest(returnable);
}
// ternary
JCExpression t1 = term();
accept(COLON);
JCExpression t2 = term1();
return F.at(pos).Conditional(t, t1, t2);
} else {
return t;
}
}
在这里,语法被称为accept(DOT)
。点是Tokens.java
此功能的工作方式是,用类似于此代码的自定义树代替JCFieldAccess Select(...)
子树:
(t == null) ? null : t.ident;
这是选项链接的工作方式。
此功能如何工作的一个示例就是这样:
代码片段:
public class Test {
public static void main(String[] args) {
Car car = new Car();
Integer wheel1 = car?.w1?.x;
Integer wheel2 = car?.w2?.x;
System.out.println("value of wheel1 is: " + wheel1);
System.out.println("value of wheel2 is: " + wheel2);
}
public static class Car {
Wheel w1 = null;
Wheel w2 = new Wheel();
public Car() {
}
}
public static class Wheel {
int x = 2;
public Wheel() {
}
}
}
这仍然不是完美的,并且有自己的问题,但是无论它是一个非常有趣的旅程,可以理解编译器的编写方式。我能够从中学到很多东西。
参考:
https://openjdk.org/groups/compiler/doc/hhgtjavac/index.html
我的承诺:
https://github.com/corretto/corretto-17/commit/37b125992c7d2b6fb55216e553168bf7b8a3a4b4