2

Is there any way to give instructions directly to the parser and lexar from the java code level? If not, how could one go about doing this at all?

The issue is that I want to have the parser evaluate a variable, back up, then assign the value of that variable as an Object name. Like this:

String s = "text";

SomeClass (s) = new SomeClass();

parser reads--> ok, s evaluates to be "text"... parser backtracks, while holding "text" in memory and assigns "text" as the name of the new instance of SomeClass, such that one can now do this:

text.callSomeMethod();

I need to do this because I have to instantiate an arbitrary number of objects of SomeClass. Each one has to have a unique name, and it would be ideal to do something like this:

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

I hope this makes sense...

reader1
  • 93
  • 1
  • 8
  • 2
    "Each one has to have a unique name" -- do you really mean that each one has to be bound to a unique identifier in the source text? Why not just put them in a Map, with the "name" as the key? Or make the name a field of SomeClass? I don't think you need the heavy artillery you're asking for. – Vance Maverick Feb 23 '11 at 00:37
  • what I mean is this: SomeClass s; SomeClass q; SomeClass p; s, q and p all have to be different. I have been told to just put them in a map, but that would require creating a large number of objects, many of which may never be needed. While that wouldn't always be an issue, im working with very processing-power / disk + RAM constrained machine. – reader1 Feb 23 '11 at 00:46
  • 2
    What problem are you trying to solve? Perhaps there are better options. – OscarRyz Feb 23 '11 at 00:50
  • Without getting into too many details, I'm writing an application that runs within a larger program. Normally, the objects would get garbage-collected after I was done with them, but the larger program maintains them, thus the need for a unique name for each. If I don't give each a unique name, the old object will get overwritten, but it is still needed in the context of the greater program. – reader1 Feb 23 '11 at 00:56
  • I think the real question is: why you think you need to do this? – Bryan Kyle Feb 23 '11 at 00:57
  • Yeah, I don't think you're making the case for the complexity you want. Just use an associative data structure to connect the names to the objects in a "soft" way. The names (as Strings) will take up memory regardless. – Vance Maverick Feb 23 '11 at 01:36
  • Vance is right: If all you want to do is to hang on to the objects at runtime, simply keep references to them in a flexible array. You can think of the index integers as an infinite supply of "names". Manufacturing names is way too much effort. – Ira Baxter Feb 24 '11 at 16:25

5 Answers5

1

What you're asking for is what some languages call MACROS. They're also sometimes known as preprocessor definitions, or simply "defines".

A decision was made to not have includes and macros and the like in Java because it introduces additional code maintenance concerns that the designers concluded was going to cause code that would not have been in the style they wanted.

However, just because it's not built into the compiler doesn't mean you couldn't add it to your build script.

As part of your build, you copy all files to a src-comp directory, and as you do, replace your tokens as they're defined.

I don't recommend doing it, but that doesn't mean it isn't possible.

corsiKa
  • 81,495
  • 25
  • 153
  • 204
  • This is a comment, not an answer. – OscarRyz Feb 23 '11 at 00:44
  • 2
    No this is an answer. There are two questions. The first is can it be done at the Java code level. The answer is no because designers left it out. The second is if not how can it be done. The answer is with your own preprocessing script. I think it answers both questions quite well. Sure it has my personal commentary in it, but that's an integral part of this site is drawing upon others' experience. – corsiKa Feb 23 '11 at 00:47
  • I will look into this, thanks. I've tried getting into ant a few times, but lacked the motivation to do all the reading. Can ant help with this? If so this might be motivation enough. – reader1 Feb 23 '11 at 00:50
  • I could see ant doing it yes. Ant tasks could cover the file move and the (perl? bash? java?) routine that does the conversion. Ant is a useful resource if you're a Java developer. – corsiKa Feb 23 '11 at 00:54
  • an own preprocessing script still would not allow creating new variables at runtime like in the loop of the question. – Paŭlo Ebermann Feb 23 '11 at 01:03
  • Setting this as the answer, as I will see if it can be my long term solution. I am using CajunLuke's solution in the short term. – reader1 Feb 23 '11 at 01:03
  • The java language designers did decide to allow language level extensions via `apt` and similar schemes, and did decide to allow DSLs to compile to java classes via the same sourcepath resolution mechanism. JSPs for example. – Mike Samuel Feb 23 '11 at 01:07
  • Don't let my downvote of his answer confuse you (I see how it could). I only downvoted him because of his statement that giving extra instructions (i.e. macros) to the Java parser would be a good thing. Harsh? Maybe - I'm not much of a downvoter (3% of my votes are downs). I really do feel it would not be a good addition to the language. However, the idea of using a map to store your variables is a good thing! I like that idea! I wouldn't use Random, because you might have a collision, I'd use a counter instead, but his is a decent idea. – corsiKa Feb 23 '11 at 01:12
  • @mike I'll admit I wasn't aware of this `apt` mechanism. I still don't recommend this approach (despite the fact it's the accepted answer.) – corsiKa Feb 23 '11 at 01:13
  • Or simply use an array or List, it is accesible by index. – Paŭlo Ebermann Feb 23 '11 at 01:13
  • @glowcoder, I don't agree or disagree with your recommendation. And I think you're right to be skeptical. Overuse of a feature like this can lead to subtly divergent languages making code hard to read and maintain. My only quibble was with the assertion that no mechanism exists. cheers. – Mike Samuel Feb 23 '11 at 01:23
1

What you describe (creating new named variables at runtime) is possible in interpreted languages like JavaScript, Lua, Bash, but not with a compiled language like Java. When the loop is executed, there is no source code there to manipulate, and all named variables have to be defined before.

Apart from this, your variables don't need a "unique" name, if you are using them sequentially (one after another), you could just as well write your loop as this:

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

If you really need your objects at the same time, put them in some sort of data structure. The simplest would be an array, you could use a Collection (like an ArrayList) or a Map (like CajunLuke wrote), if you want to find them again by key.

In fact, an array (in Java) is nothing else than a collection of variables (all of the same type), which you can index by an int.

(And the scripting languages which allow creating new variables on runtime implement this also with some kind of map String → (anything), where this map is either method/script-local or belonging to some surrounding object.)


You wrote in a comment to the question (better add those things to the question itself, it has an "edit" button):

Without getting into too many details, I'm writing an application that runs within a larger program. Normally, the objects would get garbage-collected after I was done with them, but the larger program maintains them, thus the need for a unique name for each. If I don't give each a unique name, the old object will get overwritten, but it is still needed in the context of the greater program.

So, you want to retain the objects to avoid garbage collection? Use an array (or List or anything else).

The thing is, if you want your larger program to be able to use these objects, you somehow have to give them to this larger program anyway. And then this program would have to retain references to these objects, thereby avoiding garbage collection. So it looks you want to solve a problem which does not exist by means which do not exist :-)

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
  • Your statement of "not with a compiled language like Java" implies you can't do this in other compiled languages like C or C++, where indeed you can do this there with Macros. Sure you don't define them as strings but they are simple text replacement which is what he's looking for. – corsiKa Feb 23 '11 at 01:00
  • @glowcoder: It looks like he wants to create new variables at runtime, not at compile-time (since he in fact is mixing the two). – Paŭlo Ebermann Feb 23 '11 at 01:04
  • @ Paulo, I also said without getting into too many details. The program automatically grabs these objects as they are created. I will definitely be using either a HashMap or ArrayList or so in the short term. I will be looking into the build script solution as a long term fix. This is partially because I really need to learn to use Ant anyhow. I may or may not end up sticking with the HashMap/List solution. Perhaps I should switch my accepted answer? It was difficult to choose which one to accept as I am going to try to use both. – reader1 Feb 23 '11 at 01:30
  • Huh, you are doing some strange magic here ... Anyways, creating new local variables in java is not the right way (as it is not possible at runtime in the VM, even with macros or a different JVM-based language. You could at most hide the usage of some data structure with some other syntactic construct.) – Paŭlo Ebermann Feb 23 '11 at 01:38
0

Not really an answer to the question you asked, but a possible solution to your problem: using a map.

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

That way, you can use the "variable name" as the keys into the map, and you can get by without messing with the lexer/parser.

I really hope there is a way to do specifically what you state in Java - it would be really cool.

Cajunluke
  • 3,103
  • 28
  • 28
  • -1 It would not be really cool. It was purposefully left out of the language because the designers didn't want it. – corsiKa Feb 23 '11 at 00:40
  • @glowcoder "because the designers" I think they were also the same ones that forced you to use classes _all_ the time and didn't make functions first-class? – alternative Feb 23 '11 at 00:43
  • @mathepic That would be them. Try maintaining a 3-million+ line app with includes everywhere and no coalescing of functionality. It's a nightmare (even if it does keep me employed :D ). – corsiKa Feb 23 '11 at 00:46
  • @glowcoder I'm not arguing whether or not the lack of macros is a good or a bad thing, just that "the designers made it so" is not good enough of a reason for it to be bad. – alternative Feb 23 '11 at 00:57
  • @mathepic This will be a point of disagreement, but I believe it is a reason for it to be considered bad, at ~least~ within the realm of Java (which this question is in.) – corsiKa Feb 23 '11 at 01:01
  • +1 for the right proposal (**using some data structure**) a bit before I typed mine. I don't want to engage in discussions on whether macros or any similar could be useful to Java, since they would not really be a solution to this question (if they are not simply a syntactic sugar to such a map). – Paŭlo Ebermann Feb 23 '11 at 01:16
0

No. That's not possible.

Even if you could I can't think on a way to invoke them, because there won't be compiling code that could successfully reference them.

So the options are the one described by CanjuLuke or to create your own java parser, probably using ANTRL sample Java grammar and hook what you need there.

Consider the map solution.

OscarRyz
  • 196,001
  • 113
  • 385
  • 569
0

This is answered in How do you use Java 1.6 Annotation Processing to perform compile time weaving? .

In short, there is an annotation processing tool that allows you to extend java syntax, and create DSLs that compile to java annotations.

Under JDK 1.5 you had to use apt instead of javac, but under 1.6, these are affected by the -processor flag to javac. From 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
Community
  • 1
  • 1
Mike Samuel
  • 118,113
  • 30
  • 216
  • 245