| 1 |
/* ANTLRParser.C |
| 2 |
* |
| 3 |
* SOFTWARE RIGHTS |
| 4 |
* |
| 5 |
* We reserve no LEGAL rights to the Purdue Compiler Construction Tool |
| 6 |
* Set (PCCTS) -- PCCTS is in the public domain. An individual or |
| 7 |
* company may do whatever they wish with source code distributed with |
| 8 |
* PCCTS or the code generated by PCCTS, including the incorporation of |
| 9 |
* PCCTS, or its output, into commerical software. |
| 10 |
* |
| 11 |
* We encourage users to develop software with PCCTS. However, we do ask |
| 12 |
* that credit is given to us for developing PCCTS. By "credit", |
| 13 |
* we mean that if you incorporate our source code into one of your |
| 14 |
* programs (commercial product, research project, or otherwise) that you |
| 15 |
* acknowledge this fact somewhere in the documentation, research report, |
| 16 |
* etc... If you like PCCTS and have developed a nice tool with the |
| 17 |
* output, please mention that you developed it using PCCTS. In |
| 18 |
* addition, we ask that this header remain intact in our source code. |
| 19 |
* As long as these guidelines are kept, we expect to continue enhancing |
| 20 |
* this system and expect to make other tools available as they are |
| 21 |
* completed. |
| 22 |
* |
| 23 |
* ANTLR 1.33 |
| 24 |
* Terence Parr |
| 25 |
* Parr Research Corporation |
| 26 |
* with Purdue University and AHPCRC, University of Minnesota |
| 27 |
* 1989-2000 |
| 28 |
*/ |
| 29 |
|
| 30 |
#include "pcctscfg.h" |
| 31 |
|
| 32 |
#include "pccts_stdlib.h" |
| 33 |
#include "pccts_stdarg.h" |
| 34 |
#include "pccts_string.h" |
| 35 |
#include "pccts_stdio.h" |
| 36 |
|
| 37 |
PCCTS_NAMESPACE_STD |
| 38 |
|
| 39 |
/* I have to put this here due to C++ limitation |
| 40 |
* that you can't have a 'forward' decl for enums. |
| 41 |
* I hate C++!!!!!!!!!!!!!!! |
| 42 |
* Of course, if I could use real templates, this would go away. |
| 43 |
*/ |
| 44 |
// MR1 |
| 45 |
// MR1 10-Apr-97 133MR1 Prevent use of varying sizes for the |
| 46 |
// MR1 ANTLRTokenType enum |
| 47 |
// MR1 |
| 48 |
|
| 49 |
enum ANTLRTokenType { TER_HATES_CPP=0, ITS_TOO_COMPLICATED=9999}; // MR1 |
| 50 |
|
| 51 |
#define ANTLR_SUPPORT_CODE |
| 52 |
|
| 53 |
#include ATOKEN_H |
| 54 |
#include ATOKENBUFFER_H |
| 55 |
#include APARSER_H |
| 56 |
|
| 57 |
static const int zzINF_DEF_TOKEN_BUFFER_SIZE = 2000; /* MR14 */ |
| 58 |
static const int zzINF_BUFFER_TOKEN_CHUNK_SIZE = 1000; /* MR14 */ |
| 59 |
|
| 60 |
/* L o o k a h e a d M a c r o s */ |
| 61 |
|
| 62 |
/* maximum of 32 bits/unsigned int and must be 8 bits/byte; |
| 63 |
* we only use 8 bits of it. |
| 64 |
*/ |
| 65 |
SetWordType ANTLRParser::bitmask[sizeof(SetWordType)*8] = { |
| 66 |
0x00000001, 0x00000002, 0x00000004, 0x00000008, |
| 67 |
0x00000010, 0x00000020, 0x00000040, 0x00000080 |
| 68 |
}; |
| 69 |
|
| 70 |
char ANTLRParser::eMsgBuffer[500] = ""; |
| 71 |
|
| 72 |
ANTLRParser:: |
| 73 |
~ANTLRParser() |
| 74 |
{ |
| 75 |
delete [] token_type; |
| 76 |
delete [] zzFAILtext; // MR16 Manfred Kogler |
| 77 |
} |
| 78 |
|
| 79 |
ANTLRParser:: |
| 80 |
ANTLRParser(ANTLRTokenBuffer *_inputTokens, |
| 81 |
int k, |
| 82 |
int use_inf_look, |
| 83 |
int dlook, |
| 84 |
int ssize) |
| 85 |
{ |
| 86 |
LLk = k; |
| 87 |
can_use_inf_look = use_inf_look; |
| 88 |
/* MR14 */ if (dlook != 0) { |
| 89 |
/* MR14 */ panic("ANTLRParser::ANTLRParser - Demand lookahead not supported in C++ mode"); |
| 90 |
/* MR14 */ |
| 91 |
/* MR14 */ }; |
| 92 |
demand_look = 0; /* demand_look = dlook; */ |
| 93 |
bsetsize = ssize; |
| 94 |
guessing = 0; |
| 95 |
token_tbl = NULL; |
| 96 |
eofToken = (ANTLRTokenType)1; |
| 97 |
|
| 98 |
// allocate lookahead buffer |
| 99 |
token_type = new ANTLRTokenType[LLk]; |
| 100 |
lap = 0; |
| 101 |
labase = 0; |
| 102 |
#ifdef ZZDEFER_FETCH |
| 103 |
stillToFetch = 0; // MR19 |
| 104 |
#endif |
| 105 |
dirty = 0; |
| 106 |
inf_labase = 0; // MR7 |
| 107 |
inf_last = 0; // MR7 |
| 108 |
/* prime lookahead buffer, point to inputTokens */ |
| 109 |
this->inputTokens = _inputTokens; |
| 110 |
this->inputTokens->setMinTokens(k); |
| 111 |
_inputTokens->setParser(this); // MR1 |
| 112 |
resynchConsumed=1; // MR8 |
| 113 |
zzFAILtext=NULL; // MR9 |
| 114 |
traceOptionValueDefault=0; // MR10 |
| 115 |
traceReset(); // MR10 |
| 116 |
zzGuessSeq=0; // MR10 |
| 117 |
syntaxErrCount=0; // MR11 |
| 118 |
} |
| 119 |
|
| 120 |
void ANTLRParser::init() |
| 121 |
{ |
| 122 |
prime_lookahead(); |
| 123 |
resynchConsumed=1; // MR8 |
| 124 |
traceReset(); // MR10 |
| 125 |
} |
| 126 |
|
| 127 |
void ANTLRParser::traceReset() |
| 128 |
{ |
| 129 |
traceOptionValue=traceOptionValueDefault; |
| 130 |
traceGuessOptionValue=1; |
| 131 |
traceCurrentRuleName=NULL; |
| 132 |
traceDepth=0; |
| 133 |
} |
| 134 |
|
| 135 |
|
| 136 |
#ifdef _MSC_VER // MR23 |
| 137 |
//Turn off warning: |
| 138 |
//interaction between '_setjmp' and C++ object destruction is non-portable |
| 139 |
#pragma warning(disable : 4611) |
| 140 |
#endif |
| 141 |
int ANTLRParser:: |
| 142 |
guess(ANTLRParserState *st) |
| 143 |
{ |
| 144 |
saveState(st); |
| 145 |
guessing = 1; |
| 146 |
return setjmp(guess_start.state); |
| 147 |
} |
| 148 |
#ifdef _MSC_VER // MR23 |
| 149 |
#pragma warning(default: 4611) |
| 150 |
#endif |
| 151 |
|
| 152 |
void ANTLRParser:: |
| 153 |
saveState(ANTLRParserState *buf) |
| 154 |
{ |
| 155 |
buf->guess_start = guess_start; |
| 156 |
buf->guessing = guessing; |
| 157 |
buf->inf_labase = inf_labase; |
| 158 |
buf->inf_last = inf_last; |
| 159 |
buf->dirty = dirty; |
| 160 |
buf->traceOptionValue=traceOptionValue; /* MR10 */ |
| 161 |
buf->traceGuessOptionValue=traceGuessOptionValue; /* MR10 */ |
| 162 |
buf->traceCurrentRuleName=traceCurrentRuleName; /* MR10 */ |
| 163 |
buf->traceDepth=traceDepth; /* MR10 */ |
| 164 |
} |
| 165 |
|
| 166 |
void ANTLRParser:: |
| 167 |
restoreState(ANTLRParserState *buf) |
| 168 |
{ |
| 169 |
int i; |
| 170 |
int prevTraceOptionValue; |
| 171 |
|
| 172 |
guess_start = buf->guess_start; |
| 173 |
guessing = buf->guessing; |
| 174 |
inf_labase = buf->inf_labase; |
| 175 |
inf_last = buf->inf_last; |
| 176 |
dirty = buf->dirty; |
| 177 |
|
| 178 |
// restore lookahead buffer from k tokens before restored TokenBuffer position |
| 179 |
// if demand_look, then I guess we don't look backwards for these tokens. |
| 180 |
for (i=1; i<=LLk; i++) token_type[i-1] = |
| 181 |
inputTokens->bufferedToken(i-LLk)->getType(); |
| 182 |
lap = 0; |
| 183 |
labase = 0; |
| 184 |
|
| 185 |
/* MR10 */ |
| 186 |
|
| 187 |
prevTraceOptionValue=traceOptionValue; |
| 188 |
traceOptionValue=buf->traceOptionValue; |
| 189 |
if ( (prevTraceOptionValue > 0) != |
| 190 |
(traceOptionValue > 0)) { |
| 191 |
if (traceCurrentRuleName != NULL) { /* MR21 */ |
| 192 |
if (traceOptionValue > 0) { |
| 193 |
/* MR23 */ printMessage(stderr, |
| 194 |
"trace enable restored in rule %s depth %d\n", |
| 195 |
traceCurrentRuleName, |
| 196 |
traceDepth); |
| 197 |
}; |
| 198 |
if (traceOptionValue <= 0) { |
| 199 |
/* MR23 */ printMessage(stderr, |
| 200 |
"trace disable restored in rule %s depth %d\n", |
| 201 |
traceCurrentRuleName, /* MR21 */ |
| 202 |
traceDepth); |
| 203 |
}; |
| 204 |
} |
| 205 |
}; |
| 206 |
traceGuessOptionValue=buf->traceGuessOptionValue; |
| 207 |
traceCurrentRuleName=buf->traceCurrentRuleName; |
| 208 |
traceDepth=buf->traceDepth; |
| 209 |
traceGuessDone(buf); |
| 210 |
} |
| 211 |
|
| 212 |
/* Get the next symbol from the input stream; put it into lookahead buffer; |
| 213 |
* fill token_type[] fast reference cache also. NLA is the next place where |
| 214 |
* a lookahead ANTLRAbstractToken should go. |
| 215 |
*/ |
| 216 |
void ANTLRParser:: |
| 217 |
consume() |
| 218 |
{ |
| 219 |
|
| 220 |
#ifdef ZZDEBUG_CONSUME_ACTION |
| 221 |
zzdebug_consume_action(); |
| 222 |
#endif |
| 223 |
|
| 224 |
// MR19 V.H. Simonis |
| 225 |
// Defer Fetch feature |
| 226 |
// Moves action of consume() into LA() function |
| 227 |
|
| 228 |
#ifdef ZZDEFER_FETCH |
| 229 |
stillToFetch++; |
| 230 |
#else |
| 231 |
NLA = inputTokens->getToken()->getType(); |
| 232 |
dirty--; |
| 233 |
lap = (lap+1)&(LLk-1); |
| 234 |
#endif |
| 235 |
|
| 236 |
} |
| 237 |
|
| 238 |
_ANTLRTokenPtr ANTLRParser:: |
| 239 |
LT(int i) |
| 240 |
{ |
| 241 |
|
| 242 |
// MR19 V.H. Simonis |
| 243 |
// Defer Fetch feature |
| 244 |
// Moves action of consume() into LA() function |
| 245 |
|
| 246 |
#ifdef ZZDEFER_FETCH |
| 247 |
undeferFetch(); |
| 248 |
#endif |
| 249 |
|
| 250 |
#ifdef DEBUG_TOKENBUFFER |
| 251 |
if ( i >= inputTokens->bufferSize() || inputTokens->minTokens() < LLk ) /* MR20 Was "<=" */ |
| 252 |
{ |
| 253 |
char buf[2000]; /* MR20 Was "static" */ |
| 254 |
sprintf(buf, "The minimum number of tokens you requested that the\nANTLRTokenBuffer buffer is not enough to satisfy your\nLT(%d) request; increase 'k' argument to constructor for ANTLRTokenBuffer\n", i); |
| 255 |
panic(buf); |
| 256 |
} |
| 257 |
#endif |
| 258 |
return inputTokens->bufferedToken(i-LLk); |
| 259 |
} |
| 260 |
|
| 261 |
void |
| 262 |
ANTLRParser:: |
| 263 |
look(int k) |
| 264 |
{ |
| 265 |
int i, c = k - (LLk-dirty); |
| 266 |
for (i=1; i<=c; i++) consume(); |
| 267 |
} |
| 268 |
|
| 269 |
/* fill the lookahead buffer up with k symbols (even if DEMAND_LOOK); |
| 270 |
*/ |
| 271 |
void |
| 272 |
ANTLRParser:: |
| 273 |
prime_lookahead() |
| 274 |
{ |
| 275 |
int i; |
| 276 |
for(i=1;i<=LLk; i++) consume(); |
| 277 |
dirty=0; |
| 278 |
// lap = 0; // MR14 Sinan Karasu (sinan.karasu@boeing.com) |
| 279 |
// labase = 0; // MR14 |
| 280 |
labase=lap; // MR14 |
| 281 |
} |
| 282 |
|
| 283 |
/* check to see if the current input symbol matches '_t'. |
| 284 |
* During NON demand lookahead mode, dirty will always be 0 and |
| 285 |
* hence the extra code for consuming tokens in _match is never |
| 286 |
* executed; the same routine can be used for both modes. |
| 287 |
*/ |
| 288 |
int ANTLRParser:: |
| 289 |
_match(ANTLRTokenType _t, ANTLRChar **MissText, |
| 290 |
ANTLRTokenType *MissTok, _ANTLRTokenPtr *BadTok, |
| 291 |
SetWordType **MissSet) |
| 292 |
{ |
| 293 |
if ( dirty==LLk ) { |
| 294 |
consume(); |
| 295 |
} |
| 296 |
if ( LA(1)!=_t ) { |
| 297 |
*MissText=NULL; |
| 298 |
*MissTok= _t; |
| 299 |
*BadTok = LT(1); |
| 300 |
*MissSet=NULL; |
| 301 |
return 0; |
| 302 |
} |
| 303 |
dirty++; |
| 304 |
labase = (labase+1)&(LLk-1); // labase maintained even if !demand look |
| 305 |
return 1; |
| 306 |
} |
| 307 |
|
| 308 |
/* check to see if the current input symbol matches '_t'. |
| 309 |
* Used during exception handling. |
| 310 |
*/ |
| 311 |
int ANTLRParser:: |
| 312 |
_match_wsig(ANTLRTokenType _t) |
| 313 |
{ |
| 314 |
if ( dirty==LLk ) { |
| 315 |
consume(); |
| 316 |
} |
| 317 |
if ( LA(1)!=_t ) return 0; |
| 318 |
dirty++; |
| 319 |
labase = (labase+1)&(LLk-1); // labase maintained even if !demand look |
| 320 |
return 1; |
| 321 |
} |
| 322 |
|
| 323 |
/* check to see if the current input symbol matches any token in a set. |
| 324 |
* During NON demand lookahead mode, dirty will always be 0 and |
| 325 |
* hence the extra code for consuming tokens in _match is never |
| 326 |
* executed; the same routine can be used for both modes. |
| 327 |
*/ |
| 328 |
int ANTLRParser:: |
| 329 |
_setmatch(SetWordType *tset, ANTLRChar **MissText, |
| 330 |
ANTLRTokenType *MissTok, _ANTLRTokenPtr *BadTok, |
| 331 |
SetWordType **MissSet, SetWordType *tokclassErrset) |
| 332 |
{ |
| 333 |
if ( dirty==LLk ) { |
| 334 |
consume(); |
| 335 |
} |
| 336 |
if ( !set_el(LA(1), tset) ) { |
| 337 |
*MissText=NULL; /* MR23 */ |
| 338 |
*MissTok=(ANTLRTokenType) 0; /* MR23 */ |
| 339 |
*BadTok=LT(1); /* MR23 */ |
| 340 |
*MissSet=tokclassErrset; /* MR23 */ |
| 341 |
return 0; |
| 342 |
} |
| 343 |
dirty++; |
| 344 |
labase = (labase+1)&(LLk-1); // labase maintained even if !demand look |
| 345 |
return 1; |
| 346 |
} |
| 347 |
|
| 348 |
int ANTLRParser:: |
| 349 |
_setmatch_wsig(SetWordType *tset) |
| 350 |
{ |
| 351 |
if ( dirty==LLk ) { |
| 352 |
consume(); |
| 353 |
} |
| 354 |
if ( !set_el(LA(1), tset) ) return 0; |
| 355 |
dirty++; |
| 356 |
labase = (labase+1)&(LLk-1); // labase maintained even if !demand look |
| 357 |
return 1; |
| 358 |
} |
| 359 |
|
| 360 |
/* Exception handling routines */ |
| 361 |
// |
| 362 |
// 7-Apr-97 133MR1 |
| 363 |
// Change suggested by Eli Sternheim (eli@interhdl.com) |
| 364 |
// |
| 365 |
void ANTLRParser:: |
| 366 |
consumeUntil(SetWordType *st) |
| 367 |
{ |
| 368 |
ANTLRTokenType tmp; // MR1 |
| 369 |
const int Eof=1; // MR1 |
| 370 |
while ( !set_el( (tmp=LA(1)), st) && tmp!=Eof) { consume(); } // MR1 |
| 371 |
} |
| 372 |
|
| 373 |
// |
| 374 |
// 7-Apr-97 133MR1 |
| 375 |
// Change suggested by Eli Sternheim (eli@interhdl.com) |
| 376 |
// |
| 377 |
void ANTLRParser:: |
| 378 |
consumeUntilToken(int t) |
| 379 |
{ |
| 380 |
int tmp; // MR1 |
| 381 |
const int Eof=1; // MR1 |
| 382 |
while ( (tmp=LA(1)) !=t && tmp!=Eof) { consume(); } // MR1 |
| 383 |
} |
| 384 |
|
| 385 |
|
| 386 |
/* Old error stuff */ |
| 387 |
|
| 388 |
void ANTLRParser:: |
| 389 |
resynch(SetWordType *wd,SetWordType mask) |
| 390 |
{ |
| 391 |
|
| 392 |
/* MR8 S.Bochnak@microtool.com.pl */ |
| 393 |
/* MR8 Change file scope static "consumed" to instance var */ |
| 394 |
|
| 395 |
/* if you enter here without having consumed a token from last resynch |
| 396 |
* force a token consumption. |
| 397 |
*/ |
| 398 |
/* MR8 */ if ( !resynchConsumed ) {consume(); resynchConsumed=1; return;} |
| 399 |
|
| 400 |
/* if current token is in resynch set, we've got what we wanted */ |
| 401 |
|
| 402 |
/* MR8 */ if ( wd[LA(1)]&mask || LA(1) == eofToken ) {resynchConsumed=0; return;} |
| 403 |
|
| 404 |
/* scan until we find something in the resynch set */ |
| 405 |
|
| 406 |
while ( !(wd[LA(1)]&mask) && LA(1) != eofToken ) {consume();} |
| 407 |
|
| 408 |
/* MR8 */ resynchConsumed=1; |
| 409 |
} |
| 410 |
|
| 411 |
/* standard error reporting function that assumes DLG-based scanners; |
| 412 |
* you should redefine in subclass to change it or if you use your |
| 413 |
* own scanner. |
| 414 |
*/ |
| 415 |
|
| 416 |
/* MR23 THM There appears to be a parameter "badText" passed to syn() |
| 417 |
which is not present in the parameter list. This may be |
| 418 |
because in C mode there is no attribute function which |
| 419 |
returns the text, so the text representation of the token |
| 420 |
must be passed explicitly. I think. |
| 421 |
*/ |
| 422 |
|
| 423 |
void ANTLRParser:: |
| 424 |
syn(_ANTLRTokenPtr /*tok MR23*/, ANTLRChar *egroup, SetWordType *eset, |
| 425 |
ANTLRTokenType etok, int k) |
| 426 |
{ |
| 427 |
int line; |
| 428 |
|
| 429 |
line = LT(1)->getLine(); |
| 430 |
|
| 431 |
syntaxErrCount++; /* MR11 */ |
| 432 |
|
| 433 |
/* MR23 If the token is not an EOF token, then use the ->getText() value. |
| 434 |
|
| 435 |
If the token is the EOF token the text returned by ->getText() |
| 436 |
may be garbage. If the text from the token table is "@" use |
| 437 |
"<eof>" instead, because end-users don't know what "@" means. |
| 438 |
If the text is not "@" then use that text, which must have been |
| 439 |
supplied by the grammar writer. |
| 440 |
*/ |
| 441 |
const char * errorAt = LT(1)->getText(); |
| 442 |
if (LA(1) == eofToken) { |
| 443 |
errorAt = parserTokenName(LA(1)); |
| 444 |
if (errorAt[0] == '@') errorAt = "<eof>"; |
| 445 |
} |
| 446 |
/* MR23 */ printMessage(stderr, "line %d: syntax error at \"%s\"", |
| 447 |
line, errorAt); |
| 448 |
if ( !etok && !eset ) {/* MR23 */ printMessage(stderr, "\n"); return;} |
| 449 |
if ( k==1 ) /* MR23 */ printMessage(stderr, " missing"); |
| 450 |
else |
| 451 |
{ |
| 452 |
/* MR23 */ printMessage(stderr, "; \"%s\" not", LT(k)->getText()); // MR23 use LT(k) since k>1 |
| 453 |
if ( set_deg(eset)>1 ) /* MR23 */ printMessage(stderr, " in"); |
| 454 |
} |
| 455 |
if ( set_deg(eset)>0 ) edecode(eset); |
| 456 |
else /* MR23 */ printMessage(stderr, " %s", token_tbl[etok]); |
| 457 |
if ( strlen(egroup) > 0 ) /* MR23 */ printMessage(stderr, " in %s", egroup); |
| 458 |
/* MR23 */ printMessage(stderr, "\n"); |
| 459 |
} |
| 460 |
|
| 461 |
/* is b an element of set p? */ |
| 462 |
int ANTLRParser:: |
| 463 |
set_el(ANTLRTokenType b, SetWordType *p) |
| 464 |
{ |
| 465 |
return( p[DIVWORD(b)] & bitmask[MODWORD(b)] ); |
| 466 |
} |
| 467 |
|
| 468 |
int ANTLRParser:: |
| 469 |
set_deg(SetWordType *a) |
| 470 |
{ |
| 471 |
/* Fast compute degree of a set... the number |
| 472 |
of elements present in the set. Assumes |
| 473 |
that all word bits are used in the set |
| 474 |
*/ |
| 475 |
register SetWordType *p = a; |
| 476 |
register SetWordType *endp = &(a[bsetsize]); |
| 477 |
register int degree = 0; |
| 478 |
|
| 479 |
if ( a == NULL ) return 0; |
| 480 |
while ( p < endp ) |
| 481 |
{ |
| 482 |
register SetWordType t = *p; |
| 483 |
register SetWordType *b = &(bitmask[0]); |
| 484 |
do { |
| 485 |
if (t & *b) ++degree; |
| 486 |
} while (++b < &(bitmask[sizeof(SetWordType)*8])); |
| 487 |
p++; |
| 488 |
} |
| 489 |
|
| 490 |
return(degree); |
| 491 |
} |
| 492 |
|
| 493 |
void ANTLRParser:: |
| 494 |
edecode(SetWordType *a) |
| 495 |
{ |
| 496 |
register SetWordType *p = a; |
| 497 |
register SetWordType *endp = &(p[bsetsize]); |
| 498 |
register unsigned e = 0; |
| 499 |
|
| 500 |
if ( set_deg(a)>1 ) /* MR23 */ printMessage(stderr, " {"); |
| 501 |
do { |
| 502 |
register SetWordType t = *p; |
| 503 |
register SetWordType *b = &(bitmask[0]); |
| 504 |
do { |
| 505 |
if ( t & *b ) /* MR23 */ printMessage(stderr, " %s", token_tbl[e]); |
| 506 |
e++; |
| 507 |
} while (++b < &(bitmask[sizeof(SetWordType)*8])); |
| 508 |
} while (++p < endp); |
| 509 |
if ( set_deg(a)>1 ) /* MR23 */ printMessage(stderr, " }"); |
| 510 |
} |
| 511 |
|
| 512 |
/* input looks like: |
| 513 |
* zzFAIL(k, e1, e2, ...,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk) |
| 514 |
* where the zzMiss stuff is set here to the token that did not match |
| 515 |
* (and which set wasn't it a member of). |
| 516 |
*/ |
| 517 |
|
| 518 |
// MR9 29-Sep-97 Stan Bochnak (S.Bochnak@microTool.com.pl) |
| 519 |
// MR9 Original fix to static allocated text didn't |
| 520 |
// MR9 work because a pointer to it was passed back |
| 521 |
// MR9 to caller. Replace with instance variable. |
| 522 |
|
| 523 |
const int SETWORDCOUNT=20; |
| 524 |
|
| 525 |
void |
| 526 |
ANTLRParser::FAIL(int k, ...) |
| 527 |
{ |
| 528 |
// |
| 529 |
// MR1 10-Apr-97 |
| 530 |
// |
| 531 |
|
| 532 |
if (zzFAILtext == NULL) zzFAILtext=new char [1000]; // MR9 |
| 533 |
SetWordType **f=new SetWordType *[SETWORDCOUNT]; // MR1 // MR9 |
| 534 |
SetWordType **miss_set; |
| 535 |
ANTLRChar **miss_text; |
| 536 |
_ANTLRTokenPtr *bad_tok; |
| 537 |
ANTLRChar **bad_text; |
| 538 |
// |
| 539 |
// 7-Apr-97 133MR1 |
| 540 |
// err_k is passed as a "int *", not "unsigned *" |
| 541 |
// |
| 542 |
int *err_k; // MR1 |
| 543 |
int i; |
| 544 |
va_list ap; |
| 545 |
|
| 546 |
va_start(ap, k); |
| 547 |
|
| 548 |
zzFAILtext[0] = '\0'; |
| 549 |
if ( k > SETWORDCOUNT ) panic("FAIL: overflowed buffer"); |
| 550 |
for (i=1; i<=k; i++) /* collect all lookahead sets */ |
| 551 |
{ |
| 552 |
f[i-1] = va_arg(ap, SetWordType *); |
| 553 |
} |
| 554 |
for (i=1; i<=k; i++) /* look for offending token */ |
| 555 |
{ |
| 556 |
if ( i>1 ) strcat(zzFAILtext, " "); |
| 557 |
strcat(zzFAILtext, LT(i)->getText()); |
| 558 |
if ( !set_el(LA(i), f[i-1]) ) break; |
| 559 |
} |
| 560 |
miss_set = va_arg(ap, SetWordType **); |
| 561 |
miss_text = va_arg(ap, ANTLRChar **); |
| 562 |
bad_tok = va_arg(ap, _ANTLRTokenPtr *); |
| 563 |
bad_text = va_arg(ap, ANTLRChar **); |
| 564 |
err_k = va_arg(ap, int *); // MR1 |
| 565 |
if ( i>k ) |
| 566 |
{ |
| 567 |
/* bad; lookahead is permutation that cannot be matched, |
| 568 |
* but, the ith token of lookahead is valid at the ith position |
| 569 |
* (The old LL sub 1 (k) versus LL(k) parsing technique) |
| 570 |
*/ |
| 571 |
*miss_set = NULL; |
| 572 |
*miss_text = LT(1)->getText(); |
| 573 |
*bad_tok = LT(1); |
| 574 |
*bad_text = (*bad_tok)->getText(); |
| 575 |
*err_k = k; |
| 576 |
// |
| 577 |
// MR4 20-May-97 erroneously deleted contents of f[] |
| 578 |
// MR4 reported by Bruce Guenter (bruceg@qcc.sk.ca) |
| 579 |
// MR1 10-Apr-97 release temporary storage |
| 580 |
// |
| 581 |
delete [] f; // MR1 |
| 582 |
return; // MR1 |
| 583 |
} |
| 584 |
/* MR23 printMessage(stderr, "%s not in %dth set\n", zztokens[LA(i)], i);*/ |
| 585 |
*miss_set = f[i-1]; |
| 586 |
*miss_text = zzFAILtext; |
| 587 |
*bad_tok = LT(i); |
| 588 |
*bad_text = (*bad_tok)->getText(); |
| 589 |
if ( i==1 ) *err_k = 1; |
| 590 |
else *err_k = k; |
| 591 |
// |
| 592 |
// MR4 20-May-97 erroneously deleted contents of f[] |
| 593 |
// MR4 reported by Bruce Guenter (bruceg@qcc.sk.ca) |
| 594 |
// MR1 10-Apr-97 release temporary storage |
| 595 |
// |
| 596 |
delete [] f; // MR1 |
| 597 |
return; // MR1 |
| 598 |
} |
| 599 |
|
| 600 |
int ANTLRParser:: |
| 601 |
_match_wdfltsig(ANTLRTokenType tokenWanted, SetWordType *whatFollows) |
| 602 |
{ |
| 603 |
if ( dirty==LLk ) consume(); |
| 604 |
|
| 605 |
if ( LA(1)!=tokenWanted ) |
| 606 |
{ |
| 607 |
syntaxErrCount++; /* MR11 */ |
| 608 |
/* MR23 */ printMessage(stderr, |
| 609 |
"line %d: syntax error at \"%s\" missing %s\n", |
| 610 |
LT(1)->getLine(), |
| 611 |
(LA(1)==eofToken && LT(1)->getText()[0] == '@')?"<eof>":LT(1)->getText(), /* MR21a */ |
| 612 |
token_tbl[tokenWanted]); |
| 613 |
consumeUntil( whatFollows ); |
| 614 |
return 0; |
| 615 |
} |
| 616 |
else { |
| 617 |
dirty++; |
| 618 |
labase = (labase+1)&(LLk-1); // labase maintained even if !demand look |
| 619 |
/* if ( !demand_look ) consume(); */ |
| 620 |
return 1; |
| 621 |
} |
| 622 |
} |
| 623 |
|
| 624 |
|
| 625 |
int ANTLRParser:: |
| 626 |
_setmatch_wdfltsig(SetWordType *tokensWanted, |
| 627 |
ANTLRTokenType tokenTypeOfSet, |
| 628 |
SetWordType *whatFollows) |
| 629 |
{ |
| 630 |
if ( dirty==LLk ) consume(); |
| 631 |
if ( !set_el(LA(1), tokensWanted) ) |
| 632 |
{ |
| 633 |
syntaxErrCount++; /* MR11 */ |
| 634 |
/* MR23 */ printMessage(stderr, |
| 635 |
"line %d: syntax error at \"%s\" missing %s\n", |
| 636 |
LT(1)->getLine(), |
| 637 |
(LA(1)==eofToken && LT(1)->getText()[0] == '@')?"<eof>":LT(1)->getText(), /* MR21a */ |
| 638 |
token_tbl[tokenTypeOfSet]); |
| 639 |
consumeUntil( whatFollows ); |
| 640 |
return 0; |
| 641 |
} |
| 642 |
else { |
| 643 |
dirty++; |
| 644 |
labase = (labase+1)&(LLk-1); // labase maintained even if !demand look |
| 645 |
/* if ( !demand_look ) consume(); */ |
| 646 |
return 1; |
| 647 |
} |
| 648 |
} |
| 649 |
|
| 650 |
char *ANTLRParser:: |
| 651 |
eMsgd(char *err,int d) |
| 652 |
{ |
| 653 |
sprintf(eMsgBuffer, err, d); // dangerous, but I don't care |
| 654 |
return eMsgBuffer; |
| 655 |
} |
| 656 |
|
| 657 |
char *ANTLRParser:: |
| 658 |
eMsg(char *err, char *s) |
| 659 |
{ |
| 660 |
sprintf(eMsgBuffer, err, s); |
| 661 |
return eMsgBuffer; |
| 662 |
} |
| 663 |
|
| 664 |
char *ANTLRParser:: |
| 665 |
eMsg2(char *err,char *s, char *t) |
| 666 |
{ |
| 667 |
sprintf(eMsgBuffer, err, s, t); |
| 668 |
return eMsgBuffer; |
| 669 |
} |
| 670 |
|
| 671 |
void ANTLRParser:: |
| 672 |
panic(const char *msg) // MR20 const |
| 673 |
{ |
| 674 |
/* MR23 */ printMessage(stderr, "ANTLR panic: %s\n", msg); |
| 675 |
exit(PCCTS_EXIT_FAILURE); // MR1 |
| 676 |
} |
| 677 |
|
| 678 |
const ANTLRChar *ANTLRParser:: // MR1 |
| 679 |
parserTokenName(int tok) { // MR1 |
| 680 |
return token_tbl[tok]; // MR1 |
| 681 |
} // MR1 |
| 682 |
|
| 683 |
void ANTLRParser::traceGuessDone(const ANTLRParserState *state) { |
| 684 |
|
| 685 |
int doIt=0; |
| 686 |
|
| 687 |
if (traceCurrentRuleName == NULL) return; |
| 688 |
|
| 689 |
if (traceOptionValue <= 0) { |
| 690 |
doIt=0; |
| 691 |
} else if (traceGuessOptionValue <= 0) { |
| 692 |
doIt=0; |
| 693 |
} else { |
| 694 |
doIt=1; |
| 695 |
}; |
| 696 |
|
| 697 |
if (doIt) { |
| 698 |
/* MR23 */ printMessage(stderr,"guess done - returning to rule %s {\"%s\"} at depth %d", |
| 699 |
state->traceCurrentRuleName, |
| 700 |
LT(1)->getType() == eofToken ? "@" : LT(1)->getText(), |
| 701 |
state->traceDepth); |
| 702 |
if (state->guessing != 0) { |
| 703 |
/* MR23 */ printMessage(stderr," (guess mode continues - an enclosing guess is still active)"); |
| 704 |
} else { |
| 705 |
/* MR23 */ printMessage(stderr," (guess mode ends)"); |
| 706 |
}; |
| 707 |
/* MR23 */ printMessage(stderr,"\n"); |
| 708 |
}; |
| 709 |
} |
| 710 |
|
| 711 |
void ANTLRParser::traceGuessFail() { |
| 712 |
|
| 713 |
int doIt=0; |
| 714 |
|
| 715 |
if (traceCurrentRuleName == NULL) return; /* MR21 */ |
| 716 |
|
| 717 |
if (traceOptionValue <= 0) { |
| 718 |
doIt=0; |
| 719 |
} else if (guessing && traceGuessOptionValue <= 0) { |
| 720 |
doIt=0; |
| 721 |
} else { |
| 722 |
doIt=1; |
| 723 |
}; |
| 724 |
|
| 725 |
if (doIt) { |
| 726 |
/* MR23 */ printMessage(stderr,"guess failed in %s\n",traceCurrentRuleName); |
| 727 |
}; |
| 728 |
} |
| 729 |
|
| 730 |
/* traceOption: |
| 731 |
zero value turns off trace |
| 732 |
*/ |
| 733 |
|
| 734 |
void ANTLRParser::tracein(const ANTLRChar * rule) { |
| 735 |
|
| 736 |
int doIt=0; |
| 737 |
|
| 738 |
traceDepth++; |
| 739 |
traceCurrentRuleName=rule; |
| 740 |
|
| 741 |
if (traceOptionValue <= 0) { |
| 742 |
doIt=0; |
| 743 |
} else if (guessing && traceGuessOptionValue <= 0) { |
| 744 |
doIt=0; |
| 745 |
} else { |
| 746 |
doIt=1; |
| 747 |
}; |
| 748 |
|
| 749 |
if (doIt) { |
| 750 |
/* MR23 */ printMessage(stderr,"enter rule %s {\"%s\"} depth %d", |
| 751 |
rule, |
| 752 |
LT(1)->getType() == eofToken ? "@" : LT(1)->getText(), |
| 753 |
traceDepth); |
| 754 |
if (guessing) /* MR23 */ printMessage(stderr," guessing"); |
| 755 |
/* MR23 */ printMessage(stderr,"\n"); |
| 756 |
}; |
| 757 |
return; |
| 758 |
} |
| 759 |
|
| 760 |
void ANTLRParser::traceout(const ANTLRChar * rule) { |
| 761 |
|
| 762 |
int doIt=0; |
| 763 |
|
| 764 |
traceDepth--; |
| 765 |
|
| 766 |
if (traceOptionValue <= 0) { |
| 767 |
doIt=0; |
| 768 |
} else if (guessing && traceGuessOptionValue <= 0) { |
| 769 |
doIt=0; |
| 770 |
} else { |
| 771 |
doIt=1; |
| 772 |
}; |
| 773 |
|
| 774 |
if (doIt) { |
| 775 |
/* MR23 */ printMessage(stderr,"exit rule %s {\"%s\"} depth %d", |
| 776 |
rule, |
| 777 |
LT(1)->getType() == eofToken ? "@" : LT(1)->getText(), |
| 778 |
traceDepth+1); |
| 779 |
if (guessing) /* MR23 */ printMessage(stderr," guessing"); |
| 780 |
/* MR23 */ printMessage(stderr,"\n"); |
| 781 |
}; |
| 782 |
} |
| 783 |
|
| 784 |
int ANTLRParser::traceOption(int delta) { |
| 785 |
|
| 786 |
int prevValue=traceOptionValue; |
| 787 |
|
| 788 |
traceOptionValue=traceOptionValue+delta; |
| 789 |
|
| 790 |
if (traceCurrentRuleName != NULL) { |
| 791 |
if (prevValue <= 0 && traceOptionValue > 0) { |
| 792 |
/* MR23 */ printMessage(stderr,"trace enabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth); |
| 793 |
}; |
| 794 |
if (prevValue > 0 && traceOptionValue <= 0) { |
| 795 |
/* MR23 */ printMessage(stderr,"trace disabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth); |
| 796 |
}; |
| 797 |
}; |
| 798 |
|
| 799 |
return prevValue; |
| 800 |
} |
| 801 |
|
| 802 |
int ANTLRParser::traceGuessOption(int delta) { |
| 803 |
|
| 804 |
int prevValue=traceGuessOptionValue; |
| 805 |
|
| 806 |
traceGuessOptionValue=traceGuessOptionValue+delta; |
| 807 |
|
| 808 |
if (traceCurrentRuleName != NULL) { |
| 809 |
if (prevValue <= 0 && traceGuessOptionValue > 0) { |
| 810 |
/* MR23 */ printMessage(stderr,"guess trace enabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth); |
| 811 |
}; |
| 812 |
if (prevValue > 0 && traceGuessOptionValue <= 0) { |
| 813 |
/* MR23 */ printMessage(stderr,"guess trace disabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth); |
| 814 |
}; |
| 815 |
}; |
| 816 |
return prevValue; |
| 817 |
} |
| 818 |
|
| 819 |
// MR19 V.H. Simonis Defer Fetch feature |
| 820 |
|
| 821 |
void ANTLRParser::undeferFetch() |
| 822 |
{ |
| 823 |
|
| 824 |
#ifdef ZZDEFER_FETCH |
| 825 |
if (stillToFetch) { |
| 826 |
for (int stillToFetch_x = 0; stillToFetch_x < stillToFetch; ++stillToFetch_x) { |
| 827 |
NLA = inputTokens->getToken()->getType(); |
| 828 |
dirty--; |
| 829 |
lap = (lap+1)&(LLk-1); |
| 830 |
} |
| 831 |
stillToFetch = 0; |
| 832 |
} |
| 833 |
#else |
| 834 |
return; |
| 835 |
#endif |
| 836 |
|
| 837 |
} |
| 838 |
|
| 839 |
int ANTLRParser::isDeferFetchEnabled() |
| 840 |
{ |
| 841 |
#ifdef ZZDEFER_FETCH |
| 842 |
return 1; |
| 843 |
#else |
| 844 |
return 0; |
| 845 |
#endif |
| 846 |
} |
| 847 |
|
| 848 |
//MR23 |
| 849 |
int ANTLRParser::printMessage(FILE* pFile, const char* pFormat, ...) |
| 850 |
{ |
| 851 |
va_list marker; |
| 852 |
va_start( marker, pFormat ); |
| 853 |
int iRet = printMessageV(pFile, pFormat, marker); |
| 854 |
va_end( marker ); |
| 855 |
return iRet; |
| 856 |
} |
| 857 |
|
| 858 |
int ANTLRParser::printMessageV(FILE* pFile, const char* pFormat, va_list arglist) // MR23 |
| 859 |
{ |
| 860 |
return vfprintf(pFile, pFormat, arglist); |
| 861 |
} |
| 862 |
|
| 863 |
// MR23 Move semantic predicate error handling from macro to virtual function |
| 864 |
// |
| 865 |
// Called by the zzfailed_pred |
| 866 |
|
| 867 |
void ANTLRParser::failedSemanticPredicate(const char* predicate) |
| 868 |
{ |
| 869 |
printMessage(stdout,"line %d: semantic error; failed predicate: '%s'\n", |
| 870 |
LT(1)->getLine(), predicate); |
| 871 |
} |