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
00167 protected void mismatch(IntStream input, int ttype, BitSet follow)
00168 throws RecognitionException
00169 {
00170 if ( mismatchIsUnwantedToken(input, ttype) ) {
00171 throw new UnwantedTokenException(ttype, input);
00172 }
00173 else if ( mismatchIsMissingToken(input, follow) ) {
00174 throw new MissingTokenException(ttype, input, null);
00175 }
00176 throw new MismatchedTokenException(ttype, input);
00177 }
00178
00194 public void reportError(RecognitionException e) {
00195
00196
00197 if ( state.errorRecovery ) {
00198
00199 return;
00200 }
00201 state.syntaxErrors++;
00202 state.errorRecovery = true;
00203
00204 displayRecognitionError(this.getTokenNames(), e);
00205 }
00206
00207 public void displayRecognitionError(String[] tokenNames,
00208 RecognitionException e)
00209 {
00210 String hdr = getErrorHeader(e);
00211 String msg = getErrorMessage(e, tokenNames);
00212 emitErrorMessage(hdr+" "+msg);
00213 }
00214
00237 public String getErrorMessage(RecognitionException e, String[] tokenNames) {
00238 String msg = e.getMessage();
00239 if ( e instanceof UnwantedTokenException ) {
00240 UnwantedTokenException ute = (UnwantedTokenException)e;
00241 String tokenName="<unknown>";
00242 if ( ute.expecting== Token.EOF ) {
00243 tokenName = "EOF";
00244 }
00245 else {
00246 tokenName = tokenNames[ute.expecting];
00247 }
00248 msg = "extraneous input "+getTokenErrorDisplay(ute.getUnexpectedToken())+
00249 " expecting "+tokenName;
00250 }
00251 else if ( e instanceof MissingTokenException ) {
00252 MissingTokenException mte = (MissingTokenException)e;
00253 String tokenName="<unknown>";
00254 if ( mte.expecting== Token.EOF ) {
00255 tokenName = "EOF";
00256 }
00257 else {
00258 tokenName = tokenNames[mte.expecting];
00259 }
00260 msg = "missing "+tokenName+" at "+getTokenErrorDisplay(e.token);
00261 }
00262 else if ( e instanceof MismatchedTokenException ) {
00263 MismatchedTokenException mte = (MismatchedTokenException)e;
00264 String tokenName="<unknown>";
00265 if ( mte.expecting== Token.EOF ) {
00266 tokenName = "EOF";
00267 }
00268 else {
00269 tokenName = tokenNames[mte.expecting];
00270 }
00271 msg = "mismatched input "+getTokenErrorDisplay(e.token)+
00272 " expecting "+tokenName;
00273 }
00274 else if ( e instanceof MismatchedTreeNodeException ) {
00275 MismatchedTreeNodeException mtne = (MismatchedTreeNodeException)e;
00276 String tokenName="<unknown>";
00277 if ( mtne.expecting==Token.EOF ) {
00278 tokenName = "EOF";
00279 }
00280 else {
00281 tokenName = tokenNames[mtne.expecting];
00282 }
00283 msg = "mismatched tree node: "+mtne.node+
00284 " expecting "+tokenName;
00285 }
00286 else if ( e instanceof NoViableAltException ) {
00287 NoViableAltException nvae = (NoViableAltException)e;
00288
00289
00290
00291 msg = "no viable alternative at input "+getTokenErrorDisplay(e.token);
00292 }
00293 else if ( e instanceof EarlyExitException ) {
00294 EarlyExitException eee = (EarlyExitException)e;
00295
00296 msg = "required (...)+ loop did not match anything at input "+
00297 getTokenErrorDisplay(e.token);
00298 }
00299 else if ( e instanceof MismatchedSetException ) {
00300 MismatchedSetException mse = (MismatchedSetException)e;
00301 msg = "mismatched input "+getTokenErrorDisplay(e.token)+
00302 " expecting set "+mse.expecting;
00303 }
00304 else if ( e instanceof MismatchedNotSetException ) {
00305 MismatchedNotSetException mse = (MismatchedNotSetException)e;
00306 msg = "mismatched input "+getTokenErrorDisplay(e.token)+
00307 " expecting set "+mse.expecting;
00308 }
00309 else if ( e instanceof FailedPredicateException ) {
00310 FailedPredicateException fpe = (FailedPredicateException)e;
00311 msg = "rule "+fpe.ruleName+" failed predicate: {"+
00312 fpe.predicateText+"}?";
00313 }
00314 return msg;
00315 }
00316
00324 public int getNumberOfSyntaxErrors() {
00325 return state.syntaxErrors;
00326 }
00327
00329 public String getErrorHeader(RecognitionException e) {
00330 return "line "+e.line+":"+e.charPositionInLine;
00331 }
00332
00341 public String getTokenErrorDisplay(Token t) {
00342 String s = t.getText();
00343 if ( s==null ) {
00344 if ( t.getType()==Token.EOF ) {
00345 s = "<EOF>";
00346 }
00347 else {
00348 s = "<"+t.getType()+">";
00349 }
00350 }
00351 s = s.replaceAll("\n","\\\\n");
00352 s = s.replaceAll("\r","\\\\r");
00353 s = s.replaceAll("\t","\\\\t");
00354 return "'"+s+"'";
00355 }
00356
00358 public void emitErrorMessage(String msg) {
00359 System.err.println(msg);
00360 }
00361
00368 public void recover(IntStream input, RecognitionException re) {
00369 if ( state.lastErrorIndex==input.index() ) {
00370
00371
00372
00373
00374 input.consume();
00375 }
00376 state.lastErrorIndex = input.index();
00377 BitSet followSet = computeErrorRecoverySet();
00378 beginResync();
00379 consumeUntil(input, followSet);
00380 endResync();
00381 }
00382
00386 public void beginResync() {
00387 }
00388
00389 public void endResync() {
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
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483 protected BitSet computeErrorRecoverySet() {
00484 return combineFollows(false);
00485 }
00486
00539 protected BitSet computeContextSensitiveRuleFOLLOW() {
00540 return combineFollows(true);
00541 }
00542
00543 protected BitSet combineFollows(boolean exact) {
00544 int top = state._fsp;
00545 BitSet followSet = new BitSet();
00546 for (int i=top; i>=0; i--) {
00547 BitSet localFollowSet = (BitSet)state.following[i];
00548
00549
00550
00551
00552 followSet.orInPlace(localFollowSet);
00553 if ( exact ) {
00554
00555 if ( localFollowSet.member(Token.EOR_TOKEN_TYPE) ) {
00556
00557
00558 if ( i>0 ) {
00559 followSet.remove(Token.EOR_TOKEN_TYPE);
00560 }
00561 }
00562 else {
00563 break;
00564 }
00565 }
00566 }
00567 return followSet;
00568 }
00569
00599 protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow)
00600 throws RecognitionException
00601 {
00602 RecognitionException e = null;
00603
00604 if ( mismatchIsUnwantedToken(input, ttype) ) {
00605 e = new UnwantedTokenException(ttype, input);
00606
00607
00608
00609
00610
00611 beginResync();
00612 input.consume();
00613 endResync();
00614 reportError(e);
00615
00616 Object matchedSymbol = getCurrentInputSymbol(input);
00617 input.consume();
00618 return matchedSymbol;
00619 }
00620
00621 if ( mismatchIsMissingToken(input, follow) ) {
00622 Object inserted = getMissingSymbol(input, e, ttype, follow);
00623 e = new MissingTokenException(ttype, input, inserted);
00624 reportError(e);
00625 return inserted;
00626 }
00627
00628 e = new MismatchedTokenException(ttype, input);
00629 throw e;
00630 }
00631
00633 public Object recoverFromMismatchedSet(IntStream input,
00634 RecognitionException e,
00635 BitSet follow)
00636 throws RecognitionException
00637 {
00638 if ( mismatchIsMissingToken(input, follow) ) {
00639
00640 reportError(e);
00641
00642 return getMissingSymbol(input, e, Token.INVALID_TOKEN_TYPE, follow);
00643 }
00644
00645 throw e;
00646 }
00647
00657 protected Object getCurrentInputSymbol(IntStream input) { return null; }
00658
00678 protected Object getMissingSymbol(IntStream input,
00679 RecognitionException e,
00680 int expectedTokenType,
00681 BitSet follow)
00682 {
00683 return null;
00684 }
00685
00686 public void consumeUntil(IntStream input, int tokenType) {
00687
00688 int ttype = input.LA(1);
00689 while (ttype != Token.EOF && ttype != tokenType) {
00690 input.consume();
00691 ttype = input.LA(1);
00692 }
00693 }
00694
00696 public void consumeUntil(IntStream input, BitSet set) {
00697
00698 int ttype = input.LA(1);
00699 while (ttype != Token.EOF && !set.member(ttype) ) {
00700
00701 input.consume();
00702 ttype = input.LA(1);
00703 }
00704 }
00705
00707 protected void pushFollow(BitSet fset) {
00708 if ( (state._fsp +1)>=state.following.length ) {
00709 BitSet[] f = new BitSet[state.following.length*2];
00710 System.arraycopy(state.following, 0, f, 0, state.following.length);
00711 state.following = f;
00712 }
00713 state.following[++state._fsp] = fset;
00714 }
00715
00724 public List getRuleInvocationStack() {
00725 String parserClassName = getClass().getName();
00726 return getRuleInvocationStack(new Throwable(), parserClassName);
00727 }
00728
00736 public static List getRuleInvocationStack(Throwable e,
00737 String recognizerClassName)
00738 {
00739 List rules = new ArrayList();
00740 StackTraceElement[] stack = e.getStackTrace();
00741 int i = 0;
00742 for (i=stack.length-1; i>=0; i--) {
00743 StackTraceElement t = stack[i];
00744 if ( t.getClassName().startsWith("org.antlr.runtime.") ) {
00745 continue;
00746 }
00747 if ( t.getMethodName().equals(NEXT_TOKEN_RULE_NAME) ) {
00748 continue;
00749 }
00750 if ( !t.getClassName().equals(recognizerClassName) ) {
00751 continue;
00752 }
00753 rules.add(t.getMethodName());
00754 }
00755 return rules;
00756 }
00757
00758 public int getBacktrackingLevel() {
00759 return state.backtracking;
00760 }
00761
00766 public String[] getTokenNames() {
00767 return null;
00768 }
00769
00773 public String getGrammarFileName() {
00774 return null;
00775 }
00776
00777 public abstract String getSourceName();
00778
00782 public List toStrings(List tokens) {
00783 if ( tokens==null ) return null;
00784 List strings = new ArrayList(tokens.size());
00785 for (int i=0; i<tokens.size(); i++) {
00786 strings.add(((Token)tokens.get(i)).getText());
00787 }
00788 return strings;
00789 }
00790
00801 public int getRuleMemoization(int ruleIndex, int ruleStartIndex) {
00802 if ( state.ruleMemo[ruleIndex]==null ) {
00803 state.ruleMemo[ruleIndex] = new HashMap();
00804 }
00805 Integer stopIndexI =
00806 (Integer)state.ruleMemo[ruleIndex].get(new Integer(ruleStartIndex));
00807 if ( stopIndexI==null ) {
00808 return MEMO_RULE_UNKNOWN;
00809 }
00810 return stopIndexI.intValue();
00811 }
00812
00822 public boolean alreadyParsedRule(IntStream input, int ruleIndex) {
00823 int stopIndex = getRuleMemoization(ruleIndex, input.index());
00824 if ( stopIndex==MEMO_RULE_UNKNOWN ) {
00825 return false;
00826 }
00827 if ( stopIndex==MEMO_RULE_FAILED ) {
00828
00829 state.failed=true;
00830 }
00831 else {
00832
00833 input.seek(stopIndex+1);
00834 }
00835 return true;
00836 }
00837
00841 public void memoize(IntStream input,
00842 int ruleIndex,
00843 int ruleStartIndex)
00844 {
00845 int stopTokenIndex = state.failed?MEMO_RULE_FAILED:input.index()-1;
00846 if ( state.ruleMemo==null ) {
00847 System.err.println("!!!!!!!!! memo array is null for "+ getGrammarFileName());
00848 }
00849 if ( ruleIndex >= state.ruleMemo.length ) {
00850 System.err.println("!!!!!!!!! memo size is "+state.ruleMemo.length+", but rule index is "+ruleIndex);
00851 }
00852 if ( state.ruleMemo[ruleIndex]!=null ) {
00853 state.ruleMemo[ruleIndex].put(
00854 new Integer(ruleStartIndex), new Integer(stopTokenIndex)
00855 );
00856 }
00857 }
00858
00862 public int getRuleMemoizationCacheSize() {
00863 int n = 0;
00864 for (int i = 0; state.ruleMemo!=null && i < state.ruleMemo.length; i++) {
00865 Map ruleMap = state.ruleMemo[i];
00866 if ( ruleMap!=null ) {
00867 n += ruleMap.size();
00868 }
00869 }
00870 return n;
00871 }
00872
00873 public void traceIn(String ruleName, int ruleIndex, Object inputSymbol) {
00874 System.out.print("enter "+ruleName+" "+inputSymbol);
00875 if ( state.failed ) {
00876 System.out.println(" failed="+state.failed);
00877 }
00878 if ( state.backtracking>0 ) {
00879 System.out.print(" backtracking="+state.backtracking);
00880 }
00881 System.out.println();
00882 }
00883
00884 public void traceOut(String ruleName,
00885 int ruleIndex,
00886 Object inputSymbol)
00887 {
00888 System.out.print("exit "+ruleName+" "+inputSymbol);
00889 if ( state.failed ) {
00890 System.out.println(" failed="+state.failed);
00891 }
00892 if ( state.backtracking>0 ) {
00893 System.out.print(" backtracking="+state.backtracking);
00894 }
00895 System.out.println();
00896 }
00897
00898 }