bug fixes in error handling part deux

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 9112]
This commit is contained in:
parrt 2011-10-06 13:28:36 -08:00
parent 251a42ddbb
commit 547d58514d
9 changed files with 80 additions and 23 deletions

View File

@ -277,6 +277,7 @@ public abstract class BaseRecognizer extends Recognizer<ParserATNSimulator> {
* configuration information.
*/
public void setState(int atnState) {
// System.err.println("setState "+atnState);
_ctx.s = atnState;
if ( traceATNStates ) _ctx.trace(atnState);
}

View File

@ -74,6 +74,11 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
*/
@Override
public void recover(BaseRecognizer recognizer) {
// System.out.println("recover in "+recognizer.getRuleInvocationStack()+
// " index="+recognizer.getInputStream().index()+
// ", lastErrorIndex="+
// lastErrorIndex+
// ", states="+lastErrorStates);
if ( lastErrorIndex==recognizer.getInputStream().index() &&
lastErrorStates.contains(recognizer._ctx.s) )
{
@ -81,7 +86,8 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
// state in ATN; must be a case where LT(1) is in the recovery
// token set so nothing got consumed. Consume a single token
// at least to prevent an infinite loop; this is a failsafe.
// recognizer.getInputStream().consume();
// System.err.println("seen error condition before index="+
// lastErrorIndex+", states="+lastErrorStates);
recognizer.consume();
}
lastErrorIndex = recognizer.getInputStream().index();
@ -96,6 +102,8 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
*/
@Override
public void sync(BaseRecognizer recognizer) {
// If already recovering, don't try to sync
if ( errorRecoveryMode ) return;
// TODO: CACHE THESE RESULTS!!
IntervalSet expecting = getExpectedTokens(recognizer);
// TODO: subclass this class for treeparsers

View File

@ -95,10 +95,14 @@ public class ParserATNSimulator extends ATNSimulator {
//dump(dfa);
// start with the DFA
int m = input.mark();
try {
int alt = execDFA(input, dfa, dfa.s0, outerContext);
input.seek(m);
return alt;
}
finally {
input.seek(m);
}
}
}
public int predictATN(DFA dfa, TokenStream input,
@ -155,7 +159,7 @@ public class ParserATNSimulator extends ATNSimulator {
DFAState prevAcceptState = null;
DFAState s = s0;
int t = input.LA(1);
int start = input.index();
int startIndex = input.index();
loop:
while ( true ) {
if ( dfa_debug ) System.out.println("DFA state "+s.stateNumber+" LA(1)=="+t);
@ -167,9 +171,9 @@ public class ParserATNSimulator extends ATNSimulator {
if ( predI!=null ) return predI;
// System.out.println("start all over with ATN; can't use DFA");
// start all over with ATN; can't use DFA
input.seek(start);
input.seek(startIndex);
DFA throwAwayDFA = new DFA(dfa.atnStartState);
int alt = execATN(input, throwAwayDFA, start, s0.configs, false);
int alt = execATN(input, throwAwayDFA, startIndex, s0.configs, false);
s.ctxToPrediction.put(outerContext, alt);
return alt;
}
@ -187,11 +191,11 @@ public class ParserATNSimulator extends ATNSimulator {
if ( dfa_debug ) {
System.out.println("ATN exec upon "+
getInputString(input, start) +
getInputString(input, startIndex) +
" at DFA state "+s.stateNumber);
}
try {
alt = execATN(input, dfa, start, s.configs, false);
alt = execATN(input, dfa, startIndex, s.configs, false);
// this adds edge even if next state is accept for
// same alt; e.g., s0-A->:s1=>2-B->:s2=>2
// TODO: This next stuff kills edge, but extra states remain. :(
@ -217,7 +221,14 @@ public class ParserATNSimulator extends ATNSimulator {
}
}
DFAState target = s.edges[t+1];
if ( target == ERROR ) break;
if ( target == ERROR ) {
NoViableAltException nvae =
new NoViableAltException(parser, input,
input.get(startIndex),
input.LT(1),
s.configs, outerContext);
throw nvae;
}
s = target;
input.consume();
t = input.LA(1);
@ -366,7 +377,7 @@ public class ParserATNSimulator extends ATNSimulator {
} while ( true );
if ( prevAccept==null ) {
System.out.println("no viable token at input "+ getLookaheadName(input) +", index "+input.index());
// System.out.println("no viable token at input "+ getLookaheadName(input) +", index "+input.index());
NoViableAltException nvae =
new NoViableAltException(parser, input,
input.get(startIndex),

26
tool/playground/AA.g Normal file
View File

@ -0,0 +1,26 @@
grammar AA;
prog: classDef+ ;
classDef
: 'class' ID '{' member+ '}'
;
member
: 'int' ID ';' {System.out.println("var "+$ID.text);}
| 'int' ID '(' ')' '{' stat '}' {System.out.println("func "+$ID.text);}
;
stat: expr ';'
{System.out.println("found expr: "+$stat.text);}
| ID '=' expr ';'
{System.out.println("found assign: "+$stat.text);}
;
expr: INT
| ID '(' ')'
;
ID : ('a'..'z'|'A'..'Z')+ ;
INT : '0'..'9'+ ;
WS : (' '|'\t'|'\n'|'\r')+ {$channel=HIDDEN;} ;

View File

@ -280,7 +280,7 @@ while ( <loopExpr> ) {
>>
LL1PlusBlock(choice, alts, iteration, loopExpr, error) ::= <<
setState(<choice.stateNumber>);
setState(<choice.blockStartStateNumber>); <! alt block decision !>
_errHandler.sync(this);
do {
switch ( _input.LA(1) ) {
@ -297,12 +297,12 @@ do {
>>
LL1PlusBlockSingleAlt(choice, loopExpr, alts, preamble, iteration) ::= <<
setState(<choice.stateNumber>);
setState(<choice.blockStartStateNumber>); <! alt block decision !>
_errHandler.sync(this);
<preamble; separator="\n">
do {
<alts; separator="\n">
setState(<choice.stateNumber>);
setState(<choice.stateNumber>); <! loopback/exit decision !>
_errHandler.sync(this);
<iteration>
} while ( <loopExpr> );
@ -352,7 +352,7 @@ case <i>:
>>
PlusBlock(choice, alts, error) ::= <<
setState(<choice.stateNumber>);
setState(<choice.blockStartStateNumber>); <! alt block decision !>
_errHandler.sync(this);
int _alt<choice.uniqueID> = _interp.adaptivePredict(_input,<choice.decision>,_ctx);
do {
@ -364,7 +364,7 @@ case <i>:
default :
<error>
}
setState(<choice.stateNumber>);
setState(<choice.stateNumber>); <! loopback/exit decision !>
_errHandler.sync(this);
_alt<choice.uniqueID> = _interp.adaptivePredict(_input,<choice.decision>,_ctx);
} while ( _alt<choice.uniqueID>!=<choice.exitAlt> && _alt<choice.uniqueID>!=-1 );

View File

@ -33,10 +33,16 @@ import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.tool.GrammarAST;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
/** */
public abstract class LL1Loop extends Choice {
/** The state associated wih the (A|B|...) block not loopback, which
* is super.stateNumber
*/
public int blockStartStateNumber;
@ModelElement public OutputModelObject loopExpr;
@ModelElement public List<SrcOp> iteration;

View File

@ -56,6 +56,7 @@ public class LL1PlusBlock extends LL1Loop {
PlusBlockStartState blkStart = (PlusBlockStartState)plusRoot.atnState;
stateNumber = blkStart.loopBackState.stateNumber;
blockStartStateNumber = blkStart.stateNumber;
this.decision = blkStart.decision;
Grammar g = factory.getGrammar();

View File

@ -43,6 +43,7 @@ public class LL1PlusBlockSingleAlt extends LL1Loop {
PlusBlockStartState blkStart = (PlusBlockStartState)blkAST.atnState;
stateNumber = blkStart.loopBackState.stateNumber;
blockStartStateNumber = blkStart.stateNumber;
PlusBlockStartState plus = (PlusBlockStartState)blkAST.atnState;
this.decision = plus.loopBackState.decision;
IntervalSet[] altLookSets = factory.getGrammar().decisionLOOK.get(decision);

View File

@ -43,10 +43,13 @@ public class LL1StarBlock extends LL1Loop {
public String loopLabel;
public String[] exitLook;
public LL1StarBlock(OutputModelFactory factory, GrammarAST blkAST, List<CodeBlockForAlt> alts) {
super(factory, blkAST, alts);
public LL1StarBlock(OutputModelFactory factory, GrammarAST starRootAST, List<CodeBlockForAlt> alts) {
super(factory, starRootAST, alts);
StarLoopEntryState star = (StarLoopEntryState)starRootAST.atnState;
blockStartStateNumber =
starRootAST.atnState.transition(0).target.stateNumber;
StarLoopEntryState star = (StarLoopEntryState)blkAST.atnState;
this.decision = star.decision;
/** Lookahead for each alt 1..n */
@ -56,7 +59,7 @@ public class LL1StarBlock extends LL1Loop {
System.arraycopy(altLookSets, 0, copy, 0, altLookSets.length-1); // remove last (exit) alt
altLookSets = copy;
altLook = getAltLookaheadAsStringLists(altLookSets);
loopLabel = factory.getGenerator().target.getLoopLabel(blkAST);
loopLabel = factory.getGenerator().target.getLoopLabel(starRootAST);
this.exitLook =
factory.getGenerator().target.getTokenTypesAsTargetLabels(factory.getGrammar(), lastLook.toArray());