We're forced to exec args, even if dependent on _localctx. If no actual context to use, create dummy context to use for arg eval only.

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 8922]
This commit is contained in:
parrt 2011-07-29 11:45:27 -08:00
parent dcfb804ed3
commit 4b5cd3a9ba
5 changed files with 63 additions and 11 deletions

View File

@ -227,7 +227,8 @@ public class Recognizer<ATNInterpreter> {
}
/** Create context for a rule reference IN fromRuleIndex using parent _localctx.
* Used only when there are arguments to the rule function.
* Used only when there are arguments to the rule function. _localctx
* must be correct context for fromRuleIndex.
*/
public RuleContext newContext(RuleContext _localctx, int s, int fromRuleIndex, int actionIndex) {
return new ParserRuleContext(_localctx, s);

View File

@ -494,6 +494,7 @@ public class ParserATNSimulator extends ATNSimulator {
if ( parser != null ) {
RuleContext ctx = getCurrentExecContext(config);
int argIndex = ((RuleTransition) t).argIndex;
int targetRuleIndex = t.target.ruleIndex;
if ( debug ) {
System.out.println("CALL rule "+parser.getRuleNames()[t.target.ruleIndex]+
", arg="+ argIndex +
@ -501,12 +502,18 @@ public class ParserATNSimulator extends ATNSimulator {
}
int fromRuleIndex = config.state.ruleIndex;
if ( argIndex>=0 ) {
// we're forced to exec args, even if dependent on _localctx.
// If no actual context to use, create dummy context to use
// for arg eval only.
if ( ctx == null ) {
// get dummy context for fromRuleIndex
ctx = parser.newContext(null, config.state.stateNumber, fromRuleIndex);
}
newContext = parser.newContext(ctx, t.target.stateNumber,
fromRuleIndex,
argIndex);
}
else {
int targetRuleIndex = t.target.ruleIndex;
newContext = parser.newContext(ctx, t.target.stateNumber, targetRuleIndex);
}

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.
*/
import org.antlr.v4.runtime.*;
public class TestU {
public static void main(String[] args) throws Exception {
ULexer t = new ULexer(new ANTLRFileStream(args[0]));
CommonTokenStream tokens = new CommonTokenStream(t);
UParser p = new UParser(tokens);
ParserRuleContext ret = p.a(33);
// System.out.println(((Tree)ret.tree).toStringTree());
}
}

View File

@ -80,7 +80,7 @@ dumpActions(recog, argFuncs, actionFuncs, sempredFuncs) ::= <<
public RuleContext newContext(RuleContext _localctx, int s, int fromRuleIndex, int actionIndex) {
switch ( fromRuleIndex ) {
<recog.argFuncs.values:{f|
case <f.ruleIndex> : return <f.name>_argEval(_localctx, s, actionIndex);}; separator="\n">
case <f.ruleIndex> : return <f.name>_argEval((<f.ctxType>)_localctx, s, actionIndex);}; separator="\n">
}
return new RuleContext(_localctx, s);
}
@ -116,7 +116,7 @@ public <p.name>(TokenStream input) {
RuleArgFunction(r, actions) ::= <<
/** arg computations for rules called FROM and evaluated in context of <r.name> */
public RuleContext <r.name>_argEval(RuleContext _localctx, int s, int actionIndex) {
public RuleContext <r.name>_argEval(<r.ctxType> _localctx, int s, int actionIndex) {
switch ( actionIndex ) {
<actions:{index|
case <index> : return new <r.actions.(index).ctxType>(_localctx, s, <actions.(index)>);}; separator="\n">
@ -330,9 +330,9 @@ cases(ttypes) ::= <<
<ttypes:{t | case <t>:}; separator="\n">
>>
InvokeRule(r) ::= <<
InvokeRule(r, argExprsChunks) ::= <<
_localctx.s = <r.stateNumber>;
<if(r.labels)><r.labels:{l | <labelref(l)> = }><endif><r.name>(<r.argExprs:{e| <e>}; separator=",">);
<if(r.labels)><r.labels:{l | <labelref(l)> = }><endif><r.name>(<argExprsChunks:{e| <e>}>);
>>
MatchToken(m) ::= <<

View File

@ -30,6 +30,7 @@
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.*;
import org.antlr.v4.codegen.model.actions.ActionChunk;
import org.antlr.v4.codegen.model.decl.*;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.runtime.atn.RuleTransition;
@ -42,9 +43,10 @@ import java.util.List;
public class InvokeRule extends RuleElement implements LabeledOp {
public String name;
public OrderedHashSet<Decl> labels = new OrderedHashSet<Decl>(); // TODO: should need just 1
public String argExprs;
public String ctxName;
@ModelElement public List<ActionChunk> argExprsChunks;
public InvokeRule(OutputModelFactory factory, GrammarAST ast, GrammarAST labelAST) {
super(factory, ast);
if ( ast.atnState!=null ) {
@ -58,20 +60,22 @@ public class InvokeRule extends RuleElement implements LabeledOp {
ctxName = gen.target.getRuleFunctionContextStructName(r);
// TODO: move to factory
RuleFunction rf = factory.getCurrentRuleFunction();
if ( labelAST!=null ) {
// for x=r, define <rule-context-type> x and list_x
String label = labelAST.getText();
RuleContextDecl d = new RuleContextDecl(factory,label,ctxName);
labels.add(d);
factory.getCurrentRuleFunction().addContextDecl(d);
rf.addContextDecl(d);
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
String listLabel = gen.target.getListLabel(label);
RuleContextListDecl l = new RuleContextListDecl(factory, listLabel, ctxName);
factory.getCurrentRuleFunction().addContextDecl(l);
rf.addContextDecl(l);
}
}
if ( ast.getChildCount()>0 ) {
argExprs = ast.getChild(0).getText();
ActionAST arg = (ActionAST)ast.getChild(0);
argExprsChunks = ActionTranslator.translateAction(factory, rf, arg.token, arg);
}
// If action refs rule as rulename not label, we need to define implicit label
@ -79,7 +83,7 @@ public class InvokeRule extends RuleElement implements LabeledOp {
String label = gen.target.getImplicitRuleLabel(ast.getText());
RuleContextDecl d = new RuleContextDecl(factory,label,ctxName);
labels.add(d);
factory.getCurrentRuleFunction().addContextDecl(d);
rf.addContextDecl(d);
}
// LinearApproximator approx = new LinearApproximator(factory.g, ATN.INVALID_DECISION_NUMBER);