给Java解析器/词法分析器提供指令

时间:2011-02-23 00:21:22

标签: java parsing lexer

有没有办法直接向java代码级别的解析器和lexar发出指令?如果没有,怎么可能会这样做呢?

问题是我希望解析器评估变量,备份,然后将该变量的值指定为Object名称。像这样:

String s = "text";

SomeClass (s) = new SomeClass();

解析器读取 - >好吧,s评估为“文字”......  解析器回溯,同时在内存中保存“text”并将“text”指定为SomeClass的新实例的名称,以便现在可以执行此操作:

text.callSomeMethod();

我需要这样做,因为我必须实例化SomeClass的任意数量的对象。每个人都必须有一个独特的名字,这样做是理想的:

while (someArbitrarySet.hasNext()) {
    String s = "token" + Math.random();
    SomeClass (s) = new SomeClass();
    (s).callSomeMethod();
}

我希望这是有道理的......

5 个答案:

答案 0 :(得分:1)

您要求的是某些语言称为MACROS。它们有时也称为预处理器定义,或简称为“定义”。

决定在Java中没有包含和宏等,因为它引入了额外的代码维护问题,设计人员总结这些问题会导致代码不符合他们想要的样式。

但是,仅仅因为它没有内置到编译器中并不意味着你无法将它添加到构建脚本中。

作为构建的一部分,您将所有文件复制到src-comp目录,并且像您一样,在您定义的标记时替换它们。

我不建议这样做,但这并不意味着它不可能。

答案 1 :(得分:1)

您所描述的内容(在运行时创建新的命名变量)可以在JavaScript,Lua,Bash等解释语言中使用,但不能使用Java等编译语言。执行循环时,没有源代码可供操作,所有命名变量都必须在之前定义。

除此之外,你的变量不需要一个“唯一”的名字,如果你按顺序使用它们(一个接一个),你也可以这样写你的循环:

while (someArbitrarySet.hasNext()) {
    SomeClass sC = new SomeClass();
    sC.callSomeMethod();
}

如果您确实需要同时使用对象,请将它们放在某种数据结构中。最简单的是数组,你可以使用Collection(如ArrayList)或Map(如CajunLuke写的),如果你想通过键再次找到它们。

实际上,一个数组(在Java中)只不过是一个变量集合(所有相同的类型),你可以用int来索引。

(允许在运行时创建新变量的脚本语言也使用某种地图字符串→(任何东西)实现这一点,其中此映射是方法/脚本本地或属于某些周围对象。)


您在对问题的评论中写道(最好将这些内容添加到问题本身,它有一个“编辑”按钮):

  

没有太多细节,我正在编写一个在更大程序中运行的应用程序。通常情况下,对象在完成后会被垃圾收集,但是较大的程序会对它们进行维护,因此每个对象都需要一个唯一的名称。如果我不给每个人一个唯一的名字,旧的对象将被覆盖,但在更大的程序的上下文中仍然需要它。

那么,您想保留对象以避免垃圾回收吗?使用数组(或List或其他任何东西)。

问题是,如果您希望更大的程序能够使用这些对象,那么无论如何,您都必须将它们提供给更大的程序。然后这个程序必须保留对这些对象的引用,从而避免垃圾收集。因此,您希望通过不存在的方式解决不存在的问题: - )

答案 2 :(得分:0)

不是你问的问题的答案,而是你问题的可能解决方案:使用地图。

Map variables = new HashMap();
while (someArbitrarySet.hasNext()) {
    String s = "token" + Math.random();
    variables.put(s, new SomeClass());
    variables.get(s).callSomeMethod();
}

这样,您可以使用“变量名称”作为地图中的键,您可以轻松使用词法分析器/解析器。

我真的希望有一种方法能够专门用Java来表达你的意思 - 这真的很酷。

答案 3 :(得分:0)

没有。那是不可能的。

即使你能够想到一种方法来调用它们,因为不会编译可以成功引用它们的代码。

所以选项是CanjuLuke描述的选项或创建自己的java解析器,可能使用ANTRL sample Java grammar并挂钩你需要的东西。

考虑地图解决方案。

答案 4 :(得分:0)

这在How do you use Java 1.6 Annotation Processing to perform compile time weaving?中得到解答。

简而言之,有一个注释处理工具,允许您扩展java语法,并创建编译为java注释的DSL。

在JDK 1.5下,您必须使用apt而不是javac,但在1.6下,这些会受到-processor javac标志的影响。来自javac -help

-processor <class1>[<class2>,<class3>...]Names of the annotation processors to run; bypasses default discovery process
-processorpath <path>      Specify where to find annotation processors