diff --git a/runtime/Java/src/org/antlr/v4/runtime/Recognizer.java b/runtime/Java/src/org/antlr/v4/runtime/Recognizer.java index 620310b46..a91a1a54f 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/Recognizer.java +++ b/runtime/Java/src/org/antlr/v4/runtime/Recognizer.java @@ -227,7 +227,8 @@ public class Recognizer { } /** 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); diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java b/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java index b1e0a1ff2..b414b67dd 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java @@ -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); } diff --git a/tool/playground/TestU.java b/tool/playground/TestU.java new file mode 100644 index 000000000..09b09f26b --- /dev/null +++ b/tool/playground/TestU.java @@ -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()); + } +} diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg index 731527b0e..a70ccbd48 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg @@ -80,7 +80,7 @@ dumpActions(recog, argFuncs, actionFuncs, sempredFuncs) ::= << public RuleContext newContext(RuleContext _localctx, int s, int fromRuleIndex, int actionIndex) { switch ( fromRuleIndex ) { : return _argEval(_localctx, s, actionIndex);}; separator="\n"> +case : return _argEval(()_localctx, s, actionIndex);}; separator="\n"> } return new RuleContext(_localctx, s); } @@ -116,7 +116,7 @@ public (TokenStream input) { RuleArgFunction(r, actions) ::= << /** arg computations for rules called FROM and evaluated in context of */ -public RuleContext _argEval(RuleContext _localctx, int s, int actionIndex) { +public RuleContext _argEval( _localctx, int s, int actionIndex) { switch ( actionIndex ) { : return new (_localctx, s, );}; separator="\n"> @@ -330,9 +330,9 @@ cases(ttypes) ::= << :}; separator="\n"> >> -InvokeRule(r) ::= << +InvokeRule(r, argExprsChunks) ::= << _localctx.s = ; - = }>(}; separator=",">); + = }>(}>); >> MatchToken(m) ::= << diff --git a/tool/src/org/antlr/v4/codegen/model/InvokeRule.java b/tool/src/org/antlr/v4/codegen/model/InvokeRule.java index 0da869b0a..ffc91430d 100644 --- a/tool/src/org/antlr/v4/codegen/model/InvokeRule.java +++ b/tool/src/org/antlr/v4/codegen/model/InvokeRule.java @@ -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 labels = new OrderedHashSet(); // TODO: should need just 1 - public String argExprs; public String ctxName; + @ModelElement public List 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 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);