bug fixes in error handling part deux
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 9112]
This commit is contained in:
parent
251a42ddbb
commit
547d58514d
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;} ;
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
Loading…
Reference in New Issue