got sync in

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 9101]
This commit is contained in:
parrt 2011-10-02 20:31:26 -08:00
parent bf48ca5b73
commit 8508dd6da0
12 changed files with 107 additions and 96 deletions

View File

@ -52,7 +52,12 @@ public interface ANTLRErrorStrategy {
*/ */
void recover(BaseRecognizer recognizer); void recover(BaseRecognizer recognizer);
/** Implement Jim Idle's magic sync mechanism in closures and optional /** Make sure that the current lookahead symbol is consistent with
* what were expecting at this point in the ATN. You can call this
* anytime but ANTLR only generates code to check before loops
* and each iteration.
*
* Implements Jim Idle's magic sync mechanism in closures and optional
* subrules. E.g., * subrules. E.g.,
* *
* a : sync ( stuff sync )* ; * a : sync ( stuff sync )* ;
@ -80,5 +85,5 @@ public interface ANTLRErrorStrategy {
* when it matches a valid token (indicating no longer in recovery mode) * when it matches a valid token (indicating no longer in recovery mode)
* and from its own reset method. * and from its own reset method.
*/ */
void reset(); void endErrorCondition();
} }

View File

@ -58,7 +58,7 @@ public abstract class BaseRecognizer extends Recognizer<ParserATNSimulator> {
* matched a token. Prevents generation of more than one error message * matched a token. Prevents generation of more than one error message
* per error. * per error.
*/ */
protected boolean errorRecovery = false; // protected boolean errorRecovery = false;
/** Did the recognizer encounter a syntax error? Track how many. */ /** Did the recognizer encounter a syntax error? Track how many. */
protected int syntaxErrors = 0; protected int syntaxErrors = 0;
@ -70,8 +70,8 @@ public abstract class BaseRecognizer extends Recognizer<ParserATNSimulator> {
/** reset the parser's state */ /** reset the parser's state */
public void reset() { public void reset() {
if ( getInputStream()!=null ) getInputStream().seek(0); if ( getInputStream()!=null ) getInputStream().seek(0);
_errHandler.reset(); _errHandler.endErrorCondition();
errorRecovery = false; // errorRecovery = false;
_ctx = null; _ctx = null;
} }
@ -92,8 +92,8 @@ public abstract class BaseRecognizer extends Recognizer<ParserATNSimulator> {
Object matchedSymbol = getCurrentInputSymbol(); Object matchedSymbol = getCurrentInputSymbol();
if ( getInputStream().LA(1)==ttype ) { if ( getInputStream().LA(1)==ttype ) {
getInputStream().consume(); getInputStream().consume();
errorRecovery = false; // errorRecovery = false;
_errHandler.reset(); _errHandler.endErrorCondition();
if ( buildParseTrees ) _ctx.addChild((Token)matchedSymbol); if ( buildParseTrees ) _ctx.addChild((Token)matchedSymbol);
return matchedSymbol; return matchedSymbol;
} }
@ -102,8 +102,8 @@ public abstract class BaseRecognizer extends Recognizer<ParserATNSimulator> {
/** Match the wildcard: in a symbol */ /** Match the wildcard: in a symbol */
public void matchAny() { public void matchAny() {
errorRecovery = false; // errorRecovery = false;
_errHandler.reset(); _errHandler.endErrorCondition();
getInputStream().consume(); getInputStream().consume();
} }
@ -143,32 +143,6 @@ public abstract class BaseRecognizer extends Recognizer<ParserATNSimulator> {
return traceATNStates; return traceATNStates;
} }
/** Report a recognition problem.
*
* This method sets errorRecovery to indicate the parser is recovering
* not parsing. Once in recovery mode, no errors are generated.
* To get out of recovery mode, the parser must successfully match
* a token (after a resync). So it will go:
*
* 1. error occurs
* 2. enter recovery mode, report error
* 3. consume until token found in resynch set
* 4. try to resume parsing
* 5. next match() will reset errorRecovery mode
*/
public void reportError(RecognitionException e) {
// if we've already reported an error and have not matched a token
// yet successfully, don't report any errors.
if ( errorRecovery ) {
//System.err.print("[SPURIOUS] ");
return;
}
syntaxErrors++; // don't count spurious
errorRecovery = true;
notifyListeners(e.offendingToken, e.getMessage(), e);
}
/** Get number of recognition errors (lexer, parser, tree parser). Each /** Get number of recognition errors (lexer, parser, tree parser). Each
* recognizer tracks its own number. So parser and lexer each have * recognizer tracks its own number. So parser and lexer each have
* separate count. Does not count the spurious errors found between * separate count. Does not count the spurious errors found between

View File

@ -23,8 +23,12 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
protected IntervalSet lastErrorStates; protected IntervalSet lastErrorStates;
protected void beginErrorCondition() {
errorRecovery = true;
}
@Override @Override
public void reset() { public void endErrorCondition() {
errorRecovery = false; errorRecovery = false;
lastErrorStates = null; lastErrorStates = null;
lastErrorIndex = -1; lastErrorIndex = -1;
@ -35,6 +39,11 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
RecognitionException e) RecognitionException e)
throws RecognitionException throws RecognitionException
{ {
// if we've already reported an error and have not matched a token
// yet successfully, don't report any errors.
if ( errorRecovery ) return; // don't count spurious errors
recognizer.syntaxErrors++;
beginErrorCondition();
if ( e instanceof NoViableAltException ) { if ( e instanceof NoViableAltException ) {
reportNoViableAlternative(recognizer, (NoViableAltException) e); reportNoViableAlternative(recognizer, (NoViableAltException) e);
} }
@ -69,22 +78,36 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
lastErrorIndex = recognizer.getInputStream().index(); lastErrorIndex = recognizer.getInputStream().index();
if ( lastErrorStates==null ) lastErrorStates = new IntervalSet(); if ( lastErrorStates==null ) lastErrorStates = new IntervalSet();
lastErrorStates.add(recognizer._ctx.s); lastErrorStates.add(recognizer._ctx.s);
IntervalSet followSet = computeErrorRecoverySet(recognizer); IntervalSet followSet = getErrorRecoverySet(recognizer);
consumeUntil(recognizer, followSet); consumeUntil(recognizer, followSet);
} }
/** Make sure that the current lookahead symbol is consistent with
* what were expecting at this point in the ATN.
*/
@Override @Override
public void sync(BaseRecognizer recognizer) { public void sync(BaseRecognizer recognizer) {
System.out.println("sync");
// TODO: CACHE THESE RESULTS!!
IntervalSet expecting = getExpectedTokens(recognizer);
// TODO: subclass this class for treeparsers
TokenStream tokens = (TokenStream)recognizer.getInputStream();
Token la = tokens.LT(1);
if ( expecting.contains(la.getType()) ) {
endErrorCondition();
return;
}
recoverInline(recognizer);
} }
public void reportNoViableAlternative(BaseRecognizer recognizer, public void reportNoViableAlternative(BaseRecognizer recognizer,
NoViableAltException e) NoViableAltException e)
throws RecognitionException throws RecognitionException
{ {
if ( recognizer.errorRecovery ) return; // TODO: subclass this class for treeparsers
trackError(recognizer); TokenStream tokens = (TokenStream)recognizer.getInputStream();
String input = tokens.toString(e.startToken, e.offendingToken);
String msg = "no viable alternative at input "+getTokenErrorDisplay(e.offendingToken); String msg = "no viable alternative at input "+escapeWSAndQuote(input);
recognizer.notifyListeners(e.offendingToken, msg, e); recognizer.notifyListeners(e.offendingToken, msg, e);
} }
@ -92,9 +115,6 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
InputMismatchException e) InputMismatchException e)
throws RecognitionException throws RecognitionException
{ {
if ( recognizer.errorRecovery ) return;
trackError(recognizer);
String msg = "mismatched input "+getTokenErrorDisplay(e.offendingToken)+ String msg = "mismatched input "+getTokenErrorDisplay(e.offendingToken)+
" expecting "+e.getExpectedTokens().toString(recognizer.getTokenNames()); " expecting "+e.getExpectedTokens().toString(recognizer.getTokenNames());
recognizer.notifyListeners(e.offendingToken, msg, e); recognizer.notifyListeners(e.offendingToken, msg, e);
@ -104,9 +124,6 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
FailedPredicateException e) FailedPredicateException e)
throws RecognitionException throws RecognitionException
{ {
if ( recognizer.errorRecovery ) return;
trackError(recognizer);
String ruleName = recognizer.getRuleNames()[recognizer._ctx.getRuleIndex()]; String ruleName = recognizer.getRuleNames()[recognizer._ctx.getRuleIndex()];
String msg = "rule "+ruleName+" failed predicate: {"+ String msg = "rule "+ruleName+" failed predicate: {"+
e.predicateText+"}?"; e.predicateText+"}?";
@ -114,11 +131,11 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
} }
public void reportUnwantedToken(BaseRecognizer recognizer) { public void reportUnwantedToken(BaseRecognizer recognizer) {
if ( recognizer.errorRecovery ) return; if ( errorRecovery ) return;
trackError(recognizer); recognizer.syntaxErrors++;
beginErrorCondition();
Token t = (Token)recognizer.getCurrentInputSymbol(); Token t = (Token)recognizer.getCurrentInputSymbol();
String tokenName = getTokenErrorDisplay(t); String tokenName = getTokenErrorDisplay(t);
IntervalSet expecting = getExpectedTokens(recognizer); IntervalSet expecting = getExpectedTokens(recognizer);
String msg = "extraneous input "+tokenName+" expecting "+ String msg = "extraneous input "+tokenName+" expecting "+
@ -127,8 +144,9 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
} }
public void reportMissingToken(BaseRecognizer recognizer) { public void reportMissingToken(BaseRecognizer recognizer) {
if ( recognizer.errorRecovery ) return; if ( errorRecovery ) return;
trackError(recognizer); recognizer.syntaxErrors++;
beginErrorCondition();
Token t = (Token)recognizer.getCurrentInputSymbol(); Token t = (Token)recognizer.getCurrentInputSymbol();
IntervalSet expecting = getExpectedTokens(recognizer); IntervalSet expecting = getExpectedTokens(recognizer);
@ -268,6 +286,10 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
s = "<"+t.getType()+">"; s = "<"+t.getType()+">";
} }
} }
return escapeWSAndQuote(s);
}
protected String escapeWSAndQuote(String s) {
s = s.replaceAll("\n","\\\\n"); s = s.replaceAll("\n","\\\\n");
s = s.replaceAll("\r","\\\\r"); s = s.replaceAll("\r","\\\\r");
s = s.replaceAll("\t","\\\\t"); s = s.replaceAll("\t","\\\\t");
@ -366,7 +388,7 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
* Like Grosch I implement context-sensitive FOLLOW sets that are combined * Like Grosch I implement context-sensitive FOLLOW sets that are combined
* at run-time upon error to avoid overhead during parsing. * at run-time upon error to avoid overhead during parsing.
*/ */
protected IntervalSet computeErrorRecoverySet(BaseRecognizer recognizer) { protected IntervalSet getErrorRecoverySet(BaseRecognizer recognizer) {
ATN atn = recognizer._interp.atn; ATN atn = recognizer._interp.atn;
RuleContext ctx = recognizer._ctx; RuleContext ctx = recognizer._ctx;
IntervalSet recoverSet = new IntervalSet(); IntervalSet recoverSet = new IntervalSet();
@ -393,9 +415,9 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
} }
} }
protected void trackError(BaseRecognizer recognizer) { // protected void trackError(BaseRecognizer recognizer) {
recognizer.syntaxErrors++; // recognizer.syntaxErrors++;
recognizer.errorRecovery = true; // recognizer.errorRecovery = true;
} // }
} }

View File

@ -106,8 +106,7 @@ public class TreeParser extends BaseRecognizer {
* corresponding UP node. * corresponding UP node.
*/ */
public void matchAny(IntStream ignore) { // ignore stream, copy of input public void matchAny(IntStream ignore) { // ignore stream, copy of input
errorRecovery = false; _errHandler.endErrorCondition();
// failed = false;
Object look = _input.LT(1); Object look = _input.LT(1);
if ( _input.getTreeAdaptor().getChildCount(look)==0 ) { if ( _input.getTreeAdaptor().getChildCount(look)==0 ) {
_input.consume(); // not subtree, consume 1 node and return _input.consume(); // not subtree, consume 1 node and return

View File

@ -218,6 +218,7 @@ CodeBlockForAlt(c, locals, preamble, ops) ::= <<
>> >>
LL1AltBlock(choice, preamble, alts, error) ::= << LL1AltBlock(choice, preamble, alts, error) ::= <<
setState(<choice.stateNumber>);
<if(choice.label)><labelref(choice.label)> = _input.LT(1);<endif> <if(choice.label)><labelref(choice.label)> = _input.LT(1);<endif>
<preamble; separator="\n"> <preamble; separator="\n">
switch ( _input.LA(1) ) { switch ( _input.LA(1) ) {
@ -230,6 +231,7 @@ switch ( _input.LA(1) ) {
>> >>
LL1OptionalBlock(choice, alts, error) ::= << LL1OptionalBlock(choice, alts, error) ::= <<
setState(<choice.stateNumber>);
switch ( _input.LA(1) ) { switch ( _input.LA(1) ) {
<choice.altLook,alts:{look,alt| <cases(ttypes=look)> <choice.altLook,alts:{look,alt| <cases(ttypes=look)>
<alt> <alt>
@ -240,6 +242,7 @@ switch ( _input.LA(1) ) {
>> >>
LL1OptionalBlockSingleAlt(choice, expr, alts, preamble, error, followExpr) ::= << LL1OptionalBlockSingleAlt(choice, expr, alts, preamble, error, followExpr) ::= <<
setState(<choice.stateNumber>);
<preamble; separator="\n"> <preamble; separator="\n">
if ( <expr> ) { if ( <expr> ) {
<alts; separator="\n"> <alts; separator="\n">
@ -247,7 +250,9 @@ if ( <expr> ) {
<!else if ( !(<followExpr>) ) <error>!> <!else if ( !(<followExpr>) ) <error>!>
>> >>
LL1StarBlock(choice, alts, sync) ::= << LL1StarBlock(choice, alts) ::= <<
setState(<choice.stateNumber>);
_errHandler.sync(this);
<choice.loopLabel>: <choice.loopLabel>:
while (true) { while (true) {
switch ( _input.LA(1) ) { switch ( _input.LA(1) ) {
@ -257,21 +262,26 @@ while (true) {
<cases(choice.exitLook)> <cases(choice.exitLook)>
break <choice.loopLabel>; break <choice.loopLabel>;
} }
//<sync> setState(<choice.stateNumber>);
_errHandler.sync(this);
} }
>> >>
LL1StarBlockSingleAlt(choice, loopExpr, alts, preamble, iteration, sync) ::= << LL1StarBlockSingleAlt(choice, loopExpr, alts, preamble, iteration) ::= <<
setState(<choice.stateNumber>);
_errHandler.sync(this);
<preamble; separator="\n"> <preamble; separator="\n">
while ( <loopExpr> ) { while ( <loopExpr> ) {
<alts; separator="\n"> <alts; separator="\n">
setState(<choice.stateNumber>);
_errHandler.sync(this);
<iteration> <iteration>
//<sync>
} }
>> >>
LL1PlusBlock(choice, alts, iteration, loopExpr, sync, error, iterationSync) ::= << LL1PlusBlock(choice, alts, iteration, loopExpr, error) ::= <<
//<sync> setState(<choice.stateNumber>);
_errHandler.sync(this);
do { do {
switch ( _input.LA(1) ) { switch ( _input.LA(1) ) {
<choice.altLook,alts:{look,alt| <cases(look)> <choice.altLook,alts:{look,alt| <cases(look)>
@ -280,26 +290,28 @@ do {
default : default :
<error> <error>
} }
setState(<choice.stateNumber>);
_errHandler.sync(this);
<iteration> <iteration>
//<iterationSync>
} while ( <loopExpr> ); } while ( <loopExpr> );
>> >>
LL1PlusBlockSingleAlt(choice, loopExpr, alts, preamble, iteration, LL1PlusBlockSingleAlt(choice, loopExpr, alts, preamble, iteration) ::= <<
sync, iterationSync) ::= setState(<choice.stateNumber>);
<< _errHandler.sync(this);
//<sync>
<preamble; separator="\n"> <preamble; separator="\n">
do { do {
<alts; separator="\n"> <alts; separator="\n">
setState(<choice.stateNumber>);
_errHandler.sync(this);
<iteration> <iteration>
// <iterationSync>
} while ( <loopExpr> ); } while ( <loopExpr> );
>> >>
// LL(*) stuff // LL(*) stuff
AltBlock(choice, preamble, alts, error) ::= << AltBlock(choice, preamble, alts, error) ::= <<
setState(<choice.stateNumber>);
<if(choice.label)><labelref(choice.label)> = _input.LT(1);<endif> <if(choice.label)><labelref(choice.label)> = _input.LT(1);<endif>
<preamble; separator="\n"> <preamble; separator="\n">
switch ( _interp.adaptivePredict(_input,<choice.decision>,_ctx) ) { switch ( _interp.adaptivePredict(_input,<choice.decision>,_ctx) ) {
@ -311,6 +323,7 @@ case <i>:
>> >>
OptionalBlock(choice, alts, error) ::= << OptionalBlock(choice, alts, error) ::= <<
setState(<choice.stateNumber>);
switch ( _interp.adaptivePredict(_input,<choice.decision>,_ctx) ) { switch ( _interp.adaptivePredict(_input,<choice.decision>,_ctx) ) {
<alts:{alt | <alts:{alt |
case <i>: case <i>:
@ -322,6 +335,8 @@ case <i>:
// TODO: we we need uniqueID? a single _alt might work // TODO: we we need uniqueID? a single _alt might work
StarBlock(choice, alts, sync) ::= << StarBlock(choice, alts, sync) ::= <<
setState(<choice.stateNumber>);
_errHandler.sync(this);
int _alt<choice.uniqueID> = _interp.adaptivePredict(_input,<choice.decision>,_ctx); int _alt<choice.uniqueID> = _interp.adaptivePredict(_input,<choice.decision>,_ctx);
while ( _alt<choice.uniqueID>!=<choice.exitAlt> && _alt<choice.uniqueID>!=-1 ) { while ( _alt<choice.uniqueID>!=<choice.exitAlt> && _alt<choice.uniqueID>!=-1 ) {
switch ( _alt<choice.uniqueID> ) { switch ( _alt<choice.uniqueID> ) {
@ -330,11 +345,15 @@ case <i>:
<alt> <alt>
break;}; separator="\n"> break;}; separator="\n">
} }
setState(<choice.stateNumber>);
_errHandler.sync(this);
_alt<choice.uniqueID> = _interp.adaptivePredict(_input,<choice.decision>,_ctx); _alt<choice.uniqueID> = _interp.adaptivePredict(_input,<choice.decision>,_ctx);
} }
>> >>
PlusBlock(choice, alts, error) ::= << PlusBlock(choice, alts, error) ::= <<
setState(<choice.stateNumber>);
_errHandler.sync(this);
int _alt<choice.uniqueID> = _interp.adaptivePredict(_input,<choice.decision>,_ctx); int _alt<choice.uniqueID> = _interp.adaptivePredict(_input,<choice.decision>,_ctx);
do { do {
switch ( _alt<choice.uniqueID> ) { switch ( _alt<choice.uniqueID> ) {
@ -345,6 +364,8 @@ case <i>:
default : default :
<error> <error>
} }
setState(<choice.stateNumber>);
_errHandler.sync(this);
_alt<choice.uniqueID> = _interp.adaptivePredict(_input,<choice.decision>,_ctx); _alt<choice.uniqueID> = _interp.adaptivePredict(_input,<choice.decision>,_ctx);
} while ( _alt<choice.uniqueID>!=<choice.exitAlt> && _alt<choice.uniqueID>!=-1 ); } while ( _alt<choice.uniqueID>!=<choice.exitAlt> && _alt<choice.uniqueID>!=-1 );
>> >>

View File

@ -39,7 +39,6 @@ import java.util.*;
public abstract class LL1Loop extends Choice { public abstract class LL1Loop extends Choice {
@ModelElement public OutputModelObject loopExpr; @ModelElement public OutputModelObject loopExpr;
@ModelElement public List<SrcOp> iteration; @ModelElement public List<SrcOp> iteration;
@ModelElement public Sync sync;
public LL1Loop(OutputModelFactory factory, public LL1Loop(OutputModelFactory factory,
GrammarAST blkAST, GrammarAST blkAST,

View File

@ -41,7 +41,6 @@ public class LL1PlusBlock extends LL1Loop {
/** Token names for each alt 0..n-1 */ /** Token names for each alt 0..n-1 */
public List<String[]> altLook; public List<String[]> altLook;
@ModelElement public Sync iterationSync;
public String loopLabel; public String loopLabel;
public String loopCounterVar; public String loopCounterVar;
public String[] exitLook; public String[] exitLook;
@ -73,10 +72,5 @@ public class LL1PlusBlock extends LL1Loop {
IntervalSet exitLookSet = altLookSets[altLookSets.length-1]; IntervalSet exitLookSet = altLookSets[altLookSets.length-1];
this.exitLook = gen.target.getTokenTypesAsTargetLabels(g, this.exitLook = gen.target.getTokenTypesAsTargetLabels(g,
exitLookSet.toArray()); exitLookSet.toArray());
//IntervalSet iterationExpected = (IntervalSet)loopBackLook.or(exitLookSet);
// this.sync = new Sync(factory, plusRoot, loopBackLook, decision, "enter");
// this.iterationSync = new Sync(factory, plusRoot, iterationExpected, decision, "iter");
// this.earlyExitError = new ThrowEarlyExitException(factory, plusRoot, null);
} }
} }

View File

@ -38,21 +38,14 @@ import java.util.List;
/** */ /** */
public class LL1PlusBlockSingleAlt extends LL1Loop { public class LL1PlusBlockSingleAlt extends LL1Loop {
@ModelElement public Sync iterationSync;
public LL1PlusBlockSingleAlt(OutputModelFactory factory, GrammarAST blkAST, List<CodeBlockForAlt> alts) { public LL1PlusBlockSingleAlt(OutputModelFactory factory, GrammarAST blkAST, List<CodeBlockForAlt> alts) {
super(factory, blkAST, alts); super(factory, blkAST, alts);
PlusBlockStartState plus = (PlusBlockStartState)blkAST.atnState; PlusBlockStartState plus = (PlusBlockStartState)blkAST.atnState;
this.decision = plus.loopBackState.decision; this.decision = plus.loopBackState.decision;
IntervalSet[] altLookSets = factory.getGrammar().decisionLOOK.get(decision); IntervalSet[] altLookSets = factory.getGrammar().decisionLOOK.get(decision);
IntervalSet exitLook = altLookSets[altLookSets.length-1];
IntervalSet loopBackLook = altLookSets[1]; IntervalSet loopBackLook = altLookSets[1];
loopExpr = addCodeForLoopLookaheadTempVar(loopBackLook); loopExpr = addCodeForLoopLookaheadTempVar(loopBackLook);
this.sync = new Sync(factory, blkAST, loopBackLook, decision, "enter");
IntervalSet iterationExpected = (IntervalSet) loopBackLook.or(exitLook);
iterationSync = new Sync(factory, blkAST, iterationExpected, decision, "iter");
} }
} }

View File

@ -46,7 +46,6 @@ public class LL1StarBlock extends LL1Loop {
public LL1StarBlock(OutputModelFactory factory, GrammarAST blkAST, List<CodeBlockForAlt> alts) { public LL1StarBlock(OutputModelFactory factory, GrammarAST blkAST, List<CodeBlockForAlt> alts) {
super(factory, blkAST, alts); super(factory, blkAST, alts);
// StarBlockStartState blkStart = (StarBlockStartState)blkAST.atnState;
StarLoopEntryState star = (StarLoopEntryState)blkAST.atnState; StarLoopEntryState star = (StarLoopEntryState)blkAST.atnState;
this.decision = star.decision; this.decision = star.decision;
@ -61,7 +60,5 @@ public class LL1StarBlock extends LL1Loop {
this.exitLook = this.exitLook =
factory.getGenerator().target.getTokenTypesAsTargetLabels(factory.getGrammar(), lastLook.toArray()); factory.getGenerator().target.getTokenTypesAsTargetLabels(factory.getGrammar(), lastLook.toArray());
// this.sync = new Sync(factory, blkAST, expecting, decision, "iter");
} }
} }

View File

@ -48,8 +48,5 @@ public class LL1StarBlockSingleAlt extends LL1Loop {
IntervalSet enterLook = altLookSets[1]; IntervalSet enterLook = altLookSets[1];
IntervalSet exitLook = altLookSets[2]; IntervalSet exitLook = altLookSets[2];
loopExpr = addCodeForLoopLookaheadTempVar(enterLook); loopExpr = addCodeForLoopLookaheadTempVar(enterLook);
IntervalSet enterExpecting = (IntervalSet)exitLook.or(enterLook);
this.sync = new Sync(factory, starRoot, enterExpecting, decision, "iter");
} }
} }

View File

@ -44,7 +44,6 @@ public class StarBlock extends Loop {
{ {
super(factory, blkOrEbnfRootAST, alts); super(factory, blkOrEbnfRootAST, alts);
loopLabel = factory.getGenerator().target.getLoopLabel(blkOrEbnfRootAST); loopLabel = factory.getGenerator().target.getLoopLabel(blkOrEbnfRootAST);
// BlockStartState star = (BlockStartState)blkOrEbnfRootAST.atnState;
StarLoopEntryState star = (StarLoopEntryState)blkOrEbnfRootAST.atnState; StarLoopEntryState star = (StarLoopEntryState)blkOrEbnfRootAST.atnState;
decision = star.decision; decision = star.decision;
exitAlt = alts.size()+1; exitAlt = alts.size()+1;

View File

@ -108,7 +108,7 @@ public class TestParseErrors extends BaseTest {
";\n" + ";\n" +
"q : 'e' ;\n"; "q : 'e' ;\n";
String found = execParser("T.g", grammar, "TParser", "TLexer", "a", "ae", false); String found = execParser("T.g", grammar, "TParser", "TLexer", "a", "ae", false);
String expecting = "line 1:1 no viable alternative at input 'e'\n"; String expecting = "line 1:1 no viable alternative at input 'ae'\n";
String result = stderrDuringParse; String result = stderrDuringParse;
assertEquals(expecting, result); assertEquals(expecting, result);
} }
@ -122,7 +122,7 @@ public class TestParseErrors extends BaseTest {
"q : 'e' ;\n"; "q : 'e' ;\n";
System.out.println(grammar); System.out.println(grammar);
String found = execParser("T.g", grammar, "TParser", "TLexer", "a", "abe", false); String found = execParser("T.g", grammar, "TParser", "TLexer", "a", "abe", false);
String expecting = "line 1:2 no viable alternative at input 'e'\n"; String expecting = "line 1:2 no viable alternative at input 'abe'\n";
String result = stderrDuringParse; String result = stderrDuringParse;
assertEquals(expecting, result); assertEquals(expecting, result);
} }
@ -135,11 +135,22 @@ public class TestParseErrors extends BaseTest {
";\n" + ";\n" +
"q : 'e' ;\n"; "q : 'e' ;\n";
String found = execParser("T.g", grammar, "TParser", "TLexer", "a", "aaae", false); String found = execParser("T.g", grammar, "TParser", "TLexer", "a", "aaae", false);
String expecting = "line 1:3 no viable alternative at input 'e'\n"; String expecting = "line 1:3 no viable alternative at input 'aaae'\n";
String result = stderrDuringParse; String result = stderrDuringParse;
assertEquals(expecting, result); assertEquals(expecting, result);
} }
@Test public void testSingleTokenDeletionBeforeLoop() throws Exception {
String grammar =
"grammar T;\n" +
"a : 'a' 'b'*;";
String found = execParser("T.g", grammar, "TParser", "TLexer", "a", "aabc", false);
String expecting = "line 1:1 extraneous input 'a' expecting {<EOF>, 'b'}\n";
String result = stderrDuringParse;
assertEquals(expecting, result);
}
@Test public void testLL1ErrorInfo() throws Exception { @Test public void testLL1ErrorInfo() throws Exception {
String grammar = String grammar =
"grammar T;\n" + "grammar T;\n" +