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 4316e0e70..20cbc562e 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 @@ -74,9 +74,37 @@ LL1StarBlockSingleAlt(choice, expr, alts, preamble) ::= << while ( ) { + = input.LA(1); } >> +LL1PlusBlock(choice, alts) ::= << +int = 0; +: +while (true) { + switch ( input.LA(1) ) { + + + break;}; separator="\n"> + + if ( >= 1 ) break ; + else error + default : + error + } +} +>> + +//LL1PlusBlockSingleAlt ::= LL1PlusBlock + +LL1PlusBlockSingleAlt(choice, expr, alts, preamble) ::= << + +do { + + = input.LA(1); +} while ( ); +>> + TestSet(s) ::= << .member(input.LA(1)) >> diff --git a/tool/src/org/antlr/v4/automata/ParserNFAFactory.java b/tool/src/org/antlr/v4/automata/ParserNFAFactory.java index 373eec8a5..79d2d7729 100644 --- a/tool/src/org/antlr/v4/automata/ParserNFAFactory.java +++ b/tool/src/org/antlr/v4/automata/ParserNFAFactory.java @@ -298,6 +298,8 @@ public class ParserNFAFactory implements NFAFactory { PlusBlockStartState start = (PlusBlockStartState)newState(PlusBlockStartState.class, plusAST); LoopbackState loop = (LoopbackState)newState(LoopbackState.class, plusAST); BlockEndState end = (BlockEndState)newState(BlockEndState.class, plusAST); + start.endState = end; // points past loopback state + start.loopBackState = loop; epsilon(start, blk.left); epsilon(loop, blk.left); epsilon(blk.right, loop); diff --git a/tool/src/org/antlr/v4/automata/PlusBlockStartState.java b/tool/src/org/antlr/v4/automata/PlusBlockStartState.java index 13cace60b..b86966121 100644 --- a/tool/src/org/antlr/v4/automata/PlusBlockStartState.java +++ b/tool/src/org/antlr/v4/automata/PlusBlockStartState.java @@ -1,6 +1,7 @@ package org.antlr.v4.automata; /** */ -public class PlusBlockStartState extends BasicState { +public class PlusBlockStartState extends BlockStartState { + public LoopbackState loopBackState; public PlusBlockStartState(NFA nfa) { super(nfa); } } diff --git a/tool/src/org/antlr/v4/codegen/CodeGenerator.java b/tool/src/org/antlr/v4/codegen/CodeGenerator.java index e505af2a3..90e63f5f5 100644 --- a/tool/src/org/antlr/v4/codegen/CodeGenerator.java +++ b/tool/src/org/antlr/v4/codegen/CodeGenerator.java @@ -3,6 +3,7 @@ package org.antlr.v4.codegen; import org.antlr.v4.automata.DFA; import org.antlr.v4.codegen.src.*; import org.antlr.v4.misc.IntSet; +import org.antlr.v4.misc.IntervalSet; import org.antlr.v4.parse.ANTLRParser; import org.antlr.v4.tool.BlockAST; import org.antlr.v4.tool.ErrorType; @@ -121,6 +122,8 @@ public abstract class CodeGenerator { else c = new LL1StarBlock(this, ebnfRoot, alts); break; case ANTLRParser.POSITIVE_CLOSURE : + if ( alts.size()==1 ) c = new LL1PlusBlockSingleAlt(this, ebnfRoot, alts); + else c = new LL1PlusBlock(this, ebnfRoot, alts); break; default : c = new LL1Choice(this, blkAST, alts); @@ -129,6 +132,17 @@ public abstract class CodeGenerator { return c; } + public OutputModelObject getLL1Test(Choice choice, IntervalSet look, GrammarAST blkAST) { + OutputModelObject expr; + if ( look.size() < target.getInlineTestsVsBitsetThreshold() ) { + expr = new TestSetInline(this, choice, blkAST, look); + } + else { + expr = new TestSet(this, blkAST, look); + } + return expr; + } + public void write(ST code, String fileName) throws IOException { long start = System.currentTimeMillis(); Writer w = g.tool.getOutputFile(g, fileName); @@ -185,4 +199,12 @@ public abstract class CodeGenerator { outputModel.bitSetDefs.add(b); return b; } + + public String getLoopLabel(GrammarAST ast) { + return "loop"+ ast.token.getTokenIndex(); + } + + public String getLoopCounter(GrammarAST ast) { + return "cnt"+ ast.token.getTokenIndex(); + } } diff --git a/tool/src/org/antlr/v4/codegen/src/LL1OptionalBlockSingleAlt.java b/tool/src/org/antlr/v4/codegen/src/LL1OptionalBlockSingleAlt.java index ff0e4052a..9f04d4388 100644 --- a/tool/src/org/antlr/v4/codegen/src/LL1OptionalBlockSingleAlt.java +++ b/tool/src/org/antlr/v4/codegen/src/LL1OptionalBlockSingleAlt.java @@ -13,12 +13,7 @@ public class LL1OptionalBlockSingleAlt extends LL1OptionalBlock { public LL1OptionalBlockSingleAlt(CodeGenerator gen, GrammarAST blkAST, List alts) { super(gen, blkAST, alts); IntervalSet look = altLookSets[1]; - if ( look.size() < gen.target.getInlineTestsVsBitsetThreshold() ) { - expr = new TestSetInline(gen, this, blkAST, look); - } - else { - expr = new TestSet(gen, blkAST, look); - } + expr = gen.getLL1Test(this, look, blkAST); } @Override diff --git a/tool/src/org/antlr/v4/codegen/src/LL1PlusBlock.java b/tool/src/org/antlr/v4/codegen/src/LL1PlusBlock.java new file mode 100644 index 000000000..4832ab95b --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/src/LL1PlusBlock.java @@ -0,0 +1,28 @@ +package org.antlr.v4.codegen.src; + +import org.antlr.v4.automata.DFA; +import org.antlr.v4.automata.PlusBlockStartState; +import org.antlr.v4.codegen.CodeGenerator; +import org.antlr.v4.misc.IntervalSet; +import org.antlr.v4.tool.GrammarAST; + +import java.util.List; + +/** */ +public class LL1PlusBlock extends LL1Choice { + public String loopLabel; + public String loopCounterVar; + public String[] exitLook; + public LL1PlusBlock(CodeGenerator gen, GrammarAST blkAST, List alts) { + super(gen, blkAST, alts); + PlusBlockStartState plusStart = (PlusBlockStartState)blkAST.nfaState; + int enterExitDecision = plusStart.decision; + + DFA dfa = gen.g.decisionDFAs.get(enterExitDecision); + IntervalSet exitLook = dfa.startState.edge(1).label; + this.exitLook = gen.target.getTokenTypesAsTargetLabels(gen.g, exitLook.toArray()); + + loopLabel = gen.getLoopLabel(blkAST); + loopCounterVar = gen.getLoopCounter(blkAST); + } +} diff --git a/tool/src/org/antlr/v4/codegen/src/LL1PlusBlockSingleAlt.java b/tool/src/org/antlr/v4/codegen/src/LL1PlusBlockSingleAlt.java new file mode 100644 index 000000000..4c41eb720 --- /dev/null +++ b/tool/src/org/antlr/v4/codegen/src/LL1PlusBlockSingleAlt.java @@ -0,0 +1,25 @@ +package org.antlr.v4.codegen.src; + +import org.antlr.v4.codegen.CodeGenerator; +import org.antlr.v4.misc.IntervalSet; +import org.antlr.v4.tool.GrammarAST; + +import java.util.ArrayList; +import java.util.List; + +/** */ +public class LL1PlusBlockSingleAlt extends LL1Choice { + public Object expr; + public LL1PlusBlockSingleAlt(CodeGenerator gen, GrammarAST blkAST, List alts) { + super(gen, blkAST, alts); + IntervalSet loopBackLook = altLookSets[2]; // loop exit is alt 1 + expr = gen.getLL1Test(this, loopBackLook, blkAST); + } + + @Override + public List getChildren() { + final List sup = super.getChildren(); + return new ArrayList() {{ if ( sup!=null ) addAll(sup); add("expr"); }}; + } + +} diff --git a/tool/src/org/antlr/v4/codegen/src/LL1StarBlock.java b/tool/src/org/antlr/v4/codegen/src/LL1StarBlock.java index 50e871472..b4852cfec 100644 --- a/tool/src/org/antlr/v4/codegen/src/LL1StarBlock.java +++ b/tool/src/org/antlr/v4/codegen/src/LL1StarBlock.java @@ -25,6 +25,7 @@ public class LL1StarBlock extends LL1Choice { IntervalSet exitLook = dfa.startState.edge(1).label; this.exitLook = gen.target.getTokenTypesAsTargetLabels(gen.g, exitLook.toArray()); - loopLabel = "loop"+blkAST.token.getTokenIndex(); + loopLabel = gen.getLoopLabel(blkAST); } + } diff --git a/tool/src/org/antlr/v4/codegen/src/LL1StarBlockSingleAlt.java b/tool/src/org/antlr/v4/codegen/src/LL1StarBlockSingleAlt.java index f486ac83c..20cd21a81 100644 --- a/tool/src/org/antlr/v4/codegen/src/LL1StarBlockSingleAlt.java +++ b/tool/src/org/antlr/v4/codegen/src/LL1StarBlockSingleAlt.java @@ -1,13 +1,24 @@ package org.antlr.v4.codegen.src; import org.antlr.v4.codegen.CodeGenerator; +import org.antlr.v4.misc.IntervalSet; import org.antlr.v4.tool.GrammarAST; +import java.util.ArrayList; import java.util.List; /** */ -public class LL1StarBlockSingleAlt extends LL1OptionalBlockSingleAlt { +public class LL1StarBlockSingleAlt extends LL1Choice { + public Object expr; public LL1StarBlockSingleAlt(CodeGenerator gen, GrammarAST blkAST, List alts) { super(gen, blkAST, alts); + IntervalSet look = altLookSets[1]; + expr = gen.getLL1Test(this, look, blkAST); + } + + @Override + public List getChildren() { + final List sup = super.getChildren(); + return new ArrayList() {{ if ( sup!=null ) addAll(sup); add("expr"); }}; } }