| 1 | # include "dextern" |
| 2 | # define IDENTIFIER 257 |
| 3 | # define MARK 258 |
| 4 | # define TERM 259 |
| 5 | # define LEFT 260 |
| 6 | # define RIGHT 261 |
| 7 | # define BINARY 262 |
| 8 | # define PREC 263 |
| 9 | # define LCURLY 264 |
| 10 | # define C_IDENTIFIER 265 /* name followed by colon */ |
| 11 | # define NUMBER 266 |
| 12 | # define START 267 |
| 13 | # define TYPEDEF 268 |
| 14 | # define TYPENAME 269 |
| 15 | # define UNION 270 |
| 16 | # define ENDFILE 0 |
| 17 | |
| 18 | /* communication variables between various I/O routines */ |
| 19 | |
| 20 | char *infile; /* input file name */ |
| 21 | int numbval; /* value of an input number */ |
| 22 | char tokname[NAMESIZE]; /* input token name */ |
| 23 | |
| 24 | /* storage of names */ |
| 25 | |
| 26 | char cnames[CNAMSZ]; /* place where token and nonterminal names are stored */ |
| 27 | int cnamsz = CNAMSZ; /* size of cnames */ |
| 28 | char * cnamp = cnames; /* place where next name is to be put in */ |
| 29 | int ndefout = 3; /* number of defined symbols output */ |
| 30 | |
| 31 | /* storage of types */ |
| 32 | int ntypes; /* number of types defined */ |
| 33 | char * typeset[NTYPES]; /* pointers to type tags */ |
| 34 | |
| 35 | /* symbol tables for tokens and nonterminals */ |
| 36 | |
| 37 | int ntokens = 0; |
| 38 | struct toksymb tokset[NTERMS]; |
| 39 | int toklev[NTERMS]; |
| 40 | int nnonter = -1; |
| 41 | struct ntsymb nontrst[NNONTERM]; |
| 42 | int start; /* start symbol */ |
| 43 | |
| 44 | /* assigned token type values */ |
| 45 | int extval = 0; |
| 46 | |
| 47 | /* input and output file descriptors */ |
| 48 | |
| 49 | FILE * finput; /* yacc input file */ |
| 50 | FILE * faction; /* file for saving actions */ |
| 51 | FILE * fdefine; /* file for # defines */ |
| 52 | FILE * ftable; /* y.tab.c file */ |
| 53 | FILE * ftemp; /* tempfile to pass 2 */ |
| 54 | FILE * foutput; /* y.output file */ |
| 55 | |
| 56 | /* storage for grammar rules */ |
| 57 | |
| 58 | int mem0[MEMSIZE] ; /* production storage */ |
| 59 | int *mem = mem0; |
| 60 | int nprod= 1; /* number of productions */ |
| 61 | int *prdptr[NPROD]; /* pointers to descriptions of productions */ |
| 62 | int levprd[NPROD] ; /* precedence levels for the productions */ |
| 63 | |
| 64 | |
| 65 | setup(argc,argv) int argc; char *argv[]; |
| 66 | { int i,j,lev,t, ty; |
| 67 | int c; |
| 68 | int *p; |
| 69 | char actname[8]; |
| 70 | |
| 71 | foutput = NULL; |
| 72 | fdefine = NULL; |
| 73 | i = 1; |
| 74 | while( argc >= 2 && argv[1][0] == '-' ) { |
| 75 | while( *++(argv[1]) ){ |
| 76 | switch( *argv[1] ){ |
| 77 | case 'v': |
| 78 | case 'V': |
| 79 | foutput = fopen(FILEU, "w" ); |
| 80 | if( foutput == NULL ) error( "cannot open y.output" ); |
| 81 | continue; |
| 82 | case 'D': |
| 83 | case 'd': |
| 84 | fdefine = fopen( FILED, "w" ); |
| 85 | continue; |
| 86 | case 'o': |
| 87 | case 'O': |
| 88 | fprintf( stderr, "`o' flag now default in yacc\n" ); |
| 89 | continue; |
| 90 | |
| 91 | case 'r': |
| 92 | case 'R': |
| 93 | error( "Ratfor Yacc is dead: sorry...\n" ); |
| 94 | |
| 95 | default: |
| 96 | error( "illegal option: %c", *argv[1]); |
| 97 | } |
| 98 | } |
| 99 | argv++; |
| 100 | argc--; |
| 101 | } |
| 102 | |
| 103 | ftable = fopen( OFILE, "w" ); |
| 104 | if( ftable == NULL ) error( "cannot open table file" ); |
| 105 | |
| 106 | ftemp = fopen( TEMPNAME, "w" ); |
| 107 | faction = fopen( ACTNAME, "w" ); |
| 108 | if( ftemp==NULL || faction==NULL ) error( "cannot open temp file" ); |
| 109 | |
| 110 | if( argc < 2 || ((finput=fopen( infile=argv[1], "r" )) == NULL ) ){ |
| 111 | error( "cannot open input file" ); |
| 112 | } |
| 113 | |
| 114 | cnamp = cnames; |
| 115 | defin(0,"$end"); |
| 116 | extval = 0400; |
| 117 | defin(0,"error"); |
| 118 | defin(1,"$accept"); |
| 119 | mem=mem0; |
| 120 | lev = 0; |
| 121 | ty = 0; |
| 122 | i=0; |
| 123 | |
| 124 | /* sorry -- no yacc parser here..... |
| 125 | we must bootstrap somehow... */ |
| 126 | |
| 127 | for( t=gettok(); t!=MARK && t!= ENDFILE; ){ |
| 128 | switch( t ){ |
| 129 | |
| 130 | case ';': |
| 131 | t = gettok(); |
| 132 | break; |
| 133 | |
| 134 | case START: |
| 135 | if( (t=gettok()) != IDENTIFIER ){ |
| 136 | error( "bad %%start construction" ); |
| 137 | } |
| 138 | start = chfind(1,tokname); |
| 139 | t = gettok(); |
| 140 | continue; |
| 141 | |
| 142 | case TYPEDEF: |
| 143 | if( (t=gettok()) != TYPENAME ) error( "bad syntax in %%type" ); |
| 144 | ty = numbval; |
| 145 | for(;;){ |
| 146 | t = gettok(); |
| 147 | switch( t ){ |
| 148 | |
| 149 | case IDENTIFIER: |
| 150 | if( (t=chfind( 1, tokname ) ) < NTBASE ) { |
| 151 | j = TYPE( toklev[t] ); |
| 152 | if( j!= 0 && j != ty ){ |
| 153 | error( "type redeclaration of token %s", |
| 154 | tokset[t].name ); |
| 155 | } |
| 156 | else SETTYPE( toklev[t],ty); |
| 157 | } |
| 158 | else { |
| 159 | j = nontrst[t-NTBASE].tvalue; |
| 160 | if( j != 0 && j != ty ){ |
| 161 | error( "type redeclaration of nonterminal %s", |
| 162 | nontrst[t-NTBASE].name ); |
| 163 | } |
| 164 | else nontrst[t-NTBASE].tvalue = ty; |
| 165 | } |
| 166 | case ',': |
| 167 | continue; |
| 168 | |
| 169 | case ';': |
| 170 | t = gettok(); |
| 171 | break; |
| 172 | default: |
| 173 | break; |
| 174 | } |
| 175 | break; |
| 176 | } |
| 177 | continue; |
| 178 | |
| 179 | case UNION: |
| 180 | /* copy the union declaration to the output */ |
| 181 | cpyunion(); |
| 182 | t = gettok(); |
| 183 | continue; |
| 184 | |
| 185 | case LEFT: |
| 186 | case BINARY: |
| 187 | case RIGHT: |
| 188 | ++i; |
| 189 | case TERM: |
| 190 | lev = t-TERM; /* nonzero means new prec. and assoc. */ |
| 191 | ty = 0; |
| 192 | |
| 193 | /* get identifiers so defined */ |
| 194 | |
| 195 | t = gettok(); |
| 196 | if( t == TYPENAME ){ /* there is a type defined */ |
| 197 | ty = numbval; |
| 198 | t = gettok(); |
| 199 | } |
| 200 | |
| 201 | for(;;) { |
| 202 | switch( t ){ |
| 203 | |
| 204 | case ',': |
| 205 | t = gettok(); |
| 206 | continue; |
| 207 | |
| 208 | case ';': |
| 209 | break; |
| 210 | |
| 211 | case IDENTIFIER: |
| 212 | j = chfind(0,tokname); |
| 213 | if( lev ){ |
| 214 | if( ASSOC(toklev[j]) ) error( "redeclaration of precedence of %s", tokname ); |
| 215 | SETASC(toklev[j],lev); |
| 216 | SETPLEV(toklev[j],i); |
| 217 | } |
| 218 | if( ty ){ |
| 219 | if( TYPE(toklev[j]) ) error( "redeclaration of type of %s", tokname ); |
| 220 | SETTYPE(toklev[j],ty); |
| 221 | } |
| 222 | if( (t=gettok()) == NUMBER ){ |
| 223 | tokset[j].value = numbval; |
| 224 | if( j < ndefout && j>2 ){ |
| 225 | error( "please define type number of %s earlier", |
| 226 | tokset[j].name ); |
| 227 | } |
| 228 | t=gettok(); |
| 229 | } |
| 230 | continue; |
| 231 | |
| 232 | } |
| 233 | |
| 234 | break; |
| 235 | } |
| 236 | |
| 237 | continue; |
| 238 | |
| 239 | case LCURLY: |
| 240 | defout(); |
| 241 | cpycode(); |
| 242 | t = gettok(); |
| 243 | continue; |
| 244 | |
| 245 | default: |
| 246 | error( "syntax error" ); |
| 247 | |
| 248 | } |
| 249 | |
| 250 | } |
| 251 | |
| 252 | if( t == ENDFILE ){ |
| 253 | error( "unexpected EOF before %%" ); |
| 254 | } |
| 255 | |
| 256 | /* t is MARK */ |
| 257 | |
| 258 | defout(); |
| 259 | |
| 260 | fprintf( ftable, "#define yyclearin yychar = -1\n" ); |
| 261 | fprintf( ftable, "#define yyerrok yyerrflag = 0\n" ); |
| 262 | fprintf( ftable, "extern int yychar;\nextern short yyerrflag;\n" ); |
| 263 | fprintf( ftable, "#ifndef YYMAXDEPTH\n#define YYMAXDEPTH 150\n#endif\n" ); |
| 264 | if( !ntypes ) fprintf( ftable, "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n" ); |
| 265 | fprintf( ftable, "YYSTYPE yylval, yyval;\n" ); |
| 266 | |
| 267 | prdptr[0]=mem; |
| 268 | /* added production */ |
| 269 | *mem++ = NTBASE; |
| 270 | *mem++ = start; /* if start is 0, we will overwrite with the lhs of the first rule */ |
| 271 | *mem++ = 1; |
| 272 | *mem++ = 0; |
| 273 | prdptr[1]=mem; |
| 274 | |
| 275 | while( (t=gettok()) == LCURLY ) cpycode(); |
| 276 | |
| 277 | if( t != C_IDENTIFIER ) error( "bad syntax on first rule" ); |
| 278 | |
| 279 | if( !start ) prdptr[0][1] = chfind(1,tokname); |
| 280 | |
| 281 | /* read rules */ |
| 282 | |
| 283 | while( t!=MARK && t!=ENDFILE ){ |
| 284 | |
| 285 | /* process a rule */ |
| 286 | |
| 287 | if( t == '|' ){ |
| 288 | *mem++ = *prdptr[nprod-1]; |
| 289 | } |
| 290 | else if( t == C_IDENTIFIER ){ |
| 291 | *mem = chfind(1,tokname); |
| 292 | if( *mem < NTBASE ) error( "token illegal on LHS of grammar rule" ); |
| 293 | ++mem; |
| 294 | } |
| 295 | else error( "illegal rule: missing semicolon or | ?" ); |
| 296 | |
| 297 | /* read rule body */ |
| 298 | |
| 299 | |
| 300 | t = gettok(); |
| 301 | more_rule: |
| 302 | while( t == IDENTIFIER ) { |
| 303 | *mem = chfind(1,tokname); |
| 304 | if( *mem<NTBASE ) levprd[nprod] = toklev[*mem]; |
| 305 | ++mem; |
| 306 | t = gettok(); |
| 307 | } |
| 308 | |
| 309 | |
| 310 | if( t == PREC ){ |
| 311 | if( gettok()!=IDENTIFIER) error( "illegal %%prec syntax" ); |
| 312 | j = chfind(2,tokname); |
| 313 | if( j>=NTBASE)error("nonterminal %s illegal after %%prec", nontrst[j-NTBASE].name); |
| 314 | levprd[nprod]=toklev[j]; |
| 315 | t = gettok(); |
| 316 | } |
| 317 | |
| 318 | if( t == '=' ){ |
| 319 | levprd[nprod] |= ACTFLAG; |
| 320 | fprintf( faction, "\ncase %d:", nprod ); |
| 321 | cpyact( mem-prdptr[nprod]-1 ); |
| 322 | fprintf( faction, " break;" ); |
| 323 | if( (t=gettok()) == IDENTIFIER ){ |
| 324 | /* action within rule... */ |
| 325 | |
| 326 | sprintf( actname, "$$%d", nprod ); |
| 327 | j = chfind(1,actname); /* make it a nonterminal */ |
| 328 | |
| 329 | /* the current rule will become rule number nprod+1 */ |
| 330 | /* move the contents down, and make room for the null */ |
| 331 | |
| 332 | for( p=mem; p>=prdptr[nprod]; --p ) p[2] = *p; |
| 333 | mem += 2; |
| 334 | |
| 335 | /* enter null production for action */ |
| 336 | |
| 337 | p = prdptr[nprod]; |
| 338 | |
| 339 | *p++ = j; |
| 340 | *p++ = -nprod; |
| 341 | |
| 342 | /* update the production information */ |
| 343 | |
| 344 | levprd[nprod+1] = levprd[nprod] & ~ACTFLAG; |
| 345 | levprd[nprod] = ACTFLAG; |
| 346 | |
| 347 | if( ++nprod >= NPROD ) error( "more than %d rules", NPROD ); |
| 348 | prdptr[nprod] = p; |
| 349 | |
| 350 | /* make the action appear in the original rule */ |
| 351 | *mem++ = j; |
| 352 | |
| 353 | /* get some more of the rule */ |
| 354 | |
| 355 | goto more_rule; |
| 356 | } |
| 357 | |
| 358 | } |
| 359 | |
| 360 | while( t == ';' ) t = gettok(); |
| 361 | |
| 362 | *mem++ = -nprod; |
| 363 | |
| 364 | /* check that default action is reasonable */ |
| 365 | |
| 366 | if( ntypes && !(levprd[nprod]&ACTFLAG) && nontrst[*prdptr[nprod]-NTBASE].tvalue ){ |
| 367 | /* no explicit action, LHS has value */ |
| 368 | register tempty; |
| 369 | tempty = prdptr[nprod][1]; |
| 370 | if( tempty < 0 ) error( "must return a value, since LHS has a type" ); |
| 371 | else if( tempty >= NTBASE ) tempty = nontrst[tempty-NTBASE].tvalue; |
| 372 | else tempty = TYPE( toklev[tempty] ); |
| 373 | if( tempty != nontrst[*prdptr[nprod]-NTBASE].tvalue ){ |
| 374 | error( "default action causes potential type clash" ); |
| 375 | } |
| 376 | } |
| 377 | |
| 378 | if( ++nprod >= NPROD ) error( "more than %d rules", NPROD ); |
| 379 | prdptr[nprod] = mem; |
| 380 | levprd[nprod]=0; |
| 381 | |
| 382 | } |
| 383 | |
| 384 | /* end of all rules */ |
| 385 | |
| 386 | finact(); |
| 387 | if( t == MARK ){ |
| 388 | fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile ); |
| 389 | while( (c=getc(finput)) != EOF ) putc( c, ftable ); |
| 390 | } |
| 391 | fclose( finput ); |
| 392 | } |
| 393 | |
| 394 | finact(){ |
| 395 | /* finish action routine */ |
| 396 | |
| 397 | fclose(faction); |
| 398 | |
| 399 | fprintf( ftable, "# define YYERRCODE %d\n", tokset[2].value ); |
| 400 | |
| 401 | } |
| 402 | |
| 403 | defin( t, s ) register char *s; { |
| 404 | /* define s to be a terminal if t=0 |
| 405 | or a nonterminal if t=1 */ |
| 406 | |
| 407 | register val; |
| 408 | |
| 409 | if (t) { |
| 410 | if( ++nnonter >= NNONTERM ) error("too many nonterminals, limit %d",NNONTERM); |
| 411 | nontrst[nnonter].name = cstash(s); |
| 412 | return( NTBASE + nnonter ); |
| 413 | } |
| 414 | /* must be a token */ |
| 415 | if( ++ntokens >= NTERMS ) error("too many terminals, limit %d",NTERMS ); |
| 416 | tokset[ntokens].name = cstash(s); |
| 417 | |
| 418 | /* establish value for token */ |
| 419 | |
| 420 | if( s[0]==' ' && s[2]=='\0' ) /* single character literal */ |
| 421 | val = s[1]; |
| 422 | else if ( s[0]==' ' && s[1]=='\\' ) { /* escape sequence */ |
| 423 | if( s[3] == '\0' ){ /* single character escape sequence */ |
| 424 | switch ( s[2] ){ |
| 425 | /* character which is escaped */ |
| 426 | case 'n': val = '\n'; break; |
| 427 | case 'r': val = '\r'; break; |
| 428 | case 'b': val = '\b'; break; |
| 429 | case 't': val = '\t'; break; |
| 430 | case 'f': val = '\f'; break; |
| 431 | case '\'': val = '\''; break; |
| 432 | case '"': val = '"'; break; |
| 433 | case '\\': val = '\\'; break; |
| 434 | default: error( "invalid escape" ); |
| 435 | } |
| 436 | } |
| 437 | else if( s[2] <= '7' && s[2]>='0' ){ /* \nnn sequence */ |
| 438 | if( s[3]<'0' || s[3] > '7' || s[4]<'0' || |
| 439 | s[4]>'7' || s[5] != '\0' ) error("illegal \\nnn construction" ); |
| 440 | val = 64*s[2] + 8*s[3] + s[4] - 73*'0'; |
| 441 | if( val == 0 ) error( "'\\000' is illegal" ); |
| 442 | } |
| 443 | } |
| 444 | else { |
| 445 | val = extval++; |
| 446 | } |
| 447 | tokset[ntokens].value = val; |
| 448 | toklev[ntokens] = 0; |
| 449 | return( ntokens ); |
| 450 | } |
| 451 | |
| 452 | defout(){ /* write out the defines (at the end of the declaration section) */ |
| 453 | |
| 454 | register int i, c; |
| 455 | register char *cp; |
| 456 | |
| 457 | for( i=ndefout; i<=ntokens; ++i ){ |
| 458 | |
| 459 | cp = tokset[i].name; |
| 460 | if( *cp == ' ' ) ++cp; /* literals */ |
| 461 | |
| 462 | for( ; (c= *cp)!='\0'; ++cp ){ |
| 463 | |
| 464 | if( islower(c) || isupper(c) || isdigit(c) || c=='_' ); /* VOID */ |
| 465 | else goto nodef; |
| 466 | } |
| 467 | |
| 468 | fprintf( ftable, "# define %s %d\n", tokset[i].name, tokset[i].value ); |
| 469 | if( fdefine != NULL ) fprintf( fdefine, "# define %s %d\n", tokset[i].name, tokset[i].value ); |
| 470 | |
| 471 | nodef: ; |
| 472 | } |
| 473 | |
| 474 | ndefout = ntokens+1; |
| 475 | |
| 476 | } |
| 477 | |
| 478 | char * |
| 479 | cstash( s ) register char *s; { |
| 480 | char *temp; |
| 481 | |
| 482 | temp = cnamp; |
| 483 | do { |
| 484 | if( cnamp >= &cnames[cnamsz] ) error("too many characters in id's and literals" ); |
| 485 | else *cnamp++ = *s; |
| 486 | } while ( *s++ ); |
| 487 | return( temp ); |
| 488 | } |
| 489 | |
| 490 | gettok() { |
| 491 | register i, base; |
| 492 | static int peekline; /* number of '\n' seen in lookahead */ |
| 493 | register c, match, reserve; |
| 494 | |
| 495 | begin: |
| 496 | reserve = 0; |
| 497 | lineno += peekline; |
| 498 | peekline = 0; |
| 499 | c = getc(finput); |
| 500 | while( c==' ' || c=='\n' || c=='\t' || c=='\f' ){ |
| 501 | if( c == '\n' ) ++lineno; |
| 502 | c=getc(finput); |
| 503 | } |
| 504 | if( c == '/' ){ /* skip comment */ |
| 505 | lineno += skipcom(); |
| 506 | goto begin; |
| 507 | } |
| 508 | |
| 509 | switch(c){ |
| 510 | |
| 511 | case EOF: |
| 512 | return(ENDFILE); |
| 513 | case '{': |
| 514 | ungetc( c, finput ); |
| 515 | return( '=' ); /* action ... */ |
| 516 | case '<': /* get, and look up, a type name (union member name) */ |
| 517 | i = 0; |
| 518 | while( (c=getc(finput)) != '>' && c>=0 && c!= '\n' ){ |
| 519 | tokname[i] = c; |
| 520 | if( ++i >= NAMESIZE ) --i; |
| 521 | } |
| 522 | if( c != '>' ) error( "unterminated < ... > clause" ); |
| 523 | tokname[i] = '\0'; |
| 524 | for( i=1; i<=ntypes; ++i ){ |
| 525 | if( !strcmp( typeset[i], tokname ) ){ |
| 526 | numbval = i; |
| 527 | return( TYPENAME ); |
| 528 | } |
| 529 | } |
| 530 | typeset[numbval = ++ntypes] = cstash( tokname ); |
| 531 | return( TYPENAME ); |
| 532 | |
| 533 | case '"': |
| 534 | case '\'': |
| 535 | match = c; |
| 536 | tokname[0] = ' '; |
| 537 | i = 1; |
| 538 | for(;;){ |
| 539 | c = getc(finput); |
| 540 | if( c == '\n' || c == EOF ) |
| 541 | error("illegal or missing ' or \"" ); |
| 542 | if( c == '\\' ){ |
| 543 | c = getc(finput); |
| 544 | tokname[i] = '\\'; |
| 545 | if( ++i >= NAMESIZE ) --i; |
| 546 | } |
| 547 | else if( c == match ) break; |
| 548 | tokname[i] = c; |
| 549 | if( ++i >= NAMESIZE ) --i; |
| 550 | } |
| 551 | break; |
| 552 | |
| 553 | case '%': |
| 554 | case '\\': |
| 555 | |
| 556 | switch(c=getc(finput)) { |
| 557 | |
| 558 | case '0': return(TERM); |
| 559 | case '<': return(LEFT); |
| 560 | case '2': return(BINARY); |
| 561 | case '>': return(RIGHT); |
| 562 | case '%': |
| 563 | case '\\': return(MARK); |
| 564 | case '=': return(PREC); |
| 565 | case '{': return(LCURLY); |
| 566 | default: reserve = 1; |
| 567 | } |
| 568 | |
| 569 | default: |
| 570 | |
| 571 | if( isdigit(c) ){ /* number */ |
| 572 | numbval = c-'0' ; |
| 573 | base = (c=='0') ? 8 : 10 ; |
| 574 | for( c=getc(finput); isdigit(c) ; c=getc(finput) ){ |
| 575 | numbval = numbval*base + c - '0'; |
| 576 | } |
| 577 | ungetc( c, finput ); |
| 578 | return(NUMBER); |
| 579 | } |
| 580 | else if( islower(c) || isupper(c) || c=='_' || c=='.' || c=='$' ){ |
| 581 | i = 0; |
| 582 | while( islower(c) || isupper(c) || isdigit(c) || c=='_' || c=='.' || c=='$' ){ |
| 583 | tokname[i] = c; |
| 584 | if( reserve && isupper(c) ) tokname[i] += 'a'-'A'; |
| 585 | if( ++i >= NAMESIZE ) --i; |
| 586 | c = getc(finput); |
| 587 | } |
| 588 | } |
| 589 | else return(c); |
| 590 | |
| 591 | ungetc( c, finput ); |
| 592 | } |
| 593 | |
| 594 | tokname[i] = '\0'; |
| 595 | |
| 596 | if( reserve ){ /* find a reserved word */ |
| 597 | if( !strcmp(tokname,"term")) return( TERM ); |
| 598 | if( !strcmp(tokname,"token")) return( TERM ); |
| 599 | if( !strcmp(tokname,"left")) return( LEFT ); |
| 600 | if( !strcmp(tokname,"nonassoc")) return( BINARY ); |
| 601 | if( !strcmp(tokname,"binary")) return( BINARY ); |
| 602 | if( !strcmp(tokname,"right")) return( RIGHT ); |
| 603 | if( !strcmp(tokname,"prec")) return( PREC ); |
| 604 | if( !strcmp(tokname,"start")) return( START ); |
| 605 | if( !strcmp(tokname,"type")) return( TYPEDEF ); |
| 606 | if( !strcmp(tokname,"union")) return( UNION ); |
| 607 | error("invalid escape, or illegal reserved word: %s", tokname ); |
| 608 | } |
| 609 | |
| 610 | /* look ahead to distinguish IDENTIFIER from C_IDENTIFIER */ |
| 611 | |
| 612 | c = getc(finput); |
| 613 | while( c==' ' || c=='\t'|| c=='\n' || c=='\f' || c== '/' ) { |
| 614 | if( c == '\n' ) ++peekline; |
| 615 | else if( c == '/' ){ /* look for comments */ |
| 616 | peekline += skipcom(); |
| 617 | } |
| 618 | c = getc(finput); |
| 619 | } |
| 620 | if( c == ':' ) return( C_IDENTIFIER ); |
| 621 | ungetc( c, finput ); |
| 622 | return( IDENTIFIER ); |
| 623 | } |
| 624 | |
| 625 | fdtype( t ){ /* determine the type of a symbol */ |
| 626 | register v; |
| 627 | if( t >= NTBASE ) v = nontrst[t-NTBASE].tvalue; |
| 628 | else v = TYPE( toklev[t] ); |
| 629 | if( v <= 0 ) error( "must specify type for %s", (t>=NTBASE)?nontrst[t-NTBASE].name: |
| 630 | tokset[t].name ); |
| 631 | return( v ); |
| 632 | } |
| 633 | |
| 634 | chfind( t, s ) register char *s; { |
| 635 | int i; |
| 636 | |
| 637 | if (s[0]==' ')t=0; |
| 638 | TLOOP(i){ |
| 639 | if(!strcmp(s,tokset[i].name)){ |
| 640 | return( i ); |
| 641 | } |
| 642 | } |
| 643 | NTLOOP(i){ |
| 644 | if(!strcmp(s,nontrst[i].name)) { |
| 645 | return( i+NTBASE ); |
| 646 | } |
| 647 | } |
| 648 | /* cannot find name */ |
| 649 | if( t>1 ) |
| 650 | error( "%s should have been defined earlier", s ); |
| 651 | return( defin( t, s ) ); |
| 652 | } |
| 653 | |
| 654 | cpyunion(){ |
| 655 | /* copy the union declaration to the output, and the define file if present */ |
| 656 | |
| 657 | int level, c; |
| 658 | fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile ); |
| 659 | fprintf( ftable, "typedef union " ); |
| 660 | if( fdefine ) fprintf( fdefine, "\ntypedef union " ); |
| 661 | |
| 662 | level = 0; |
| 663 | for(;;){ |
| 664 | if( (c=getc(finput)) < 0 ) error( "EOF encountered while processing %%union" ); |
| 665 | putc( c, ftable ); |
| 666 | if( fdefine ) putc( c, fdefine ); |
| 667 | |
| 668 | switch( c ){ |
| 669 | |
| 670 | case '\n': |
| 671 | ++lineno; |
| 672 | break; |
| 673 | |
| 674 | case '{': |
| 675 | ++level; |
| 676 | break; |
| 677 | |
| 678 | case '}': |
| 679 | --level; |
| 680 | if( level == 0 ) { /* we are finished copying */ |
| 681 | fprintf( ftable, " YYSTYPE;\n" ); |
| 682 | if( fdefine ) fprintf( fdefine, " YYSTYPE;\nextern YYSTYPE yylval;\n" ); |
| 683 | return; |
| 684 | } |
| 685 | } |
| 686 | } |
| 687 | } |
| 688 | |
| 689 | cpycode(){ /* copies code between \{ and \} */ |
| 690 | |
| 691 | int c; |
| 692 | c = getc(finput); |
| 693 | if( c == '\n' ) { |
| 694 | c = getc(finput); |
| 695 | lineno++; |
| 696 | } |
| 697 | fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile ); |
| 698 | while( c>=0 ){ |
| 699 | if( c=='\\' ) |
| 700 | if( (c=getc(finput)) == '}' ) return; |
| 701 | else putc('\\', ftable ); |
| 702 | if( c=='%' ) |
| 703 | if( (c=getc(finput)) == '}' ) return; |
| 704 | else putc('%', ftable ); |
| 705 | putc( c , ftable ); |
| 706 | if( c == '\n' ) ++lineno; |
| 707 | c = getc(finput); |
| 708 | } |
| 709 | error("eof before %%}" ); |
| 710 | } |
| 711 | |
| 712 | skipcom(){ /* skip over comments */ |
| 713 | register c, i=0; /* i is the number of lines skipped */ |
| 714 | |
| 715 | /* skipcom is called after reading a / */ |
| 716 | |
| 717 | if( getc(finput) != '*' ) error( "illegal comment" ); |
| 718 | c = getc(finput); |
| 719 | while( c != EOF ){ |
| 720 | while( c == '*' ){ |
| 721 | if( (c=getc(finput)) == '/' ) return( i ); |
| 722 | } |
| 723 | if( c == '\n' ) ++i; |
| 724 | c = getc(finput); |
| 725 | } |
| 726 | error( "EOF inside comment" ); |
| 727 | /* NOTREACHED */ |
| 728 | } |
| 729 | |
| 730 | cpyact(offset){ /* copy C action to the next ; or closing } */ |
| 731 | int brac, c, match, j, s, tok; |
| 732 | |
| 733 | fprintf( faction, "\n# line %d \"%s\"\n", lineno, infile ); |
| 734 | |
| 735 | brac = 0; |
| 736 | |
| 737 | loop: |
| 738 | c = getc(finput); |
| 739 | swt: |
| 740 | switch( c ){ |
| 741 | |
| 742 | case ';': |
| 743 | if( brac == 0 ){ |
| 744 | putc( c , faction ); |
| 745 | return; |
| 746 | } |
| 747 | goto lcopy; |
| 748 | |
| 749 | case '{': |
| 750 | brac++; |
| 751 | goto lcopy; |
| 752 | |
| 753 | case '$': |
| 754 | s = 1; |
| 755 | tok = -1; |
| 756 | c = getc(finput); |
| 757 | if( c == '<' ){ /* type description */ |
| 758 | ungetc( c, finput ); |
| 759 | if( gettok() != TYPENAME ) error( "bad syntax on $<ident> clause" ); |
| 760 | tok = numbval; |
| 761 | c = getc(finput); |
| 762 | } |
| 763 | if( c == '$' ){ |
| 764 | fprintf( faction, "yyval"); |
| 765 | if( ntypes ){ /* put out the proper tag... */ |
| 766 | if( tok < 0 ) tok = fdtype( *prdptr[nprod] ); |
| 767 | fprintf( faction, ".%s", typeset[tok] ); |
| 768 | } |
| 769 | goto loop; |
| 770 | } |
| 771 | if( c == '-' ){ |
| 772 | s = -s; |
| 773 | c = getc(finput); |
| 774 | } |
| 775 | if( isdigit(c) ){ |
| 776 | j=0; |
| 777 | while( isdigit(c) ){ |
| 778 | j= j*10+c-'0'; |
| 779 | c = getc(finput); |
| 780 | } |
| 781 | |
| 782 | j = j*s - offset; |
| 783 | if( j > 0 ){ |
| 784 | error( "Illegal use of $%d", j+offset ); |
| 785 | } |
| 786 | |
| 787 | fprintf( faction, "yypvt[-%d]", -j ); |
| 788 | if( ntypes ){ /* put out the proper tag */ |
| 789 | if( j+offset <= 0 && tok < 0 ) error( "must specify type of $%d", j+offset ); |
| 790 | if( tok < 0 ) tok = fdtype( prdptr[nprod][j+offset] ); |
| 791 | fprintf( faction, ".%s", typeset[tok] ); |
| 792 | } |
| 793 | goto swt; |
| 794 | } |
| 795 | putc( '$' , faction ); |
| 796 | if( s<0 ) putc('-', faction ); |
| 797 | goto swt; |
| 798 | |
| 799 | case '}': |
| 800 | if( --brac ) goto lcopy; |
| 801 | putc( c, faction ); |
| 802 | return; |
| 803 | |
| 804 | |
| 805 | case '/': /* look for comments */ |
| 806 | putc( c , faction ); |
| 807 | c = getc(finput); |
| 808 | if( c != '*' ) goto swt; |
| 809 | |
| 810 | /* it really is a comment */ |
| 811 | |
| 812 | putc( c , faction ); |
| 813 | c = getc(finput); |
| 814 | while( c != EOF ){ |
| 815 | while( c=='*' ){ |
| 816 | putc( c , faction ); |
| 817 | if( (c=getc(finput)) == '/' ) goto lcopy; |
| 818 | } |
| 819 | putc( c , faction ); |
| 820 | if( c == '\n' )++lineno; |
| 821 | c = getc(finput); |
| 822 | } |
| 823 | error( "EOF inside comment" ); |
| 824 | |
| 825 | case '\'': /* character constant */ |
| 826 | match = '\''; |
| 827 | goto string; |
| 828 | |
| 829 | case '"': /* character string */ |
| 830 | match = '"'; |
| 831 | |
| 832 | string: |
| 833 | |
| 834 | putc( c , faction ); |
| 835 | while( c=getc(finput) ){ |
| 836 | |
| 837 | if( c=='\\' ){ |
| 838 | putc( c , faction ); |
| 839 | c=getc(finput); |
| 840 | if( c == '\n' ) ++lineno; |
| 841 | } |
| 842 | else if( c==match ) goto lcopy; |
| 843 | else if( c=='\n' ) error( "newline in string or char. const." ); |
| 844 | putc( c , faction ); |
| 845 | } |
| 846 | error( "EOF in string or character constant" ); |
| 847 | |
| 848 | case EOF: |
| 849 | error("action does not terminate" ); |
| 850 | |
| 851 | case '\n': ++lineno; |
| 852 | goto lcopy; |
| 853 | |
| 854 | } |
| 855 | |
| 856 | lcopy: |
| 857 | putc( c , faction ); |
| 858 | goto loop; |
| 859 | } |