How to select Antlr4 starting rule at runtime? - java

Antlr4 creates methods inside extends Parser, which have names the same as rules. For example, if I have rule named "program" in my grammar, it will create method program(). I can call this method, to do parsing.
But what if I wish to select starting rule at runtime?
I looked at implementation and found the beginning
public final ProgramContext program() throws RecognitionException {
ProgramContext _localctx = new ProgramContext(_ctx, getState());
enterRule(_localctx, 0, RULE_program);
it implies, that I can't select rule by name or index, because I need two things simultaneously: ProgramContext class and RULE_program constant.
Is it possible in fact?
Can I define some default rule and call it automatically?

All parser grammar rules are implemented by methods in the generated parser. If your grammar defines
program : .... ;
statemt : .... ;
the grammar will have methods
public final ProgramContext program() throws RecognitionException ....
public final StatemtContext statemt() throws RecognitionException ....
Either can be called as the start rule for evaluating a token stream.
See this answer suggesting a way to programmatically identify parser rules.

No, this is not possible with the generated parser. However, look in the ParserInterpreter class (which allows to specify the start rule index). This class emulates the real parser but works differently than that and is probably not what you want, but maybe it gives you an idea.

As I understand you can choose any starting rule via reflection. I suggest the following code on Java as an example:
Method startMethod = parser.getClass().getMethod("customStartRule", new Class[] {});
ParserRuleContext ast = (ParserRuleContext)startMethod.invoke(parser, new Object[] {});
All start rules you can find in ruleNames array in generated parser.

Related

How to instruct the grammar to NOT generate certain methods in the ANTLR listener?

I have this grammar:
foo : bar EOF;
bar : 'hello';
The listener interface, which ANTLR generates, contains these four methods:
public void enterFoo(final FooParser.LicenseContext ctx);
public void exitFoo(final FooParser.LicenseContext ctx);
public void enterBar(final FooParser.LicenseContext ctx);
public void exitBar(final FooParser.LicenseContext ctx);
Two of them are not needed for me: exitFoo() and enterBar(). Is it possible to tell ANTLR somehow to NOT generate them in the interface? I would actually prefer to find a way to somehow tell the grammar which grammar rules need those enter/exit methods, and all others would be ignored. Is it possible?
You cannot suppress the generation of any of these methods, because the parser expects them to be there when triggering the listener for each parse step.

Generate a call to a method with a variable number of arguments

I'm using JavaPoet to generate classes given a list of fields.
Generating a constructor that takes this list of fields and turns it into a list of parameters is fairly straightforward with something like the following:
val constructor = MethodSpec.constructorBuilder()
for ((fieldName, typeName) <- fields) {
constructor.addParameter(typeName, fieldName)
}
I would also like to generate a static method that instantiates a new object of the generated class, which requires me to generate a code block that uses the aforementioned list of fields.
Currently, I'm achieving this with something like the following:
method
.addStatement(s"return new $$T(${fields.map(_._1).mkString(", ")})", className)
It works, but I was wondering if there was a more "idiomatic" way to use JavaPoet to build a list of arguments with the built-in templating support.
In order to avoid mixing Scala's interpolation and JavaPoet's templating it looks like the best way to achieve this is by making a CodeBlock that contains the parameter list and embedding it in the code with a template, as in the following example:
val params = fields.map { case (name, _) => CodeBlock.of(name) }
val paramList = CodeBlock.join(params.asJava)
method.addStatement("return new $T($L)", className, paramList)
The template here makes use of the $L placeholder that will be replaced by a literal (in this case, the assembled list of parameters).

expression engine using groovy

I am trying to expose a expression engine built on top of groovy for end users. I have some excel style keywords and user can use variables within those keywords (which need to be substituted at runtime) for evaluation.
example, static keyword FIRSTCHAR(varName) will return the first character of a string. I have got this to work in a way.
Current Implementation
I have overridden the groovy class loader to create a compilation unit with an overridden PrimaryClassNodeOperation something like
class MyGroovyClassLoader extends GroovyClassLoader {
protected CompilationUnit createCompilationUnit(
CompilerConfiguration config, CodeSource source) {
CompilationUnit cu = super.createCompilationUnit(config, source);
cu.addPhaseOperation(new PrimaryClassNodeOperation(){
#Override
public void call(SourceUnit source, GeneratorContext context, ClassNode classNode)
throws CompilationFailedException {
source.getAST().getStatementBlock().visit(visitor);
}
}, Phases.SEMANTIC_ANALYSIS);
return cu;
}
}
The visitor then recognizes the static expression and variable expression. However, using this approach I am having difficulties in
1) Supporting variable names with dot (.) since dot is considered a property expression. Can I during this phase keep the property expression as variable expression.
2) Also, for an expression like (left(name,1)=='S' && right(name,1)=='n') [first character in name is s and last is n] - I want the equal to check to be single equals rather than double equals, and/AND instead of && or .and() so something like (left(name,1)='S' and right(name,1)='n')
What's the best way to achieve such customizations?
The best approach would be to use a custom parser (since you dont want your users to write any groovy) and then use groovy to actually implement the back-end
eg: Very indicative, your implementation can vary
(left(name,1)='S')
For the snipet above, tokens could be method:left, args:((var:name),(val:1)), exp:EQUALS, val:'S'
Have a map at the back which equates your tokens to groovy equivalents
You could then be fire your parsed tokens against a groovy class, of course the methods and arguments dont exist, use some groovy tricks to translate it to your actual implementation 1

XText register global variables

I want to build tool support for the jape language from gate with the help of XText. Jape is basically a pattern language over annotations; you declare the actions to take when you encounter those annotations. The problem is that the actions can be written in java. After struggling with jdt for a while, I was unable to make it work over parts of the parsed content. So I gave up and decided to use the xbase support with XBlockExpression for that.
The problem is that there are some variables that can be used in the actions - for example there is a variable bindings which allows you to bind and then get annotations from the pattern. So my question is how to register those variables in the xblock scope. After reading the documentation for 3 hours I am still nowhere closer.
Here is a minimal grammar for my problem
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.xbase.Xbase
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Model:
greetings=Greeting;
Greeting:
block=XBlockExpression;
I want to parse files with content like this:
{
val testAS = bindings.get("test") as AnnotationSet
}
I started by plugging in my own scope provider but that didn't help me much. Here is the implementation for the provider:
package org.xtext.example.mydsl;
import java.util.List;
public class MyScopeProvider extends XbaseScopeProvider {
XbaseFactory factory = new XbaseFactoryImpl();
#Override
public IScope getScope(EObject context, EReference reference) {
//System.err.println(context);
//System.err.println(reference);
List<IValidatedEObjectDescription> descriptions = Lists.newArrayList();
XVariableDeclaration variableDeclaration = factory
.createXVariableDeclaration();
variableDeclaration.setName("bindings");
IValidatedEObjectDescription variableDescription = createLocalVarDescription(variableDeclaration);
System.err.println(variableDescription);
IScope scope = super.getScope(context, reference);
System.err.println(variableDeclaration);
return new JvmFeatureScope(scope, "test", descriptions);
}
}
Any help will be appreciated
You should try to implement a JvmModelInferrer for your language where you add the implicitly available variables either as fields or operation arguments in the inferred type. That will do the trick. The approach is nicely documented in the 7 language examples on xtext.org

Get the name of the functions called by a class

There are two classes A and B in the same package.
how to get name of the functions of class A called by class B.
Restriction is that the code of A and B cannot be modified.
You cannot use Java reflection to do static code analysis tasks like this. The reflection APIs don't provide the information that is needed.
Off the top of my head, I can think of two approaches that will work:
If you only have the ".class" files, then you can use a bytecode library such as BCEL to load the classes and traverse them to identify all of the method calls.
If you have source code, you could also use some existing Java parser library to create ASTs for your code and analyse them.
(The first approach is probably simpler if all you want is a list of class and method names.)
Reflection can be very useful, but very complicated if you don't understand it.
If you have the name of the class, and want to print the methods:
Class c = Class.forName(the_class_name);
for(Method m : c.getMethods()) {
System.out.println(m.toString());
}
If you want the name of a class given any Object:
String className = the_object.getClass().getName();
A combination of the two could look like this:
for(Method m : the_object.getClass().getMethods())
System.out.println(m.toString());
I think what you are asking for is the names of all the methods from A that B calls.
That can't really be done with reflection, mostly because Java doesn't provide any method for doing this.
The API, as always, provides more information. If you look through there, you might come up with a simple work around.
"Class of all the functions called by class A or class B" is confusing. But, If You want to get the class and function name of caller to a method detectsName described in your class A , then following code will be useful to you.
public class A {
public void detectsName() {
Throwable t = new Throwable();
StackTraceElement traceLine = t.getStackTrace()[1];
// t.printStackTrace();
String className = traceLine.getClassName();
String methodName = traceLine.getMethodName();
int lineNumber = traceLine.getLineNumber();
System.out.println(className);
System.out.println(methodName);
System.out.println(lineNumber);
}
}
If you call this method from any other class say - B, it will be detected.
public class B {
public static void main(String[] args) {
A a = new A();
a.detectsName();
}
}
Dependency Finder can do queries for this. Its approach is to generate meta data in XML and then use regexp based comparison. You may be specifically looking for feature called 'closure' with inbound reference..

Categories

Resources