got 61/81 rewrite ast tests working

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 8846]
This commit is contained in:
parrt 2011-07-08 17:50:25 -08:00
parent 671a7f9038
commit 557e3a8389
40 changed files with 578 additions and 134 deletions

View File

@ -2,7 +2,9 @@ grammar T;
options {output=AST;} options {output=AST;}
tokens {I;} tokens {I;}
a : x=A -> $a ; a : x+=b x+=b -> {new CommonTree()} ;
atom : A ;
b : B | C ; b : B | C ;

View File

@ -27,6 +27,7 @@ import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA; import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.misc.*; import org.antlr.v4.runtime.misc.*;
import org.antlr.v4.runtime.tree.*;
import java.util.List; import java.util.List;
import java.util.Iterator; import java.util.Iterator;
import java.util.ArrayList; import java.util.ArrayList;
@ -328,13 +329,13 @@ SetDynScopeAttr_negIndex(s, indexChunks, rhsChunks) ::=
SetDynScopeAttr_index(s, indexChunks, rhsChunks) ::= SetDynScopeAttr_index(s, indexChunks, rhsChunks) ::=
"<s.scope>.get(<indexChunks>).<s.attr> =<rhsChunks>;" "<s.scope>.get(<indexChunks>).<s.attr> =<rhsChunks>;"
AddToLabelList(a) ::= "_localctx.<a.listName>.add(<labelref(first(a.opWithResultToAdd.labels))>);" AddToLabelList(a) ::= "_localctx.<a.listName>.add(<labelref(a.label)>);"
TokenDecl(t) ::= "Token <t.name>;" TokenDecl(t) ::= "Token <t.name>;"
TokenTypeDecl(t) ::= "int <t.name>;" TokenTypeDecl(t) ::= "int <t.name>;"
TokenListDecl(t) ::= "List\<Token> <t.name> = new ArrayList\<Token>();" TokenListDecl(t) ::= "List\<Token> <t.name> = new ArrayList\<Token>();"
RuleContextDecl(r) ::= "<r.ctxName> <r.name>;" RuleContextDecl(r) ::= "<r.ctxName> <r.name>;"
RuleContextListDecl(rdecl) ::= "List\<<rdecl.decl.ctxName>> <rdecl.name> = new ArrayList\<<rdecl.decl.ctxName>>();" RuleContextListDecl(rdecl) ::= "List\<<rdecl.ctxName>> <rdecl.name> = new ArrayList\<<rdecl.ctxName>>();"
/** Default RuleContext type name for a Parser rule */ /** Default RuleContext type name for a Parser rule */
ParserRuleContext() ::= "ParserRuleContext" ParserRuleContext() ::= "ParserRuleContext"
@ -378,6 +379,7 @@ _adaptor.setTokenBoundaries(_localctx.tree, _localctx.start, _localctx.stop);
ElementListDecl(d) ::= "List\<Object> <d.name> = _adaptor.createElementList();" ElementListDecl(d) ::= "List\<Object> <d.name> = _adaptor.createElementList();"
ElementListName(elemName) ::= "_track_<elemName>" ElementListName(elemName) ::= "_track_<elemName>"
ClearElementList(c) ::= "<c.name>.clear();"
TrackRuleElement(e) ::= "<e.name>.add(<labelref(e.label)>.tree);" TrackRuleElement(e) ::= "<e.name>.add(<labelref(e.label)>.tree);"
TrackTokenElement(e) ::= "<e.name>.add(_adaptor.create(<labelref(e.label)>));" TrackTokenElement(e) ::= "<e.name>.add(_adaptor.create(<labelref(e.label)>));"
@ -450,6 +452,22 @@ RewriteRuleRef(r) ::= "_adaptor.addChild(<r.rootName>, <r.iterName>.next());"
RewriteRuleRefIsRoot(r) ::= RewriteRuleRefIsRoot(r) ::=
"<r.rootName> = _adaptor.becomeRoot(<r.iterName>.next(), <r.rootName>);" "<r.rootName> = _adaptor.becomeRoot(<r.iterName>.next(), <r.rootName>);"
RewriteLabelRef(t) ::= "<RewriteAddChild(t.rootName, {<t.iterName>.next()})>"
RewriteLabelRefIsRoot(t) ::= "<RewriteBecomeRoot({<t.iterName>.next()}, t.rootName)>"
// -> $e in rule e
RewriteSelfRuleLabelRef(s) ::= "<RewriteAddChild(s.rootName, {_localctx.tree})>"
RewriteSelfRuleLabelRefIsRoot(s) ::= "<RewriteBecomeRoot({_localctx.tree}, s.rootName)>"
RewriteAction(a, chunks) ::= "<RewriteAddChild(a.rootName, chunks)>"
RewriteActionIsRoot(a, chunks) ::= "<RewriteBecomeRoot(chunks, a.rootName)>"
// how to add child, make root
RewriteAddChild(rootName, child) ::= "_adaptor.addChild(<rootName>, <child>);"
RewriteBecomeRoot(newRoot, rootName) ::=
"<rootName> = _adaptor.becomeRoot(<newRoot>, <rootName>);"
/* /*
BitSetDecl(b) ::= << BitSetDecl(b) ::= <<
public static final LABitSet <b.name>=new LABitSet(new long[]{<b.hexWords:{it|<it>L};separator=",">}<if(b.fset.EOF)>, true<endif>); public static final LABitSet <b.name>=new LABitSet(new long[]{<b.hexWords:{it|<it>L};separator=",">}<if(b.fset.EOF)>, true<endif>);

View File

@ -95,6 +95,10 @@ public abstract class BlankOutputModelFactory implements OutputModelFactory {
return rewrite_tokenRef(ID, isRoot, null); return rewrite_tokenRef(ID, isRoot, null);
} }
public List<SrcOp> rewrite_labelRef(GrammarAST ID, boolean isRoot) { return null; }
public List<SrcOp> rewrite_action(ActionAST action, boolean isRoot) { return null; }
// BLOCKS // BLOCKS
public Choice getChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts) { return null; } public Choice getChoiceBlock(BlockAST blkAST, List<CodeBlockForAlt> alts) { return null; }

View File

@ -103,6 +103,10 @@ public class CodeGeneratorExtension {
public List<SrcOp> rewrite_stringRef(List<SrcOp> ops) { return ops; } public List<SrcOp> rewrite_stringRef(List<SrcOp> ops) { return ops; }
public List<SrcOp> rewrite_labelRef(List<SrcOp> ops) { return ops; }
public List<SrcOp> rewrite_action(List<SrcOp> ops) { return ops; }
// BLOCKS // BLOCKS
public List<SrcOp> getChoiceBlock(List<SrcOp> ops) { return ops; } public List<SrcOp> getChoiceBlock(List<SrcOp> ops) { return ops; }

View File

@ -51,6 +51,7 @@ public abstract class DefaultOutputModelFactory extends BlankOutputModelFactory
public Stack<RuleFunction> currentRule = new Stack<RuleFunction>(); public Stack<RuleFunction> currentRule = new Stack<RuleFunction>();
public Alternative currentAlt; public Alternative currentAlt;
public CodeBlock currentBlock; public CodeBlock currentBlock;
public CodeBlock currentAlternativeBlock;
protected DefaultOutputModelFactory(CodeGenerator gen) { protected DefaultOutputModelFactory(CodeGenerator gen) {
this.gen = gen; this.gen = gen;
@ -93,6 +94,14 @@ public abstract class DefaultOutputModelFactory extends BlankOutputModelFactory
return currentBlock; return currentBlock;
} }
public void setCurrentAlternativeBlock(CodeBlock currentAlternativeBlock) {
this.currentAlternativeBlock = currentAlternativeBlock;
}
public CodeBlock getCurrentAlternativeBlock() {
return currentAlternativeBlock;
}
public int getCodeBlockLevel() { return controller.walker.codeBlockLevel; } public int getCodeBlockLevel() { return controller.walker.codeBlockLevel; }
public int getTreeLevel() { return controller.walker.treeLevel; } public int getTreeLevel() { return controller.walker.treeLevel; }

View File

@ -323,6 +323,18 @@ public class OutputModelController {
return rewrite_tokenRef(ID, isRoot, null); return rewrite_tokenRef(ID, isRoot, null);
} }
public List<SrcOp> rewrite_labelRef(GrammarAST ID, boolean isRoot) {
List<SrcOp> ops = delegate.rewrite_labelRef(ID, isRoot);
for (CodeGeneratorExtension ext : extensions) ops = ext.rewrite_labelRef(ops);
return ops;
}
public List<SrcOp> rewrite_action(ActionAST action, boolean isRoot) {
List<SrcOp> ops = delegate.rewrite_action(action, isRoot);
for (CodeGeneratorExtension ext : extensions) ops = ext.rewrite_action(ops);
return ops;
}
public OutputModelObject getRoot() { return delegate.getRoot(); } public OutputModelObject getRoot() { return delegate.getRoot(); }
public void setRoot(OutputModelObject root) { delegate.setRoot(root); } public void setRoot(OutputModelObject root) { delegate.setRoot(root); }
@ -343,6 +355,12 @@ public class OutputModelController {
public CodeBlock getCurrentBlock() { return delegate.getCurrentBlock(); } public CodeBlock getCurrentBlock() { return delegate.getCurrentBlock(); }
public void setCurrentAlternativeBlock(CodeBlock currentAlternativeBlock) {
delegate.setCurrentAlternativeBlock(currentAlternativeBlock);
}
public CodeBlock getCurrentAlternativeBlock() { return delegate.getCurrentAlternativeBlock(); }
public int getCodeBlockLevel() { return delegate.getCodeBlockLevel(); } public int getCodeBlockLevel() { return delegate.getCodeBlockLevel(); }
public int getTreeLevel() { return delegate.getTreeLevel(); } public int getTreeLevel() { return delegate.getTreeLevel(); }

View File

@ -112,6 +112,10 @@ public interface OutputModelFactory {
List<SrcOp> rewrite_stringRef(GrammarAST ID, boolean isRoot); List<SrcOp> rewrite_stringRef(GrammarAST ID, boolean isRoot);
List<SrcOp> rewrite_labelRef(GrammarAST ID, boolean isRoot);
List<SrcOp> rewrite_action(ActionAST action, boolean isRoot);
// CONTEXT MANIPULATION // CONTEXT MANIPULATION
// TODO: move to controller? // TODO: move to controller?
@ -136,6 +140,10 @@ public interface OutputModelFactory {
CodeBlock getCurrentBlock(); CodeBlock getCurrentBlock();
void setCurrentAlternativeBlock(CodeBlock currentAlternativeBlock);
CodeBlock getCurrentAlternativeBlock();
int getCodeBlockLevel(); int getCodeBlockLevel();
int getTreeLevel(); int getTreeLevel();

View File

@ -33,6 +33,7 @@ import org.antlr.v4.codegen.model.*;
import org.antlr.v4.codegen.model.ast.*; import org.antlr.v4.codegen.model.ast.*;
import org.antlr.v4.codegen.model.decl.*; import org.antlr.v4.codegen.model.decl.*;
import org.antlr.v4.misc.Utils; import org.antlr.v4.misc.Utils;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.tool.*; import org.antlr.v4.tool.*;
import java.util.List; import java.util.List;
@ -70,7 +71,7 @@ public class ParserASTExtension extends CodeGeneratorExtension {
} }
else { else {
InvokeRule invokeOp = (InvokeRule)Utils.find(ops, InvokeRule.class); InvokeRule invokeOp = (InvokeRule)Utils.find(ops, InvokeRule.class);
SrcOp treeOp = new RuleBecomeRoot(factory, invokeOp.ast, invokeOp); SrcOp treeOp = new RuleBecomeRoot(factory, invokeOp.ast, invokeOp.getLabels().get(0));
return DefaultOutputModelFactory.list(ops, treeOp); return DefaultOutputModelFactory.list(ops, treeOp);
} }
} }
@ -83,7 +84,7 @@ public class ParserASTExtension extends CodeGeneratorExtension {
} }
else { else {
MatchToken matchOp = (MatchToken)Utils.find(ops, MatchToken.class); MatchToken matchOp = (MatchToken)Utils.find(ops, MatchToken.class);
SrcOp treeOp = new TokenBecomeRoot(factory, matchOp.ast, matchOp); SrcOp treeOp = new TokenBecomeRoot(factory, matchOp.ast, matchOp.getLabels().get(0));
return DefaultOutputModelFactory.list(ops, treeOp); return DefaultOutputModelFactory.list(ops, treeOp);
} }
} }
@ -92,32 +93,79 @@ public class ParserASTExtension extends CodeGeneratorExtension {
public List<SrcOp> leafRule(List<SrcOp> ops) { public List<SrcOp> leafRule(List<SrcOp> ops) {
InvokeRule invokeOp = (InvokeRule)Utils.find(ops, InvokeRule.class); InvokeRule invokeOp = (InvokeRule)Utils.find(ops, InvokeRule.class);
Alternative alt = factory.getCurrentAlt(); Alternative alt = factory.getCurrentAlt();
RuleContextDecl label = (RuleContextDecl)invokeOp.getLabels().get(0);
if ( alt.hasRewrite() ) { if ( alt.hasRewrite() ) {
RuleFunction rf = factory.getCurrentRuleFunction(); CodeBlock blk = factory.getCurrentAlternativeBlock();
rf.addLocalDecl(new ElementListDecl(factory, invokeOp.ast)); String elemListName = factory.getGenerator().target.getElementListName(invokeOp.ast.getText());
TrackRuleElement t = new TrackRuleElement(factory, invokeOp.ast, invokeOp); blk.addLocalDecl(new ElementListDecl(factory, elemListName));
return DefaultOutputModelFactory.list(ops, t); // track any explicit label like _track_label but not implicit label
if ( !label.isImplicit ) {
String labelListName =
factory.getGenerator().target.getElementListName(label.name);
blk.addLocalDecl(new ElementListDecl(factory, labelListName));
}
String trackName = factory.getGenerator().target.getElementListName(invokeOp.ast.getText());
TrackRuleElement t = new TrackRuleElement(factory, invokeOp.ast, trackName, label);
ops.add(t);
if ( !label.isImplicit ) {
trackName = factory.getGenerator().target.getElementListName(label.name);
TrackRuleElement t2 = new TrackRuleElement(factory, invokeOp.ast, trackName,
label);
if ( invokeOp.ast.parent.getType() == ANTLRParser.ASSIGN ) {
// if x=A must keep it a single-element list; clear before add
ClearElementList c = new ClearElementList(factory, invokeOp.ast, trackName);
ops.add(c);
}
ops.add(t2);
}
} }
else { else {
SrcOp treeOp = new AddRuleLeaf(factory, invokeOp.ast, invokeOp); SrcOp treeOp = new AddRuleLeaf(factory, invokeOp.ast, label);
return DefaultOutputModelFactory.list(ops, treeOp); ops.add(treeOp);
} }
return ops;
} }
@Override @Override
public List<SrcOp> leafToken(List<SrcOp> ops) { public List<SrcOp> leafToken(List<SrcOp> ops) {
MatchToken matchOp = (MatchToken)Utils.find(ops, MatchToken.class); MatchToken matchOp = (MatchToken)Utils.find(ops, MatchToken.class);
TokenDecl label = (TokenDecl)matchOp.getLabels().get(0);
Alternative alt = factory.getCurrentAlt(); Alternative alt = factory.getCurrentAlt();
if ( alt.hasRewrite() ) { if ( alt.hasRewrite() ) {
RuleFunction rf = factory.getCurrentRuleFunction(); CodeBlock blk = factory.getCurrentAlternativeBlock();
rf.addLocalDecl(new ElementListDecl(factory, matchOp.ast)); // First declare tracking lists for elements, labels
TrackTokenElement t = new TrackTokenElement(factory, matchOp.ast, matchOp); // track the named element like _track_A
return DefaultOutputModelFactory.list(ops, t); String elemListName = factory.getGenerator().target.getElementListName(matchOp.ast.getText());
blk.addLocalDecl(new ElementListDecl(factory, elemListName));
// track any explicit label like _track_label but not implicit label
if ( !label.isImplicit ) {
String labelListName =
factory.getGenerator().target.getElementListName(label.name);
blk.addLocalDecl(new ElementListDecl(factory, labelListName));
}
// Now, generate track instructions for element and any labels
// do element
String trackName = factory.getGenerator().target.getElementListName(matchOp.ast.getText());
TrackTokenElement t = new TrackTokenElement(factory, matchOp.ast, trackName,
label);
ops.add(t);
if ( !label.isImplicit ) { // track all explicit labels
trackName = factory.getGenerator().target.getElementListName(label.name);
TrackTokenElement t2 = new TrackTokenElement(factory, matchOp.ast, trackName,
label);
if ( matchOp.ast.parent.getType() == ANTLRParser.ASSIGN ) {
// if x=A must keep it a single-element list; clear before add
ClearElementList c = new ClearElementList(factory, matchOp.ast, trackName);
ops.add(c);
}
ops.add(t2);
}
} }
else { else {
SrcOp treeOp = new AddTokenLeaf(factory, matchOp.ast, matchOp); SrcOp treeOp = new AddTokenLeaf(factory, matchOp.ast, label);
return DefaultOutputModelFactory.list(ops, treeOp); ops.add(treeOp);
} }
return ops;
} }
@Override @Override

View File

@ -78,14 +78,14 @@ public class ParserFactory extends DefaultOutputModelFactory {
// If no manual label and action refs as token/rule not label or // If no manual label and action refs as token/rule not label or
// we're adding to trees, we need to define implicit label // we're adding to trees, we need to define implicit label
if ( controller.needsImplicitLabel(ID, invokeOp) ) defineImplicitLabel(ID, invokeOp); if ( controller.needsImplicitLabel(ID, invokeOp) ) defineImplicitLabel(ID, invokeOp);
AddToLabelList listLabelOp = getListLabel(invokeOp, label); AddToLabelList listLabelOp = getListLabelIfPresent(invokeOp, label);
return list(invokeOp, listLabelOp); return list(invokeOp, listLabelOp);
} }
public List<SrcOp> tokenRef(GrammarAST ID, GrammarAST label, GrammarAST args) { public List<SrcOp> tokenRef(GrammarAST ID, GrammarAST label, GrammarAST args) {
LabeledOp matchOp = new MatchToken(this, (TerminalAST) ID, label); LabeledOp matchOp = new MatchToken(this, (TerminalAST) ID, label);
if ( controller.needsImplicitLabel(ID, matchOp) ) defineImplicitLabel(ID, matchOp); if ( controller.needsImplicitLabel(ID, matchOp) ) defineImplicitLabel(ID, matchOp);
AddToLabelList listLabelOp = getListLabel(matchOp, label); AddToLabelList listLabelOp = getListLabelIfPresent(matchOp, label);
return list(matchOp, listLabelOp); return list(matchOp, listLabelOp);
} }
@ -277,6 +277,33 @@ public class ParserFactory extends DefaultOutputModelFactory {
return list(tokenRef); return list(tokenRef);
} }
@Override
public List<SrcOp> rewrite_labelRef(GrammarAST ID, boolean isRoot) {
String rootName = gen.target.getRootName(getTreeLevel());
String iterName = gen.target.getRewriteIteratorName(ID, getCodeBlockLevel());
if ( ID.getText().equals(getCurrentRuleFunction().rule.name) ) { // $e in rule e
RewriteSelfRuleLabelRef labelRef;
if ( isRoot ) labelRef = new RewriteSelfRuleLabelRef(this, ID, rootName);
else labelRef = new RewriteSelfRuleLabelRef(this, ID, rootName);
return list(labelRef);
}
else { // normal element label
RewriteLabelRef labelRef;
if ( isRoot ) labelRef = new RewriteLabelRefIsRoot(this, ID, rootName, iterName);
else labelRef = new RewriteLabelRef(this, ID, rootName, iterName);
return list(labelRef);
}
}
@Override
public List<SrcOp> rewrite_action(ActionAST actionAST, boolean isRoot) {
String rootName = gen.target.getRootName(getTreeLevel());
RewriteAction action;
if ( isRoot ) action = new RewriteActionIsRoot(this, actionAST, rootName);
else action = new RewriteAction(this, actionAST, rootName);
return list(action);
}
// support // support
public void defineImplicitLabel(GrammarAST ID, LabeledOp op) { public void defineImplicitLabel(GrammarAST ID, LabeledOp op) {
@ -286,20 +313,22 @@ public class ParserFactory extends DefaultOutputModelFactory {
String implLabel = gen.target.getImplicitRuleLabel(ID.getText()); String implLabel = gen.target.getImplicitRuleLabel(ID.getText());
String ctxName = gen.target.getRuleFunctionContextStructName(r); String ctxName = gen.target.getRuleFunctionContextStructName(r);
d = new RuleContextDecl(this, implLabel, ctxName); d = new RuleContextDecl(this, implLabel, ctxName);
((RuleContextDecl)d).isImplicit = true;
} }
else { else {
String implLabel = gen.target.getImplicitTokenLabel(ID.getText()); String implLabel = gen.target.getImplicitTokenLabel(ID.getText());
d = new TokenDecl(this, implLabel); d = new TokenDecl(this, implLabel);
((TokenDecl)d).isImplicit = true;
} }
op.getLabels().add(d); op.getLabels().add(d);
getCurrentRuleFunction().addLocalDecl(d); getCurrentRuleFunction().addLocalDecl(d);
} }
public AddToLabelList getListLabel(LabeledOp op, GrammarAST label) { public AddToLabelList getListLabelIfPresent(LabeledOp op, GrammarAST label) {
AddToLabelList labelOp = null; AddToLabelList labelOp = null;
if ( label!=null && label.parent.getType()==ANTLRParser.PLUS_ASSIGN ) { if ( label!=null && label.parent.getType()==ANTLRParser.PLUS_ASSIGN ) {
String listLabel = gen.target.getListLabel(label.getText()); String listLabel = gen.target.getListLabel(label.getText());
labelOp = new AddToLabelList(this, listLabel, op); labelOp = new AddToLabelList(this, listLabel, op.getLabels().get(0));
} }
return labelOp; return labelOp;
} }

View File

@ -83,7 +83,9 @@ alternative_with_rewrite returns [CodeBlockForAlt altCodeBlock]
alternative returns [CodeBlockForAlt altCodeBlock, List<SrcOp> ops] alternative returns [CodeBlockForAlt altCodeBlock, List<SrcOp> ops]
@init { @init {
// set alt if outer ALT only // set alt if outer ALT only
if ( inContext("RULE BLOCK") && ((AltAST)$start).alt!=null ) controller.setCurrentAlt(((AltAST)$start).alt); if ( inContext("RULE BLOCK") && ((AltAST)$start).alt!=null ) {
controller.setCurrentAlt(((AltAST)$start).alt);
}
} }
: ^(ALT_REWRITE : ^(ALT_REWRITE
a=alternative a=alternative
@ -100,6 +102,9 @@ alternative returns [CodeBlockForAlt altCodeBlock, List<SrcOp> ops]
$altCodeBlock = controller.alternative(controller.getCurrentAlt()); $altCodeBlock = controller.alternative(controller.getCurrentAlt());
$ops = elems; $ops = elems;
controller.setCurrentBlock($altCodeBlock); controller.setCurrentBlock($altCodeBlock);
if ( inContext("RULE BLOCK") || inContext("RULE BLOCK ALT_REWRITE") ) { // outer block
controller.setCurrentAlternativeBlock($altCodeBlock);
}
} }
^( ALT ( element {if ($element.omos!=null) elems.addAll($element.omos);} )+ ) ^( ALT ( element {if ($element.omos!=null) elems.addAll($element.omos);} )+ )
; ;
@ -243,8 +248,8 @@ rewriteTreeAtom[boolean isRoot] returns [List<SrcOp> omos]
| RULE_REF {$omos = controller.rewrite_ruleRef($RULE_REF, $isRoot);} | RULE_REF {$omos = controller.rewrite_ruleRef($RULE_REF, $isRoot);}
| ^(STRING_LITERAL elementOptions) {$omos = controller.rewrite_stringRef($STRING_LITERAL, $isRoot);} | ^(STRING_LITERAL elementOptions) {$omos = controller.rewrite_stringRef($STRING_LITERAL, $isRoot);}
| STRING_LITERAL {$omos = controller.rewrite_stringRef($STRING_LITERAL, $isRoot);} | STRING_LITERAL {$omos = controller.rewrite_stringRef($STRING_LITERAL, $isRoot);}
| LABEL | LABEL {$omos = controller.rewrite_labelRef($LABEL, $isRoot);}
| ACTION | ACTION {$omos = controller.rewrite_action((ActionAST)$ACTION, $isRoot);}
; ;
rewriteTreeEbnf returns [CodeBlock op] rewriteTreeEbnf returns [CodeBlock op]

View File

@ -30,7 +30,7 @@
package org.antlr.v4.codegen; package org.antlr.v4.codegen;
import org.antlr.v4.parse.ANTLRParser; import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.runtime.Lexer; import org.antlr.v4.runtime.*;
import org.antlr.v4.tool.*; import org.antlr.v4.tool.*;
import org.stringtemplate.v4.ST; import org.stringtemplate.v4.ST;
@ -230,23 +230,21 @@ public class Target {
public String getRewriteIteratorName(GrammarAST elem, int level) { public String getRewriteIteratorName(GrammarAST elem, int level) {
ST st = gen.templates.getInstanceOf("RewriteIteratorName"); ST st = gen.templates.getInstanceOf("RewriteIteratorName");
st.add("elemName", getElementName(elem)); st.add("elemName", getElementName(elem.getText()));
st.add("level", level); st.add("level", level);
return st.render(); return st.render();
} }
public String getElementListName(GrammarAST elem) { public String getElementListName(String name) {
ST st = gen.templates.getInstanceOf("ElementListName"); ST st = gen.templates.getInstanceOf("ElementListName");
st.add("elemName", getElementName(elem)); st.add("elemName", getElementName(name));
return st.render(); return st.render();
} }
public String getElementName(GrammarAST elem) { public String getElementName(String name) {
String text = elem.getText(); if ( gen.g.getRule(name)!=null ) return name;
if ( gen.g.getRule(text)==null ) { int ttype = gen.g.getTokenType(name);
int ttype = gen.g.getTokenType(text); if ( ttype==Token.INVALID_TYPE ) return name;
text = getTokenTypeAsTargetLabel(gen.g, ttype); return getTokenTypeAsTargetLabel(gen.g, ttype);
}
return text;
} }
} }

View File

@ -30,15 +30,15 @@
package org.antlr.v4.codegen.model; package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.ast.ElementASTOp;
import org.antlr.v4.codegen.model.decl.Decl;
/** */ /** */
public class AddToLabelList extends SrcOp { public class AddToLabelList extends ElementASTOp {
public String listName; public String listName;
public LabeledOp opWithResultToAdd;
public AddToLabelList(OutputModelFactory factory, String listName, LabeledOp opWithResultToAdd) { public AddToLabelList(OutputModelFactory factory, String listName, Decl label) {
super(factory); super(factory, null, label);
this.listName = listName; this.listName = listName;
this.opWithResultToAdd = opWithResultToAdd;
} }
} }

View File

@ -33,14 +33,15 @@ import org.antlr.v4.codegen.*;
import org.antlr.v4.codegen.model.decl.*; import org.antlr.v4.codegen.model.decl.*;
import org.antlr.v4.parse.ANTLRParser; import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.runtime.atn.RuleTransition; import org.antlr.v4.runtime.atn.RuleTransition;
import org.antlr.v4.runtime.misc.OrderedHashSet;
import org.antlr.v4.tool.*; import org.antlr.v4.tool.*;
import java.util.*; import java.util.List;
/** */ /** */
public class InvokeRule extends RuleElement implements LabeledOp { public class InvokeRule extends RuleElement implements LabeledOp {
public String name; public String name;
public List<Decl> labels = new ArrayList<Decl>(); public OrderedHashSet<Decl> labels = new OrderedHashSet<Decl>(); // TODO: should need just 1
public String argExprs; public String argExprs;
public String ctxName; public String ctxName;
@ -64,7 +65,7 @@ public class InvokeRule extends RuleElement implements LabeledOp {
factory.getCurrentRuleFunction().addContextDecl(d); factory.getCurrentRuleFunction().addContextDecl(d);
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) { if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
String listLabel = gen.target.getListLabel(label); String listLabel = gen.target.getListLabel(label);
RuleContextListDecl l = new RuleContextListDecl(factory, listLabel, d); RuleContextListDecl l = new RuleContextListDecl(factory, listLabel, ctxName);
factory.getCurrentRuleFunction().addContextDecl(l); factory.getCurrentRuleFunction().addContextDecl(l);
} }
} }
@ -89,6 +90,6 @@ public class InvokeRule extends RuleElement implements LabeledOp {
} }
public List<Decl> getLabels() { public List<Decl> getLabels() {
return labels; return labels.elements();
} }
} }

View File

@ -47,7 +47,7 @@ public class MatchToken extends RuleElement implements LabeledOp {
CodeGenerator gen = factory.getGenerator(); CodeGenerator gen = factory.getGenerator();
int ttype = g.getTokenType(ast.getText()); int ttype = g.getTokenType(ast.getText());
name = gen.target.getTokenTypeAsTargetLabel(g, ttype); name = gen.target.getTokenTypeAsTargetLabel(g, ttype);
if ( labelAST!=null ) { if ( labelAST!=null ) { // TODO: move to factory
String label = labelAST.getText(); String label = labelAST.getText();
TokenDecl d = new TokenDecl(factory, label); TokenDecl d = new TokenDecl(factory, label);
labels.add(d); labels.add(d);

View File

@ -30,11 +30,11 @@
package org.antlr.v4.codegen.model.ast; package org.antlr.v4.codegen.model.ast;
import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.LabeledOp; import org.antlr.v4.codegen.model.decl.Decl;
import org.antlr.v4.tool.GrammarAST; import org.antlr.v4.tool.GrammarAST;
public class AddRuleLeaf extends ElementASTOp { public class AddRuleLeaf extends ElementASTOp {
public AddRuleLeaf(OutputModelFactory factory, GrammarAST ast, LabeledOp opWithResultToAdd) { public AddRuleLeaf(OutputModelFactory factory, GrammarAST ast, Decl label) {
super(factory, ast, opWithResultToAdd); super(factory, ast, label);
} }
} }

View File

@ -30,12 +30,12 @@
package org.antlr.v4.codegen.model.ast; package org.antlr.v4.codegen.model.ast;
import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.LabeledOp; import org.antlr.v4.codegen.model.decl.Decl;
import org.antlr.v4.tool.GrammarAST; import org.antlr.v4.tool.GrammarAST;
/** */ /** */
public class AddTokenLeaf extends ElementASTOp { public class AddTokenLeaf extends ElementASTOp {
public AddTokenLeaf(OutputModelFactory factory, GrammarAST ast, LabeledOp opWithResultToAdd) { public AddTokenLeaf(OutputModelFactory factory, GrammarAST ast, Decl label) {
super(factory, ast, opWithResultToAdd); super(factory, ast, label);
} }
} }

View File

@ -0,0 +1,43 @@
/*
[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.SrcOp;
import org.antlr.v4.tool.GrammarAST;
public class ClearElementList extends SrcOp {
public String name;
public ClearElementList(OutputModelFactory factory, GrammarAST ast, String name) {
super(factory, ast);
this.name = name;
}
}

View File

@ -30,17 +30,15 @@
package org.antlr.v4.codegen.model.ast; package org.antlr.v4.codegen.model.ast;
import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.*; import org.antlr.v4.codegen.model.SrcOp;
import org.antlr.v4.codegen.model.decl.Decl; import org.antlr.v4.codegen.model.decl.Decl;
import org.antlr.v4.tool.GrammarAST; import org.antlr.v4.tool.GrammarAST;
public class ElementASTOp extends SrcOp { public class ElementASTOp extends SrcOp {
public LabeledOp opWithResultToAdd;
public Decl label; public Decl label;
public ElementASTOp(OutputModelFactory factory, GrammarAST ast, LabeledOp opWithResultToAdd) { public ElementASTOp(OutputModelFactory factory, GrammarAST ast, Decl label) {
super(factory, ast); super(factory, ast);
this.opWithResultToAdd = opWithResultToAdd; this.label = label;
label = opWithResultToAdd.getLabels().get(0);
} }
} }

View File

@ -0,0 +1,53 @@
/*
[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.*;
import org.antlr.v4.codegen.model.*;
import org.antlr.v4.codegen.model.actions.ActionChunk;
import org.antlr.v4.tool.ActionAST;
import java.util.List;
public class RewriteAction extends SrcOp {
public String rootName;
@ModelElement public List<ActionChunk> chunks;
public RewriteAction(OutputModelFactory factory, ActionAST ast, String rootName) {
super(factory, ast);
this.rootName = rootName;
if ( ast!=null ) {
chunks = ActionTranslator.translateAction(factory,
factory.getCurrentRuleFunction(),
ast.token, ast);
}
}
}

View File

@ -0,0 +1,39 @@
/*
[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.tool.ActionAST;
public class RewriteActionIsRoot extends RewriteAction {
public RewriteActionIsRoot(OutputModelFactory factory, ActionAST ast, String rootName) {
super(factory, ast, rootName);
}
}

View File

@ -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.SrcOp;
import org.antlr.v4.tool.GrammarAST;
public class RewriteLabelRef extends SrcOp {
public String rootName;
public String iterName;
public RewriteLabelRef(OutputModelFactory factory, GrammarAST ast,
String rootName, String iterName) {
super(factory, ast);
this.rootName = rootName;
this.iterName = iterName;
}
}

View File

@ -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.tool.GrammarAST;
public class RewriteLabelRefIsRoot extends RewriteLabelRef {
public RewriteLabelRefIsRoot(OutputModelFactory factory, GrammarAST ast,
String rootName, String iterName) {
super(factory, ast, rootName, iterName);
}
}

View File

@ -0,0 +1,43 @@
/*
[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.SrcOp;
import org.antlr.v4.tool.GrammarAST;
public class RewriteSelfRuleLabelRef extends SrcOp {
public String rootName;
public RewriteSelfRuleLabelRef(OutputModelFactory factory, GrammarAST ast, String rootName) {
super(factory, ast);
this.rootName = rootName;
}
}

View File

@ -0,0 +1,39 @@
/*
[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.tool.GrammarAST;
public class RewriteSelfRuleLabelRefIsRoot extends RewriteSelfRuleLabelRef {
public RewriteSelfRuleLabelRefIsRoot(OutputModelFactory factory, GrammarAST ast, String rootName) {
super(factory, ast, rootName);
}
}

View File

@ -30,11 +30,11 @@
package org.antlr.v4.codegen.model.ast; package org.antlr.v4.codegen.model.ast;
import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.LabeledOp; import org.antlr.v4.codegen.model.decl.Decl;
import org.antlr.v4.tool.GrammarAST; import org.antlr.v4.tool.GrammarAST;
public class RuleBecomeRoot extends ElementASTOp { public class RuleBecomeRoot extends ElementASTOp {
public RuleBecomeRoot(OutputModelFactory factory, GrammarAST ast, LabeledOp opWithResultToAdd) { public RuleBecomeRoot(OutputModelFactory factory, GrammarAST ast, Decl label) {
super(factory, ast, opWithResultToAdd); super(factory, ast, label);
} }
} }

View File

@ -30,12 +30,12 @@
package org.antlr.v4.codegen.model.ast; package org.antlr.v4.codegen.model.ast;
import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.LabeledOp; import org.antlr.v4.codegen.model.decl.Decl;
import org.antlr.v4.tool.GrammarAST; import org.antlr.v4.tool.GrammarAST;
/** */ /** */
public class TokenBecomeRoot extends ElementASTOp { public class TokenBecomeRoot extends ElementASTOp {
public TokenBecomeRoot(OutputModelFactory factory, GrammarAST ast, LabeledOp opWithResultToAdd) { public TokenBecomeRoot(OutputModelFactory factory, GrammarAST ast, Decl label) {
super(factory, ast, opWithResultToAdd); super(factory, ast, label);
} }
} }

View File

@ -30,13 +30,13 @@
package org.antlr.v4.codegen.model.ast; package org.antlr.v4.codegen.model.ast;
import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.LabeledOp; import org.antlr.v4.codegen.model.decl.Decl;
import org.antlr.v4.tool.GrammarAST; import org.antlr.v4.tool.GrammarAST;
public class TrackRuleElement extends ElementASTOp { public class TrackRuleElement extends ElementASTOp {
public String name; public String name;
public TrackRuleElement(OutputModelFactory factory, GrammarAST ast, LabeledOp opWithResultToAdd) { public TrackRuleElement(OutputModelFactory factory, GrammarAST ast, String trackName, Decl label) {
super(factory, ast, opWithResultToAdd); super(factory, ast, label);
name = factory.getGenerator().target.getElementListName(ast); name = trackName;
} }
} }

View File

@ -30,13 +30,13 @@
package org.antlr.v4.codegen.model.ast; package org.antlr.v4.codegen.model.ast;
import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.LabeledOp; import org.antlr.v4.codegen.model.decl.Decl;
import org.antlr.v4.tool.GrammarAST; import org.antlr.v4.tool.GrammarAST;
public class TrackTokenElement extends ElementASTOp { public class TrackTokenElement extends ElementASTOp {
public String name; public String name;
public TrackTokenElement(OutputModelFactory factory, GrammarAST ast, LabeledOp opWithResultToAdd) { public TrackTokenElement(OutputModelFactory factory, GrammarAST ast, String trackName, Decl label) {
super(factory, ast, opWithResultToAdd); super(factory, ast, label);
name = factory.getGenerator().target.getElementListName(ast); name = trackName;
} }
} }

View File

@ -30,10 +30,9 @@
package org.antlr.v4.codegen.model.decl; package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.tool.GrammarAST;
public class ElementListDecl extends Decl { public class ElementListDecl extends Decl {
public ElementListDecl(OutputModelFactory factory, GrammarAST elem) { public ElementListDecl(OutputModelFactory factory, String name) {
super(factory, factory.getGenerator().target.getElementListName(elem)); super(factory, name);
} }
} }

View File

@ -40,6 +40,6 @@ public class RewriteIteratorDecl extends Decl {
{ {
super(factory, factory.getGenerator().target super(factory, factory.getGenerator().target
.getRewriteIteratorName(elem, codeBlockLevel)); .getRewriteIteratorName(elem, codeBlockLevel));
listName = factory.getGenerator().target.getElementListName(elem); listName = factory.getGenerator().target.getElementListName(elem.getText());
} }
} }

View File

@ -34,6 +34,8 @@ import org.antlr.v4.codegen.OutputModelFactory;
/** */ /** */
public class RuleContextDecl extends Decl { public class RuleContextDecl extends Decl {
public String ctxName; public String ctxName;
public boolean isImplicit;
public RuleContextDecl(OutputModelFactory factory, String name, String ctxName) { public RuleContextDecl(OutputModelFactory factory, String name, String ctxName) {
super(factory, name); super(factory, name);
this.ctxName = ctxName; this.ctxName = ctxName;

View File

@ -31,10 +31,9 @@ package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.codegen.OutputModelFactory;
public class RuleContextListDecl extends Decl { public class RuleContextListDecl extends RuleContextDecl {
public RuleContextDecl decl; public RuleContextListDecl(OutputModelFactory factory, String name, String ctxName) {
public RuleContextListDecl(OutputModelFactory factory, String name, RuleContextDecl decl) { super(factory, name, ctxName);
super(factory, name); isImplicit = false;
this.decl = decl;
} }
} }

View File

@ -31,13 +31,14 @@ package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.ModelElement; import org.antlr.v4.codegen.model.ModelElement;
import org.antlr.v4.runtime.misc.OrderedHashSet;
import org.antlr.v4.tool.Attribute; import org.antlr.v4.tool.Attribute;
import java.util.*; import java.util.Collection;
/** */ /** */
public class StructDecl extends Decl { public class StructDecl extends Decl {
@ModelElement public List<Decl> attrs = new ArrayList<Decl>(); @ModelElement public OrderedHashSet<Decl> attrs = new OrderedHashSet<Decl>();
@ModelElement public Collection<Attribute> ctorAttrs; @ModelElement public Collection<Attribute> ctorAttrs;
public StructDecl(OutputModelFactory factory) { public StructDecl(OutputModelFactory factory) {

View File

@ -33,6 +33,8 @@ import org.antlr.v4.codegen.OutputModelFactory;
/** */ /** */
public class TokenDecl extends Decl { public class TokenDecl extends Decl {
public boolean isImplicit;
public TokenDecl(OutputModelFactory factory, String varName) { public TokenDecl(OutputModelFactory factory, String varName) {
super(factory, varName); super(factory, varName);
} }

View File

@ -32,7 +32,7 @@ package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.codegen.OutputModelFactory;
/** */ /** */
public class TokenListDecl extends Decl { public class TokenListDecl extends TokenDecl {
public TokenListDecl(OutputModelFactory factory, String varName) { public TokenListDecl(OutputModelFactory factory, String varName) {
super(factory, varName); super(factory, varName);
} }

View File

@ -700,12 +700,9 @@ blockSuffixe
; ;
ebnfSuffix ebnfSuffix
@init { : QUESTION -> OPTIONAL[$start]
Token op = input.LT(1); | STAR -> CLOSURE[$start]
} | PLUS -> POSITIVE_CLOSURE[$start]
: QUESTION -> OPTIONAL[op]
| STAR -> CLOSURE[op]
| PLUS -> POSITIVE_CLOSURE[op]
; ;
atom: // Qualified reference delegate.rule. This must be atom: // Qualified reference delegate.rule. This must be
@ -839,15 +836,15 @@ nakedRewrite
// rule altAndRewrite makes REWRITE root. for ST, we use ST_REWRITE // rule altAndRewrite makes REWRITE root. for ST, we use ST_REWRITE
rewriteAlt returns [boolean isTemplate] rewriteAlt returns [boolean isTemplate]
options {backtrack=true;} options {backtrack=true;}
: // try to parse a template rewrite : // If we are not building templates, then we must be
rewriteTemplate {$isTemplate=true;}
| // If we are not building templates, then we must be
// building ASTs or have rewrites in a grammar that does not // building ASTs or have rewrites in a grammar that does not
// have output=AST; options. If that is the case, we will issue // have output=AST; options. If that is the case, we will issue
// errors/warnings in the next phase, so we just eat them here // errors/warnings in the next phase, so we just eat them here
rewriteTreeAlt rewriteTreeAlt
| // try to parse a template rewrite
rewriteTemplate {$isTemplate=true;} // must be 2nd so "ACTION ..." matches as tree rewrite
| ETC | ETC
| /* empty rewrite */ -> EPSILON | /* empty rewrite */ -> EPSILON
@ -888,8 +885,8 @@ rewriteTreeEbnf
; ;
rewriteEbnfSuffix rewriteEbnfSuffix
: OPTIONAL : QUESTION -> OPTIONAL[$start]
| CLOSURE | STAR -> CLOSURE[$start]
; ;
rewriteTree rewriteTree

View File

@ -232,6 +232,7 @@ ruleArg
currentRule.args = ScopeParser.parseTypeList($ARG_ACTION.text); currentRule.args = ScopeParser.parseTypeList($ARG_ACTION.text);
currentRule.args.type = AttributeDict.DictType.ARG; currentRule.args.type = AttributeDict.DictType.ARG;
currentRule.args.ast = $ARG_ACTION; currentRule.args.ast = $ARG_ACTION;
((ActionAST)$ARG_ACTION).resolver = currentRule.alt[currentAlt];
} }
; ;
@ -260,8 +261,16 @@ ruleScopeSpec
rewriteElement rewriteElement
//@init {System.out.println("rewriteElement: "+((Tree)input.LT(1)).getText());} //@init {System.out.println("rewriteElement: "+((Tree)input.LT(1)).getText());}
: :
{inContext("RESULT ...")}? (TOKEN_REF|RULE_REF|STRING_LITERAL|LABEL) {inContext("RESULT ...")}? t=(TOKEN_REF|RULE_REF|STRING_LITERAL|LABEL)
{currentRule.alt[currentAlt].rewriteElements.add($start);} {
currentRule.alt[currentAlt].rewriteElements.add($start);
if ( $t.getType()==TOKEN_REF && t.getChildCount()>0 ) {
GrammarAST arg = (GrammarAST)t.getChild(0);
if ( arg.getType()==ARG_ACTION ) {
((ActionAST)arg).resolver = currentRule.alt[currentAlt];
}
}
}
; ;
labeledElement labeledElement
@ -285,12 +294,13 @@ terminal
currentRule.alt[currentAlt].tokenRefs.map($STRING_LITERAL.text, (TerminalAST)$STRING_LITERAL); currentRule.alt[currentAlt].tokenRefs.map($STRING_LITERAL.text, (TerminalAST)$STRING_LITERAL);
} }
} }
| TOKEN_REF | (tref=TOKEN_REF | ^(tref=TOKEN_REF ARG_ACTION .?))
{ {
terminals.add($TOKEN_REF); terminals.add($tref);
tokenIDRefs.add($TOKEN_REF); tokenIDRefs.add($tref);
if ( currentRule!=null ) { if ( currentRule!=null ) {
currentRule.alt[currentAlt].tokenRefs.map($TOKEN_REF.text, (TerminalAST)$TOKEN_REF); currentRule.alt[currentAlt].tokenRefs.map($tref.text, (TerminalAST)$tref);
if ( $ARG_ACTION!=null ) ((ActionAST)$ARG_ACTION).resolver = currentRule.alt[currentAlt];
} }
} }
; ;

View File

@ -90,15 +90,22 @@ public class UseDefAnalyzer {
return UseDefAnalyzer.getRewriteElementRefs(g, ebnfRoot, 1, deep); return UseDefAnalyzer.getRewriteElementRefs(g, ebnfRoot, 1, deep);
} }
/** Get list of rule refs, token refs mentioned on left, and labels not
* referring to rule result like $e in rule e.
*/
public static List<GrammarAST> filterForRuleAndTokenRefs(Alternative alt, public static List<GrammarAST> filterForRuleAndTokenRefs(Alternative alt,
List<GrammarAST> refs) List<GrammarAST> refs)
{ {
List<GrammarAST> elems = new ArrayList<GrammarAST>(); List<GrammarAST> elems = new ArrayList<GrammarAST>();
if ( refs!=null ) { if ( refs!=null ) {
for (GrammarAST ref : refs) { for (GrammarAST ref : refs) {
boolean imaginary = ref.getType()== ANTLRParser.TOKEN_REF && boolean imaginary =
!alt.tokenRefs.containsKey(ref.getText()); ref.getType()== ANTLRParser.TOKEN_REF &&
if ( !imaginary ) elems.add(ref); !alt.tokenRefs.containsKey(ref.getText());
boolean selfLabel =
ref.getType()==ANTLRParser.LABEL &&
ref.getText().equals(alt.rule.name);
if ( !imaginary && !selfLabel ) elems.add(ref);
} }
} }
return elems; return elems;

View File

@ -39,7 +39,7 @@ import java.util.*;
* or rule of a grammar. * or rule of a grammar.
*/ */
public class Alternative implements AttributeResolver { public class Alternative implements AttributeResolver {
Rule rule; public Rule rule;
public AltAST ast; public AltAST ast;
@ -72,7 +72,7 @@ public class Alternative implements AttributeResolver {
/** (ALT_REWRITE (ALT ...) (-> (ALT ...))) */ /** (ALT_REWRITE (ALT ...) (-> (ALT ...))) */
public boolean hasRewrite() { public boolean hasRewrite() {
return ast!=null && ast.getType()==ANTLRParser.ALT_REWRITE; return ast.getNodesWithType(ANTLRParser.ALT_REWRITE).size()>0;
} }
public boolean resolvesToToken(String x, ActionAST node) { public boolean resolvesToToken(String x, ActionAST node) {

View File

@ -29,7 +29,7 @@
package org.antlr.v4.test; package org.antlr.v4.test;
import org.junit.*; import org.junit.Test;
public class TestRewriteAST extends BaseTest { public class TestRewriteAST extends BaseTest {
protected boolean debug = false; protected boolean debug = false;
@ -288,20 +288,6 @@ public class TestRewriteAST extends BaseTest {
assertEquals("a\n", found); assertEquals("a\n", found);
} }
@Test public void testPositiveClosureSingleRule() throws Exception {
String grammar =
"grammar T;\n" +
"options {output=AST;}\n" +
"a : b b -> b+;\n" +
"b : ID ;\n" +
"ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+;\n" +
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
String found = execParser("T.g", grammar, "TParser", "TLexer",
"a", "a b", debug);
assertEquals("a b\n", found);
}
@Test public void testSinglePredicateT() throws Exception { @Test public void testSinglePredicateT() throws Exception {
String grammar = String grammar =
"grammar T;\n" + "grammar T;\n" +
@ -501,7 +487,7 @@ public class TestRewriteAST extends BaseTest {
"options {output=AST;}\n" + "options {output=AST;}\n" +
"tokens {BLOCK;}\n" + "tokens {BLOCK;}\n" +
"a : b b ;\n" + "a : b b ;\n" +
"b : (ID INT -> INT ID | INT INT -> INT+ )\n" + "b : (ID INT -> INT ID | INT INT -> INT* )\n" +
" ;\n" + " ;\n" +
"ID : 'a'..'z'+ ;\n" + "ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+;\n" + "INT : '0'..'9'+;\n" +
@ -544,15 +530,15 @@ public class TestRewriteAST extends BaseTest {
"INT : '0'..'9'+;\n" + "INT : '0'..'9'+;\n" +
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
String found = execParser("T.g", grammar, "TParser", "TLexer", String found = execParser("T.g", grammar, "TParser", "TLexer",
"a", "a b c d; 42", debug); "a", "a b c; 42", debug);
assertEquals("d 42\n", found); assertEquals("c 42\n", found);
} }
@Test public void testRewriteActions() throws Exception { @Test public void testRewriteActions() throws Exception {
String grammar = String grammar =
"grammar T;\n" + "grammar T;\n" +
"options {output=AST;}\n" + "options {output=AST;}\n" +
"a : atom -> ^({adaptor.create(INT,\"9\")} atom) ;\n" + "a : atom -> ^({_adaptor.create(INT,\"9\")} atom) ;\n" +
"atom : INT ;\n" + "atom : INT ;\n" +
"ID : 'a'..'z'+ ;\n" + "ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+;\n" + "INT : '0'..'9'+;\n" +
@ -566,7 +552,7 @@ public class TestRewriteAST extends BaseTest {
String grammar = String grammar =
"grammar T;\n" + "grammar T;\n" +
"options {output=AST;}\n" + "options {output=AST;}\n" +
"a : atom -> {adaptor.create(INT,\"9\")} atom ;\n" + "a : atom -> {_adaptor.create(INT,\"9\")} atom ;\n" +
"atom : INT ;\n" + "atom : INT ;\n" +
"ID : 'a'..'z'+ ;\n" + "ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+;\n" + "INT : '0'..'9'+;\n" +
@ -786,7 +772,7 @@ public class TestRewriteAST extends BaseTest {
"grammar T;\n" + "grammar T;\n" +
"options {output=AST;}\n" + "options {output=AST;}\n" +
"tokens {VAR;}\n"+ "tokens {VAR;}\n"+
"a : first=ID others+=ID* -> $first VAR $others+ ;\n" + "a : first=ID others+=ID* -> $first VAR $others* ;\n" +
"op : '+'|'-' ;\n" + "op : '+'|'-' ;\n" +
"ID : 'a'..'z'+ ;\n" + "ID : 'a'..'z'+ ;\n" +
"INT : '0'..'9'+;\n" + "INT : '0'..'9'+;\n" +
@ -801,7 +787,7 @@ public class TestRewriteAST extends BaseTest {
"grammar T;\n" + "grammar T;\n" +
"options {output=AST;}\n" + "options {output=AST;}\n" +
"tokens {BLOCK;}\n" + "tokens {BLOCK;}\n" +
"a : A A b=B B b=B c+=C C c+=C D {String s=$D.text;} -> A+ B+ C+ D ;\n" + "a : A A b=B B b=B c+=C C c+=C D {String s=$D.text;} -> A* B* C* D ;\n" +
"type : 'int' | 'float' ;\n" + "type : 'int' | 'float' ;\n" +
"A : 'a' ;\n" + "A : 'a' ;\n" +
"B : 'b' ;\n" + "B : 'b' ;\n" +
@ -868,7 +854,7 @@ public class TestRewriteAST extends BaseTest {
"grammar T;\n" + "grammar T;\n" +
"options {output=AST;}\n" + "options {output=AST;}\n" +
"tokens {BLOCK;}\n" + "tokens {BLOCK;}\n" +
"a : x+=b x+=b -> $x+;\n"+ "a : x+=b x+=b -> $x*;\n"+
"b : ID ;\n"+ "b : ID ;\n"+
"ID : 'a'..'z'+ ;\n" + "ID : 'a'..'z'+ ;\n" +
"WS : (' '|'\\n') {$channel=HIDDEN;} ;\n"; "WS : (' '|'\\n') {$channel=HIDDEN;} ;\n";
@ -1001,11 +987,7 @@ public class TestRewriteAST extends BaseTest {
assertEquals("2\n", found); assertEquals("2\n", found);
} }
@Ignore @Test public void testSetWithLabel() throws Exception {
// TODO: FAILS. The should probably generate a warning from antlr
// See http://www.antlr.org:8888/browse/ANTLR-162
//
public void testSetWithLabel() throws Exception {
String grammar = String grammar =
"grammar T;\n" + "grammar T;\n" +
@ -1041,7 +1023,7 @@ public class TestRewriteAST extends BaseTest {
"tokens {PARMS;} \n" + "tokens {PARMS;} \n" +
"\n" + "\n" +
"modulo \n" + "modulo \n" +
" : 'modulo' ID ('(' parms+ ')')? -> ^('modulo' ID ^(PARMS parms+)?) \n" + " : 'modulo' ID ('(' parms+ ')')? -> ^('modulo' ID ^(PARMS parms*)?) \n" +
" ; \n" + " ; \n" +
"parms : '#'|ID; \n" + "parms : '#'|ID; \n" +
"ID : ('a'..'z' | 'A'..'Z')+;\n" + "ID : ('a'..'z' | 'A'..'Z')+;\n" +