Parse a formula using ANTLR4 - java

I am trying to parse a mathematical formula to a subset of LaTeX using ANTLR4. For example it should parse (a+4)/(b*10) to \frac{a+4}{b\cdot 10}.
My simple grammar creates a tree like this:
Now I am trying to implement parse tree listeners to somehow construct the LaTeX String while the tree is traversed. Here, I am failing because to construct a String like \frac{}{} it has to be built recursively. The parse tree walker, however, visits one tree node after the other (in a breadth-first way as far as I can tell).
I've read about parse tree visitors that might be what I need. But I wasn't able to find some examples how these visitors are applied.
Could you provide an example how parse tree listeners/visitors can be used in this particular case? Do you think my approach to use ANTLR for the parser makes sense in the first place?

You can create a parse tree walker by implementing the ParseTreeVisitor interface. For ease of use, you can specify Antlr to generate a base visitor when compiling the grammar (in Antlrworks, Run->Generate Recognizer->Next->Generate Visitor->Next->Finish). The base visitor will be called MyGrammarBaseVisitor. Note that the visitor has a generic type T, which every single visit method should return. I recommend using Void for manual manipulation or String for ease of use during code generation.
After you extend the base visitor (I'll assume here we're dealing with String), you need to override the visit methods. These methods are named after the grammar rules you have. Each of these methods will receive a ParserContext ctx parameter, which you use to visit child rules and/or get terminal values. For example, you could do this:
class MyVisitor extends MyGrammarBaseVisitor<String> {
#Override
public String visitMultiplicative(MyGrammarParser.MultiplicativeContext ctx) {
if (ctx.opMult().getText().equals("/")) return "\\frac{" + visit(ctx.expr(0)) + "}{" + visit(ctx.expr(1)) + "}";
else return visit(ctx.expr(0)) + "\\cdot " + visit(ctx.expr(1));
}
// visit methods for other rules...
}
I'm assuming your multiplicative rule looks like multiplicative: expr opMult expr; opMult: '*' | '/'; You can find more information in The Definitive Antlr 4 Reference. You may also find more information and examples in the Antlr documentation.

Related

What benefits does JSON dot-notation give over hierarchical structure?

We are working on a Java REST service which accepts JSON input but the consumers of this service want to send the json in dot-notation format instead of hierarchical structure.
So for example they prefer following input -
{
“person.address.city”: “San Francisco”
}
over:
{
“person”:{
“address”:{
“city”: “San Francisco”
}
}
}
Does the former notation have any benefits over the latter?
I could find below article which talks about this way of data representation:
https://docs.oracle.com/en/database/oracle/oracle-database/12.2/adjsn/simple-dot-notation-access-to-json-data.html#GUID-7249417B-A337-4854-8040-192D5CEFD576
Edit: From Java perspective, the hierarchical structure can be deserialized into typed classes. On the other hand, the dot-notation might have to be parsed as strings to get values.
This is just another OVER format (arrangement). Simplifies reading. It has nothing to do with the JSON format itself.
It could also be:
{
“person/address/city”: “San Francisco”
}
One benefit of the dot notation is that it flattens out the hierarchical structure, making it easier to store / manipulate the data in non hierarchical systems.
Using dot notation, you can transform a complex tree structure to a simple key value pairs structure. You can then store it to a simple Java HashMap or even in a Redis Hash.
This is how traditional key-value stores can expand their use cases to include more complex storage requirements.

JavaParser: How to add new language elements

I want to create a Java transpiler that will read nearly-Java code (call it JavaHash) and emit "pure" Java code on the other end. In particular, I want to add a new token that is the hashtag "#" in front of a hashmap member so that I might access it similar to a JavaScript hash object:
Map<String, String> foo = new HashMap<String, String>();
...
foo.put("name", "Roger");
...
String name = #foo.name;
I can't get the JavaParser to do anything but throw an error on the "#" hashtag.
Are there ways to catch tokens before they are parsed?
This is very far from trivial, but doable.
JavaParser is based on JavaCC, it uses the following grammar to generate parser code. The parser then creates an abstract syntax tree using code model classes.
If you want to add new language elements, you will need to:
implement code model classes;
extend the grammar used for parser generation.
This is not so easy, you will need good knowledge and understanding of JavaCC. But it is absolutely doable.
The rest is peanuts. You'll write a visitor and use it to traverse the AST. Once you've encountered the node of the appropriate type, simply transform the part of AST into "normal" Java and serialize.
By the way, JavaParser is a very good basis to build something like what you want. So congratulations to your choice, this is half of the deal, actually.

In Neo4j, is there any way to restrict nodes and relation types in path while using Java API?

I have source node and destination node I want to put restriction on nodes and relation types in the path. I am using Neo4j Java API.
Consider following toy example,
We have three person nodes A, B & C.
Source Node: A & Destination Node: B. There are many other kind of paths may exists between them. I want to restrict paths to specific format like-
(person) -[worksAt]-> (company) -[CompetitorOf]-> (company) <-[worksAt]- (person)
This can be very easily achieved from cypher query, but I want to know is there any way we can do it using Java API.
NOTE:
Kindly do not suggest putting restriction on path length, that
doesn't solve the problem. I want to restrict the node and relation
types in path.
Example mentioned above is toy example. Graph I am trying to work is more complex and there are many possible paths not feasible to traverse and validate individual paths.
It's not really clear from your question what you're actually trying to compute. Do you have A and B and want to find if their companies are competitors? Do you have C and want to find who among their friends work at competing companies?
Anyway, if you're using the traversal API (you're talking about paths), you can write a custom PathExpander which will use the last relationship in the Path to determine the next type of relationship to traverse.
If you're just traversing the relationships manually, I don't really see the problem: just call Node.getRelationships(RelationshipType, Direction) with the proper parameters at each step.
Contrary to what you do in Cypher, you don't declare the pattern you're looking for in the path, you just compute the path to follow the wanted pattern.
After reading the Neo4j java documentation carefully and experimenting with the code I got following solution working-
To filter path explored by PathFinder create a custom PathExpander using PathExpanderBuilder.
PathExpanderBuilder pathExpanderBuilder = PathExpanderBuilder.empty();
pathExpanderBuilder.add(RelationshipType.withName("worksat"), Direction.OUTGOING);
pathExpanderBuilder.add(RelationshipType.withName("competitorof"), Direction.BOTH);
pathExpanderBuilder.add(RelationshipType.withName("worksat"), Direction.INCOMING);
PathExpander<Object> pathExpander pathExpander = pathExpanderBuilder.build();
Once you create a custom PathExpander you can use it to create appropriate PathFinder which will filter traversal by the PathFinder.
PathFinder<Path> allPathFinder = GraphAlgoFactory.allSimplePaths(this.pathExpander, 4);
Iterable<Path> allPaths = allPathFinder.findAllPaths(sourceNode, targetNode);
In our example sourceNode would be Node 'A' and targetNode would be Node 'B'.

Using Odata4j to create abstract syntax tree for Query Parameter expressions

Im exposing REST services through use of Sprint MVC 4.0 framework and I try following Odata specification for the Query Parameters such as $filter, $search and $orderBy. Each of these contains expressions that I need to parse, build abstract syntax trees and validate. They are all retrieved as String.
I do not need all the constructions that are defined in the Odata grammer (http://docs.oasis-open.org/odata/odata/v4.0/cos01/abnf/odata-abnf-construction-rules.txt), I just pick the ones that are relevant for my uses cases (very few actually)
I would like some tip on how to parse and build the abstract tree in a easy way and if Odata4j might be used as a Utility library to do this job for me? I would like to avoid dragging bunch of new dependencies to odata4j, since I will only use small piece of the code.
You can certainly use odata4j for building ASTs for query parameters. I've done that for exactly the purposes you cite. I split off the query parameters, and then split again on '&' to get parameters. For each of these I inspect the parameter name ($select, $filter, etc.) and then based on that use the corresponding OptionsQueryParser static method on the value, returning an number, or list, or AST specific to that query parameter. For expression ASTs, look at PrintExpressionVisitor and use that as a pattern for writing your own visitor to walk the AST.

How to add a code snippet to method body with JDT/AST

I'm trying to generate Java source code with JDT/AST. I now have MethodDeclaration and want to add a code snippet (from another source) to the method body. The code snippet can contain any Java code, even syntactically invalid code. I just can't find the way to do this.
With JCodeModel you would use JBlock#directStatement(String s) method.
Is there a way to do this with JDT/AST?
Since you have a well-formed tree for the rest of the application, and you want to insert non-well-formed text at a particular place, you pretty much can't do it with the standard tree node insertion mechanisms.
What matters is that you produce text for the valid program text with the fragment inserted in at at the right place. Somewhere in there must be a piece of logic that prints the AST as text. What you need to do is to ask that the AST be printed as text, and catch it in the middle of that process, at the precise point necessary, to insert your arbitrary text.
Our DMS Software Reengineering Toolkit has enter/exit print-node hooks in its prettyprinter to allow this kind of thing to happen.
If such things don't exist in JDT/AST, you can try to modify its prettyprinter to give you that hook. Alternatively, you might consider modifying JDT/AST by adding a another tree node type that isn't part of the standard set, that simply holds arbitrary text but acts like a method node. Presumably each node controls what is printed; then you could define the prettyprinting for that tree node, to cause it to output its text.
A final really hacky solution: insert a perfectly valid AST where the arbitrary text will go, containing somewhere a bogus identifier with a unique name, e.g., ZZZ. Then, print the AST to a string, and post-process the string to replace the bogus trees containing the unique name with the actual user text.
You first need to parse the code snippet into an AST. You can use the ASTParser API for this purpose.
It is possible to get the compilation problems of a compilation unit (See CompilationUnit.getProblems()).
There are a couple of ways to modify Java code using JDT. I'd suggest that you consider the ASTRewrite API for modifying the body of a method.
You can manipulate the AST with the ASTParser API - and the output doesn't even have to compile.
Here's an example for your case:
String textToInsert = "Some text";
StringLiteral stringLiteral = methodDeclaration.getAST().newStringLiteral();
rewriter.set(stringLiteral, StringLiteral.ESCAPED_VALUE_PROPERTY, textToInsert, null);
ListRewrite methodStatements = rewriter.getListRewrite(methodDeclaration.getBody(), Block.STATEMENTS_PROPERTY);
methodStatements.insertFirst(stringLiteral, null);
Result:
public void myMethod() {
Some text
}

Categories