|
|
1.1 ! root 1: /* parse.y - parser for flex input */ ! 2: ! 3: %token CHAR NUMBER SECTEND SCDECL XSCDECL WHITESPACE NAME PREVCCL EOF_OP ! 4: ! 5: %{ ! 6: ! 7: /*- ! 8: * Copyright (c) 1990 The Regents of the University of California. ! 9: * All rights reserved. ! 10: * ! 11: * This code is derived from software contributed to Berkeley by ! 12: * Vern Paxson. ! 13: * ! 14: * The United States Government has rights in this work pursuant ! 15: * to contract no. DE-AC03-76SF00098 between the United States ! 16: * Department of Energy and the University of California. ! 17: * ! 18: * Redistribution and use in source and binary forms are permitted provided ! 19: * that: (1) source distributions retain this entire copyright notice and ! 20: * comment, and (2) distributions including binaries display the following ! 21: * acknowledgement: ``This product includes software developed by the ! 22: * University of California, Berkeley and its contributors'' in the ! 23: * documentation or other materials provided with the distribution and in ! 24: * all advertising materials mentioning features or use of this software. ! 25: * Neither the name of the University nor the names of its contributors may ! 26: * be used to endorse or promote products derived from this software without ! 27: * specific prior written permission. ! 28: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 29: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 30: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 31: */ ! 32: ! 33: #ifndef lint ! 34: static char sccsid[] = "@(#)parse.y 5.2 (Berkeley) 6/18/90"; ! 35: #endif /* not lint */ ! 36: ! 37: #include "flexdef.h" ! 38: ! 39: int pat, scnum, eps, headcnt, trailcnt, anyccl, lastchar, i, actvp, rulelen; ! 40: int trlcontxt, xcluflg, cclsorted, varlength, variable_trail_rule; ! 41: Char clower(); ! 42: ! 43: static int madeany = false; /* whether we've made the '.' character class */ ! 44: int previous_continued_action; /* whether the previous rule's action was '|' */ ! 45: ! 46: %} ! 47: ! 48: %% ! 49: goal : initlex sect1 sect1end sect2 initforrule ! 50: { /* add default rule */ ! 51: int def_rule; ! 52: ! 53: pat = cclinit(); ! 54: cclnegate( pat ); ! 55: ! 56: def_rule = mkstate( -pat ); ! 57: ! 58: finish_rule( def_rule, false, 0, 0 ); ! 59: ! 60: for ( i = 1; i <= lastsc; ++i ) ! 61: scset[i] = mkbranch( scset[i], def_rule ); ! 62: ! 63: if ( spprdflt ) ! 64: fputs( "YY_FATAL_ERROR( \"flex scanner jammed\" )", ! 65: temp_action_file ); ! 66: else ! 67: fputs( "ECHO", temp_action_file ); ! 68: ! 69: fputs( ";\n\tYY_BREAK\n", temp_action_file ); ! 70: } ! 71: ; ! 72: ! 73: initlex : ! 74: { ! 75: /* initialize for processing rules */ ! 76: ! 77: /* create default DFA start condition */ ! 78: scinstal( "INITIAL", false ); ! 79: } ! 80: ; ! 81: ! 82: sect1 : sect1 startconddecl WHITESPACE namelist1 '\n' ! 83: | ! 84: | error '\n' ! 85: { synerr( "unknown error processing section 1" ); } ! 86: ; ! 87: ! 88: sect1end : SECTEND ! 89: ; ! 90: ! 91: startconddecl : SCDECL ! 92: { ! 93: /* these productions are separate from the s1object ! 94: * rule because the semantics must be done before ! 95: * we parse the remainder of an s1object ! 96: */ ! 97: ! 98: xcluflg = false; ! 99: } ! 100: ! 101: | XSCDECL ! 102: { xcluflg = true; } ! 103: ; ! 104: ! 105: namelist1 : namelist1 WHITESPACE NAME ! 106: { scinstal( nmstr, xcluflg ); } ! 107: ! 108: | NAME ! 109: { scinstal( nmstr, xcluflg ); } ! 110: ! 111: | error ! 112: { synerr( "bad start condition list" ); } ! 113: ; ! 114: ! 115: sect2 : sect2 initforrule flexrule '\n' ! 116: | ! 117: ; ! 118: ! 119: initforrule : ! 120: { ! 121: /* initialize for a parse of one rule */ ! 122: trlcontxt = variable_trail_rule = varlength = false; ! 123: trailcnt = headcnt = rulelen = 0; ! 124: current_state_type = STATE_NORMAL; ! 125: previous_continued_action = continued_action; ! 126: new_rule(); ! 127: } ! 128: ; ! 129: ! 130: flexrule : scon '^' rule ! 131: { ! 132: pat = $3; ! 133: finish_rule( pat, variable_trail_rule, ! 134: headcnt, trailcnt ); ! 135: ! 136: for ( i = 1; i <= actvp; ++i ) ! 137: scbol[actvsc[i]] = ! 138: mkbranch( scbol[actvsc[i]], pat ); ! 139: ! 140: if ( ! bol_needed ) ! 141: { ! 142: bol_needed = true; ! 143: ! 144: if ( performance_report ) ! 145: pinpoint_message( ! 146: "'^' operator results in sub-optimal performance" ); ! 147: } ! 148: } ! 149: ! 150: | scon rule ! 151: { ! 152: pat = $2; ! 153: finish_rule( pat, variable_trail_rule, ! 154: headcnt, trailcnt ); ! 155: ! 156: for ( i = 1; i <= actvp; ++i ) ! 157: scset[actvsc[i]] = ! 158: mkbranch( scset[actvsc[i]], pat ); ! 159: } ! 160: ! 161: | '^' rule ! 162: { ! 163: pat = $2; ! 164: finish_rule( pat, variable_trail_rule, ! 165: headcnt, trailcnt ); ! 166: ! 167: /* add to all non-exclusive start conditions, ! 168: * including the default (0) start condition ! 169: */ ! 170: ! 171: for ( i = 1; i <= lastsc; ++i ) ! 172: if ( ! scxclu[i] ) ! 173: scbol[i] = mkbranch( scbol[i], pat ); ! 174: ! 175: if ( ! bol_needed ) ! 176: { ! 177: bol_needed = true; ! 178: ! 179: if ( performance_report ) ! 180: pinpoint_message( ! 181: "'^' operator results in sub-optimal performance" ); ! 182: } ! 183: } ! 184: ! 185: | rule ! 186: { ! 187: pat = $1; ! 188: finish_rule( pat, variable_trail_rule, ! 189: headcnt, trailcnt ); ! 190: ! 191: for ( i = 1; i <= lastsc; ++i ) ! 192: if ( ! scxclu[i] ) ! 193: scset[i] = mkbranch( scset[i], pat ); ! 194: } ! 195: ! 196: | scon EOF_OP ! 197: { build_eof_action(); } ! 198: ! 199: | EOF_OP ! 200: { ! 201: /* this EOF applies to all start conditions ! 202: * which don't already have EOF actions ! 203: */ ! 204: actvp = 0; ! 205: ! 206: for ( i = 1; i <= lastsc; ++i ) ! 207: if ( ! sceof[i] ) ! 208: actvsc[++actvp] = i; ! 209: ! 210: if ( actvp == 0 ) ! 211: pinpoint_message( ! 212: "warning - all start conditions already have <<EOF>> rules" ); ! 213: ! 214: else ! 215: build_eof_action(); ! 216: } ! 217: ! 218: | error ! 219: { synerr( "unrecognized rule" ); } ! 220: ; ! 221: ! 222: scon : '<' namelist2 '>' ! 223: ; ! 224: ! 225: namelist2 : namelist2 ',' NAME ! 226: { ! 227: if ( (scnum = sclookup( nmstr )) == 0 ) ! 228: format_pinpoint_message( ! 229: "undeclared start condition %s", nmstr ); ! 230: ! 231: else ! 232: actvsc[++actvp] = scnum; ! 233: } ! 234: ! 235: | NAME ! 236: { ! 237: if ( (scnum = sclookup( nmstr )) == 0 ) ! 238: format_pinpoint_message( ! 239: "undeclared start condition %s", nmstr ); ! 240: else ! 241: actvsc[actvp = 1] = scnum; ! 242: } ! 243: ! 244: | error ! 245: { synerr( "bad start condition list" ); } ! 246: ; ! 247: ! 248: rule : re2 re ! 249: { ! 250: if ( transchar[lastst[$2]] != SYM_EPSILON ) ! 251: /* provide final transition \now/ so it ! 252: * will be marked as a trailing context ! 253: * state ! 254: */ ! 255: $2 = link_machines( $2, mkstate( SYM_EPSILON ) ); ! 256: ! 257: mark_beginning_as_normal( $2 ); ! 258: current_state_type = STATE_NORMAL; ! 259: ! 260: if ( previous_continued_action ) ! 261: { ! 262: /* we need to treat this as variable trailing ! 263: * context so that the backup does not happen ! 264: * in the action but before the action switch ! 265: * statement. If the backup happens in the ! 266: * action, then the rules "falling into" this ! 267: * one's action will *also* do the backup, ! 268: * erroneously. ! 269: */ ! 270: if ( ! varlength || headcnt != 0 ) ! 271: { ! 272: fprintf( stderr, ! 273: "%s: warning - trailing context rule at line %d made variable because\n", ! 274: program_name, linenum ); ! 275: fprintf( stderr, ! 276: " of preceding '|' action\n" ); ! 277: } ! 278: ! 279: /* mark as variable */ ! 280: varlength = true; ! 281: headcnt = 0; ! 282: } ! 283: ! 284: if ( varlength && headcnt == 0 ) ! 285: { /* variable trailing context rule */ ! 286: /* mark the first part of the rule as the accepting ! 287: * "head" part of a trailing context rule ! 288: */ ! 289: /* by the way, we didn't do this at the beginning ! 290: * of this production because back then ! 291: * current_state_type was set up for a trail ! 292: * rule, and add_accept() can create a new ! 293: * state ... ! 294: */ ! 295: add_accept( $1, num_rules | YY_TRAILING_HEAD_MASK ); ! 296: variable_trail_rule = true; ! 297: } ! 298: ! 299: else ! 300: trailcnt = rulelen; ! 301: ! 302: $$ = link_machines( $1, $2 ); ! 303: } ! 304: ! 305: | re2 re '$' ! 306: { synerr( "trailing context used twice" ); } ! 307: ! 308: | re '$' ! 309: { ! 310: if ( trlcontxt ) ! 311: { ! 312: synerr( "trailing context used twice" ); ! 313: $$ = mkstate( SYM_EPSILON ); ! 314: } ! 315: ! 316: else if ( previous_continued_action ) ! 317: { ! 318: /* see the comment in the rule for "re2 re" ! 319: * above ! 320: */ ! 321: if ( ! varlength || headcnt != 0 ) ! 322: { ! 323: fprintf( stderr, ! 324: "%s: warning - trailing context rule at line %d made variable because\n", ! 325: program_name, linenum ); ! 326: fprintf( stderr, ! 327: " of preceding '|' action\n" ); ! 328: } ! 329: ! 330: /* mark as variable */ ! 331: varlength = true; ! 332: headcnt = 0; ! 333: } ! 334: ! 335: trlcontxt = true; ! 336: ! 337: if ( ! varlength ) ! 338: headcnt = rulelen; ! 339: ! 340: ++rulelen; ! 341: trailcnt = 1; ! 342: ! 343: eps = mkstate( SYM_EPSILON ); ! 344: $$ = link_machines( $1, ! 345: link_machines( eps, mkstate( '\n' ) ) ); ! 346: } ! 347: ! 348: | re ! 349: { ! 350: $$ = $1; ! 351: ! 352: if ( trlcontxt ) ! 353: { ! 354: if ( varlength && headcnt == 0 ) ! 355: /* both head and trail are variable-length */ ! 356: variable_trail_rule = true; ! 357: else ! 358: trailcnt = rulelen; ! 359: } ! 360: } ! 361: ; ! 362: ! 363: ! 364: re : re '|' series ! 365: { ! 366: varlength = true; ! 367: $$ = mkor( $1, $3 ); ! 368: } ! 369: ! 370: | series ! 371: { $$ = $1; } ! 372: ; ! 373: ! 374: ! 375: re2 : re '/' ! 376: { ! 377: /* this rule is written separately so ! 378: * the reduction will occur before the trailing ! 379: * series is parsed ! 380: */ ! 381: ! 382: if ( trlcontxt ) ! 383: synerr( "trailing context used twice" ); ! 384: else ! 385: trlcontxt = true; ! 386: ! 387: if ( varlength ) ! 388: /* we hope the trailing context is fixed-length */ ! 389: varlength = false; ! 390: else ! 391: headcnt = rulelen; ! 392: ! 393: rulelen = 0; ! 394: ! 395: current_state_type = STATE_TRAILING_CONTEXT; ! 396: $$ = $1; ! 397: } ! 398: ; ! 399: ! 400: series : series singleton ! 401: { ! 402: /* this is where concatenation of adjacent patterns ! 403: * gets done ! 404: */ ! 405: $$ = link_machines( $1, $2 ); ! 406: } ! 407: ! 408: | singleton ! 409: { $$ = $1; } ! 410: ; ! 411: ! 412: singleton : singleton '*' ! 413: { ! 414: varlength = true; ! 415: ! 416: $$ = mkclos( $1 ); ! 417: } ! 418: ! 419: | singleton '+' ! 420: { ! 421: varlength = true; ! 422: ! 423: $$ = mkposcl( $1 ); ! 424: } ! 425: ! 426: | singleton '?' ! 427: { ! 428: varlength = true; ! 429: ! 430: $$ = mkopt( $1 ); ! 431: } ! 432: ! 433: | singleton '{' NUMBER ',' NUMBER '}' ! 434: { ! 435: varlength = true; ! 436: ! 437: if ( $3 > $5 || $3 < 0 ) ! 438: { ! 439: synerr( "bad iteration values" ); ! 440: $$ = $1; ! 441: } ! 442: else ! 443: { ! 444: if ( $3 == 0 ) ! 445: $$ = mkopt( mkrep( $1, $3, $5 ) ); ! 446: else ! 447: $$ = mkrep( $1, $3, $5 ); ! 448: } ! 449: } ! 450: ! 451: | singleton '{' NUMBER ',' '}' ! 452: { ! 453: varlength = true; ! 454: ! 455: if ( $3 <= 0 ) ! 456: { ! 457: synerr( "iteration value must be positive" ); ! 458: $$ = $1; ! 459: } ! 460: ! 461: else ! 462: $$ = mkrep( $1, $3, INFINITY ); ! 463: } ! 464: ! 465: | singleton '{' NUMBER '}' ! 466: { ! 467: /* the singleton could be something like "(foo)", ! 468: * in which case we have no idea what its length ! 469: * is, so we punt here. ! 470: */ ! 471: varlength = true; ! 472: ! 473: if ( $3 <= 0 ) ! 474: { ! 475: synerr( "iteration value must be positive" ); ! 476: $$ = $1; ! 477: } ! 478: ! 479: else ! 480: $$ = link_machines( $1, copysingl( $1, $3 - 1 ) ); ! 481: } ! 482: ! 483: | '.' ! 484: { ! 485: if ( ! madeany ) ! 486: { ! 487: /* create the '.' character class */ ! 488: anyccl = cclinit(); ! 489: ccladd( anyccl, '\n' ); ! 490: cclnegate( anyccl ); ! 491: ! 492: if ( useecs ) ! 493: mkeccl( ccltbl + cclmap[anyccl], ! 494: ccllen[anyccl], nextecm, ! 495: ecgroup, csize, csize ); ! 496: ! 497: madeany = true; ! 498: } ! 499: ! 500: ++rulelen; ! 501: ! 502: $$ = mkstate( -anyccl ); ! 503: } ! 504: ! 505: | fullccl ! 506: { ! 507: if ( ! cclsorted ) ! 508: /* sort characters for fast searching. We use a ! 509: * shell sort since this list could be large. ! 510: */ ! 511: cshell( ccltbl + cclmap[$1], ccllen[$1], true ); ! 512: ! 513: if ( useecs ) ! 514: mkeccl( ccltbl + cclmap[$1], ccllen[$1], ! 515: nextecm, ecgroup, csize, csize ); ! 516: ! 517: ++rulelen; ! 518: ! 519: $$ = mkstate( -$1 ); ! 520: } ! 521: ! 522: | PREVCCL ! 523: { ! 524: ++rulelen; ! 525: ! 526: $$ = mkstate( -$1 ); ! 527: } ! 528: ! 529: | '"' string '"' ! 530: { $$ = $2; } ! 531: ! 532: | '(' re ')' ! 533: { $$ = $2; } ! 534: ! 535: | CHAR ! 536: { ! 537: ++rulelen; ! 538: ! 539: if ( caseins && $1 >= 'A' && $1 <= 'Z' ) ! 540: $1 = clower( $1 ); ! 541: ! 542: $$ = mkstate( $1 ); ! 543: } ! 544: ; ! 545: ! 546: fullccl : '[' ccl ']' ! 547: { $$ = $2; } ! 548: ! 549: | '[' '^' ccl ']' ! 550: { ! 551: /* *Sigh* - to be compatible Unix lex, negated ccls ! 552: * match newlines ! 553: */ ! 554: #ifdef NOTDEF ! 555: ccladd( $3, '\n' ); /* negated ccls don't match '\n' */ ! 556: cclsorted = false; /* because we added the newline */ ! 557: #endif ! 558: cclnegate( $3 ); ! 559: $$ = $3; ! 560: } ! 561: ; ! 562: ! 563: ccl : ccl CHAR '-' CHAR ! 564: { ! 565: if ( $2 > $4 ) ! 566: synerr( "negative range in character class" ); ! 567: ! 568: else ! 569: { ! 570: if ( caseins ) ! 571: { ! 572: if ( $2 >= 'A' && $2 <= 'Z' ) ! 573: $2 = clower( $2 ); ! 574: if ( $4 >= 'A' && $4 <= 'Z' ) ! 575: $4 = clower( $4 ); ! 576: } ! 577: ! 578: for ( i = $2; i <= $4; ++i ) ! 579: ccladd( $1, i ); ! 580: ! 581: /* keep track if this ccl is staying in alphabetical ! 582: * order ! 583: */ ! 584: cclsorted = cclsorted && ($2 > lastchar); ! 585: lastchar = $4; ! 586: } ! 587: ! 588: $$ = $1; ! 589: } ! 590: ! 591: | ccl CHAR ! 592: { ! 593: if ( caseins ) ! 594: if ( $2 >= 'A' && $2 <= 'Z' ) ! 595: $2 = clower( $2 ); ! 596: ! 597: ccladd( $1, $2 ); ! 598: cclsorted = cclsorted && ($2 > lastchar); ! 599: lastchar = $2; ! 600: $$ = $1; ! 601: } ! 602: ! 603: | ! 604: { ! 605: cclsorted = true; ! 606: lastchar = 0; ! 607: $$ = cclinit(); ! 608: } ! 609: ; ! 610: ! 611: string : string CHAR ! 612: { ! 613: if ( caseins ) ! 614: if ( $2 >= 'A' && $2 <= 'Z' ) ! 615: $2 = clower( $2 ); ! 616: ! 617: ++rulelen; ! 618: ! 619: $$ = link_machines( $1, mkstate( $2 ) ); ! 620: } ! 621: ! 622: | ! 623: { $$ = mkstate( SYM_EPSILON ); } ! 624: ; ! 625: ! 626: %% ! 627: ! 628: ! 629: /* build_eof_action - build the "<<EOF>>" action for the active start ! 630: * conditions ! 631: */ ! 632: ! 633: void build_eof_action() ! 634: ! 635: { ! 636: register int i; ! 637: ! 638: for ( i = 1; i <= actvp; ++i ) ! 639: { ! 640: if ( sceof[actvsc[i]] ) ! 641: format_pinpoint_message( ! 642: "multiple <<EOF>> rules for start condition %s", ! 643: scname[actvsc[i]] ); ! 644: ! 645: else ! 646: { ! 647: sceof[actvsc[i]] = true; ! 648: fprintf( temp_action_file, "case YY_STATE_EOF(%s):\n", ! 649: scname[actvsc[i]] ); ! 650: } ! 651: } ! 652: ! 653: line_directive_out( temp_action_file ); ! 654: } ! 655: ! 656: ! 657: /* synerr - report a syntax error */ ! 658: ! 659: void synerr( str ) ! 660: char str[]; ! 661: ! 662: { ! 663: syntaxerror = true; ! 664: pinpoint_message( str ); ! 665: } ! 666: ! 667: ! 668: /* format_pinpoint_message - write out a message formatted with one string, ! 669: * pinpointing its location ! 670: */ ! 671: ! 672: void format_pinpoint_message( msg, arg ) ! 673: char msg[], arg[]; ! 674: ! 675: { ! 676: char errmsg[MAXLINE]; ! 677: ! 678: (void) sprintf( errmsg, msg, arg ); ! 679: pinpoint_message( errmsg ); ! 680: } ! 681: ! 682: ! 683: /* pinpoint_message - write out a message, pinpointing its location */ ! 684: ! 685: void pinpoint_message( str ) ! 686: char str[]; ! 687: ! 688: { ! 689: fprintf( stderr, "\"%s\", line %d: %s\n", infilename, linenum, str ); ! 690: } ! 691: ! 692: ! 693: /* yyerror - eat up an error message from the parser; ! 694: * currently, messages are ignore ! 695: */ ! 696: ! 697: void yyerror( msg ) ! 698: char msg[]; ! 699: ! 700: { ! 701: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.