good start on * and ? in rewrites

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 8826]
This commit is contained in:
parrt 2011-07-04 17:47:44 -08:00
parent fbc92258f6
commit df80cb7622
23 changed files with 331 additions and 76 deletions

View File

@ -1,11 +1,15 @@
grammar T;
options {output=AST;}
tokens {I;}
/*
a : A b C -> ^(A ^(b C))
| B
;
b : B | C ;
*/
c : A B C -> (A B C*)* ;
A : 'a';
B : 'b';

View File

@ -2,7 +2,6 @@ import org.antlr.v4.Tool;
import org.antlr.v4.automata.ParserATNFactory;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.runtime.tree.Tree;
import org.antlr.v4.semantics.SemanticPipeline;
import org.antlr.v4.tool.*;
@ -13,8 +12,8 @@ public class TestT {
TLexer t = new TLexer(new ANTLRFileStream(args[0]));
CommonTokenStream tokens = new CommonTokenStream(t);
TParser p = new TParser(tokens);
ParserRuleContext ret = p.a();
System.out.println(((Tree)ret.tree).toStringTree());
// ParserRuleContext ret = p.a();
// System.out.println(((Tree)ret.tree).toStringTree());
}
public static void dump() throws Exception {

View File

@ -389,6 +389,28 @@ TreeRewrite(tr, locals, preamble, ops) ::= <<
_localctx.tree = _root0;
>>
RewriteIteratorDecl(d) ::= "Iterator <d.name>;"
RewriteIteratorInit(i) ::= "<i.decl.name> = <i.decl.listName>.iterator();"
RewriteIteratorName(elemName,level) ::= "it<level>_<elemName>"
RewriteTreeOptional(o, locals, preamble, ops) ::= <<
// ?
<locals; separator="\n">
<preamble; separator="\n">
//if ( true ) {
<ops; separator="\n">
//}
>>
RewriteTreeClosure(c, locals, preamble, ops) ::= <<
// *
<locals; separator="\n">
<preamble; separator="\n">
//while ( <c.iteratorDecls:{d | <d.name>.hasNext()}; separator=" || "> ) {
<ops; separator="\n">
//}
>>
RewriteTreeStructure(t, locals, preamble, ops) ::= <<
{
<locals; separator="\n">
@ -397,15 +419,11 @@ RewriteTreeStructure(t, locals, preamble, ops) ::= <<
_adaptor.addChild(<labelref(t.enclosingBlock.rootDecl)>, <labelref(t.rootDecl)>);
}
>>
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());"
RewriteTokenRefIsRoot(t) ::= <%
<labelref(t.enclosingBlock.rootDecl)> =
_adaptor.becomeRoot(<t.decl.name>.next(), <labelref(t.enclosingBlock.rootDecl)>);
%>
RewriteTokenRef(t) ::= "_adaptor.addChild(<t.rootName>, <t.decl.name>.next());"
RewriteTokenRefIsRoot(t) ::= <<
<t.rootName> = _adaptor.becomeRoot(<t.decl.name>.next(), <t.rootName>);
>>
RewriteRuleRef(r) ::= "_adaptor.addChild(<r.enclosingBlock.rootDecl.name>, <r.decl.name>.next());"
RewriteRuleRefIsRoot(r) ::= <%
<labelref(r.enclosingBlock.rootDecl)> =

View File

@ -79,9 +79,13 @@ public abstract class BlankOutputModelFactory implements OutputModelFactory {
// AST REWRITES
public TreeRewrite treeRewrite(GrammarAST ast, int rewriteLevel) { return null; }
public TreeRewrite treeRewrite(GrammarAST ast) { return null; }
public RewriteTreeStructure rewrite_tree(GrammarAST root, int rewriteLevel) { return null; }
public RewriteTreeOptional rewrite_optional(GrammarAST ast) { return null; }
public RewriteTreeClosure rewrite_closure(GrammarAST ast) { return null; }
public RewriteTreeStructure rewrite_tree(GrammarAST root) { return null; }
public List<SrcOp> rewrite_ruleRef(GrammarAST ID, boolean isRoot) { return null; }

View File

@ -91,6 +91,10 @@ public class CodeGeneratorExtension {
public TreeRewrite treeRewrite(TreeRewrite r) { return r; }
public RewriteTreeOptional rewrite_optional(RewriteTreeOptional o) { return o; }
public RewriteTreeClosure rewrite_closure(RewriteTreeClosure c) { return c; }
public RewriteTreeStructure rewrite_tree(RewriteTreeStructure t) { return t; }
public List<SrcOp> rewrite_ruleRef(List<SrcOp> ops) { return ops; }

View File

@ -30,7 +30,7 @@
package org.antlr.v4.codegen;
import org.antlr.v4.codegen.model.*;
import org.antlr.v4.codegen.model.decl.CodeBlock;
import org.antlr.v4.codegen.model.decl.*;
import org.antlr.v4.tool.*;
import java.util.*;
@ -93,6 +93,10 @@ public abstract class DefaultOutputModelFactory extends BlankOutputModelFactory
return currentBlock;
}
public int getCodeBlockLevel() { return controller.walker.codeBlockLevel; }
public int getTreeLevel() { return controller.walker.treeLevel; }
// MISC
public static List<SrcOp> list(Object... values) {
@ -105,5 +109,13 @@ public abstract class DefaultOutputModelFactory extends BlankOutputModelFactory
}
return x;
}
public Decl getCurrentDeclForName(String name) {
for (Decl d : getCurrentBlock().locals.elements()) {
if ( d.name.equals(name) ) return d;
}
return null;
}
}

View File

@ -49,6 +49,11 @@ public class OutputModelController implements OutputModelFactory {
/** Post-processing CodeGeneratorExtension objects; done in order given. */
public List<CodeGeneratorExtension> extensions = new ArrayList<CodeGeneratorExtension>();
/** While walking code in rules, this is set to the tree walker that
* triggers actions.
*/
public SourceGenTriggers walker;
public OutputModelController(OutputModelFactory factory) {
this.delegate = factory;
}
@ -76,9 +81,9 @@ public class OutputModelController implements OutputModelFactory {
GrammarASTAdaptor adaptor = new GrammarASTAdaptor(r.ast.token.getInputStream());
GrammarAST blk = (GrammarAST)r.ast.getFirstChildWithType(ANTLRParser.BLOCK);
CommonTreeNodeStream nodes = new CommonTreeNodeStream(adaptor,blk);
SourceGenTriggers genTriggers = new SourceGenTriggers(nodes, this);
walker = new SourceGenTriggers(nodes, this);
try {
function.code = DefaultOutputModelFactory.list(genTriggers.block(null, null)); // walk AST of rule alts/elements
function.code = DefaultOutputModelFactory.list(walker.block(null, null)); // walk AST of rule alts/elements
}
catch (Exception e){
e.printStackTrace(System.err);
@ -278,14 +283,27 @@ public class OutputModelController implements OutputModelFactory {
// REWRITES
public TreeRewrite treeRewrite(GrammarAST ast, int rewriteLevel) {
TreeRewrite r = delegate.treeRewrite(ast, rewriteLevel);
public TreeRewrite treeRewrite(GrammarAST ast) {
TreeRewrite r = delegate.treeRewrite(ast);
for (CodeGeneratorExtension ext : extensions) r = ext.treeRewrite(r);
return r;
}
public RewriteTreeStructure rewrite_tree(GrammarAST root, int rewriteLevel) {
RewriteTreeStructure t = delegate.rewrite_tree(root, rewriteLevel);
public RewriteTreeOptional rewrite_optional(GrammarAST ast) {
RewriteTreeOptional o = delegate.rewrite_optional(ast);
for (CodeGeneratorExtension ext : extensions) o = ext.rewrite_optional(o);
return o;
}
public RewriteTreeClosure rewrite_closure(GrammarAST ast) {
List<GrammarAST> refs = getElementReferencesShallow(ast);
RewriteTreeClosure c = delegate.rewrite_closure(ast);
for (CodeGeneratorExtension ext : extensions) c = ext.rewrite_closure(c);
return c;
}
public RewriteTreeStructure rewrite_tree(GrammarAST root) {
RewriteTreeStructure t = delegate.rewrite_tree(root);
for (CodeGeneratorExtension ext : extensions) t = ext.rewrite_tree(t);
return t;
}
@ -323,4 +341,76 @@ public class OutputModelController implements OutputModelFactory {
public void setCurrentBlock(CodeBlock blk) { delegate.setCurrentBlock(blk); }
public CodeBlock getCurrentBlock() { return delegate.getCurrentBlock(); }
public int getCodeBlockLevel() { return delegate.getCodeBlockLevel(); }
public int getTreeLevel() { return delegate.getTreeLevel(); }
// SUPPORT
/** Given (('?'|'*') (REWRITE_BLOCK (ALT ...))) return list of element refs at
* top level of REWRITE_BLOCK.
*/
public List<GrammarAST> getElementReferencesShallow(GrammarAST ebnfRoot) {
if ( ebnfRoot.getType()!=ANTLRParser.CLOSURE &&
ebnfRoot.getType()!=ANTLRParser.OPTIONAL )
{
return null;
}
GrammarAST blkAST = (GrammarAST)ebnfRoot.getChild(0);
if ( blkAST.getType()!=ANTLRParser.REWRITE_BLOCK ) return null;
GrammarAST altAST = (GrammarAST)blkAST.getChild(0);
if ( altAST.getType()!=ANTLRParser.ALT ) return null;
IntervalSet elementTokenTypes = getRewriteElementTokenTypeSet();
Alternative alt = getCurrentAlt();
List<GrammarAST> elems = new ArrayList<GrammarAST>();
for (Object o : altAST.getChildren()) {
GrammarAST ref = (GrammarAST)o;
if ( elementTokenTypes.member(ref.getType()) ) {
boolean imaginary = ref.getType()==ANTLRParser.TOKEN_REF &&
!alt.tokenRefs.containsKey(ref.getText());
if ( !imaginary ) elems.add(ref);
}
}
return elems;
}
/** Given (('?'|'*') (REWRITE_BLOCK (ALT ...))) return list of element refs at
* or below toplevel REWRITE_BLOCK.
*/
public List<GrammarAST> getElementReferencesDeep(GrammarAST ebnfRoot) {
if ( ebnfRoot.getType()!=ANTLRParser.CLOSURE &&
ebnfRoot.getType()!=ANTLRParser.OPTIONAL )
{
return null;
}
GrammarAST blkAST = (GrammarAST)ebnfRoot.getChild(0);
if ( blkAST.getType()!=ANTLRParser.REWRITE_BLOCK ) return null;
GrammarAST altAST = (GrammarAST)blkAST.getChild(0);
if ( altAST.getType()!=ANTLRParser.ALT ) return null;
List<GrammarAST> elems = new ArrayList<GrammarAST>();
Alternative alt = getCurrentAlt();
IntervalSet elementTokenTypes = getRewriteElementTokenTypeSet();
List<GrammarAST> refs = altAST.getNodesWithType(elementTokenTypes);
if ( refs!=null ) {
for (GrammarAST ref : refs) {
boolean imaginary = ref.getType()==ANTLRParser.TOKEN_REF &&
!alt.tokenRefs.containsKey(ref.getText());
if ( !imaginary ) elems.add(ref);
}
}
return elems;
}
public IntervalSet getRewriteElementTokenTypeSet() {
IntervalSet elementTokenTypes = new IntervalSet();
elementTokenTypes.add(ANTLRParser.TOKEN_REF); // might be imaginary
elementTokenTypes.add(ANTLRParser.RULE_REF);
elementTokenTypes.add(ANTLRParser.STRING_LITERAL);
elementTokenTypes.add(ANTLRParser.LABEL);
return elementTokenTypes;
}
}

View File

@ -98,9 +98,13 @@ public interface OutputModelFactory {
// Though dealing with ASTs, we must deal with here since these are
// triggered from elements in ANTLR's internal GrammarAST
TreeRewrite treeRewrite(GrammarAST ast, int rewriteLevel);
TreeRewrite treeRewrite(GrammarAST ast);
RewriteTreeStructure rewrite_tree(GrammarAST root, int rewriteLevel);
RewriteTreeOptional rewrite_optional(GrammarAST ast);
RewriteTreeClosure rewrite_closure(GrammarAST ast);
RewriteTreeStructure rewrite_tree(GrammarAST root);
List<SrcOp> rewrite_ruleRef(GrammarAST ID, boolean isRoot);
@ -110,6 +114,8 @@ public interface OutputModelFactory {
// CONTEXT MANIPULATION
// TODO: move to controller?
OutputModelObject getRoot();
void setRoot(OutputModelObject root);
@ -129,4 +135,8 @@ public interface OutputModelFactory {
void setCurrentBlock(CodeBlock blk);
CodeBlock getCurrentBlock();
int getCodeBlockLevel();
int getTreeLevel();
}

View File

@ -45,7 +45,7 @@ public class ParserASTExtension extends CodeGeneratorExtension {
@Override
public CodeBlockForAlt alternative(CodeBlockForAlt blk) {
Alternative alt = factory.getCurrentAlt();
if ( !alt.hasRewrite() ) blk.addLocalDecl( new RootDecl(factory, 0) );
if ( !alt.hasRewrite() ) blk.addLocalDecl( new RootDecl(factory) );
return blk;
}

View File

@ -169,29 +169,49 @@ public class ParserFactory extends DefaultOutputModelFactory {
}
public boolean needsImplicitLabel(GrammarAST ID, LabeledOp op) {
return op.getLabels().size()==0 &&
(getCurrentAlt().tokenRefsInActions.containsKey(ID.getText()) ||
getCurrentAlt().ruleRefsInActions.containsKey(ID.getText()));
return op.getLabels().size()==0 &&
(getCurrentAlt().tokenRefsInActions.containsKey(ID.getText()) ||
getCurrentAlt().ruleRefsInActions.containsKey(ID.getText()));
}
// AST REWRITE
@Override
public TreeRewrite treeRewrite(GrammarAST ast, int rewriteLevel) {
return new TreeRewrite(this, rewriteLevel);
public TreeRewrite treeRewrite(GrammarAST ast) {
return new TreeRewrite(this, getTreeLevel(), getCodeBlockLevel());
}
@Override
public RewriteTreeStructure rewrite_tree(GrammarAST root, int rewriteLevel) {
return new RewriteTreeStructure(this, root, rewriteLevel);
public RewriteTreeOptional rewrite_optional(GrammarAST ast) {
List<GrammarAST> refs = controller.getElementReferencesDeep(ast);
return new RewriteTreeOptional(this, ast);
}
@Override
public RewriteTreeClosure rewrite_closure(GrammarAST ast) {
RewriteTreeClosure c =
new RewriteTreeClosure(this, ast, getTreeLevel(), getCodeBlockLevel());
List<GrammarAST> refs = controller.getElementReferencesShallow(ast);
if ( refs!=null ) {
for (GrammarAST ref : refs) {
RewriteIteratorDecl d = new RewriteIteratorDecl(this, ref);
c.addLocalDecl(d);
c.iteratorDecls.add(d);
RewriteIteratorInit init = new RewriteIteratorInit(this, d);
c.addPreambleOp(init);
}
}
return c;
}
@Override
public RewriteTreeStructure rewrite_tree(GrammarAST root) {
return new RewriteTreeStructure(this, root, getTreeLevel(), getCodeBlockLevel());
}
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);
RewriteIteratorDecl d = new RewriteIteratorDecl(this, ID);
RewriteRuleRef ruleRef;
if ( isRoot ) ruleRef = new RewriteRuleRefIsRoot(this, ID, d);
else ruleRef = new RewriteRuleRef(this, ID, d);
@ -199,13 +219,12 @@ public class ParserFactory extends DefaultOutputModelFactory {
}
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);
String itName = gen.target.getRewriteIteratorName(ID, getCodeBlockLevel());
String rootName = gen.target.getRootName(getTreeLevel());
RewriteIteratorDecl d = (RewriteIteratorDecl)getCurrentDeclForName(itName);
RewriteTokenRef tokenRef;
if ( isRoot ) tokenRef = new RewriteTokenRefIsRoot(this, ID, d);
else tokenRef = new RewriteTokenRef(this, ID, d);
if ( isRoot ) tokenRef = new RewriteTokenRefIsRoot(this, ID, rootName, d);
else tokenRef = new RewriteTokenRef(this, ID, rootName, d);
return list(tokenRef);
}

View File

@ -18,7 +18,8 @@ import java.util.HashMap;
}
@members {
public int codeBlockLevel = 0;
public int codeBlockLevel = -1;
public int treeLevel = -1;
public OutputModelFactory factory;
public SourceGenTriggers(TreeNodeStream input, OutputModelFactory factory) {
this(input);
@ -194,7 +195,9 @@ elementOption
rewrite returns [Rewrite code]
: {
$code = factory.treeRewrite($start, codeBlockLevel++);
treeLevel = 0;
codeBlockLevel++;
$code = factory.treeRewrite($start);
CodeBlock save = factory.getCurrentBlock();
factory.setCurrentBlock($code);
}
@ -229,7 +232,7 @@ rewriteTreeAlt returns [List<SrcOp> omos]
rewriteTreeElement returns [List<SrcOp> omos]
: rewriteTreeAtom[false] {$omos = $rewriteTreeAtom.omos;}
| rewriteTree {$omos = $rewriteTree.omos;}
| rewriteTreeEbnf {$omos = $rewriteTreeEbnf.omos;}
| rewriteTreeEbnf {$omos = DefaultOutputModelFactory.list($rewriteTreeEbnf.op);}
;
rewriteTreeAtom[boolean isRoot] returns [List<SrcOp> omos]
@ -244,15 +247,32 @@ rewriteTreeAtom[boolean isRoot] returns [List<SrcOp> omos]
| ACTION
;
rewriteTreeEbnf returns [List<SrcOp> omos]
: ^('?' ^(REWRITE_BLOCK rewriteTreeAlt))
| ^('*' ^(REWRITE_BLOCK rewriteTreeAlt))
rewriteTreeEbnf returns [CodeBlock op]
: ^( (a=OPTIONAL|a=CLOSURE)
^( REWRITE_BLOCK
{
codeBlockLevel++;
if ( $a.getType()==OPTIONAL ) $op = factory.rewrite_optional($start);
else $op = factory.rewrite_closure($start);
CodeBlock save = factory.getCurrentBlock();
factory.setCurrentBlock($op);
}
alt=rewriteTreeAlt
)
)
{
$op.addOps($alt.omos);
factory.setCurrentBlock(save);
codeBlockLevel--;
}
;
rewriteTree returns [List<SrcOp> omos]
: {
codeBlockLevel++;
treeLevel++;
List<SrcOp> elems = new ArrayList<SrcOp>();
RewriteTreeStructure t = factory.rewrite_tree($start, codeBlockLevel++);
RewriteTreeStructure t = factory.rewrite_tree($start);
CodeBlock save = factory.getCurrentBlock();
factory.setCurrentBlock(t);
}
@ -264,6 +284,7 @@ rewriteTree returns [List<SrcOp> omos]
t.ops = elems;
$omos = DefaultOutputModelFactory.list(t);
factory.setCurrentBlock(save);
treeLevel--;
codeBlockLevel--;
}
;

View File

@ -33,7 +33,7 @@ import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.decl.CodeBlock;
public class Rewrite extends CodeBlock {
public Rewrite(OutputModelFactory factory) {
super(factory);
public Rewrite(OutputModelFactory factory, int treeLevel, int codeBlockLevel) {
super(factory, treeLevel, codeBlockLevel);
}
}

View File

@ -51,6 +51,7 @@ public class RuleFunction extends OutputModelObject {
public ATNState startState;
public int index;
public Collection<Attribute> args = null;
public Rule rule;
@ModelElement public List<SrcOp> code;
@ModelElement public OrderedHashSet<Decl> locals; // TODO: move into ctx?
@ -59,13 +60,10 @@ public class RuleFunction extends OutputModelObject {
@ModelElement public Action finallyAction;
@ModelElement public List<SrcOp> postamble;
public RuleFunction(OutputModelFactory factory) {
super(factory);
}
public RuleFunction(OutputModelFactory factory, Rule r) {
super(factory);
this.name = r.name;
this.rule = r;
if ( r.modifiers!=null && r.modifiers.size()>0 ) {
this.modifiers = new ArrayList<String>();
for (GrammarAST t : r.modifiers) modifiers.add(t.getText());

View File

@ -37,8 +37,12 @@ import org.antlr.v4.tool.GrammarAST;
public class RewriteTokenRef extends SrcOp {
/** Which iterator decl are we associated with? */
public RewriteIteratorDecl decl;
public RewriteTokenRef(OutputModelFactory factory, GrammarAST ast, RewriteIteratorDecl decl) {
public String rootName;
public RewriteTokenRef(OutputModelFactory factory, GrammarAST ast,
String rootName, RewriteIteratorDecl decl)
{
super(factory, ast);
this.rootName = rootName;
this.decl = decl;
}
}

View File

@ -34,7 +34,9 @@ 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);
public RewriteTokenRefIsRoot(OutputModelFactory factory, GrammarAST ast,
String rootName, RewriteIteratorDecl decl)
{
super(factory, ast, rootName, decl);
}
}

View File

@ -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.decl.*;
import org.antlr.v4.tool.GrammarAST;
import java.util.*;
public class RewriteTreeClosure extends CodeBlock {
public List<Decl> iteratorDecls = new ArrayList<Decl>();
public RewriteTreeClosure(OutputModelFactory factory, GrammarAST ast,
int treeLevel, int codeBlockLevel)
{
super(factory, treeLevel, codeBlockLevel);
this.ast = ast;
}
}

View File

@ -27,15 +27,19 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.codegen.model.decl;
package org.antlr.v4.codegen.model.ast;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.decl.*;
import org.antlr.v4.tool.GrammarAST;
public class NestedDecl extends Decl {
public int level;
import java.util.*;
public NestedDecl(OutputModelFactory factory, String name, int level) {
super(factory, name);
this.level = level;
public class RewriteTreeOptional extends CodeBlock {
public List<Decl> iteratorDecls = new ArrayList<Decl>();
public RewriteTreeOptional(OutputModelFactory factory, GrammarAST ast) {
super(factory);
this.ast = ast;
}
}

View File

@ -34,10 +34,14 @@ import org.antlr.v4.tool.GrammarAST;
/** ^(A B C) */
public class RewriteTreeStructure extends TreeRewrite {
public int treeLevel;
public RewriteTreeStructure(OutputModelFactory factory,
GrammarAST ast,
int level)
int treeLevel,
int codeBlockLevel)
{
super(factory, level);
super(factory, treeLevel, codeBlockLevel);
this.treeLevel = treeLevel;
}
}

View File

@ -34,13 +34,11 @@ import org.antlr.v4.codegen.model.Rewrite;
import org.antlr.v4.codegen.model.decl.RootDecl;
public class TreeRewrite extends Rewrite {
public int level;
public RootDecl rootDecl;
public TreeRewrite(OutputModelFactory factory, int level) {
super(factory);
this.level = level;
rootDecl = new RootDecl(factory, level); // track here too for easy access in template
public TreeRewrite(OutputModelFactory factory, int treeLevel, int codeBlockLevel) {
super(factory, treeLevel, codeBlockLevel);
rootDecl = new RootDecl(factory);
addLocalDecl(rootDecl);
}
}

View File

@ -36,6 +36,9 @@ import org.antlr.v4.runtime.misc.OrderedHashSet;
import java.util.*;
public class CodeBlock extends SrcOp {
public int codeBlockLevel;
public int treeLevel;
@ModelElement public OrderedHashSet<Decl> locals;
@ModelElement public List<SrcOp> preamble;
@ModelElement public List<SrcOp> ops;
@ -44,6 +47,12 @@ public class CodeBlock extends SrcOp {
super(factory);
}
public CodeBlock(OutputModelFactory factory, int treeLevel, int codeBlockLevel) {
super(factory);
this.treeLevel = treeLevel;
this.codeBlockLevel = codeBlockLevel;
}
/** Add local var decl */
public void addLocalDecl(Decl d) {
if ( locals==null ) locals = new OrderedHashSet<Decl>();
@ -60,4 +69,9 @@ public class CodeBlock extends SrcOp {
if ( ops==null ) ops = new ArrayList<SrcOp>();
ops.add(op);
}
public void addOps(List<SrcOp> ops) {
if ( this.ops==null ) this.ops = new ArrayList<SrcOp>();
this.ops.addAll(ops);
}
}

View File

@ -32,10 +32,13 @@ package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.tool.GrammarAST;
public class RewriteIteratorDecl extends NestedDecl {
public class RewriteIteratorDecl extends Decl {
public String listName;
public RewriteIteratorDecl(OutputModelFactory factory, GrammarAST elem, int level) {
super(factory, factory.getGenerator().target.getRewriteIteratorName(elem, level), level);
public RewriteIteratorDecl(OutputModelFactory factory,
GrammarAST elem)
{
super(factory, factory.getGenerator().target
.getRewriteIteratorName(elem, factory.getCodeBlockLevel()));
listName = factory.getGenerator().target.getElementListName(elem);
}
}

View File

@ -31,8 +31,9 @@ package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;
public class RootDecl extends NestedDecl {
public RootDecl(OutputModelFactory factory, int level) {
super(factory, factory.getGenerator().target.getRootName(level), level);
public class RootDecl extends Decl {
public RootDecl(OutputModelFactory factory) {
super(factory,
factory.getGenerator().target.getRootName(factory.getCodeBlockLevel()));
}
}

View File

@ -159,7 +159,6 @@ public class Rule implements AttributeResolver {
return refs;
}
// TODO: called frequently; make it more efficient
public MultiMap<String, LabelElementPair> getLabelDefs() {
MultiMap<String, LabelElementPair> defs =
new MultiMap<String, LabelElementPair>();