forked from jasder/antlr
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>
|
<preamble>
|
||||||
while ( <expr> ) {
|
while ( <expr> ) {
|
||||||
<alts; separator="\n">
|
<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) ::= <<
|
TestSet(s) ::= <<
|
||||||
<s.set.name>.member(input.LA(1))
|
<s.set.name>.member(input.LA(1))
|
||||||
>>
|
>>
|
||||||
|
|
|
@ -298,6 +298,8 @@ public class ParserNFAFactory implements NFAFactory {
|
||||||
PlusBlockStartState start = (PlusBlockStartState)newState(PlusBlockStartState.class, plusAST);
|
PlusBlockStartState start = (PlusBlockStartState)newState(PlusBlockStartState.class, plusAST);
|
||||||
LoopbackState loop = (LoopbackState)newState(LoopbackState.class, plusAST);
|
LoopbackState loop = (LoopbackState)newState(LoopbackState.class, plusAST);
|
||||||
BlockEndState end = (BlockEndState)newState(BlockEndState.class, plusAST);
|
BlockEndState end = (BlockEndState)newState(BlockEndState.class, plusAST);
|
||||||
|
start.endState = end; // points past loopback state
|
||||||
|
start.loopBackState = loop;
|
||||||
epsilon(start, blk.left);
|
epsilon(start, blk.left);
|
||||||
epsilon(loop, blk.left);
|
epsilon(loop, blk.left);
|
||||||
epsilon(blk.right, loop);
|
epsilon(blk.right, loop);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.antlr.v4.automata;
|
package org.antlr.v4.automata;
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
public class PlusBlockStartState extends BasicState {
|
public class PlusBlockStartState extends BlockStartState {
|
||||||
|
public LoopbackState loopBackState;
|
||||||
public PlusBlockStartState(NFA nfa) { super(nfa); }
|
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.automata.DFA;
|
||||||
import org.antlr.v4.codegen.src.*;
|
import org.antlr.v4.codegen.src.*;
|
||||||
import org.antlr.v4.misc.IntSet;
|
import org.antlr.v4.misc.IntSet;
|
||||||
|
import org.antlr.v4.misc.IntervalSet;
|
||||||
import org.antlr.v4.parse.ANTLRParser;
|
import org.antlr.v4.parse.ANTLRParser;
|
||||||
import org.antlr.v4.tool.BlockAST;
|
import org.antlr.v4.tool.BlockAST;
|
||||||
import org.antlr.v4.tool.ErrorType;
|
import org.antlr.v4.tool.ErrorType;
|
||||||
|
@ -121,6 +122,8 @@ public abstract class CodeGenerator {
|
||||||
else c = new LL1StarBlock(this, ebnfRoot, alts);
|
else c = new LL1StarBlock(this, ebnfRoot, alts);
|
||||||
break;
|
break;
|
||||||
case ANTLRParser.POSITIVE_CLOSURE :
|
case ANTLRParser.POSITIVE_CLOSURE :
|
||||||
|
if ( alts.size()==1 ) c = new LL1PlusBlockSingleAlt(this, ebnfRoot, alts);
|
||||||
|
else c = new LL1PlusBlock(this, ebnfRoot, alts);
|
||||||
break;
|
break;
|
||||||
default :
|
default :
|
||||||
c = new LL1Choice(this, blkAST, alts);
|
c = new LL1Choice(this, blkAST, alts);
|
||||||
|
@ -129,6 +132,17 @@ public abstract class CodeGenerator {
|
||||||
return c;
|
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 {
|
public void write(ST code, String fileName) throws IOException {
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
Writer w = g.tool.getOutputFile(g, fileName);
|
Writer w = g.tool.getOutputFile(g, fileName);
|
||||||
|
@ -185,4 +199,12 @@ public abstract class CodeGenerator {
|
||||||
outputModel.bitSetDefs.add(b);
|
outputModel.bitSetDefs.add(b);
|
||||||
return 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) {
|
public LL1OptionalBlockSingleAlt(CodeGenerator gen, GrammarAST blkAST, List<CodeBlock> alts) {
|
||||||
super(gen, blkAST, alts);
|
super(gen, blkAST, alts);
|
||||||
IntervalSet look = altLookSets[1];
|
IntervalSet look = altLookSets[1];
|
||||||
if ( look.size() < gen.target.getInlineTestsVsBitsetThreshold() ) {
|
expr = gen.getLL1Test(this, look, blkAST);
|
||||||
expr = new TestSetInline(gen, this, blkAST, look);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
expr = new TestSet(gen, blkAST, look);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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;
|
IntervalSet exitLook = dfa.startState.edge(1).label;
|
||||||
this.exitLook = gen.target.getTokenTypesAsTargetLabels(gen.g, exitLook.toArray());
|
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;
|
package org.antlr.v4.codegen.src;
|
||||||
|
|
||||||
import org.antlr.v4.codegen.CodeGenerator;
|
import org.antlr.v4.codegen.CodeGenerator;
|
||||||
|
import org.antlr.v4.misc.IntervalSet;
|
||||||
import org.antlr.v4.tool.GrammarAST;
|
import org.antlr.v4.tool.GrammarAST;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
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) {
|
public LL1StarBlockSingleAlt(CodeGenerator gen, GrammarAST blkAST, List<CodeBlock> alts) {
|
||||||
super(gen, blkAST, 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