got LL(1) plus loops in
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6858]
This commit is contained in:
parent
930b1e1236
commit
e218632b67
|
@ -74,9 +74,37 @@ LL1StarBlockSingleAlt(choice, expr, alts, preamble) ::= <<
|
|||
<preamble>
|
||||
while ( <expr> ) {
|
||||
<alts; separator="\n">
|
||||
<choice.expr.nextToken.varName> = input.LA(1);
|
||||
}
|
||||
>>
|
||||
|
||||
LL1PlusBlock(choice, alts) ::= <<
|
||||
int <choice.loopCounterVar> = 0;
|
||||
<choice.loopLabel>:
|
||||
while (true) {
|
||||
switch ( input.LA(1) ) {
|
||||
<choice.altLook,alts:{look,alt| <cases(ttypes=look)>
|
||||
<alt>
|
||||
break;}; separator="\n">
|
||||
<cases(ttypes=choice.exitLook)>
|
||||
if ( <choice.loopCounterVar> >= 1 ) break <choice.loopLabel>;
|
||||
else error
|
||||
default :
|
||||
error
|
||||
}
|
||||
}
|
||||
>>
|
||||
|
||||
//LL1PlusBlockSingleAlt ::= LL1PlusBlock
|
||||
|
||||
LL1PlusBlockSingleAlt(choice, expr, alts, preamble) ::= <<
|
||||
<preamble>
|
||||
do {
|
||||
<alts; separator="\n">
|
||||
<choice.expr.nextToken.varName> = input.LA(1);
|
||||
} while ( <expr> );
|
||||
>>
|
||||
|
||||
TestSet(s) ::= <<
|
||||
<s.set.name>.member(input.LA(1))
|
||||
>>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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); }
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,12 +13,7 @@ public class LL1OptionalBlockSingleAlt extends LL1OptionalBlock {
|
|||
public LL1OptionalBlockSingleAlt(CodeGenerator gen, GrammarAST blkAST, List<CodeBlock> 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
|
||||
|
|
|
@ -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<CodeBlock> 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);
|
||||
}
|
||||
}
|
|
@ -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<CodeBlock> alts) {
|
||||
super(gen, blkAST, alts);
|
||||
IntervalSet loopBackLook = altLookSets[2]; // loop exit is alt 1
|
||||
expr = gen.getLL1Test(this, loopBackLook, blkAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getChildren() {
|
||||
final List<String> sup = super.getChildren();
|
||||
return new ArrayList<String>() {{ if ( sup!=null ) addAll(sup); add("expr"); }};
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<CodeBlock> alts) {
|
||||
super(gen, blkAST, alts);
|
||||
IntervalSet look = altLookSets[1];
|
||||
expr = gen.getLL1Test(this, look, blkAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getChildren() {
|
||||
final List<String> sup = super.getChildren();
|
||||
return new ArrayList<String>() {{ if ( sup!=null ) addAll(sup); add("expr"); }};
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue