got all locals into return struct. all vars are visible to invoked rules via $rule::attr now.

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 8757]
This commit is contained in:
parrt 2011-06-23 17:29:51 -08:00
parent d8edb713ed
commit 046b469f8e
15 changed files with 139 additions and 145 deletions

View File

@ -39,6 +39,7 @@ public class QStack<T> {
public T pop() {
if ( sp<0 ) throw new EmptyStackException();
elements[sp] = null; // let gc reclaim that element
return elements[sp--];
}

View File

@ -1,7 +1,8 @@
parser grammar T;
r[int a] returns [int b]
: x=ID y=r[34] {$b = 99;}
scope {int qq;}
: x=ID y=r[34] z+=b {$b = 99;}
;
b : r[34] ;
b : r[34] {$r::qq = 3;} ;

View File

@ -27,6 +27,8 @@ import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.misc.*;
import java.util.List;
import java.util.ArrayList;
<parser>
>>
@ -87,25 +89,16 @@ public <p.name>(TokenStream input) {
}
>>
/*
// S.g:5:1: b returns [String q, float x] : A ;
public final S.b_return b() throws RecognitionException {
b_stack.push(new b_scope());
S.b_return retval = new S.b_return();
*/
RuleFunction(currentRule,code,decls,context,scope,namedActions,finallyAction) ::= <<
<context>
<scope>
RuleFunction(currentRule,code,decls,ruleCtx,namedActions,finallyAction) ::= <<
<ruleCtx>
public QStack\<<currentRule.ctxType>\> <currentRule.name>_stk = new QStack\<<currentRule.ctxType>\>();
<if(currentRule.modifiers)><currentRule.modifiers:{f | <f> }><else>public final <endif><currentRule.ctxType> <currentRule.name>(<currentRule.args; separator=",">) throws RecognitionException {
<currentRule.ctxType> _localctx = new <currentRule.ctxType>(_ctx, <currentRule.startState><currentRule.args:{a | , <a.name>}>);
_ctx = _localctx;
<if(currentRule.scope)>
<currentRule.scope.name>_stack.push(new <currentRule.scope.name>());
<endif>
<currentRule.name>_stk.push(_localctx);
_localctx.start = input.LT(1);
//System.out.println("enter "+ruleNames[<currentRule.index>]);
<currentRule.globalScopesUsed:{s | <s>_stack.push(new <s>());}; separator="\n">
<namedActions.init>
<decls; separator="\n">
try {
@ -116,9 +109,9 @@ RuleFunction(currentRule,code,decls,context,scope,namedActions,finallyAction) ::
recover();
}
finally {
_localctx.stop = input.LT(-1);
<namedActions.after>
<currentRule.globalScopesUsed:{s | <s>_stack.pop();}; separator="\n">
<if(currentRule.scope)><currentRule.scope.name>_stack.pop();<endif>
<currentRule.name>_stk.pop();
<finallyAction>
_ctx = (ParserRuleContext)_ctx.parent;
//System.out.println("exit "+ruleNames[<currentRule.index>]);
@ -273,12 +266,12 @@ cases(ttypes) ::= <<
InvokeRule(r) ::= <<
_ctx.s = <r.stateNumber>;
<if(r.labels)><r.labels:{l | <l> = }><endif><r.name>(<r.argExprs:{e| <e>}; separator=",">);
<if(r.labels)><r.labels:{l | _localctx.<l> = }><endif><r.name>(<r.argExprs:{e| <e>}; separator=",">);
>>
MatchToken(m) ::= <<
_ctx.s = <m.stateNumber>;
<if(m.labels)><m.labels:{l | <l> = }>(Token)<endif>match(<m.name>);
<if(m.labels)><m.labels:{l | _localctx.<l> = }>(Token)<endif>match(<m.name>);
>>
// ACTION STUFF
@ -296,45 +289,54 @@ ArgRef(a) ::= "_localctx.<a.name>"
RetValueRef(a) ::= "_localctx.<a.name>"
QRetValueRef(a) ::= "<a.dict>.<a.name>"
/** How to translate $tokenLabel */
TokenRef(t) ::= "<t.name>"
TokenRef(t) ::= "_localctx.<t.name>"
SetAttr(s,rhsChunks) ::= "_localctx.<s.name> = <rhsChunks>;"
LexerSetAttr(s,rhsChunks) ::= "<s.name> = <rhsChunks>;"
//SetQAttr(s,rhsChunks) ::= "<s.dict>.<s.name> = <rhsChunks>;"
TokenPropertyRef_text(t) ::= "(<t.label>!=null?<t.label>.getText():null)"
TokenPropertyRef_type(t) ::= "(<t.label>!=null?<t.label>.getType():0)"
TokenPropertyRef_line(t) ::= "(<t.label>!=null?<t.label>.getLine():0)"
TokenPropertyRef_pos(t) ::= "(<t.label>!=null?<t.label>.getCharPositionInLine():0)"
TokenPropertyRef_channel(t) ::= "(<t.label>!=null?<t.label>.getChannel():0)"
TokenPropertyRef_index(t) ::= "(<t.label>!=null?<t.label>.getTokenIndex():0)"
TokenPropertyRef_tree(t) ::= "<t.label>_tree"
TokenPropertyRef_int(t) ::= "(<t.label>!=null?Integer.valueOf(<t.label>.getText()):0)"
TokenPropertyRef_text(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getText():null)"
TokenPropertyRef_type(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getType():0)"
TokenPropertyRef_line(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getLine():0)"
TokenPropertyRef_pos(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getCharPositionInLine():0)"
TokenPropertyRef_channel(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getChannel():0)"
TokenPropertyRef_index(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getTokenIndex():0)"
TokenPropertyRef_tree(t) ::= "_localctx.<t.label>_tree"
TokenPropertyRef_int(t) ::= "(_localctx.<t.label>!=null?Integer.valueOf(_localctx.<t.label>.getText()):0)"
RulePropertyRef_start(r) ::= "(<r.label>!=null?((<file.TokenLabelType>)<r.label>.start):null)"
RulePropertyRef_stop(r) ::= "(<r.label>!=null?((<file.TokenLabelType>)<r.label>.stop):null)"
RulePropertyRef_tree(r) ::= "(<r.label>!=null?((<file.ASTLabelType>)<r.label>.tree):null)"
RulePropertyRef_text(r) ::= "(<r.label>!=null?((TokenStream)input).toString(<r.label>.start,<r.label>.stop):null)"
RulePropertyRef_st(r) ::= "(<r.label>!=null?<r.label>.st:null)"
RulePropertyRef_start(r) ::= "(_localctx.<r.label>!=null?((<file.TokenLabelType>)_localctx.<r.label>.start):null)"
RulePropertyRef_stop(r) ::= "(_localctx.<r.label>!=null?((<file.TokenLabelType>)_localctx.<r.label>.stop):null)"
RulePropertyRef_tree(r) ::= "(_localctx.<r.label>!=null?((<file.ASTLabelType>)_localctx.<r.label>.tree):null)"
RulePropertyRef_text(r) ::= "(_localctx.<r.label>!=null?((TokenStream)input).toString(_localctx.<r.label>.start,_localctx.<r.label>.stop):null)"
RulePropertyRef_st(r) ::= "(_localctx.<r.label>!=null?_localctx.<r.label>.st:null)"
DynScopeRef(s) ::= "<s.scope>_stack"
DynScopeAttrRef(s) ::= "<s.scope>_stack.peek().<s.attr>"
DynScopeRef(s) ::= "<s.scope>"
DynScopeAttrRef(s) ::= "<s.scope>.peek().<s.attr>"
DynScopeAttrRef_negIndex(s, indexChunks) ::=
"<s.scope>_stack.get(<s.scope>_stack.size()-<indexChunks>-1).<s.attr>"
"<s.scope>.get(<s.scope>.size()-<indexChunks>-1).<s.attr>"
DynScopeAttrRef_index(s, indexChunks) ::=
"<s.scope>_stack.get(<indexChunks>).<s.attr>"
"<s.scope>.get(<indexChunks>).<s.attr>"
SetDynScopeAttr(s, rhsChunks) ::=
"<s.scope>_stack.peek().<s.attr> =<rhsChunks>;"
"<s.scope>.peek().<s.attr> =<rhsChunks>;"
SetDynScopeAttr_negIndex(s, indexChunks, rhsChunks) ::=
"<s.scope>_stack.get(<s.scope>_stack.size()-<indexChunks>-1).<s.attr> =<rhsChunks>;"
"<s.scope>.get(<s.scope>.size()-<indexChunks>-1).<s.attr> =<rhsChunks>;"
SetDynScopeAttr_index(s, indexChunks, rhsChunks) ::=
"<s.scope>_stack.get(<indexChunks>).<s.attr> =<rhsChunks>;"
"<s.scope>.get(<indexChunks>).<s.attr> =<rhsChunks>;"
AddToList(a) ::= "<a.listName>.add(<first(a.opWithResultToAdd.labels)>);"
AddToLabelList(a) ::= "_localctx.<a.listName>.add(_localctx.<first(a.opWithResultToAdd.labels)>);"
TokenDecl(t) ::= "Token <t.name>;"
TokenTypeDecl(t) ::= "int <t.name>;"
TokenListDecl(t) ::= "List\<Token> <t.name> = new ArrayList\<Token>();"
RuleContextDecl(r) ::= "<r.ctxName> <r.name>;"
RuleContextListDecl(rdecl) ::= "List\<<rdecl.decl.ctxName>> <rdecl.name> = new ArrayList\<<rdecl.decl.ctxName>>();"
/** Default RuleContext type name for a Parser rule */
ParserRuleContext() ::= "ParserRuleContext"
RuleDynamicScopeStructName(ruleName) ::= "<ruleName>_stk"
ImplicitTokenLabel(tokenName) ::= "_t<tokenName>"
ImplicitRuleLabel(ruleName) ::= "_r<ruleName>"
CaptureNextToken(d) ::= "<d.varName> = input.LT(1);"
CaptureNextTokenType(d) ::= "<d.varName> = input.LA(1);"
@ -348,14 +350,7 @@ public static class <s.name> extends ParserRuleContext {
<s.ctorAttrs:{a | this.<a.name> = <a.name>;}; separator="\n">
}
<endif>
};
>>
DynamicScopeStruct(d,attrs) ::= <<
public static class <d.name> {
<attrs:{a | <a>;}; separator="\n">
};
public QStack\<<d.name>\> <d.name>_stack = new QStack\<<d.name>\>();
}
>>
AttributeDecl(d) ::= "<d.decl>"

View File

@ -7,6 +7,7 @@ import org.antlr.v4.tool.*;
import org.stringtemplate.v4.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
/** General controller for code gen. Can instantiate sub generator(s).
@ -36,10 +37,19 @@ public class CodeGenerator {
String targetName = "org.antlr.v4.codegen."+language+"Target";
try {
Class c = Class.forName(targetName);
target = (Target)c.newInstance();
Constructor ctor = c.getConstructor(CodeGenerator.class);
target = (Target)ctor.newInstance(this);
}
catch (ClassNotFoundException cnfe) {
target = new Target(); // use default
target = new Target(this); // use default
}
catch (NoSuchMethodException nsme) {
target = new Target(this); // use default
}
catch (InvocationTargetException ite) {
g.tool.errMgr.toolError(ErrorType.CANNOT_CREATE_TARGET_GENERATOR,
ite,
targetName);
}
catch (InstantiationException ie) {
g.tool.errMgr.toolError(ErrorType.CANNOT_CREATE_TARGET_GENERATOR,
@ -63,12 +73,6 @@ public class CodeGenerator {
iae,
language);
}
// if ( EMIT_TEMPLATE_DELIMITERS ) {
// templates.emitDebugStartStopStrings(true);
// templates.doNotEmitDebugStringsForTemplate("codeFileExtension");
// templates.doNotEmitDebugStringsForTemplate("headerFileExtension");
// }
}
public ST generate() {
@ -129,12 +133,12 @@ public class CodeGenerator {
String fileName = "unknown";
try {
fileName = getRecognizerFileName();
target.genRecognizerFile(this,g,outputFileST);
target.genRecognizerFile(g,outputFileST);
if ( templates.isDefined("headerFile") ) {
fileName = getHeaderFileName();
ST extST = templates.getInstanceOf("headerFileExtension");
ST headerFileST = null;
target.genRecognizerHeaderFile(this,g,headerFileST,extST.render(lineWidth));
target.genRecognizerHeaderFile(g,headerFileST,extST.render(lineWidth));
}
// write out the vocab interchange file; used by antlr,
// does not change per target

View File

@ -30,9 +30,9 @@ public class ParserFactory extends OutputModelFactory {
@Override
public List<SrcOp> ruleRef(GrammarAST ID, GrammarAST label, GrammarAST args) {
InvokeRule r = new InvokeRule(this, ID, label);
AddToList a = null;
AddToLabelList a = null;
if ( label!=null && label.parent.getType()==ANTLRParser.PLUS_ASSIGN ) {
a = new AddToList(this, gen.target.getListLabel(label.getText()), r);
a = new AddToLabelList(this, gen.target.getListLabel(label.getText()), r);
}
return Utils.list(r, a);
}
@ -40,9 +40,9 @@ public class ParserFactory extends OutputModelFactory {
@Override
public List<SrcOp> tokenRef(GrammarAST ID, GrammarAST label, GrammarAST args) {
MatchToken m = new MatchToken(this, (TerminalAST) ID, label);
AddToList a = null;
AddToLabelList a = null;
if ( label!=null && label.parent.getType()==ANTLRParser.PLUS_ASSIGN ) {
a = new AddToList(this, gen.target.getListLabel(label.getText()), m);
a = new AddToLabelList(this, gen.target.getListLabel(label.getText()), m);
}
return Utils.list(m, a);
}

View File

@ -21,7 +21,9 @@ public class Target {
*/
protected String[] targetCharValueEscape = new String[255];
public Target() {
public CodeGenerator gen;
public Target(CodeGenerator gen) {
targetCharValueEscape['\n'] = "\\n";
targetCharValueEscape['\r'] = "\\r";
targetCharValueEscape['\t'] = "\\t";
@ -30,19 +32,18 @@ public class Target {
targetCharValueEscape['\\'] = "\\\\";
targetCharValueEscape['\''] = "\\'";
targetCharValueEscape['"'] = "\\\"";
this.gen = gen;
}
protected void genRecognizerFile(CodeGenerator generator,
Grammar g,
protected void genRecognizerFile(Grammar g,
ST outputFileST)
throws IOException
{
String fileName = generator.getRecognizerFileName();
generator.write(outputFileST, fileName);
String fileName = gen.getRecognizerFileName();
gen.write(outputFileST, fileName);
}
protected void genRecognizerHeaderFile(CodeGenerator generator,
Grammar g,
protected void genRecognizerHeaderFile(Grammar g,
ST headerFileST,
String extName) // e.g., ".h"
throws IOException
@ -162,15 +163,30 @@ public class Target {
public String getListLabel(String label) { return label+"_list"; }
public String getRuleFunctionContextStructName(Rule r) {
if ( r.args==null && r.retvals==null ) return "ParserRuleContext";
if ( r.args==null && r.retvals==null && r.scope==null && r.getLabelNames()==null ) {
return gen.templates.getInstanceOf("ParserRuleContext").render();
}
return r.name+"_ctx";
}
public String getRuleDynamicScopeStructName(String ruleName) { return ruleName+"_scope"; }
public String getRuleDynamicScopeStructName(String ruleName) {
ST st = gen.templates.getInstanceOf("RuleDynamicScopeStructName");
st.add("ruleName", ruleName);
return st.render();
}
public String getGlobalDynamicScopeStructName(String scopeName) { return scopeName; }
// should be same for all refs to same token like $ID within single rule function
public String getImplicitTokenLabel(String tokenName) { return "_t"+tokenName; }
public String getImplicitRuleLabel(String ruleName) { return "_r"+ruleName; }
public String getImplicitTokenLabel(String tokenName) {
ST st = gen.templates.getInstanceOf("ImplicitTokenLabel");
st.add("tokenName", tokenName);
return st.render();
}
public String getImplicitRuleLabel(String ruleName) {
ST st = gen.templates.getInstanceOf("ImplicitRuleLabel");
st.add("ruleName", ruleName);
return st.render();
}
public int getInlineTestsVsBitsetThreshold() { return 20; }
}

View File

@ -3,11 +3,11 @@ package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;
/** */
public class AddToList extends SrcOp {
public class AddToLabelList extends SrcOp {
public String listName;
public LabeledOp opWithResultToAdd;
public AddToList(OutputModelFactory factory, String listName, LabeledOp opWithResultToAdd) {
public AddToLabelList(OutputModelFactory factory, String listName, LabeledOp opWithResultToAdd) {
super(factory);
this.listName = listName;
this.opWithResultToAdd = opWithResultToAdd;

View File

@ -1,13 +0,0 @@
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.tool.Attribute;
import java.util.Collection;
/** */
public class DynamicScopeStruct extends StructDecl {
public DynamicScopeStruct(OutputModelFactory factory, String name, Collection<Attribute> attrList) {
super(factory, name, attrList);
}
}

View File

@ -26,13 +26,15 @@ public class InvokeRule extends RuleElement implements LabeledOp {
ctxName = factory.gen.target.getRuleFunctionContextStructName(r);
if ( labelAST!=null ) {
// for x=r, define <rule-context-type> x and list_x
String label = labelAST.getText();
labels.add(label);
RuleContextDecl d = new RuleContextDecl(factory,label,ctxName);
factory.currentRule.peek().addDecl(d);
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
// TokenListDecl l = new TokenListDecl(factory.getListLabel(label));
// factory.currentRule.peek().addDecl(l);
String listLabel = factory.gen.target.getListLabel(label);
RuleContextListDecl l = new RuleContextListDecl(factory, listLabel, d);
factory.currentRule.peek().addDecl(l);
}
}
if ( ast.getChildCount()>0 ) {

View File

@ -13,7 +13,6 @@ public class Parser extends OutputModelObject {
public Set<String> ruleNames;
public ParserFile file;
@ModelElement public List<DynamicScopeStruct> scopes = new ArrayList<DynamicScopeStruct>();
@ModelElement public List<RuleFunction> funcs = new ArrayList<RuleFunction>();
@ModelElement public SerializedATN atn;
@ModelElement public LinkedHashMap<Integer, ForcedAction> actions;
@ -37,11 +36,7 @@ public class Parser extends OutputModelObject {
// }
tokenNames = factory.g.getTokenDisplayNames();
ruleNames = factory.g.rules.keySet();
for (AttributeDict d : factory.g.scopes.values()) {
scopes.add( new DynamicScopeStruct(factory, d.name, d.attributes.values()) );
}
for (Rule r : factory.g.rules.values()) {
//if ( r.isStartRule ) funcs.add( new StartRuleFunction(factory, r) );
funcs.add( new RuleFunction(factory, r) );
}
atn = new SerializedATN(factory, factory.g.atn);

View File

@ -0,0 +1,11 @@
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.*;
public class RuleContextListDecl extends Decl {
public RuleContextDecl decl;
public RuleContextListDecl(OutputModelFactory factory, String name, RuleContextDecl decl) {
super(factory, name);
this.decl = decl;
}
}

View File

@ -24,9 +24,9 @@ public class RuleFunction extends OutputModelObject {
public Collection<Attribute> args = null;
@ModelElement public SrcOp code;
@ModelElement public OrderedHashSet<Decl> decls;
@ModelElement public StructDecl context;
@ModelElement public DynamicScopeStruct scope;
@ModelElement public OrderedHashSet<Decl> decls; // TODO: move into ctx?
@ModelElement public StructDecl ruleCtx;
//@ModelElement public DynamicScopeStruct scope;
@ModelElement public Map<String, Action> namedActions;
@ModelElement public Action finallyAction;
@ -45,31 +45,29 @@ public class RuleFunction extends OutputModelObject {
ctxType = factory.gen.target.getRuleFunctionContextStructName(r);
List<Attribute> argsAndReturnValues = new ArrayList<Attribute>();
List<Attribute> ctorAttrs = new ArrayList<Attribute>();
index = r.index;
// might need struct; build but drop later if no elements
ruleCtx = new StructDecl(factory, ctxType);
if ( r.args!=null ) {
argsAndReturnValues.addAll(r.args.attributes.values());
ruleCtx.addDecls(r.args.attributes.values());
args = r.args.attributes.values();
ctorAttrs.addAll(args);
ruleCtx.ctorAttrs = args;
}
if ( r.retvals!=null ) {
argsAndReturnValues.addAll(r.retvals.attributes.values());
ruleCtx.addDecls(r.retvals.attributes.values());
}
if ( r.scope!=null ) {
scope = new DynamicScopeStruct(factory, factory.gen.target.getRuleDynamicScopeStructName(r.name),
r.scope.attributes.values());
String scopeType = factory.gen.target.getRuleDynamicScopeStructName(r.name);
// scope = new DynamicScopeStruct(factory, scopeType);
// scope.addDecls(r.scope.attributes.values());
ruleCtx.addDecls(r.scope.attributes.values());
}
globalScopesUsed = Utils.apply(r.useScopes, "getText");
if ( argsAndReturnValues.size()>0 ) {
context = new StructDecl(factory, factory.gen.target.getRuleFunctionContextStructName(r),
argsAndReturnValues);
context.ctorAttrs = ctorAttrs;
}
if ( ruleCtx.isEmpty() ) ruleCtx = null;
ruleLabels = r.getLabelNames();
tokenLabels = r.getTokenRefs();
@ -99,17 +97,8 @@ public class RuleFunction extends OutputModelObject {
}
public void addDecl(Decl d) {
if ( decls==null ) decls = new OrderedHashSet<Decl>();
decls.add(d);
ruleCtx.addDecl(d);
// if ( decls==null ) decls = new OrderedHashSet<Decl>();
// decls.add(d);
}
// @Override
// public List<String> getChildren() {
// final List<String> sup = super.getChildren();
// return new ArrayList<String>() {{
// if ( sup!=null ) addAll(sup);
// add("context"); add("scope"); add("decls"); add("code");
// add("finallyAction"); add("namedActions");
// }};
// }
}

View File

@ -10,18 +10,19 @@ public class StructDecl extends Decl {
@ModelElement public List<Decl> attrs = new ArrayList<Decl>();
@ModelElement public Collection<Attribute> ctorAttrs;
public StructDecl(OutputModelFactory factory, String name, Collection<Attribute> attrList) {
public StructDecl(OutputModelFactory factory, String name) {
super(factory, name);
for (Attribute a : attrList) {
attrs.add(new AttributeDecl(factory, a.name, a.decl));
}
}
// @Override
// public List<String> getChildren() {
// final List<String> sup = super.getChildren();
// return new ArrayList<String>() {{
// if ( sup!=null ) addAll(sup); add("attrs");
// }};
// }
public void addDecl(Decl d) { attrs.add(d); }
public void addDecl(Attribute a) {
addDecl(new AttributeDecl(factory, a.name, a.decl));
}
public void addDecls(Collection<Attribute> attrList) {
for (Attribute a : attrList) addDecl(a);
}
public boolean isEmpty() { return attrs.size()==0; }
}

View File

@ -15,13 +15,4 @@ public class SetDynScopeAttr extends ActionChunk {
this.attr = attr;
this.rhsChunks = rhsChunks;
}
//
// @Override
// public List<String> getChildren() {
// final List<String> sup = super.getChildren();
// return new ArrayList<String>() {{
// if ( sup!=null ) addAll(sup);
// add("rhsChunks");
// }};
// }
}

View File

@ -126,6 +126,7 @@ public class Rule implements AttributeResolver {
for (int i=1; i<=numberOfAlts; i++) {
refs.addAll(alt[i].labelDefs.keySet());
}
if ( refs.size()==0 ) return null;
return refs;
}