got it generating getters, labels correctly. now to impl getters

This commit is contained in:
Terence Parr 2012-02-14 13:58:48 -08:00
parent 6c2beb530d
commit a6786743d4
14 changed files with 266 additions and 79 deletions

View File

@ -485,15 +485,20 @@ NonLocalAttrRef(s) ::= "((<s.ruleName>Context)getInvokingContext(<s.ruleIndex>
SetNonLocalAttr(s, rhsChunks) ::= SetNonLocalAttr(s, rhsChunks) ::=
"((<s.ruleName>Context)getInvokingContext(<s.ruleIndex>)).<s.name> = <rhsChunks>;" "((<s.ruleName>Context)getInvokingContext(<s.ruleIndex>)).<s.name> = <rhsChunks>;"
AddToLabelList(a) ::= "_localctx.<a.listName>.add(<labelref(a.label)>);" AddToLabelList(a) ::= "<ctx(a.label)>.<a.listName>.add(<labelref(a.label)>);"
TokenDecl(t) ::= "Token <t.name>" TokenDecl(t) ::= "public Token <t.name>;"
TokenTypeDecl(t) ::= "int <t.name>;" TokenTypeDecl(t) ::= "int <t.name>;"
TokenListDecl(t) ::= "List\<Token> <t.name> = new ArrayList\<Token>()" TokenListDecl(t) ::= "public List\<Token> <t.name> = new ArrayList\<Token>();"
RuleContextDecl(r) ::= "<r.ctxName> <r.name>" RuleContextDecl(r) ::= "public <r.ctxName> <r.name>;"
RuleContextListDecl(rdecl) ::= "List\<<rdecl.ctxName>> <rdecl.name> = new ArrayList\<<rdecl.ctxName>>()" RuleContextListDecl(rdecl) ::= "public List\<<rdecl.ctxName>> <rdecl.name> = new ArrayList\<<rdecl.ctxName>>();"
ContextGetterDecl(g) ::= "public <g.decl> get<t.name>() { }" ContextTokenGetterDecl(t) ::= "public Token <t.name>() { return null; }"
ContextTokenListGetterDecl(t) ::= "public List\<Token> <t.name>() { return null; }"
ContextTokenListIndexedGetterDecl(t) ::= "public Token <t.name>(int i) { return null; }"
ContextRuleGetterDecl(r) ::= "public <r.ctxName> <r.name>() { return null; }"
ContextRuleListGetterDecl(r) ::= "public List\<<r.ctxName>> <r.name>() { return null; }"
ContextRuleListIndexedGetterDecl(r) ::= "public <r.ctxName> <r.name>(int i) { return null; }"
LexerRuleContext() ::= "RuleContext" LexerRuleContext() ::= "RuleContext"
@ -502,18 +507,19 @@ LexerRuleContext() ::= "RuleContext"
*/ */
RuleContextNameSuffix() ::= "Context" RuleContextNameSuffix() ::= "Context"
ImplicitTokenLabel(tokenName) ::= "_<tokenName>" ImplicitTokenLabel(tokenName) ::= "<tokenName>"
ImplicitRuleLabel(ruleName) ::= "_<ruleName>" ImplicitRuleLabel(ruleName) ::= "<ruleName>"
ImplicitSetLabel(id) ::= "_tset<id>" ImplicitSetLabel(id) ::= "_tset<id>"
ListLabelName(label) ::= "<label>" ListLabelName(label) ::= "<label>"
CaptureNextToken(d) ::= "<d.varName> = _input.LT(1);" CaptureNextToken(d) ::= "<d.varName> = _input.LT(1);"
CaptureNextTokenType(d) ::= "<d.varName> = _input.LA(1);" CaptureNextTokenType(d) ::= "<d.varName> = _input.LA(1);"
StructDecl(s,attrs,visitorDispatchMethods,interfaces,extensionMembers, StructDecl(s,attrs,getters,visitorDispatchMethods,interfaces,extensionMembers,
superClass={ParserRuleContext\<<InputSymbolType()>>}) ::= << superClass={ParserRuleContext\<<InputSymbolType()>>}) ::= <<
public static class <s.name> extends <superClass><if(interfaces)> implements <interfaces; separator=", "><endif> { public static class <s.name> extends <superClass><if(interfaces)> implements <interfaces; separator=", "><endif> {
<attrs:{a | public <a>;}; separator="\n"> <attrs:{a | <a>}; separator="\n">
<getters:{g | <g>}; separator="\n">
<if(s.ctorAttrs)>public <s.name>(ParserRuleContext\<<InputSymbolType()>\> parent, int state) { super(parent, state); }<endif> <if(s.ctorAttrs)>public <s.name>(ParserRuleContext\<<InputSymbolType()>\> parent, int state) { super(parent, state); }<endif>
public <s.name>(ParserRuleContext\<<InputSymbolType()>\> parent, int state<s.ctorAttrs:{a | , <a>}>) { public <s.name>(ParserRuleContext\<<InputSymbolType()>\> parent, int state<s.ctorAttrs:{a | , <a>}>) {
super(parent, state); super(parent, state);
@ -531,9 +537,10 @@ public static class <s.name> extends <superClass><if(interfaces)> implements <in
} }
>> >>
AltLabelStructDecl(s,attrs,visitorDispatchMethods) ::= << AltLabelStructDecl(s,attrs,getters,visitorDispatchMethods) ::= <<
public static class <s.name> extends <currentRule.name>Context { public static class <s.name> extends <currentRule.name>Context {
<attrs:{a | public <a.decl> get<a.name>() {\}}; separator="\n"> <attrs:{a | <a>}; separator="\n">
<getters:{g | <g>}; separator="\n">
public <s.name>(<currentRule.name>Context ctx) { copyFrom(ctx); } public <s.name>(<currentRule.name>Context ctx) { copyFrom(ctx); }
<visitorDispatchMethods; separator="\n"> <visitorDispatchMethods; separator="\n">
} }
@ -546,7 +553,7 @@ public void <if(method.isEnter)>enter<else>exit<endif>Rule(ParseTreeListener\<<I
} }
>> >>
AttributeDecl(d) ::= "<d.decl>" AttributeDecl(d) ::= "public <d.decl>;"
/** If we don't know location of label def x, use this template */ /** If we don't know location of label def x, use this template */
labelref(x) ::= "<if(!x.isLocal)>((<x.ctx.name>)_localctx).<endif><x.name>" labelref(x) ::= "<if(!x.isLocal)>((<x.ctx.name>)_localctx).<endif><x.name>"

View File

@ -203,13 +203,13 @@ public class LeftRecursiveRuleTransformer {
LeftRecursiveRuleAltInfo altInfo = r.recPrimaryAlts.get(i); LeftRecursiveRuleAltInfo altInfo = r.recPrimaryAlts.get(i);
altInfo.altAST = (AltAST)primaryBlk.getChild(i); altInfo.altAST = (AltAST)primaryBlk.getChild(i);
altInfo.altAST.leftRecursiveAltInfo = altInfo; altInfo.altAST.leftRecursiveAltInfo = altInfo;
System.out.println(altInfo.altAST.toStringTree()); // System.out.println(altInfo.altAST.toStringTree());
} }
for (int i = 0; i < r.recOpAlts.size(); i++) { for (int i = 0; i < r.recOpAlts.size(); i++) {
LeftRecursiveRuleAltInfo altInfo = r.recOpAlts.getElement(i); LeftRecursiveRuleAltInfo altInfo = r.recOpAlts.getElement(i);
altInfo.altAST = (AltAST)opsBlk.getChild(i); altInfo.altAST = (AltAST)opsBlk.getChild(i);
altInfo.altAST.leftRecursiveAltInfo = altInfo; altInfo.altAST.leftRecursiveAltInfo = altInfo;
System.out.println(altInfo.altAST.toStringTree()); // System.out.println(altInfo.altAST.toStringTree());
} }
} }

View File

@ -31,12 +31,21 @@ package org.antlr.v4.codegen;
import org.antlr.v4.analysis.AnalysisPipeline; import org.antlr.v4.analysis.AnalysisPipeline;
import org.antlr.v4.codegen.model.*; import org.antlr.v4.codegen.model.*;
import org.antlr.v4.codegen.model.decl.*; import org.antlr.v4.codegen.model.decl.Decl;
import org.antlr.v4.codegen.model.decl.RuleContextDecl;
import org.antlr.v4.codegen.model.decl.TokenDecl;
import org.antlr.v4.codegen.model.decl.TokenListDecl;
import org.antlr.v4.parse.ANTLRParser; import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.runtime.atn.*; import org.antlr.v4.runtime.atn.DecisionState;
import org.antlr.v4.runtime.atn.PlusBlockStartState;
import org.antlr.v4.runtime.atn.StarLoopEntryState;
import org.antlr.v4.runtime.misc.IntervalSet; import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.tool.*; import org.antlr.v4.tool.Alternative;
import org.antlr.v4.tool.ast.*; import org.antlr.v4.tool.LeftRecursiveRule;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.BlockAST;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.tool.ast.TerminalAST;
import java.util.List; import java.util.List;
@ -83,7 +92,7 @@ public class ParserFactory extends DefaultOutputModelFactory {
InvokeRule invokeOp = new InvokeRule(this, ID, label); InvokeRule invokeOp = new InvokeRule(this, ID, label);
// If no manual label and action refs as token/rule not label, we need to define implicit label // If no manual label and action refs as token/rule not label, we need to define implicit label
if ( controller.needsImplicitLabel(ID, invokeOp) ) defineImplicitLabel(ID, invokeOp); if ( controller.needsImplicitLabel(ID, invokeOp) ) defineImplicitLabel(ID, invokeOp);
AddToLabelList listLabelOp = getListLabelIfPresent(invokeOp, label); AddToLabelList listLabelOp = getAddToListOpIfListLabelPresent(invokeOp, label);
return list(invokeOp, listLabelOp); return list(invokeOp, listLabelOp);
} }
@ -91,22 +100,29 @@ public class ParserFactory extends DefaultOutputModelFactory {
LabeledOp matchOp = new MatchToken(this, (TerminalAST) ID); LabeledOp matchOp = new MatchToken(this, (TerminalAST) ID);
if ( labelAST!=null ) { if ( labelAST!=null ) {
String label = labelAST.getText(); String label = labelAST.getText();
RuleFunction rf = getCurrentRuleFunction();
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) { if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
// add Token _X and List<Token> X decls
defineImplicitLabel(ID, matchOp); // adds _X
TokenListDecl l = getTokenListLabelDecl(label); TokenListDecl l = getTokenListLabelDecl(label);
getCurrentRuleFunction().addContextDecl(ID.getAltLabel(), l); rf.addContextDecl(ID.getAltLabel(), l);
}
else {
Decl d = getTokenLabelDecl(label);
((MatchToken) matchOp).labels.add(d);
rf.addContextDecl(ID.getAltLabel(), d);
} }
// String label = labelAST.getText(); // Decl d = getTokenLabelDecl(label);
Decl d = getTokenLabelDecl(label); // ((MatchToken)matchOp).labels.add(d);
((MatchToken)matchOp).labels.add(d); // getCurrentRuleFunction().addContextDecl(ID.getAltLabel(), d);
getCurrentRuleFunction().addContextDecl(ID.getAltLabel(), d); // if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) { // TokenListDecl l = getTokenListLabelDecl(label);
TokenListDecl l = getTokenListLabelDecl(label); // getCurrentRuleFunction().addContextDecl(ID.getAltLabel(), l);
getCurrentRuleFunction().addContextDecl(ID.getAltLabel(), l); // }
}
} }
if ( controller.needsImplicitLabel(ID, matchOp) ) defineImplicitLabel(ID, matchOp); if ( controller.needsImplicitLabel(ID, matchOp) ) defineImplicitLabel(ID, matchOp);
AddToLabelList listLabelOp = getListLabelIfPresent(matchOp, labelAST); AddToLabelList listLabelOp = getAddToListOpIfListLabelPresent(matchOp, labelAST);
return list(matchOp, listLabelOp); return list(matchOp, listLabelOp);
} }
@ -134,7 +150,7 @@ public class ParserFactory extends DefaultOutputModelFactory {
} }
} }
if ( controller.needsImplicitLabel(setAST, matchOp) ) defineImplicitLabel(setAST, matchOp); if ( controller.needsImplicitLabel(setAST, matchOp) ) defineImplicitLabel(setAST, matchOp);
AddToLabelList listLabelOp = getListLabelIfPresent(matchOp, labelAST); AddToLabelList listLabelOp = getAddToListOpIfListLabelPresent(matchOp, labelAST);
return list(matchOp, listLabelOp); return list(matchOp, listLabelOp);
} }
@ -153,7 +169,7 @@ public class ParserFactory extends DefaultOutputModelFactory {
} }
} }
if ( controller.needsImplicitLabel(ast, wild) ) defineImplicitLabel(ast, wild); if ( controller.needsImplicitLabel(ast, wild) ) defineImplicitLabel(ast, wild);
AddToLabelList listLabelOp = getListLabelIfPresent(wild, labelAST); AddToLabelList listLabelOp = getAddToListOpIfListLabelPresent(wild, labelAST);
return list(wild, listLabelOp); return list(wild, listLabelOp);
} }
@ -289,7 +305,7 @@ public class ParserFactory extends DefaultOutputModelFactory {
getCurrentRuleFunction().addContextDecl(ast.getAltLabel(), d); getCurrentRuleFunction().addContextDecl(ast.getAltLabel(), d);
} }
public AddToLabelList getListLabelIfPresent(LabeledOp op, GrammarAST label) { public AddToLabelList getAddToListOpIfListLabelPresent(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());

View File

@ -88,11 +88,9 @@ public class RuleFunction extends OutputModelObject {
if ( !factory.getGrammar().tool.no_auto_element_labels ) { if ( !factory.getGrammar().tool.no_auto_element_labels ) {
List<Alternative> altsNoLabels = r.getUnlabeledAlts(); List<Alternative> altsNoLabels = r.getUnlabeledAlts();
if ( altsNoLabels!=null ) { if ( altsNoLabels!=null ) {
for (Alternative alt : altsNoLabels) { Set<Decl> decls = getDeclsForAllElements(altsNoLabels);
List<Decl> decls = getLabelsForAltElements(alt.ast);
// we know to put in rule ctx, so do it directly // we know to put in rule ctx, so do it directly
for (Decl d : decls) ruleCtx.addDecl(d); for (Decl d : decls) ruleCtx.addDecl(d);
}
} }
} }
@ -107,7 +105,7 @@ public class RuleFunction extends OutputModelObject {
altToContext[altNum] = new AltLabelStructDecl(factory, r, altNum, label); altToContext[altNum] = new AltLabelStructDecl(factory, r, altNum, label);
altLabelCtxs.put(label, altToContext[altNum]); altLabelCtxs.put(label, altToContext[altNum]);
if ( !factory.getGrammar().tool.no_auto_element_labels ) { if ( !factory.getGrammar().tool.no_auto_element_labels ) {
List<Decl> decls = getLabelsForAltElements(altAST); Set<Decl> decls = getDeclsForAltElements(altAST);
// we know which ctx to put in, so do it directly // we know which ctx to put in, so do it directly
for (Decl d : decls) altToContext[altNum].addDecl(d); for (Decl d : decls) altToContext[altNum].addDecl(d);
} }
@ -142,45 +140,86 @@ public class RuleFunction extends OutputModelObject {
} }
} }
/** for all alts, find which ref X or r in way which needs List
Must see across alts. If any alt needs X or r as list, then
define as list.
*/
public Set<Decl> getDeclsForAllElements(List<Alternative> alts) {
Set<String> needsList = new HashSet<String>();
List<GrammarAST> allRefs = new ArrayList<GrammarAST>();
for (Alternative a :alts) {
IntervalSet reftypes = new IntervalSet(RULE_REF, TOKEN_REF);
List<GrammarAST> refs = a.ast.getNodesWithType(reftypes);
FrequencySet<String> altFreq = new FrequencySet<String>();
for (GrammarAST t : refs) {
String refLabelName = t.getText();
altFreq.add(refLabelName);
allRefs.add(t);
}
for (GrammarAST t : refs) {
String refLabelName = t.getText();
if ( altFreq.count(t.getText())>1 ) needsList.add(refLabelName);
}
}
Set<Decl> decls = new HashSet<Decl>();
for (GrammarAST t : allRefs) {
String refLabelName = t.getText();
List<Decl> d = getDeclForAltElement(t,
refLabelName,
needsList.contains(refLabelName));
decls.addAll(d);
}
return decls;
}
/** Get list of decls for token/rule refs. /** Get list of decls for token/rule refs.
* Single ref X becomes label X * Single ref X becomes X() getter
* Multiple refs to X become X1, X2, ... * Multiple refs to X becomes List X() method, X(int i) method.
* Ref X in a loop then is part of List * Ref X in a loop then we get List X(), X(int i)
* *
* Does not gen labels for literals like '+', 'begin', ';', ... * Does not gen labels for literals like '+', 'begin', ';', ...
*/ */
public List<Decl> getLabelsForAltElements(AltAST altAST) { public Set<Decl> getDeclsForAltElements(AltAST altAST) {
List<Decl> decls = new ArrayList<Decl>();
IntervalSet reftypes = new IntervalSet(RULE_REF, IntervalSet reftypes = new IntervalSet(RULE_REF,
TOKEN_REF); TOKEN_REF);
List<GrammarAST> refs = altAST.getNodesWithType(reftypes); List<GrammarAST> refs = altAST.getNodesWithType(reftypes);
Set<Decl> decls = new HashSet<Decl>();
FrequencySet<String> freq = new FrequencySet<String>(); FrequencySet<String> freq = new FrequencySet<String>();
for (GrammarAST t : refs) freq.add(t.getText());
for (GrammarAST t : refs) { for (GrammarAST t : refs) {
freq.add(t.getText());
}
// track which ref for X we are at so we can gen X1 if necessary
FrequencySet<String> counter = new FrequencySet<String>();
for (GrammarAST t : refs) {
boolean inLoop = t.hasAncestor(CLOSURE) || t.hasAncestor(POSITIVE_CLOSURE);
// System.out.println(altAST.toStringTree()+" "+t+" inLoop? "+inLoop);
Decl d;
String refLabelName = t.getText(); String refLabelName = t.getText();
if ( !inLoop && freq.count(refLabelName)>1 ) { boolean inLoop = t.hasAncestor(CLOSURE) || t.hasAncestor(POSITIVE_CLOSURE);
counter.add(refLabelName); boolean multipleRefs = freq.count(refLabelName)>1;
refLabelName = refLabelName+counter.count(refLabelName); boolean needList = inLoop || multipleRefs;
} // System.out.println(altAST.toStringTree()+" "+t+" inLoop? "+inLoop);
if ( t.getType()==RULE_REF ) { List<Decl> d = getDeclForAltElement(t, refLabelName, needList);
Rule rref = factory.getGrammar().getRule(t.getText()); decls.addAll(d);
String ctxName = factory.getGenerator().target }
.getRuleFunctionContextStructName(rref); return decls;
if ( inLoop ) d = new RuleContextListDecl(factory, refLabelName, ctxName); }
else d = new RuleContextDecl(factory, refLabelName, ctxName);
public List<Decl> getDeclForAltElement(GrammarAST t, String refLabelName, boolean needList) {
List<Decl> decls = new ArrayList<Decl>();
if ( t.getType()==RULE_REF ) {
Rule rref = factory.getGrammar().getRule(t.getText());
String ctxName = factory.getGenerator().target
.getRuleFunctionContextStructName(rref);
if ( needList ) {
decls.add( new ContextRuleListGetterDecl(factory, refLabelName, ctxName) );
decls.add( new ContextRuleListIndexedGetterDecl(factory, refLabelName, ctxName) );
} }
else { else {
if ( inLoop ) d = new TokenListDecl(factory, refLabelName); decls.add( new ContextRuleGetterDecl(factory, refLabelName, ctxName) );
else d = new TokenDecl(factory, refLabelName); }
}
else {
if ( needList ) {
decls.add( new ContextTokenListGetterDecl(factory, refLabelName) );
decls.add( new ContextTokenListIndexedGetterDecl(factory, refLabelName) );
}
else {
decls.add( new ContextTokenGetterDecl(factory, refLabelName) );
} }
decls.add(d);
} }
return decls; return decls;
} }

View File

@ -2,9 +2,34 @@ package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.codegen.OutputModelFactory;
/** public Token getID() { } */ public abstract class ContextGetterDecl extends Decl {
public class ContextGetterDecl extends Decl { public ContextGetterDecl(OutputModelFactory factory, String name) {
public ContextGetterDecl(OutputModelFactory factory, String name, String decl) { super(factory, name);
super(factory, name, decl); }
/** Not used for output; just used to distinguish between decl types
* to avoid dups.
*/
public String getArgType() { return ""; }; // assume no args
@Override
public int hashCode() {
return name.hashCode() + getArgType().hashCode();
}
/** Make sure that a getter does not equal a label. X() and X are ok.
* OTOH, treat X() with two diff return values as the same. Treat
* two X() with diff args as different.
*/
@Override
public boolean equals(Object obj) {
if ( obj==null ) return false;
// A() and label A are different
if ( !(obj instanceof ContextGetterDecl) ) return false;
if ( this==obj ) return true;
if ( this.hashCode() != obj.hashCode() ) return false;
return
name.equals(((Decl) obj).name) &&
getArgType().equals(((ContextGetterDecl) obj).getArgType());
} }
} }

View File

@ -0,0 +1,12 @@
package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;
/** public XContext X() { } */
public class ContextRuleGetterDecl extends ContextGetterDecl {
public String ctxName;
public ContextRuleGetterDecl(OutputModelFactory factory, String name, String ctxName) {
super(factory, name);
this.ctxName = ctxName;
}
}

View File

@ -0,0 +1,14 @@
package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;
/** public List<XContext> X() { }
* public XContext X(int i) { }
*/
public class ContextRuleListGetterDecl extends ContextGetterDecl {
public String ctxName;
public ContextRuleListGetterDecl(OutputModelFactory factory, String name, String ctxName) {
super(factory, name);
this.ctxName = ctxName;
}
}

View File

@ -0,0 +1,14 @@
package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;
public class ContextRuleListIndexedGetterDecl extends ContextRuleListGetterDecl {
public ContextRuleListIndexedGetterDecl(OutputModelFactory factory, String name, String ctxName) {
super(factory, name, ctxName);
}
@Override
public String getArgType() {
return "int";
}
}

View File

@ -0,0 +1,10 @@
package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;
/** public Token X() { } */
public class ContextTokenGetterDecl extends ContextGetterDecl {
public ContextTokenGetterDecl(OutputModelFactory factory, String name) {
super(factory, name);
}
}

View File

@ -0,0 +1,12 @@
package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;
/** public List<Token> X() { }
* public Token X(int i) { }
*/
public class ContextTokenListGetterDecl extends ContextGetterDecl {
public ContextTokenListGetterDecl(OutputModelFactory factory, String name) {
super(factory, name);
}
}

View File

@ -0,0 +1,14 @@
package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;
public class ContextTokenListIndexedGetterDecl extends ContextTokenListGetterDecl {
public ContextTokenListIndexedGetterDecl(OutputModelFactory factory, String name) {
super(factory, name);
}
@Override
public String getArgType() {
return "int";
}
}

View File

@ -54,8 +54,14 @@ public class Decl extends SrcOp {
return name.hashCode(); return name.hashCode();
} }
/** If same name, can't redefine, unless it's a getter */
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
return name.equals(((Decl)obj).name); if ( obj==null ) return false;
// A() and label A are different
if ( obj instanceof ContextGetterDecl ) return false;
if ( this==obj ) return true;
if ( this.hashCode() != obj.hashCode() ) return false;
return name.equals(((Decl) obj).name);
} }
} }

View File

@ -30,11 +30,16 @@
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.codegen.model.*; import org.antlr.v4.codegen.model.ModelElement;
import org.antlr.v4.codegen.model.OutputModelObject;
import org.antlr.v4.codegen.model.VisitorDispatchMethod;
import org.antlr.v4.runtime.misc.OrderedHashSet; import org.antlr.v4.runtime.misc.OrderedHashSet;
import org.antlr.v4.tool.*; import org.antlr.v4.tool.Attribute;
import org.antlr.v4.tool.Rule;
import java.util.*; import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/** This object models the structure holding all of the parameters, /** This object models the structure holding all of the parameters,
* return values, local variables, and labels associated with a rule. * return values, local variables, and labels associated with a rule.
@ -43,6 +48,7 @@ public class StructDecl extends Decl {
public String superClass; public String superClass;
public boolean provideCopyFrom; public boolean provideCopyFrom;
@ModelElement public OrderedHashSet<Decl> attrs = new OrderedHashSet<Decl>(); @ModelElement public OrderedHashSet<Decl> attrs = new OrderedHashSet<Decl>();
@ModelElement public OrderedHashSet<Decl> getters = new OrderedHashSet<Decl>();
@ModelElement public Collection<Attribute> ctorAttrs; @ModelElement public Collection<Attribute> ctorAttrs;
@ModelElement public List<VisitorDispatchMethod> visitorDispatchMethods; @ModelElement public List<VisitorDispatchMethod> visitorDispatchMethods;
@ModelElement public List<OutputModelObject> interfaces; @ModelElement public List<OutputModelObject> interfaces;
@ -60,7 +66,11 @@ public class StructDecl extends Decl {
visitorDispatchMethods.add(new VisitorDispatchMethod(factory, r, false)); visitorDispatchMethods.add(new VisitorDispatchMethod(factory, r, false));
} }
public void addDecl(Decl d) { attrs.add(d); d.ctx = this; } public void addDecl(Decl d) {
d.ctx = this;
if ( d instanceof ContextGetterDecl ) getters.add(d);
else attrs.add(d);
}
public void addDecl(Attribute a) { public void addDecl(Attribute a) {
addDecl(new AttributeDecl(factory, a.name, a.decl)); addDecl(new AttributeDecl(factory, a.name, a.decl));

View File

@ -29,14 +29,22 @@
package org.antlr.v4.tool.ast; package org.antlr.v4.tool.ast;
import org.antlr.runtime.*; import org.antlr.runtime.CharStream;
import org.antlr.runtime.tree.*; import org.antlr.runtime.CommonToken;
import org.antlr.v4.parse.*; import org.antlr.runtime.Token;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.antlr.runtime.tree.Tree;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.parse.GrammarASTAdaptor;
import org.antlr.v4.runtime.atn.ATNState; import org.antlr.v4.runtime.atn.ATNState;
import org.antlr.v4.runtime.misc.IntervalSet; import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.tool.Grammar; import org.antlr.v4.tool.Grammar;
import java.util.*; import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
public class GrammarAST extends CommonTree { public class GrammarAST extends CommonTree {
/** For error msgs, nice to know which grammar this AST lives in */ /** For error msgs, nice to know which grammar this AST lives in */
@ -115,8 +123,8 @@ public class GrammarAST extends CommonTree {
public String getAltLabel() { public String getAltLabel() {
List ancestors = this.getAncestors(); List ancestors = this.getAncestors();
if ( ancestors==null ) return null; if ( ancestors==null ) return null;
for (Object o : ancestors) { for (int i=ancestors.size()-1; i>=0; i--) {
GrammarAST p = (GrammarAST)o; GrammarAST p = (GrammarAST)ancestors.get(i);
if ( p.getType()== ANTLRParser.ALT ) { if ( p.getType()== ANTLRParser.ALT ) {
AltAST a = (AltAST)p; AltAST a = (AltAST)p;
if ( a.altLabel!=null ) return a.altLabel.getText(); if ( a.altLabel!=null ) return a.altLabel.getText();