Antlr4: Is antlr4's golang visitor pattern in a usable state?

Created on 6 Mar 2019  Â·  20Comments  Â·  Source: antlr/antlr4

I asked this question over on stack overflow, without much enlightenment. I was told to ask it
here.

Is antlr4's golang visitor pattern in a usable state?

I see no working examples, and I see a few pull requests that remain open. I would like to avoid going down the garden path.

https://github.com/antlr/antlr4/pull/1807

https://github.com/antlr/antlr4/issues/1843

There are also pull requests that make me think the golang target might be dead in the water.

https://github.com/antlr/antlr4/issues/2152

The fact that the antlr4 documentation page for golang is over two years stale is also not
encouraging.

So all I am really asking is should I steer clear of golang, or is the documentation just somewhere that google doesn't see :-)

Most helpful comment

Okay I wrote an implementation. I don't think it is the correct way of writing it but it is the best I could do with my limited understanding.

https://github.com/nikunjy/antlr-calc-go

I spent couple of hours trying to understand the antlr golang code base (which I think is not well written and can be improved by collaboration). If there are authors/reviewers who will review the code then I would be down to improve it but looking at the past threads it seems like golang requests have died with time.

@davesisson can you comment on this code base and let me know if this is the right way of doing the implementation. After getting frustrated I ended up writing a Visit(ParseTree) for my visitor which I think is the wrong way of writing, and I'd like you to comment on that if you have the time

func (c *CalculatorVisitorImpl) Visit(tree antlr.ParseTree) interface{} {
    switch val := tree.(type) {
    case *CalculateContext:
        return val.Accept(c)
    case *ToSetVarContext:
        return val.Accept(c)
    }
    return nil
}

I am having to write the Visit with this type switch statement, i would also have to probably write VisitChildren.

All 20 comments

Looking to use antlr with golang. Can you address some of these @parrt ?

Sorry. I don't know Go.

Might want to be honest then, and remove go from the supported language targets. At least warn the gullible user that they may be disappointed.

Are you claiming it doesn't support Go in any way?

I am claiming that I could not get the --visitor pattern to work. Nor could I find any working examples
of other people getting it to work. What I did find were issues in this repository that seem to indicate that it never worked, and that people have tried and failed to fix it. I ended up having to fall back on the listener pattern for the task I had at hand, but given what I know now, would probably
have not chosen go for the project I am/was working on.

I see. ok, well, my apologies. There are lots of different language targets for this project and it's very hard to keep track of the current state of every piece of every API. It's also no longer my focus.

Might be an idea then to keep the issue open, so that someone with time and inclination
may succeed where others have failed.

@ianamason According to @pboyer 's comment on #1841 the Go visitor implementation is in a usable state; however, the user is currently required to put in more work then, for instance, the java implementation.

@ocurr indeed I did see that issue thread, though may have incorrectly got the impression that the
matter was still unresolved. The certainly was no link to any working visitor example that I could see.
I may add a link to the issue in the original post so that others can benefit.

Is there a working example somewhere that people could follow?

The trick is that you need to include all of the methods the visitor will
use and not just the ones that you would be implementing. It's not
incredibly convenient which is why there was a proposal at one point for
redesigning the way visitors were defined.

On Mon, Apr 15, 2019 at 1:47 PM Ian A Mason notifications@github.com
wrote:

@ocurr https://github.com/ocurr indeed I did see that issue thread,
though may have incorrectly got the impression that the
matter was still unresolved. The certainly was no link to any working
visitor example that I could see.
I may add a link to the issue in the original post so that others can
benefit.

Is there a working example somewhere that people could follow?

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/antlr/antlr4/issues/2504#issuecomment-483411926, or mute
the thread
https://github.com/notifications/unsubscribe-auth/ALUC_ajCCWJK08wr_r120qKuseSMF0feks5vhOVEgaJpZM4bg9rx
.

@davesisson, a simple working example would go a long way to "resolving" this issue. Having to flesh out all the methods still sounds a simpler task than trying to get the listener pattern to accomplish the same thing.

I would also like to see a working example from somewhere. I am getting hung up on some typing issues that prevent my project from even compiling, so I can't even get to the point where I can try your suggestion @davesisson

Disclaimer, I am very new to Golang so it could be something stupid that I am doing, but having a working, compiling starting point would really help me to get started.

Okay I wrote an implementation. I don't think it is the correct way of writing it but it is the best I could do with my limited understanding.

https://github.com/nikunjy/antlr-calc-go

I spent couple of hours trying to understand the antlr golang code base (which I think is not well written and can be improved by collaboration). If there are authors/reviewers who will review the code then I would be down to improve it but looking at the past threads it seems like golang requests have died with time.

@davesisson can you comment on this code base and let me know if this is the right way of doing the implementation. After getting frustrated I ended up writing a Visit(ParseTree) for my visitor which I think is the wrong way of writing, and I'd like you to comment on that if you have the time

func (c *CalculatorVisitorImpl) Visit(tree antlr.ParseTree) interface{} {
    switch val := tree.(type) {
    case *CalculateContext:
        return val.Accept(c)
    case *ToSetVarContext:
        return val.Accept(c)
    }
    return nil
}

I am having to write the Visit with this type switch statement, i would also have to probably write VisitChildren.

okay I think i am getting the hang of it (?)
Wrote a generic rules engine too if anyone is looking for that kind of thing
https://github.com/nikunjy/rules

Any comments here @davesisson ?

@nikunjy what do you think is wrong with your example? @parrt Huge fan of Antlr4, and agreed it is worth placing a warning here until the visitor pattern is known to work in Go.

I've been able to get the visitor working but the default code generated with the -vistor option for golang seems like it could be improved.

The most glaring issue (imo) is the composition of the Base{xxxxx}Visitor type. The way the composition and the methods currently are it looks like you could do some inheritance/method overriding (similar to how listener works), but it does not work the way I think most users would reasonably expect.

From my trials the most effective solution was to copy every method from the Base{xxxxx}Visitor generated by antlr and define each method on a new visitor type.

The main issue seems to be with VisitChildren which is defined on the absolute base in the antlr package. I think the idea was that users should be able to override the VisitChildren in their unique implementation of visitor, but I don't believe golang composition works that way. Perhaps the implementation was copied from Java without enough refactoring for golang?

I apologize that I have not included a suggested fix, but I have yet to come up with one.

Example:

type FooVisitor struct {
  BaseFooGrammarVisitor
}

func (v *FooVisitor) VisitChildren(ctx antlr.RuleNode) interface{} {
// do some stuff
}

func (v *FooVisitor) VisitSomeRule(ctx SomeRuleContext) interface{} {
  return v.VisitChildren(ctx)
}

v := &FooVisitor{}

start.Accept(v)

// call *FooVisitor.VisitSomeRule() => *FooVisitor.VisitChildren() => *BaseFooGrammarVisitor.VisitRuleNotOverriden() =>  *BaseParseTreeVisitor.VisitChildren
// *BasePareTreeVisitor.VisitChildren always returns nil

Here is a small go playground demo which might to help highlight my thinking https://play.golang.com/p/oVqsS6eAZPf
Apologies if I have made any omissions or mistakes.

This is my current implementation of the calculator from chapter 4 using the visitor pattern.
https://github.com/DavidGamba/go-antlr-calc
Hopefully someone finds it useful. Couldn't get the underline error to work.
As mentioned before, had to implement every method.

I really need a elegent antlr visitor for go. Is anybody fix it? Can you send a PR?

I also would like to see an official example on how to use the visitor for golang antlr.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ngundu picture ngundu  Â·  18Comments

lionelplessis picture lionelplessis  Â·  21Comments

ashishnegi picture ashishnegi  Â·  25Comments

pavelvelikhov picture pavelvelikhov  Â·  57Comments

parrt picture parrt  Â·  32Comments