got LL(1) plus loops in

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6858]
This commit is contained in:
parrt 2010-05-10 15:50:48 -08:00
parent 930b1e1236
commit e218632b67
9 changed files with 122 additions and 9 deletions

View File

@ -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))
>>

View File

@ -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);

View File

@ -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); }
}

View File

@ -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();
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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"); }};
}
}

View File

@ -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);
}
}

View File

@ -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"); }};
}
}