diff --git a/tool/playground/T.g b/tool/playground/T.g index 3c214e923..0d0ede461 100644 --- a/tool/playground/T.g +++ b/tool/playground/T.g @@ -1,7 +1,7 @@ grammar T; options {output=AST;} tokens {I;} -a : A b ';' -> A b ';' ; +a : A b C -> ^(A b C) ; b : B ; @@ -9,6 +9,7 @@ A : 'a'; B : 'b'; C : 'c'; D : 'd'; +SEMI : ';'; WS : ' '|'\t'|'\n' {skip();} ; /* diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg index aff2b8ebc..d4e52c44b 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg @@ -376,7 +376,7 @@ _adaptor.setTokenBoundaries(_localctx.tree, _localctx.start, _localctx.stop); ElementListDecl(d) ::= "List\<Object> <d.name> = _adaptor.createElementList();" ElementListName(elemName) ::= "_track_<elemName>" -TrackRuleElement(e) ::= "<e.name>.add(<labelref(e.label)>);" +TrackRuleElement(e) ::= "<e.name>.add(<labelref(e.label)>.tree);" TrackTokenElement(e) ::= "<e.name>.add(_adaptor.create(<labelref(e.label)>));" TreeRewrite(tr, locals, preamble, ops) ::= << @@ -384,12 +384,23 @@ TreeRewrite(tr, locals, preamble, ops) ::= << <CodeBlockForAlt(tr, locals, preamble, ops)> >> +RewriteTreeStructure(t, ops) ::= << +<ops; separator="\n"> +>> RewriteIteratorDecl(d) ::= "Iterator <d.name>;" RewriteIteratorInit(i) ::= "<i.decl.name> = <i.decl.listName>.iterator();" RewriteIteratorName(elemName,level) ::= "it<level>_<elemName>" RewriteTokenRef(t) ::= "_adaptor.addChild(<t.enclosingBlock.rootDecl.name>, <t.decl.name>.next());" -RewriteRuleRef(r) ::= "/* ruleref */" +RewriteTokenRefIsRoot(t) ::= <% +<labelref(t.enclosingBlock.rootDecl)> = + _adaptor.becomeRoot(<t.decl.name>.next(), <labelref(t.enclosingBlock.rootDecl)>); +%> +RewriteRuleRef(r) ::= "_adaptor.addChild(<r.enclosingBlock.rootDecl.name>, <r.decl.name>.next());" +RewriteRuleRefIsRoot(r) ::= <% +<labelref(r.enclosingBlock.rootDecl)> = + _adaptor.becomeRoot(<r.decl.name>.next(), <labelref(r.enclosingBlock.rootDecl)>); +%> /* BitSetDecl(b) ::= << diff --git a/tool/src/org/antlr/v4/codegen/BlankOutputModelFactory.java b/tool/src/org/antlr/v4/codegen/BlankOutputModelFactory.java index 3ae21db50..b4183b64a 100644 --- a/tool/src/org/antlr/v4/codegen/BlankOutputModelFactory.java +++ b/tool/src/org/antlr/v4/codegen/BlankOutputModelFactory.java @@ -79,11 +79,13 @@ public abstract class BlankOutputModelFactory implements OutputModelFactory { public TreeRewrite treeRewrite(GrammarAST ast, int rewriteLevel) { return null; } - public List<SrcOp> rewrite_ruleRef(GrammarAST ID) { return null; } + public List<SrcOp> rewrite_tree(GrammarAST root, List<SrcOp> ops) { return null; } - public List<SrcOp> rewrite_tokenRef(GrammarAST ID) { return null; } + public List<SrcOp> rewrite_ruleRef(GrammarAST ID, boolean isRoot) { return null; } - public List<SrcOp> rewrite_stringRef(GrammarAST ID) { return rewrite_tokenRef(ID); } + public List<SrcOp> rewrite_tokenRef(GrammarAST ID, boolean isRoot) { return null; } + + public List<SrcOp> rewrite_stringRef(GrammarAST ID, boolean isRoot) { return rewrite_tokenRef(ID, isRoot); } // BLOCKS diff --git a/tool/src/org/antlr/v4/codegen/CodeGeneratorExtension.java b/tool/src/org/antlr/v4/codegen/CodeGeneratorExtension.java index fbddc86b0..6ffe1672a 100644 --- a/tool/src/org/antlr/v4/codegen/CodeGeneratorExtension.java +++ b/tool/src/org/antlr/v4/codegen/CodeGeneratorExtension.java @@ -89,6 +89,8 @@ public class CodeGeneratorExtension { public TreeRewrite treeRewrite(TreeRewrite r) { return r; } + public List<SrcOp> rewrite_tree(List<SrcOp> ops) { return ops; } + public List<SrcOp> rewrite_ruleRef(List<SrcOp> ops) { return ops; } public List<SrcOp> rewrite_tokenRef(List<SrcOp> ops) { return ops; } diff --git a/tool/src/org/antlr/v4/codegen/OutputModelController.java b/tool/src/org/antlr/v4/codegen/OutputModelController.java index 923614593..eeb3fa528 100644 --- a/tool/src/org/antlr/v4/codegen/OutputModelController.java +++ b/tool/src/org/antlr/v4/codegen/OutputModelController.java @@ -278,19 +278,25 @@ public class OutputModelController implements OutputModelFactory { return r; } - public List<SrcOp> rewrite_ruleRef(GrammarAST ID) { - List<SrcOp> ops = delegate.rewrite_ruleRef(ID); + public List<SrcOp> rewrite_tree(GrammarAST root, List<SrcOp> ops) { + ops = delegate.rewrite_tree(root, ops); + for (CodeGeneratorExtension ext : extensions) ops = ext.rewrite_tree(ops); + return ops; + } + + public List<SrcOp> rewrite_ruleRef(GrammarAST ID, boolean isRoot) { + List<SrcOp> ops = delegate.rewrite_ruleRef(ID, isRoot); for (CodeGeneratorExtension ext : extensions) ops = ext.rewrite_ruleRef(ops); return ops; } - public List<SrcOp> rewrite_tokenRef(GrammarAST ID) { - List<SrcOp> ops = delegate.rewrite_tokenRef(ID); + public List<SrcOp> rewrite_tokenRef(GrammarAST ID, boolean isRoot) { + List<SrcOp> ops = delegate.rewrite_tokenRef(ID, isRoot); for (CodeGeneratorExtension ext : extensions) ops = ext.rewrite_tokenRef(ops); return ops; } - public List<SrcOp> rewrite_stringRef(GrammarAST ID) { return rewrite_tokenRef(ID); } + public List<SrcOp> rewrite_stringRef(GrammarAST ID, boolean isRoot) { return rewrite_tokenRef(ID, isRoot); } public OutputModelObject getRoot() { return delegate.getRoot(); } diff --git a/tool/src/org/antlr/v4/codegen/OutputModelFactory.java b/tool/src/org/antlr/v4/codegen/OutputModelFactory.java index d0c927f29..e9d6f7b97 100644 --- a/tool/src/org/antlr/v4/codegen/OutputModelFactory.java +++ b/tool/src/org/antlr/v4/codegen/OutputModelFactory.java @@ -98,11 +98,13 @@ public interface OutputModelFactory { TreeRewrite treeRewrite(GrammarAST ast, int rewriteLevel); - List<SrcOp> rewrite_ruleRef(GrammarAST ID); + List<SrcOp> rewrite_tree(GrammarAST root, List<SrcOp> ops); - List<SrcOp> rewrite_tokenRef(GrammarAST ID); + List<SrcOp> rewrite_ruleRef(GrammarAST ID, boolean isRoot); - List<SrcOp> rewrite_stringRef(GrammarAST ID); + List<SrcOp> rewrite_tokenRef(GrammarAST ID, boolean isRoot); + + List<SrcOp> rewrite_stringRef(GrammarAST ID, boolean isRoot); // CONTEXT MANIPULATION diff --git a/tool/src/org/antlr/v4/codegen/ParserFactory.java b/tool/src/org/antlr/v4/codegen/ParserFactory.java index 964add9c7..27be0ea24 100644 --- a/tool/src/org/antlr/v4/codegen/ParserFactory.java +++ b/tool/src/org/antlr/v4/codegen/ParserFactory.java @@ -176,20 +176,31 @@ public class ParserFactory extends DefaultOutputModelFactory { return new TreeRewrite(this, rewriteLevel); } - public List<SrcOp> rewrite_ruleRef(GrammarAST ID) { - RewriteIteratorDecl d = new RewriteIteratorDecl(this, ID, 0); - getCurrentBlock().addLocalDecl(d); - RewriteIteratorInit init = new RewriteIteratorInit(this, d); - getCurrentBlock().addPreambleOp(init); - return list(new RewriteRuleRef(this, ID)); + @Override + public List<SrcOp> rewrite_tree(GrammarAST root, List<SrcOp> ops) { + return list(new RewriteTreeStructure(this, root, ops)); } - public List<SrcOp> rewrite_tokenRef(GrammarAST ID) { + public List<SrcOp> rewrite_ruleRef(GrammarAST ID, boolean isRoot) { RewriteIteratorDecl d = new RewriteIteratorDecl(this, ID, 0); getCurrentBlock().addLocalDecl(d); RewriteIteratorInit init = new RewriteIteratorInit(this, d); getCurrentBlock().addPreambleOp(init); - return list(new RewriteTokenRef(this, ID, d)); + RewriteRuleRef ruleRef; + if ( isRoot ) ruleRef = new RewriteRuleRefIsRoot(this, ID, d); + else ruleRef = new RewriteRuleRef(this, ID, d); + return list(ruleRef); + } + + public List<SrcOp> rewrite_tokenRef(GrammarAST ID, boolean isRoot) { + RewriteIteratorDecl d = new RewriteIteratorDecl(this, ID, 0); + getCurrentBlock().addLocalDecl(d); + RewriteIteratorInit init = new RewriteIteratorInit(this, d); + getCurrentBlock().addPreambleOp(init); + RewriteTokenRef tokenRef; + if ( isRoot ) tokenRef = new RewriteTokenRefIsRoot(this, ID, d); + else tokenRef = new RewriteTokenRef(this, ID, d); + return list(tokenRef); } // support diff --git a/tool/src/org/antlr/v4/codegen/SourceGenTriggers.g b/tool/src/org/antlr/v4/codegen/SourceGenTriggers.g index f1722880f..df3979590 100644 --- a/tool/src/org/antlr/v4/codegen/SourceGenTriggers.g +++ b/tool/src/org/antlr/v4/codegen/SourceGenTriggers.g @@ -63,7 +63,7 @@ alternative returns [CodeBlockForAlt altCodeBlock] $altCodeBlock = factory.alternative(factory.getCurrentAlt()); factory.setCurrentBlock($altCodeBlock); } - ^( ALT ( element {if ($element.omos!=null) elems.addAll($element.omos);} )+ ) + ^( ALT ( element {if ($element.omos!=null) elems.addAll($element.omos);} )+ ) {$altCodeBlock.ops = elems;} ; @@ -190,19 +190,19 @@ rewriteTreeAlt returns [List<SrcOp> omos] ; rewriteTreeElement returns [List<SrcOp> omos] - : rewriteTreeAtom {$omos = $rewriteTreeAtom.omos;} + : rewriteTreeAtom[false] {$omos = $rewriteTreeAtom.omos;} | rewriteTree {$omos = $rewriteTree.omos;} | rewriteTreeEbnf {$omos = $rewriteTreeEbnf.omos;} ; -rewriteTreeAtom returns [List<SrcOp> omos] +rewriteTreeAtom[boolean isRoot] returns [List<SrcOp> omos] : ^(TOKEN_REF elementOptions ARG_ACTION) | ^(TOKEN_REF elementOptions) | ^(TOKEN_REF ARG_ACTION) - | TOKEN_REF {$omos = factory.rewrite_tokenRef($TOKEN_REF);} - | RULE_REF {$omos = factory.rewrite_ruleRef($RULE_REF);} - | ^(STRING_LITERAL elementOptions) {$omos = factory.rewrite_stringRef($STRING_LITERAL);} - | STRING_LITERAL {$omos = factory.rewrite_stringRef($STRING_LITERAL);} + | TOKEN_REF {$omos = factory.rewrite_tokenRef($TOKEN_REF, $isRoot);} + | RULE_REF {$omos = factory.rewrite_ruleRef($RULE_REF, $isRoot);} + | ^(STRING_LITERAL elementOptions) {$omos = factory.rewrite_stringRef($STRING_LITERAL, $isRoot);} + | STRING_LITERAL {$omos = factory.rewrite_stringRef($STRING_LITERAL, $isRoot);} | LABEL | ACTION ; @@ -213,7 +213,12 @@ rewriteTreeEbnf returns [List<SrcOp> omos] ; rewriteTree returns [List<SrcOp> omos] - : ^(TREE_BEGIN rewriteTreeAtom rewriteTreeElement* ) + : {List<SrcOp> elems = new ArrayList<SrcOp>();} + ^( TREE_BEGIN + rewriteTreeAtom[true] {elems.addAll($rewriteTreeAtom.omos);} + ( rewriteTreeElement {elems.addAll($rewriteTreeElement.omos);} )* + ) + {$omos = factory.rewrite_tree($TREE_BEGIN, elems);} ; rewriteSTAlt returns [List<SrcOp> omos] diff --git a/tool/src/org/antlr/v4/codegen/model/ast/RewriteRuleRef.java b/tool/src/org/antlr/v4/codegen/model/ast/RewriteRuleRef.java index edbd51a5b..f6c367296 100644 --- a/tool/src/org/antlr/v4/codegen/model/ast/RewriteRuleRef.java +++ b/tool/src/org/antlr/v4/codegen/model/ast/RewriteRuleRef.java @@ -31,10 +31,14 @@ package org.antlr.v4.codegen.model.ast; import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.codegen.model.SrcOp; +import org.antlr.v4.codegen.model.decl.RewriteIteratorDecl; import org.antlr.v4.tool.GrammarAST; public class RewriteRuleRef extends SrcOp { - public RewriteRuleRef(OutputModelFactory factory, GrammarAST ast) { + /** Which iterator decl are we associated with? */ + public RewriteIteratorDecl decl; + public RewriteRuleRef(OutputModelFactory factory, GrammarAST ast, RewriteIteratorDecl decl) { super(factory, ast); + this.decl = decl; } } diff --git a/tool/src/org/antlr/v4/codegen/model/ast/RewriteRuleRefIsRoot.java b/tool/src/org/antlr/v4/codegen/model/ast/RewriteRuleRefIsRoot.java new file mode 100644 index 000000000..e61432a30 --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/model/ast/RewriteRuleRefIsRoot.java @@ -0,0 +1,40 @@ +/* + [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.decl.RewriteIteratorDecl; +import org.antlr.v4.tool.GrammarAST; + +public class RewriteRuleRefIsRoot extends RewriteRuleRef { + public RewriteRuleRefIsRoot(OutputModelFactory factory, GrammarAST ast, RewriteIteratorDecl decl) { + super(factory, ast, decl); + } +} diff --git a/tool/src/org/antlr/v4/codegen/model/ast/RewriteTokenRefIsRoot.java b/tool/src/org/antlr/v4/codegen/model/ast/RewriteTokenRefIsRoot.java new file mode 100644 index 000000000..f02bb5aef --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/model/ast/RewriteTokenRefIsRoot.java @@ -0,0 +1,40 @@ +/* + [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.decl.RewriteIteratorDecl; +import org.antlr.v4.tool.GrammarAST; + +public class RewriteTokenRefIsRoot extends RewriteTokenRef { + public RewriteTokenRefIsRoot(OutputModelFactory factory, GrammarAST ast, RewriteIteratorDecl decl) { + super(factory, ast, decl); + } +} diff --git a/tool/src/org/antlr/v4/codegen/model/ast/RewriteTreeStructure.java b/tool/src/org/antlr/v4/codegen/model/ast/RewriteTreeStructure.java new file mode 100644 index 000000000..ad16272ed --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/model/ast/RewriteTreeStructure.java @@ -0,0 +1,46 @@ +/* + [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.tool.GrammarAST; + +import java.util.List; + +/** ^(A B C) */ +public class RewriteTreeStructure extends SrcOp { + @ModelElement public List<? extends SrcOp> ops; + + public RewriteTreeStructure(OutputModelFactory factory, GrammarAST ast, List<? extends SrcOp> ops) { + super(factory, ast); + this.ops = ops; + } +}