TestRig in ANTLRworks: how to use own classes? - java

I'm trying to build a MT940 parser using antlr4. The grammar is simple but works for most cases.
Now I want to return my own classes. This works:
file returns [String myString]
:
Header940? record+ EOF
;
I think this is becasue String is in the default java packages.
I want this:
file returns [List<MT940Record> records]
:
Header940? record+ EOF
;
The TestRig complains (logically):
/tmp/TestRigTask-1392235543340/MT940_5aParser.java:50: error: cannot find symbol
public List<MT940Record> records;
^
symbol: class MT940Record
location: class FileContext
How can I set the CLASSPATH / lib directory in the TestRig in ANLTRWorks?

In ANTLRWorks, you can't. You can add an issue for this on the issue tracker:
https://github.com/sharwell/antlrworks2/issues
Note that ANTLR 4 was designed so you no longer need to use user-defined arguments and/or return values in your grammar. Instead of returning a List<MT940Record> like you described above, you should use a listener or visitor after the parse is complete to compute the necessary result.

Related

Calling methods between groovy scripts with correct parameters

I just started learning about groovy and trying to transpose my java code to groovy scripts. Usually java allows you have a class with only methods that you can call from other classes. I wanted to translate that to groovy. I have in one file - lets call it File1- a method like this:
def retrieveData(String name){
// do something
}
and in the second file, File2, I call File1 like this:
def file1Class = this.class.classLoader.parseClass(new File("../File1.groovy"))
and then try to call the method in File1 like this:
def data = file1Class.retrieveData("String")
but it keeps giving me this error - MissingMethodException:
groovy.lang.MissingMethodException: No signature of method: static File1.retrieveData() is applicable for argument types: (java.lang.String) values: [String] Possible solutions: retrieveData(java.lang.String)
so it does recognize that I am sending in the correct number of parameters and even the correct object, but it isn't running the method as it should?
Is there something I am missing? I tried to remove the object definition from the method - in other words - like this:
def retrieveData(name){
// do something
}
but that didn't work either. I am clueless about what the next step would be. Can anyone please help push me in the right direction? I would greatly appreciate it.
See the answer provided in this StackOverflow reponse.
Use the GroovyScriptEngine class. What does the GroovyScriptEngine do? From the docs:
Specific script engine able to reload modified scripts as well as
dealing properly with dependent scripts.
See the example below.
def script = new GroovyScriptEngine( '.' ).with {
loadScriptByName( '..\File1.groovy' )
}
this.metaClass.mixin script
retrieveData()
Note how we use the loadScriptByNamemethod to
Get the class of the scriptName in question, so that you can
instantiate Groovy objects with caching and reloading.
This will allow you to access Groovy objects from files however you please.

line breaks after Java annotations in Scala code

I have a code that compiles successfully:
import javax.ws.rs.Path
trait DescriptionHandler extends ServiceAwareHandler {
#Path("/descriptions")
def getDescriptionsRoute: Route = ...
}
and it would not compile if I add a line break after Path annotation like this:
import javax.ws.rs.Path
trait DescriptionHandler extends ServiceAwareHandler {
#Path("/descriptions")
def getDescriptionsRoute: Route = ...
}
In IntelliJ IDEA it look like javax.ws.rs.Path is absent in class path.
Compiler telling me this:
Error:(19, 1) expected start of definition
def getDescriptionsRoute: Route =
What's the problem with line breaks between Java annotations and Scala methods / fields? I tried to google the issue but didn't found anything useful.
In Scala Spec/Lexical syntax/1.2 Newline characters there is an explicit statement about this case:
A single new line token is accepted
...
after an annotation.
And when there is an empty line:
if two tokens are separated by at least one completely blank line (i.e a line which contains no printable characters), then two nl tokens are inserted.
Thus blank lines are not accepted between annotation and definition.

Parsing java code and adding methods with AST (JDT Eclipse)

I have a .java file which contains a class. I want to add a method to that class but I can't find a real useful "HOWTO" or examples around.
I'm using Eclipse and its JDT plugin for AST.
I tried a code that creates an ICompilationUnit from a project
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject("ProjName");
IJavaProject javaProject = JavaCore.create(project);
IPackageFragment package1 = javaProject.getPackageFragments()[0];
ICompilationUnit unit = package1.getCompilationUnits()[0];
then add a method with astrewrite.
But it seems to work only if I run all as a Plugin Project and not a simple Java Application.
I need to write an application in java that "simply" parse a java file and adds method to its class.
What I supposed to do is:
1) Create an ICompilationUnit directly form the .java file I want to parse (eventually located in my own project's directory)
2) Using another way
Both case I can't go further. Anyone can help me?
When you need to make a change by adding something to the compilation unit, you will have to use the functions provided by CompilationUnit to create new nodes.
To add a method to "unit" you will have to :
Create a MethodDeclaration node using your compilation unit :
MethodDeclaration md = unit.getAST().newMethodDeclaration();
Customize this method declaration to your requirements :
md.setName( unit.getAST().newSimpleName( "newMethod" ) );
md.setBody( unit.getAST().newBlock() );
this will produce : void newMethod() {}
Obtain the TypeBinding from "unit" :
TypeDeclaration typeDeclaration = ( TypeDeclaration )unit.types().get( 0 );
Add your newly created MethodDeclaration to the body declarations :
typeDeclaration.bodyDeclarations().add( md );
There's a method called getMethods() on TypeDeclaration but it doesn't return a live list of MethodDeclarations, therefore you can't modify that directly.
It's really easy to read the source file as text and replace the last } with the method declaration plus }. Obviously this doesn't work if someone puts multiple top-level classes in one file (which is extremely rare and I doubt you'll have a problem with that).

Java, cannot find symbol : method methodName(org.bla.blabla.myClass)

I'm using Lucene APIs, and I get the following error on this line of my code:
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
...
Document _document = new Document();
_document.add(new Field("type", document.getType()));
Error:
CollectionIndexer.java:34: cannot find symbol
symbol : method add(org.apache.lucene.document.Field)
location: class CollectionIndexer.Document
_document.add(new Field("type", document.getType()));
This is the documentation about the method:
http://lucene.apache.org/java/3_0_3/api/all/org/apache/lucene/document/Document.html#add(org.apache.lucene.document.Fieldable)
thanks
Update: javac -cp commons-digester-2.1/commons-digester-2.1.jar:lucene-core-3.0.3.jar myApp.java
When I'm stumped over this type of error, it is usually due to the fact that I've two definitions of InterfaceName, and accidentally imported the wrong one in one or more places.
(Happens for instance when I accidentally choose java.awt.List instead of java.util.List when auto-importing missing classes.)
Make sure that ...
symbol : method methodName(org.bla.blabla.myClass)
\____________________/
... this part ...
... matches the expected package / class.
The problem comes from the fact that your document.getType() method returns a String and there
is no constructor in the Field class that matches your call.
See http://lucene.apache.org/java/3_0_3/api/all/org/apache/lucene/document/Field.html.
If I test your code in my environment Eclipse says:
The constructor Field(String, String) is undefined
Maybe you could do as the following:
Document _document = new Document();
_document.add(new Field("type", document.getType().getBytes(), Store.YES);
// Or document.add(new Field("type", document.getType().getBytes(), Store.NO);
UPDATE after source code submission --------------------
The problem comes from the fact that in your class you have an inner-class called Document. There is a name conflict between your Document class and the Lucene's one. When you instanciate your document with the line Document _document = new Document(); you're actually instanciating YOUR Document class. That's why the compiler cannot find the add method.
Multiple solution:
a. Instanciate the Document prefixing it with the Lucene package name
org.apache.lucene.document.Document _document = new org.apache.lucene.document.Document();
b. Rename your inner class so that you don't have any name conflict.
Updated based on updates to question:
Make sure your curly braces around this line up and that there is not something else causing an issue.
Reduce the code down just to as few lines as possible to eliminate any other items that could be throughing the compiler off.
Compile without the commons-digester-2.1 if you can, to eliminate possible conflicts.
Break the line up so the a Field object is created on a separate line than adding the field to the document so that you can confirm there is no problem with your constructor call.

LD_DEBUG and java

When I set LD_DEBUG=files and run my Java program, I found many errors like this:
/linux/depot/java-1.6.0_16_32/jre/lib/i386/libjava.so: error: symbol lookup error: undefined symbol: Java_sun_java2d_loops_MaskBlit_MaskBlit (fatal)
This info is horrifying, but obviously my program runs OK. Can anyone tell me why this happens?
It's not horrifying; it's what happens when you build code to run on a lot of different platforms. It's just the jvm looking for optional symbols. In this case, something to do with 2D and alpha compositing. There is an alternate code path that is taken if the symbol is not found at runtime. You can think of it as a sort of reflection for libraries.
The jvm code goes something like this:
TYPE fptr = CAST_TO_FN_PTR(TYPE, dlsym(RTLD_DEFAULT, symbol));
if (fptr != NULL) {
// Do something different because this platform supports 'symbol'
}

Categories