Skip to content

Conversation

parrt
Copy link
Member

@parrt parrt commented Feb 18, 2017

An addendum to #1665

Technically, this is not backward compatible as it changes the interface but no one was able to create custom TerminalNodes anyway so I'm adding as it improves internal code quality. addChild now sets the parent rather than create. MUCH better.

…ard compatible as it changes the interface but no one was able to create custom TerminalNodes anyway so I'm adding as it improves internal code quality. addChild now sets the parent rather than create. MUCH better.
TerminalNodeImpl node = new TerminalNodeImpl(t);
node.parent = parent;
return node;
return new TerminalNodeImpl(t);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter parent should go. It's no longer used and produces warnings e.g. in the C++ target.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the leaf might be a function of the parent though, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, in what sense? The parent is set by the caller, so why pass it into this method?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, one might want to create a different kind of leaf (i.e., type) if the parent is an expression versus a declaration. For example, an ID token might become VarRef vs VarDef leaf? Just leaving it flexible but I can see removing it if you guys feel strongly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I see your point. Have to manually take care about that parameter then in C++ (not the first time, there are many other places with the same kind of issue).

ErrorNodeImpl node = new ErrorNodeImpl(t);
node.parent = parent;
return node;
return new ErrorNodeImpl(t);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

this.children.add(child);
((ErrorNodeImpl) child).parent = this;
if ( child instanceof ErrorNode ) {
addChild((ErrorNode)child);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit weird code. You are not copying the error node, but actually create references from 2 contexts and only set the new context as parent. However, it's still in the source context, since you don't remove it from there. What is the real intention here? Really move the node or create a duplicate (like the method name suggests).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error nodes should be moved to the new context in copyFrom as it's used only for flipping contexts per the comment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I said, a bit weird. You have a copy function which moves something :-) At least I have it then like you want. But the Java code is still buggy. The error node is still in the children list of the source context, since you don't remove it from there.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The node copied from is candidate for GC as all refs to it disappear; figured it's a waste to alter it when it's dead. Maybe a better comment? :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, that is implicit knowledge, which is not visible at this point in code and for some targets like C++ it is very important to know what is managing the memory. And if you one day decide to keep the source context around you certainly forgot by that time that it contains nodes which are supposed to be in a different context.

@@ -139,12 +139,18 @@ public RuleContext addChild(RuleContext ruleInvocation) {
return addAnyChild(ruleInvocation);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't want to set the parent of the ruleInvocation context like you do for terminal and error nodes?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, that is bound up in the parsing functionality; i know it's odd.

@mike-lischke
Copy link
Member

Also, what is the meaning of a setter for a property which is directly accessbile? The parent field is public in TerminalNodeImpl. I fail to see how this makes the code better. A setter only make sense if you have side effects when changing a member,

@parrt
Copy link
Member Author

parrt commented Feb 22, 2017

@mike-lischke TerminalNode is an interface not a class so no field is available.

hanjoes added a commit to hanjoes/antlr4 that referenced this pull request Feb 25, 2017
parrt added a commit that referenced this pull request Mar 1, 2017
C++ implementation of issue #1665 and issue #1674
parrt added a commit that referenced this pull request Mar 1, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants