00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 package org.antlr.runtime;
00029
00030 import java.util.ArrayList;
00031 import java.util.HashMap;
00032 import java.util.List;
00033 import java.util.Map;
00034
00040 public abstract class BaseRecognizer {
00041 public static final int MEMO_RULE_FAILED = -2;
00042 public static final int MEMO_RULE_UNKNOWN = -1;
00043 public static final int INITIAL_FOLLOW_STACK_SIZE = 100;
00044
00045
00046 public static final int DEFAULT_TOKEN_CHANNEL = Token.DEFAULT_CHANNEL;
00047 public static final int HIDDEN = Token.HIDDEN_CHANNEL;
00048
00049 public static final String NEXT_TOKEN_RULE_NAME = "nextToken";
00050
00057 protected RecognizerSharedState state;
00058
00059 public BaseRecognizer() {
00060 state = new RecognizerSharedState();
00061 }
00062
00063 public BaseRecognizer(RecognizerSharedState state) {
00064 if ( state==null ) {
00065 state = new RecognizerSharedState();
00066 }
00067 this.state = state;
00068 }
00069
00071 public void reset() {
00072
00073 if ( state==null ) {
00074 return;
00075 }
00076 state._fsp = -1;
00077 state.errorRecovery = false;
00078 state.lastErrorIndex = -1;
00079 state.failed = false;
00080 state.syntaxErrors = 0;
00081
00082 state.backtracking = 0;
00083 for (int i = 0; state.ruleMemo!=null && i < state.ruleMemo.length; i++) {
00084 state.ruleMemo[i] = null;
00085 }
00086 }
00087
00088
00100 public Object match(IntStream input, int ttype, BitSet follow)
00101 throws RecognitionException
00102 {
00103
00104 Object matchedSymbol = getCurrentInputSymbol(input);
00105 if ( input.LA(1)==ttype ) {
00106 input.consume();
00107 state.errorRecovery = false;
00108 state.failed = false;
00109 return matchedSymbol;
00110 }
00111 if ( state.backtracking>0 ) {
00112 state.failed = true;
00113 return matchedSymbol;
00114 }
00115 matchedSymbol = recoverFromMismatchedToken(input, ttype, follow);
00116 return matchedSymbol;
00117 }
00118
00120 public void matchAny(IntStream input) {
00121 state.errorRecovery = false;
00122 state.failed = false;
00123 input.consume();
00124 }
00125
00126 public boolean mismatchIsUnwantedToken(IntStream input, int ttype) {
00127 return input.LA(2)==ttype;
00128 }
00129
00130 public boolean mismatchIsMissingToken(IntStream input, BitSet follow) {
00131 if ( follow==null ) {
00132
00133
00134 return false;
00135 }
00136
00137 if ( follow.member(Token.EOR_TOKEN_TYPE) ) {
00138 BitSet viableTokensFollowingThisRule = computeContextSensitiveRuleFOLLOW();
00139 follow = follow.or(viableTokensFollowingThisRule);
00140 if ( state._fsp>=0 ) {
00141 follow.remove(Token.EOR_TOKEN_TYPE);
00142 }
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 if ( follow.member(input.LA(1)) || follow.member(Token.EOR_TOKEN_TYPE) ) {
00155
00156 return true;
00157 }
00158 return false;
00159 }
00160
00176 public void reportError(RecognitionException e) {
00177
00178
00179 if ( state.errorRecovery ) {
00180
00181 return;
00182 }
00183 state.syntaxErrors++;
00184 state.errorRecovery = true;
00185
00186 displayRecognitionError(this.getTokenNames(), e);
00187 }
00188
00189 public void displayRecognitionError(String[] tokenNames,
00190 RecognitionException e)
00191 {
00192 String hdr = getErrorHeader(e);
00193 String msg = getErrorMessage(e, tokenNames);
00194 emitErrorMessage(hdr+" "+msg);
00195 }
00196
00219 public String getErrorMessage(RecognitionException e, String[] tokenNames) {
00220 String msg = e.getMessage();
00221 if ( e instanceof UnwantedTokenException ) {
00222 UnwantedTokenException ute = (UnwantedTokenException)e;
00223 String tokenName="<unknown>";
00224 if ( ute.expecting== Token.EOF ) {
00225 tokenName = "EOF";
00226 }
00227 else {
00228 tokenName = tokenNames[ute.expecting];
00229 }
00230 msg = "extraneous input "+getTokenErrorDisplay(ute.getUnexpectedToken())+
00231 " expecting "+tokenName;
00232 }
00233 else if ( e instanceof MissingTokenException ) {
00234 MissingTokenException mte = (MissingTokenException)e;
00235 String tokenName="<unknown>";
00236 if ( mte.expecting== Token.EOF ) {
00237 tokenName = "EOF";
00238 }
00239 else {
00240 tokenName = tokenNames[mte.expecting];
00241 }
00242 msg = "missing "+tokenName+" at "+getTokenErrorDisplay(e.token);
00243 }
00244 else if ( e instanceof MismatchedTokenException ) {
00245 MismatchedTokenException mte = (MismatchedTokenException)e;
00246 String tokenName="<unknown>";
00247 if ( mte.expecting== Token.EOF ) {
00248 tokenName = "EOF";
00249 }
00250 else {
00251 tokenName = tokenNames[mte.expecting];
00252 }
00253 msg = "mismatched input "+getTokenErrorDisplay(e.token)+
00254 " expecting "+tokenName;
00255 }
00256 else if ( e instanceof MismatchedTreeNodeException ) {
00257 MismatchedTreeNodeException mtne = (MismatchedTreeNodeException)e;
00258 String tokenName="<unknown>";
00259 if ( mtne.expecting==Token.EOF ) {
00260 tokenName = "EOF";
00261 }
00262 else {
00263 tokenName = tokenNames[mtne.expecting];
00264 }
00265 msg = "mismatched tree node: "+mtne.node+
00266 " expecting "+tokenName;
00267 }
00268 else if ( e instanceof NoViableAltException ) {
00269
00270
00271
00272
00273 msg = "no viable alternative at input "+getTokenErrorDisplay(e.token);
00274 }
00275 else if ( e instanceof EarlyExitException ) {
00276
00277
00278 msg = "required (...)+ loop did not match anything at input "+
00279 getTokenErrorDisplay(e.token);
00280 }
00281 else if ( e instanceof MismatchedSetException ) {
00282 MismatchedSetException mse = (MismatchedSetException)e;
00283 msg = "mismatched input "+getTokenErrorDisplay(e.token)+
00284 " expecting set "+mse.expecting;
00285 }
00286 else if ( e instanceof MismatchedNotSetException ) {
00287 MismatchedNotSetException mse = (MismatchedNotSetException)e;
00288 msg = "mismatched input "+getTokenErrorDisplay(e.token)+
00289 " expecting set "+mse.expecting;
00290 }
00291 else if ( e instanceof FailedPredicateException ) {
00292 FailedPredicateException fpe = (FailedPredicateException)e;
00293 msg = "rule "+fpe.ruleName+" failed predicate: {"+
00294 fpe.predicateText+"}?";
00295 }
00296 return msg;
00297 }
00298
00306 public int getNumberOfSyntaxErrors() {
00307 return state.syntaxErrors;
00308 }
00309
00311 public String getErrorHeader(RecognitionException e) {
00312 if ( getSourceName()!=null )
00313 return getSourceName()+" line "+e.line+":"+e.charPositionInLine;
00314
00315 return "line "+e.line+":"+e.charPositionInLine;
00316 }
00317
00326 public String getTokenErrorDisplay(Token t) {
00327 String s = t.getText();
00328 if ( s==null ) {
00329 if ( t.getType()==Token.EOF ) {
00330 s = "<EOF>";
00331 }
00332 else {
00333 s = "<"+t.getType()+">";
00334 }
00335 }
00336 s = s.replaceAll("\n","\\\\n");
00337 s = s.replaceAll("\r","\\\\r");
00338 s = s.replaceAll("\t","\\\\t");
00339 return "'"+s+"'";
00340 }
00341
00343 public void emitErrorMessage(String msg) {
00344 System.err.println(msg);
00345 }
00346
00353 public void recover(IntStream input, RecognitionException re) {
00354 if ( state.lastErrorIndex==input.index() ) {
00355
00356
00357
00358
00359 input.consume();
00360 }
00361 state.lastErrorIndex = input.index();
00362 BitSet followSet = computeErrorRecoverySet();
00363 beginResync();
00364 consumeUntil(input, followSet);
00365 endResync();
00366 }
00367
00371 public void beginResync() {
00372 }
00373
00374 public void endResync() {
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468 protected BitSet computeErrorRecoverySet() {
00469 return combineFollows(false);
00470 }
00471
00524 protected BitSet computeContextSensitiveRuleFOLLOW() {
00525 return combineFollows(true);
00526 }
00527
00528
00529
00530
00531
00532 protected BitSet combineFollows(boolean exact) {
00533 int top = state._fsp;
00534 BitSet followSet = new BitSet();
00535 for (int i=top; i>=0; i--) {
00536 BitSet localFollowSet = (BitSet)state.following[i];
00537
00538
00539
00540
00541 followSet.orInPlace(localFollowSet);
00542 if ( exact ) {
00543
00544 if ( localFollowSet.member(Token.EOR_TOKEN_TYPE) ) {
00545
00546
00547 if ( i>0 ) {
00548 followSet.remove(Token.EOR_TOKEN_TYPE);
00549 }
00550 }
00551 else {
00552 break;
00553 }
00554 }
00555 }
00556 return followSet;
00557 }
00558
00588 protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow)
00589 throws RecognitionException
00590 {
00591 RecognitionException e = null;
00592
00593 if ( mismatchIsUnwantedToken(input, ttype) ) {
00594 e = new UnwantedTokenException(ttype, input);
00595
00596
00597
00598
00599
00600 beginResync();
00601 input.consume();
00602 endResync();
00603 reportError(e);
00604
00605 Object matchedSymbol = getCurrentInputSymbol(input);
00606 input.consume();
00607 return matchedSymbol;
00608 }
00609
00610 if ( mismatchIsMissingToken(input, follow) ) {
00611 Object inserted = getMissingSymbol(input, e, ttype, follow);
00612 e = new MissingTokenException(ttype, input, inserted);
00613 reportError(e);
00614 return inserted;
00615 }
00616
00617 e = new MismatchedTokenException(ttype, input);
00618 throw e;
00619 }
00620
00622 public Object recoverFromMismatchedSet(IntStream input,
00623 RecognitionException e,
00624 BitSet follow)
00625 throws RecognitionException
00626 {
00627 if ( mismatchIsMissingToken(input, follow) ) {
00628
00629 reportError(e);
00630
00631 return getMissingSymbol(input, e, Token.INVALID_TOKEN_TYPE, follow);
00632 }
00633
00634 throw e;
00635 }
00636
00646 protected Object getCurrentInputSymbol(IntStream input) { return null; }
00647
00667 protected Object getMissingSymbol(IntStream input,
00668 RecognitionException e,
00669 int expectedTokenType,
00670 BitSet follow)
00671 {
00672 return null;
00673 }
00674
00675 public void consumeUntil(IntStream input, int tokenType) {
00676
00677 int ttype = input.LA(1);
00678 while (ttype != Token.EOF && ttype != tokenType) {
00679 input.consume();
00680 ttype = input.LA(1);
00681 }
00682 }
00683
00685 public void consumeUntil(IntStream input, BitSet set) {
00686
00687 int ttype = input.LA(1);
00688 while (ttype != Token.EOF && !set.member(ttype) ) {
00689
00690 input.consume();
00691 ttype = input.LA(1);
00692 }
00693 }
00694
00696 protected void pushFollow(BitSet fset) {
00697 if ( (state._fsp +1)>=state.following.length ) {
00698 BitSet[] f = new BitSet[state.following.length*2];
00699 System.arraycopy(state.following, 0, f, 0, state.following.length);
00700 state.following = f;
00701 }
00702 state.following[++state._fsp] = fset;
00703 }
00704
00713 public List getRuleInvocationStack() {
00714 String parserClassName = getClass().getName();
00715 return getRuleInvocationStack(new Throwable(), parserClassName);
00716 }
00717
00725 public static List getRuleInvocationStack(Throwable e,
00726 String recognizerClassName)
00727 {
00728 List rules = new ArrayList();
00729 StackTraceElement[] stack = e.getStackTrace();
00730 int i = 0;
00731 for (i=stack.length-1; i>=0; i--) {
00732 StackTraceElement t = stack[i];
00733 if ( t.getClassName().startsWith("org.antlr.runtime.") ) {
00734 continue;
00735 }
00736 if ( t.getMethodName().equals(NEXT_TOKEN_RULE_NAME) ) {
00737 continue;
00738 }
00739 if ( !t.getClassName().equals(recognizerClassName) ) {
00740 continue;
00741 }
00742 rules.add(t.getMethodName());
00743 }
00744 return rules;
00745 }
00746
00747 public int getBacktrackingLevel() { return state.backtracking; }
00748
00749 public void setBacktrackingLevel(int n) { state.backtracking = n; }
00750
00752 public boolean failed() { return state.failed; }
00753
00758 public String[] getTokenNames() {
00759 return null;
00760 }
00761
00765 public String getGrammarFileName() {
00766 return null;
00767 }
00768
00769 public abstract String getSourceName();
00770
00774 public List toStrings(List tokens) {
00775 if ( tokens==null ) return null;
00776 List strings = new ArrayList(tokens.size());
00777 for (int i=0; i<tokens.size(); i++) {
00778 strings.add(((Token)tokens.get(i)).getText());
00779 }
00780 return strings;
00781 }
00782
00793 public int getRuleMemoization(int ruleIndex, int ruleStartIndex) {
00794 if ( state.ruleMemo[ruleIndex]==null ) {
00795 state.ruleMemo[ruleIndex] = new HashMap();
00796 }
00797 Integer stopIndexI =
00798 (Integer)state.ruleMemo[ruleIndex].get(new Integer(ruleStartIndex));
00799 if ( stopIndexI==null ) {
00800 return MEMO_RULE_UNKNOWN;
00801 }
00802 return stopIndexI.intValue();
00803 }
00804
00814 public boolean alreadyParsedRule(IntStream input, int ruleIndex) {
00815 int stopIndex = getRuleMemoization(ruleIndex, input.index());
00816 if ( stopIndex==MEMO_RULE_UNKNOWN ) {
00817 return false;
00818 }
00819 if ( stopIndex==MEMO_RULE_FAILED ) {
00820
00821 state.failed=true;
00822 }
00823 else {
00824
00825 input.seek(stopIndex+1);
00826 }
00827 return true;
00828 }
00829
00833 public void memoize(IntStream input,
00834 int ruleIndex,
00835 int ruleStartIndex)
00836 {
00837 int stopTokenIndex = state.failed?MEMO_RULE_FAILED:input.index()-1;
00838 if ( state.ruleMemo==null ) {
00839 System.err.println("!!!!!!!!! memo array is null for "+ getGrammarFileName());
00840 }
00841 if ( ruleIndex >= state.ruleMemo.length ) {
00842 System.err.println("!!!!!!!!! memo size is "+state.ruleMemo.length+", but rule index is "+ruleIndex);
00843 }
00844 if ( state.ruleMemo[ruleIndex]!=null ) {
00845 state.ruleMemo[ruleIndex].put(
00846 new Integer(ruleStartIndex), new Integer(stopTokenIndex)
00847 );
00848 }
00849 }
00850
00854 public int getRuleMemoizationCacheSize() {
00855 int n = 0;
00856 for (int i = 0; state.ruleMemo!=null && i < state.ruleMemo.length; i++) {
00857 Map ruleMap = state.ruleMemo[i];
00858 if ( ruleMap!=null ) {
00859 n += ruleMap.size();
00860 }
00861 }
00862 return n;
00863 }
00864
00865 public void traceIn(String ruleName, int ruleIndex, Object inputSymbol) {
00866 System.out.print("enter "+ruleName+" "+inputSymbol);
00867 if ( state.backtracking>0 ) {
00868 System.out.print(" backtracking="+state.backtracking);
00869 }
00870 System.out.println();
00871 }
00872
00873 public void traceOut(String ruleName,
00874 int ruleIndex,
00875 Object inputSymbol)
00876 {
00877 System.out.print("exit "+ruleName+" "+inputSymbol);
00878 if ( state.backtracking>0 ) {
00879 System.out.print(" backtracking="+state.backtracking);
00880 if ( state.failed ) System.out.print(" failed");
00881 else System.out.print(" succeeded");
00882 }
00883 System.out.println();
00884 }
00885
00886 }