using old ast op code from v3. works fine.
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 8812]
This commit is contained in:
parent
a421082008
commit
b9daa3763c
|
@ -44,29 +44,71 @@ public abstract class BaseTreeAdaptor implements TreeAdaptor {
|
|||
|
||||
// BEGIN v4 stuff
|
||||
|
||||
/* Upon B^ in these cases:
|
||||
A B^ add kids to newRoot B
|
||||
return B
|
||||
A^ B^ add any remaining kids to A
|
||||
clear kids
|
||||
add A as child of B
|
||||
return B
|
||||
r B^ add kids to B
|
||||
clear kids
|
||||
return B
|
||||
r^ B^
|
||||
|
||||
Upon r^ in these cases:
|
||||
A r^
|
||||
A^ r^
|
||||
s r^
|
||||
s^ r^
|
||||
|
||||
A r^ B, r is (C D). result = (C D A B)
|
||||
becomeRoot((C D), (nil A))
|
||||
|
||||
A r^ B, r is (nil C D). result = (A C D B)
|
||||
becomeRoot((nil C D), (nil A))
|
||||
|
||||
todo: ref to r must chk if ^(nil list); can't just add to List<Tree>
|
||||
*/
|
||||
public Object becomeRoot(Object oldRoot, Object newRoot, List kids) {
|
||||
return null;
|
||||
// old root can be nil rooted if root set by r^ call like "r^ A"; implies a list
|
||||
if ( ((Tree)oldRoot).isNil() ) {
|
||||
addChildren(newRoot, getChildren(oldRoot)); // add old children to new root
|
||||
addChildren(newRoot, kids); // add unattached kids also
|
||||
kids.clear();
|
||||
return oldRoot;
|
||||
}
|
||||
// must be from previous root match like "A^ B^" or single node
|
||||
// result from r^ or rooted/non-nil root from r^ in "r^ A^".
|
||||
addChildren(oldRoot, kids);
|
||||
kids.clear();
|
||||
addChild(newRoot, oldRoot); // newRoot becomes root of old root
|
||||
return newRoot;
|
||||
}
|
||||
|
||||
/** if oldRoot is nil then:
|
||||
/** if oldRoot is nil then (oldRoot must be r^ result):
|
||||
* create newRoot for rootToken
|
||||
* add kids to newRoot
|
||||
* clear kids
|
||||
* return as new root
|
||||
* if oldRoot not nil then:
|
||||
* if oldRoot not nil then (must have created from A^):
|
||||
* add kids to oldRoot
|
||||
* clear kids
|
||||
* create rootToken
|
||||
* return as new root
|
||||
*/
|
||||
public Object becomeRoot(Object oldRoot, Token rootToken, List kids) {
|
||||
// first flush all previous children onto old root
|
||||
|
||||
// old root can be nil rooted if root set by r^ call like "r^ A"; implies a list
|
||||
if ( ((Tree)oldRoot).isNil() ) {
|
||||
oldRoot = create(rootToken);
|
||||
addChildren(oldRoot, kids);
|
||||
Tree newRoot = (Tree)create(rootToken);
|
||||
addChildren(newRoot, getChildren(oldRoot)); // add old children to new root
|
||||
addChildren(newRoot, kids); // add unattached kids also
|
||||
kids.clear();
|
||||
return oldRoot;
|
||||
}
|
||||
// must be from previous root match like "A^ B^" or single node
|
||||
// result from r^ or rooted/non-nil root from r^ in "r^ A^".
|
||||
addChildren(oldRoot, kids);
|
||||
kids.clear();
|
||||
Object newRoot = create(rootToken);
|
||||
|
@ -78,6 +120,31 @@ public abstract class BaseTreeAdaptor implements TreeAdaptor {
|
|||
if ( root!=null ) ((Tree)root).addChildren(kids);
|
||||
}
|
||||
|
||||
public List getChildren(Object root) { return ((Tree)root).getChildren(); }
|
||||
|
||||
/** Add remaining kids to non-null root. If null root, add kids to
|
||||
* new nil root. If only one kid, make it the root. Return the
|
||||
* root.
|
||||
*/
|
||||
public Object rulePostProcessing(Object root, List kids) {
|
||||
if ( root!=null ) {
|
||||
addChildren(root, kids);
|
||||
}
|
||||
else {
|
||||
if ( kids.size()==1 ) {
|
||||
root = kids.get(0);
|
||||
// whoever invokes rule will set parent and child index
|
||||
((Tree)root).setParent(null);
|
||||
((Tree)root).setChildIndex(-1);
|
||||
}
|
||||
if ( kids.size()>1 ) {
|
||||
root = nil();
|
||||
addChildren(root, kids);
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
// END v4 stuff
|
||||
|
||||
public Object nil() {
|
||||
|
|
|
@ -49,6 +49,8 @@ public interface Tree {
|
|||
// BEGIN v4
|
||||
void addChildren(List t);
|
||||
|
||||
List getChildren();
|
||||
|
||||
// END v4
|
||||
|
||||
Tree getChild(int i);
|
||||
|
|
|
@ -63,6 +63,14 @@ public interface TreeAdaptor {
|
|||
// If not null root, add kids to it
|
||||
public void addChildren(Object root, List kids);
|
||||
|
||||
public List getChildren(Object root);
|
||||
|
||||
/** Add remaining kids to non-null root. If null root, add kids to
|
||||
* new nil root. If only one kid, make it the root. Return the
|
||||
* root.
|
||||
*/
|
||||
public Object rulePostProcessing(Object root, List kids);
|
||||
|
||||
// END new v4 stuff
|
||||
|
||||
// C o n s t r u c t i o n
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
grammar T;
|
||||
options {output=AST;}
|
||||
a : A^ C^ D ;
|
||||
a : D^ b^ C D b;
|
||||
|
||||
b : B ;
|
||||
|
||||
|
|
|
@ -103,8 +103,8 @@ public QStack\<<currentRule.ctxType>\> <currentRule.name>_stk = new QStack\<<cur
|
|||
<locals; separator="\n">
|
||||
try {
|
||||
<code>
|
||||
<postamble; separator="\n">
|
||||
_localctx.stop = input.LT(-1);
|
||||
<postamble; separator="\n">
|
||||
<namedActions.after>
|
||||
}
|
||||
catch (RecognitionException re) {
|
||||
|
@ -359,18 +359,18 @@ labelref(x) ::= "<if(!x.isLocal)>_localctx.<endif><x.name>"
|
|||
// AST stuff (TODO: separate?)
|
||||
|
||||
KidsListDecl(d) ::= "List <d.name> = new ArrayList(5);"
|
||||
RootDecl(d) ::= "Object <d.name> = null;"
|
||||
RootDecl(d) ::= "Object <d.name> = _adaptor.nil();"
|
||||
RootName(level) ::= "_root<level>"
|
||||
KidsListName(level) ::= "_kids<level>"
|
||||
|
||||
AddTokenLeaf(a) ::= "_kids0.add(_adaptor.create(<labelref(a.label)>));"
|
||||
AddRuleLeaf(a) ::= "_kids0.add(<labelref(a.label)>.tree);"
|
||||
// TODO: need RuleBecomeRoot
|
||||
BecomeRoot(r) ::= "_root0 = _root0==null ? _adaptor.create(<labelref(r.label)>) : _adaptor.becomeRoot(_root0, <labelref(r.label)>, _kids0);"
|
||||
AddTokenLeaf(a) ::= "_adaptor.addChild(_root0, _adaptor.create(<labelref(a.label)>));"
|
||||
AddRuleLeaf(a) ::= "_adaptor.addChild(_root0, <labelref(a.label)>.tree);"
|
||||
RuleBecomeRoot(r) ::= "_root0 = _adaptor.becomeRoot(<labelref(r.label)>.tree, _root0);"
|
||||
TokenBecomeRoot(t) ::= "_root0 = _adaptor.becomeRoot(_adaptor.create(<labelref(t.label)>), _root0);"
|
||||
AssignTreeResult(a) ::= <<
|
||||
if ( _root0==null && _kids0.size()>0 ) _root0 = _adaptor.nil();
|
||||
_adaptor.addChildren(_root0, _kids0);
|
||||
_root0 = _adaptor.rulePostProcessing(_root0);
|
||||
_localctx.tree = _root0;
|
||||
_adaptor.setTokenBoundaries(_localctx.tree, _localctx.start, _localctx.stop);
|
||||
>>
|
||||
|
||||
/*
|
||||
|
|
|
@ -49,14 +49,14 @@ public class ParserASTExtension extends CodeGeneratorExtension {
|
|||
@Override
|
||||
public List<SrcOp> rootRule(List<SrcOp> ops) {
|
||||
InvokeRule invokeOp = (InvokeRule)Utils.find(ops, InvokeRule.class);
|
||||
SrcOp treeOp = new BecomeRoot(factory, invokeOp.ast, invokeOp);
|
||||
SrcOp treeOp = new RuleBecomeRoot(factory, invokeOp.ast, invokeOp);
|
||||
return DefaultOutputModelFactory.list(ops, treeOp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SrcOp> rootToken(List<SrcOp> ops) {
|
||||
MatchToken matchOp = (MatchToken)Utils.find(ops, MatchToken.class);
|
||||
SrcOp treeOp = new BecomeRoot(factory, matchOp.ast, matchOp);
|
||||
SrcOp treeOp = new TokenBecomeRoot(factory, matchOp.ast, matchOp);
|
||||
return DefaultOutputModelFactory.list(ops, treeOp);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,12 +34,11 @@ import org.antlr.v4.codegen.model.*;
|
|||
import org.antlr.v4.codegen.model.decl.Decl;
|
||||
import org.antlr.v4.tool.GrammarAST;
|
||||
|
||||
/** */
|
||||
public class BecomeRoot extends SrcOp {
|
||||
public class RuleBecomeRoot extends SrcOp {
|
||||
public LabeledOp opWithResultToAdd;
|
||||
public Decl label;
|
||||
|
||||
public BecomeRoot(OutputModelFactory factory, GrammarAST ast, LabeledOp opWithResultToAdd) {
|
||||
public RuleBecomeRoot(OutputModelFactory factory, GrammarAST ast, LabeledOp opWithResultToAdd) {
|
||||
super(factory, ast);
|
||||
this.opWithResultToAdd = opWithResultToAdd;
|
||||
label = opWithResultToAdd.getLabels().get(0);
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
[The "BSD license"]
|
||||
Copyright (c) 2011 Terence Parr
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package org.antlr.v4.codegen.model.ast;
|
||||
|
||||
import org.antlr.v4.codegen.OutputModelFactory;
|
||||
import org.antlr.v4.codegen.model.*;
|
||||
import org.antlr.v4.codegen.model.decl.Decl;
|
||||
import org.antlr.v4.tool.GrammarAST;
|
||||
|
||||
/** */
|
||||
public class TokenBecomeRoot extends SrcOp {
|
||||
public LabeledOp opWithResultToAdd;
|
||||
public Decl label;
|
||||
|
||||
public TokenBecomeRoot(OutputModelFactory factory, GrammarAST ast, LabeledOp opWithResultToAdd) {
|
||||
super(factory, ast);
|
||||
this.opWithResultToAdd = opWithResultToAdd;
|
||||
label = opWithResultToAdd.getLabels().get(0);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue