1

我想对 java 语法进行一些更改。例如,我想使用运算符“+”来添加向量。所以我想要这段代码:

public class Vector2 {
    public float x, y;
    public Vector2(float x, float y) {this.x = x;this.y = y;}
    public String toString() {...}

    public static Vector2 operator+(Vector2 a, Vector2 b) {
        return new Vector2(a.x + b.x, a.y + b.y);
    }

    public static void main(String[] args) {
        Vector2 a = new Vector2(3, 6);
        Vector2 b = new Vector2(2, 8);
        System.out.println(a + b);
    }
}

将被翻译成这个标准的java代码:

public class Vector2 {
    public float x, y;
    public Vector2(float x, float y) {this.x = x;this.y = y;}
    public String toString() {...}

    public static Vector2 operator_plus(Vector2 a, Vector2 b) {
        return new Vector2(a.x + b.x, a.y + b.y);
    }

    public static void main(String[] args) {
        Vector2 a = new Vector2(3, 6);
        Vector2 b = new Vector2(2, 8);
        System.out.println(Vector2.operator_plus(a, b));
    }
}

是否有一些好的和安全的方法可以像编写自己的编译器一样更容易地扩展 java 语法?

(我的意思不仅是运算符重载,而且本质上是扩展 java 语法的好方法。)

4

6 回答 6

6

由于 Java 不支持运算符重载,因此如果您真的想要该语法,则需要更改语言。

于 2012-12-12T12:06:54.047 回答
2

您可以查看Project Lombok的源代码以获得灵感。他们做了一些非常酷的转换。

于 2012-12-12T12:18:21.670 回答
1

这实际上取决于您想要执行的扩展类型。如果您想要功能语言的典型扩展,您可以使用结合了 OOP 和功能范式的scala 。也许您的扩展可以结合AspectJ和注释来解决。在最后一个资源中,您可以使用预编译器,但如果您认为您的扩展与 Java 的目的无关,您可以考虑使用最适合您当前需求的另一种语言。

于 2012-12-12T12:34:40.627 回答
1

我建议这样:

  1. 编写自己的或获得一个预处理器,这将使简单
  2. 替换创建一个脚本,该脚本将调用预处理器来创建临时文件
  3. 使用 java 编译器构建这些临时文件
于 2012-12-12T12:37:39.883 回答
1

你在谈论预处理器。快速答案是否定的——java 没有扩展语言的可能性。但我建议您查看MPS - 这是用于创建翻译器和 DSL 的工具。但它包含一些扩展 java 语言的示例(视频)。MPS 的主要优点之一是它具有 IntelliJ IDEA 插件 - 因此您可以轻松地将创建的扩展附加到此 IDE 并将它们用作语法糖。

于 2012-12-12T12:17:34.583 回答
0

如果您可以保持在 java 语法范围内,则可以创建注释处理器(javac 插件)来做您想做的事。注释处理器基本上是在编译时运行的 java 代码。(注意注解处理器不需要注解有任何关系)

在注释处理器的代码中使用一些技巧(基本上是强制转换),您可以访问 javac 的内部 AST - 这包括在编译期间重写 AST!

一个很好的介绍:Javac 黑客指南

用户使用您的插件所要做的就是在使用 javac 编译时将您的 .jar 包含在类路径中,因此它非常易于使用。(你可能也想做 IDE 插件)

这就是“ Java-OO ”javac-plugin 为 Java 添加运算符重载所做的工作(运算符重载不需要任何语法更改,因此它适用于注释处理器)。这也是流行的Project Lombok所做的。


然而,访问 javac 内部所需的黑客是“未记录/不受支持的”,因此它们总是存在停止处理 javac 新版本的危险。

于 2016-03-17T22:47:48.060 回答