Annotation of GNUtools/bison/reader.c, revision 1.1.1.1

1.1       root        1: /* Input parser for bison
                      2:    Copyright (C) 1984, 1986, 1989 Free Software Foundation, Inc.
                      3: 
                      4: This file is part of Bison, the GNU Compiler Compiler.
                      5: 
                      6: Bison is free software; you can redistribute it and/or modify
                      7: it under the terms of the GNU General Public License as published by
                      8: the Free Software Foundation; either version 2, or (at your option)
                      9: any later version.
                     10: 
                     11: Bison is distributed in the hope that it will be useful,
                     12: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     14: GNU General Public License for more details.
                     15: 
                     16: You should have received a copy of the GNU General Public License
                     17: along with Bison; see the file COPYING.  If not, write to
                     18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     19: 
                     20: 
                     21: /* read in the grammar specification and record it in the format described in gram.h.
                     22:   All guards are copied into the fguard file and all actions into faction,
                     23:   in each case forming the body of a C function (yyguard or yyaction)
                     24:   which contains a switch statement to decide which guard or action to execute.
                     25: 
                     26: The entry point is reader().  */
                     27: 
                     28: #include <stdio.h>
                     29: #include <ctype.h>
                     30: #include "system.h"
                     31: #include "files.h"
                     32: #include "new.h"
                     33: #include "symtab.h"
                     34: #include "lex.h"
                     35: #include "gram.h"
                     36: #include "machine.h"
                     37: 
                     38: #define        LTYPESTR        "\n#ifndef YYLTYPE\ntypedef\n  struct yyltype\n\
                     39:     {\n      int timestamp;\n      int first_line;\n      int first_column;\
                     40: \n      int last_line;\n      int last_column;\n      char *text;\n   }\n\
                     41:   yyltype;\n\n#define YYLTYPE yyltype\n#endif\n\n"
                     42: 
                     43: /* Number of slots allocated (but not necessarily used yet) in `rline'  */
                     44: int rline_allocated;
                     45: 
                     46: extern char *program_name;
                     47: extern int definesflag;
                     48: extern int nolinesflag;
                     49: extern bucket *symval;
                     50: extern int numval;
                     51: extern int failure;
                     52: extern int expected_conflicts;
                     53: extern char *token_buffer;
                     54: 
                     55: extern void init_lex();
                     56: extern void tabinit();
                     57: extern void output_headers();
                     58: extern void output_trailers();
                     59: extern void free_symtab();
                     60: extern void open_extra_files();
                     61: extern void fatal();
                     62: extern void fatals();
                     63: extern void unlex();
                     64: extern void done();
                     65: 
                     66: extern int skip_white_space();
                     67: extern int parse_percent_token();
                     68: extern int lex();
                     69: 
                     70: void read_declarations();
                     71: void copy_definition();
                     72: void parse_token_decl();
                     73: void parse_start_decl();
                     74: void parse_type_decl();
                     75: void parse_assoc_decl();
                     76: void parse_union_decl();
                     77: void parse_expect_decl();
                     78: void copy_action();
                     79: void readgram();
                     80: void record_rule_line();
                     81: void packsymbols();
                     82: void output_token_defines();
                     83: void packgram();
                     84: int read_signed_integer();
                     85: int get_type();
                     86: 
                     87: typedef
                     88:   struct symbol_list
                     89:     {
                     90:       struct symbol_list *next;
                     91:       bucket *sym;
                     92:       bucket *ruleprec;
                     93:     }
                     94:   symbol_list;
                     95: 
                     96: 
                     97: 
                     98: int lineno;
                     99: symbol_list *grammar;
                    100: int start_flag;
                    101: bucket *startval;
                    102: char **tags;
                    103: 
                    104: /* Nonzero if components of semantic values are used, implying
                    105:    they must be unions.  */
                    106: static int value_components_used;
                    107: 
                    108: static int typed;  /* nonzero if %union has been seen.  */
                    109: 
                    110: static int lastprec;  /* incremented for each %left, %right or %nonassoc seen */
                    111: 
                    112: static int gensym_count;  /* incremented for each generated symbol */
                    113: 
                    114: static bucket *errtoken;
                    115: 
                    116: /* Nonzero if any action or guard uses the @n construct.  */
                    117: static int yylsp_needed;
                    118: 
                    119: extern char *version_string;
                    120: 
                    121: void
                    122: reader()
                    123: {
                    124:   start_flag = 0;
                    125:   startval = NULL;  /* start symbol not specified yet. */
                    126: 
                    127: #if 0
                    128:   translations = 0;  /* initially assume token number translation not needed.  */
                    129: #endif
                    130:   /* Nowadays translations is always set to 1,
                    131:      since we give `error' a user-token-number
                    132:      to satisfy the Posix demand for YYERRCODE==256.  */
                    133:   translations = 1;
                    134: 
                    135:   nsyms = 1;
                    136:   nvars = 0;
                    137:   nrules = 0;
                    138:   nitems = 0;
                    139:   rline_allocated = 10;
                    140:   rline = NEW2(rline_allocated, short);
                    141: 
                    142:   typed = 0;
                    143:   lastprec = 0;
                    144: 
                    145:   gensym_count = 0;
                    146: 
                    147:   semantic_parser = 0;
                    148:   pure_parser = 0;
                    149:   yylsp_needed = 0;
                    150: 
                    151:   grammar = NULL;
                    152: 
                    153:   init_lex();
                    154:   lineno = 1;
                    155: 
                    156:   /* initialize the symbol table.  */
                    157:   tabinit();
                    158:   /* construct the error token */
                    159:   errtoken = getsym("error");
                    160:   errtoken->class = STOKEN;
                    161:   errtoken->user_token_number = 256; /* Value specified by posix.  */
                    162:   /* construct a token that represents all undefined literal tokens. */
                    163:   /* it is always token number 2.  */
                    164:   getsym("$illegal.")->class = STOKEN;
                    165:   /* Read the declaration section.  Copy %{ ... %} groups to ftable and fdefines file.
                    166:      Also notice any %token, %left, etc. found there.  */
                    167:   fprintf(ftable, "\n/*  A Bison parser, made from %s", infile);
                    168:   fprintf(ftable, " with Bison version %s  */\n\n", version_string);
                    169:   fprintf(ftable, "#define YYBISON 1  /* Identify Bison output.  */\n\n");
                    170:   read_declarations();
                    171:   /* output the definition of YYLTYPE into the fattrs and fdefines files.  */
                    172:   /* fattrs winds up in the .tab.c file, before bison.simple.  */
                    173:   fprintf(fattrs, LTYPESTR);
                    174:   /* start writing the guard and action files, if they are needed.  */
                    175:   output_headers();
                    176:   /* read in the grammar, build grammar in list form.  write out guards and actions.  */
                    177:   readgram();
                    178:   /* Now we know whether we need the line-number stack.
                    179:      If we do, write its type into the .tab.h file.  */
                    180:   if (yylsp_needed)
                    181:     {
                    182:       if (fdefines)
                    183:        fprintf(fdefines, LTYPESTR);
                    184:     }
                    185:   /* write closing delimiters for actions and guards.  */
                    186:   output_trailers();
                    187:   if (yylsp_needed)
                    188:     fprintf(ftable, "#define YYLSP_NEEDED\n\n");
                    189:   /* assign the symbols their symbol numbers.
                    190:      Write #defines for the token symbols into fdefines if requested.  */
                    191:   packsymbols();
                    192:   /* convert the grammar into the format described in gram.h.  */
                    193:   packgram();
                    194:   /* free the symbol table data structure
                    195:      since symbols are now all referred to by symbol number.  */
                    196:   free_symtab();
                    197: }
                    198: 
                    199: 
                    200: 
                    201: /* read from finput until %% is seen.  Discard the %%.
                    202: Handle any % declarations,
                    203: and copy the contents of any %{ ... %} groups to fattrs.  */
                    204: 
                    205: void
                    206: read_declarations ()
                    207: {
                    208:   register int c;
                    209:   register int tok;
                    210: 
                    211:   for (;;)
                    212:     {
                    213:       c = skip_white_space();
                    214: 
                    215:       if (c == '%')
                    216:        {
                    217:          tok = parse_percent_token();
                    218: 
                    219:          switch (tok)
                    220:            {
                    221:            case TWO_PERCENTS:
                    222:              return;
                    223: 
                    224:            case PERCENT_LEFT_CURLY:
                    225:              copy_definition();
                    226:              break;
                    227: 
                    228:            case TOKEN:
                    229:              parse_token_decl (STOKEN, SNTERM);
                    230:              break;
                    231:        
                    232:            case NTERM:
                    233:              parse_token_decl (SNTERM, STOKEN);
                    234:              break;
                    235:        
                    236:            case TYPE:
                    237:              parse_type_decl();
                    238:              break;
                    239:        
                    240:            case START:
                    241:              parse_start_decl();
                    242:              break;
                    243:        
                    244:            case UNION:
                    245:              parse_union_decl();
                    246:              break;
                    247:        
                    248:            case EXPECT:
                    249:              parse_expect_decl();
                    250:              break;
                    251:        
                    252:            case LEFT:
                    253:              parse_assoc_decl(LEFT_ASSOC);
                    254:              break;
                    255: 
                    256:            case RIGHT:
                    257:              parse_assoc_decl(RIGHT_ASSOC);
                    258:              break;
                    259: 
                    260:            case NONASSOC:
                    261:              parse_assoc_decl(NON_ASSOC);
                    262:              break;
                    263: 
                    264:            case SEMANTIC_PARSER:
                    265:              if (semantic_parser == 0)
                    266:                {
                    267:                  semantic_parser = 1;
                    268:                  open_extra_files();
                    269:                }
                    270:              break;
                    271: 
                    272:            case PURE_PARSER:
                    273:              pure_parser = 1;
                    274:              break;
                    275: 
                    276:            default:
                    277:              fatal("junk after `%%' in definition section");
                    278:            }
                    279:        }
                    280:       else if (c == EOF)
                    281:         fatal("no input grammar");
                    282:       else if (c >= 040 && c <= 0177)
                    283:        fatals ("unknown character `%c' in declaration section", c);
                    284:       else
                    285:        fatals ("unknown character with code 0x%x in declaration section", c);
                    286:     }
                    287: }
                    288: 
                    289: 
                    290: /* copy the contents of a %{ ... %} into the definitions file.
                    291: The %{ has already been read.  Return after reading the %}.  */
                    292: 
                    293: void
                    294: copy_definition ()
                    295: {
                    296:   register int c;
                    297:   register int match;
                    298:   register int ended;
                    299:   register int after_percent;  /* -1 while reading a character if prev char was % */
                    300:   int cplus_comment;
                    301: 
                    302:   if (!nolinesflag)
                    303:     fprintf(fattrs, "#line %d \"%s\"\n", lineno, infile);
                    304: 
                    305:   after_percent = 0;
                    306: 
                    307:   c = getc(finput);
                    308: 
                    309:   for (;;)
                    310:     {
                    311:       switch (c)
                    312:        {
                    313:        case '\n':
                    314:          putc(c, fattrs);
                    315:          lineno++;
                    316:          break;
                    317: 
                    318:        case '%':
                    319:           after_percent = -1;
                    320:          break;
                    321:              
                    322:        case '\'':
                    323:        case '"':
                    324:          match = c;
                    325:          putc(c, fattrs);
                    326:          c = getc(finput);
                    327: 
                    328:          while (c != match)
                    329:            {
                    330:              if (c == EOF || c == '\n')
                    331:                fatal("unterminated string");
                    332: 
                    333:              putc(c, fattrs);
                    334:              
                    335:              if (c == '\\')
                    336:                {
                    337:                  c = getc(finput);
                    338:                  if (c == EOF)
                    339:                    fatal("unterminated string");
                    340:                  putc(c, fattrs);
                    341:                  if (c == '\n')
                    342:                    lineno++;
                    343:                }
                    344: 
                    345:              c = getc(finput);
                    346:            }
                    347: 
                    348:          putc(c, fattrs);
                    349:          break;
                    350: 
                    351:        case '/':
                    352:          putc(c, fattrs);
                    353:          c = getc(finput);
                    354:          if (c != '*' && c != '/')
                    355:            continue;
                    356: 
                    357:          cplus_comment = (c == '/');
                    358:          putc(c, fattrs);
                    359:          c = getc(finput);
                    360: 
                    361:          ended = 0;
                    362:          while (!ended)
                    363:            {
                    364:              if (!cplus_comment && c == '*')
                    365:                {
                    366:                  while (c == '*')
                    367:                    {
                    368:                      putc(c, fattrs);
                    369:                      c = getc(finput);
                    370:                    }
                    371: 
                    372:                  if (c == '/')
                    373:                    {
                    374:                      putc(c, fattrs);
                    375:                      ended = 1;
                    376:                    }
                    377:                }
                    378:              else if (c == '\n')
                    379:                {
                    380:                  lineno++;
                    381:                  putc(c, fattrs);
                    382:                  if (cplus_comment)
                    383:                    ended = 1;
                    384:                  else
                    385:                    c = getc(finput);
                    386:                }
                    387:              else if (c == EOF)
                    388:                fatal("unterminated comment in `%{' definition");
                    389:              else
                    390:                {
                    391:                  putc(c, fattrs);
                    392:                  c = getc(finput);
                    393:                }
                    394:            }
                    395: 
                    396:          break;
                    397: 
                    398:        case EOF:
                    399:          fatal("unterminated `%{' definition");
                    400: 
                    401:        default:
                    402:          putc(c, fattrs);
                    403:        }
                    404: 
                    405:       c = getc(finput);
                    406: 
                    407:       if (after_percent)
                    408:        {
                    409:          if (c == '}')
                    410:            return;
                    411:          putc('%', fattrs);
                    412:        }
                    413:       after_percent = 0;
                    414: 
                    415:     }
                    416: 
                    417: }
                    418: 
                    419: 
                    420: 
                    421: /* parse what comes after %token or %nterm.
                    422: For %token, what_is is STOKEN and what_is_not is SNTERM.
                    423: For %nterm, the arguments are reversed.  */
                    424: 
                    425: void
                    426: parse_token_decl (what_is, what_is_not)
                    427:      int what_is, what_is_not;
                    428: {
                    429: /*   register int start_lineno; JF */
                    430:   register int token = 0;
                    431:   register int prev;
                    432:   register char *typename = 0;
                    433:   int k;
                    434: 
                    435: /*   start_lineno = lineno; JF */
                    436: 
                    437:   for (;;)
                    438:     {
                    439:       if(ungetc(skip_white_space(), finput) == '%')
                    440:        return;
                    441: 
                    442: /*      if (lineno != start_lineno)
                    443:        return; JF */
                    444: 
                    445:       /* we have not passed a newline, so the token now starting is in this declaration */
                    446:       prev = token;
                    447: 
                    448:       token = lex();
                    449:       if (token == COMMA)
                    450:        continue;
                    451:       if (token == TYPENAME)
                    452:        {
                    453:          k = strlen(token_buffer);
                    454:          typename = NEW2(k + 1, char);
                    455:          strcpy(typename, token_buffer);
                    456:          value_components_used = 1;
                    457:        }
                    458:       else if (token == IDENTIFIER)
                    459:        {
                    460:          int oldclass = symval->class;
                    461: 
                    462:          if (symval->class == what_is_not)
                    463:            fatals("symbol %s redefined", symval->tag);
                    464:          symval->class = what_is;
                    465:          if (what_is == SNTERM && oldclass != SNTERM)
                    466:            symval->value = nvars++;
                    467: 
                    468:          if (typename)
                    469:            {
                    470:              if (symval->type_name == NULL)
                    471:                symval->type_name = typename;
                    472:              else
                    473:                fatals("type redeclaration for %s", symval->tag);
                    474:            }
                    475:        }
                    476:       else if (prev == IDENTIFIER && token == NUMBER)
                    477:         {
                    478:          symval->user_token_number = numval;
                    479:          translations = 1;
                    480:         }
                    481:       else
                    482:        fatal("invalid text in %token or %nterm declaration");
                    483:     }
                    484: 
                    485: }
                    486: 
                    487: 
                    488: 
                    489: /* parse what comes after %start */
                    490: 
                    491: void
                    492: parse_start_decl ()
                    493: {
                    494:   if (start_flag)
                    495:     fatal("multiple %start declarations");
                    496:   start_flag = 1;
                    497:   if (lex() != IDENTIFIER)
                    498:     fatal("invalid %start declaration");
                    499:   startval = symval;
                    500: }
                    501: 
                    502: 
                    503: 
                    504: /* read in a %type declaration and record its information for get_type_name to access */
                    505: 
                    506: void
                    507: parse_type_decl ()
                    508: {
                    509:   register int k;
                    510:   register char *name;
                    511: /*   register int start_lineno; JF */
                    512: 
                    513:   if (lex() != TYPENAME)
                    514:     fatal("ill-formed %type declaration");
                    515: 
                    516:   k = strlen(token_buffer);
                    517:   name = NEW2(k + 1, char);
                    518:   strcpy(name, token_buffer);
                    519: 
                    520: /*   start_lineno = lineno; */
                    521: 
                    522:   for (;;)
                    523:     {
                    524:       register int t;
                    525: 
                    526:       if(ungetc(skip_white_space(), finput) == '%')
                    527:        return;
                    528: 
                    529: /*       if (lineno != start_lineno)
                    530:        return; JF */
                    531: 
                    532:       /* we have not passed a newline, so the token now starting is in this declaration */
                    533: 
                    534:       t = lex();
                    535: 
                    536:       switch (t)
                    537:        {
                    538: 
                    539:        case COMMA:
                    540:        case SEMICOLON:
                    541:          break;
                    542: 
                    543:        case IDENTIFIER:
                    544:          if (symval->type_name == NULL)
                    545:            symval->type_name = name;
                    546:          else
                    547:            fatals("type redeclaration for %s", symval->tag);
                    548: 
                    549:          break;
                    550: 
                    551:        default:
                    552:          fatal("invalid %type declaration");
                    553:        }
                    554:     }
                    555: }
                    556: 
                    557: 
                    558: 
                    559: /* read in a %left, %right or %nonassoc declaration and record its information.  */
                    560: /* assoc is either LEFT_ASSOC, RIGHT_ASSOC or NON_ASSOC.  */
                    561: 
                    562: void
                    563: parse_assoc_decl (assoc)
                    564: int assoc;
                    565: {
                    566:   register int k;
                    567:   register char *name = NULL;
                    568: /*  register int start_lineno; JF */
                    569:   register int prev = 0;       /* JF added = 0 to keep lint happy */
                    570: 
                    571:   lastprec++;  /* Assign a new precedence level, never 0.  */
                    572: 
                    573: /*   start_lineno = lineno; */
                    574: 
                    575:   for (;;)
                    576:     {
                    577:       register int t;
                    578: 
                    579:       if(ungetc(skip_white_space(), finput) == '%')
                    580:        return;
                    581: 
                    582:       /* if (lineno != start_lineno)
                    583:        return; JF */
                    584: 
                    585:       /* we have not passed a newline, so the token now starting is in this declaration */
                    586: 
                    587:       t = lex();
                    588: 
                    589:       switch (t)
                    590:        {
                    591: 
                    592:        case TYPENAME:
                    593:          k = strlen(token_buffer);
                    594:          name = NEW2(k + 1, char);
                    595:          strcpy(name, token_buffer);
                    596:          break;
                    597: 
                    598:        case COMMA:
                    599:          break;
                    600: 
                    601:        case IDENTIFIER:
                    602:          if (symval->prec != 0)
                    603:            fatals("redefining precedence of %s", symval->tag);
                    604:          symval->prec = lastprec;
                    605:          symval->assoc = assoc;
                    606:          if (symval->class == SNTERM)
                    607:            fatals("symbol %s redefined", symval->tag);
                    608:          symval->class = STOKEN;
                    609:          if (name)
                    610:            { /* record the type, if one is specified */
                    611:              if (symval->type_name == NULL)
                    612:                symval->type_name = name;
                    613:              else
                    614:                fatals("type redeclaration for %s", symval->tag);
                    615:            }
                    616:          break;
                    617: 
                    618:        case NUMBER:
                    619:          if (prev == IDENTIFIER)
                    620:             {
                    621:              symval->user_token_number = numval;
                    622:              translations = 1;
                    623:             }
                    624:           else   
                    625:            fatal("invalid text in association declaration");
                    626:          break;
                    627: 
                    628:        case SEMICOLON:
                    629:          return;
                    630: 
                    631:        default:
                    632:          fatal("malformatted association declaration");
                    633:        }
                    634: 
                    635:       prev = t;
                    636: 
                    637:     }
                    638: }
                    639: 
                    640: 
                    641: 
                    642: /* copy the union declaration into fattrs (and fdefines),
                    643:    where it is made into the
                    644:    definition of YYSTYPE, the type of elements of the parser value stack.  */
                    645: 
                    646: void
                    647: parse_union_decl()
                    648: {
                    649:   register int c;
                    650:   register int count;
                    651:   register int in_comment;
                    652:   int cplus_comment;
                    653: 
                    654:   if (typed)
                    655:     fatal("multiple %union declarations");
                    656: 
                    657:   typed = 1;
                    658: 
                    659:   if (!nolinesflag)
                    660:     fprintf(fattrs, "\n#line %d \"%s\"\n", lineno, infile);
                    661:   else
                    662:     fprintf(fattrs, "\n");
                    663: 
                    664:   fprintf(fattrs, "typedef union");
                    665:   if (fdefines)
                    666:     fprintf(fdefines, "typedef union");
                    667: 
                    668:   count = 0;
                    669:   in_comment = 0;
                    670: 
                    671:   c = getc(finput);
                    672: 
                    673:   while (c != EOF)
                    674:     {
                    675:       putc(c, fattrs);
                    676:       if (fdefines)
                    677:        putc(c, fdefines);
                    678: 
                    679:       switch (c)
                    680:        {
                    681:        case '\n':
                    682:          lineno++;
                    683:          break;
                    684: 
                    685:        case '/':
                    686:          c = getc(finput);
                    687:          if (c != '*' && c != '/')
                    688:            ungetc(c, finput);
                    689:          else
                    690:            {
                    691:              putc(c, fattrs);
                    692:              if (fdefines)
                    693:                putc(c, fdefines);
                    694:              cplus_comment = (c == '/');
                    695:              in_comment = 1;
                    696:              c = getc(finput);
                    697:              while (in_comment)
                    698:                {
                    699:                  putc(c, fattrs);
                    700:                  if (fdefines)
                    701:                    putc(c, fdefines);
                    702: 
                    703:                  if (c == '\n')
                    704:                    {
                    705:                      lineno++;
                    706:                      if (cplus_comment)
                    707:                        {
                    708:                          in_comment = 0;
                    709:                          break;
                    710:                        }
                    711:                    }
                    712:                  if (c == EOF)
                    713:                    fatal("unterminated comment");
                    714: 
                    715:                  if (!cplus_comment && c == '*')
                    716:                    {
                    717:                      c = getc(finput);
                    718:                      if (c == '/')
                    719:                        {
                    720:                          putc('/', fattrs);
                    721:                          if (fdefines)
                    722:                            putc('/', fdefines);
                    723:                          in_comment = 0;
                    724:                        }
                    725:                    }
                    726:                  else
                    727:                    c = getc(finput);
                    728:                }
                    729:            }
                    730:          break;
                    731: 
                    732: 
                    733:        case '{':
                    734:          count++;
                    735:          break;
                    736: 
                    737:        case '}':
                    738:          if (count == 0)
                    739:            fatal ("unmatched close-brace (`}')");
                    740:          count--;
                    741:          if (count == 0)
                    742:            {
                    743:              fprintf(fattrs, " YYSTYPE;\n");
                    744:              if (fdefines)
                    745:                fprintf(fdefines, " YYSTYPE;\n");
                    746:              /* JF don't choke on trailing semi */
                    747:              c=skip_white_space();
                    748:              if(c!=';') ungetc(c,finput);
                    749:              return;
                    750:            }
                    751:        }
                    752: 
                    753:       c = getc(finput);
                    754:     }
                    755: }
                    756: 
                    757: /* parse the declaration %expect N which says to expect N
                    758:    shift-reduce conflicts.  */
                    759: 
                    760: void
                    761: parse_expect_decl()
                    762: {
                    763:   register int c;
                    764:   register int count;
                    765:   char buffer[20];
                    766: 
                    767:   c = getc(finput);
                    768:   while (c == ' ' || c == '\t')
                    769:     c = getc(finput);
                    770: 
                    771:   count = 0;
                    772:   while (c >= '0' && c <= '9')
                    773:     {
                    774:       if (count < 20)
                    775:        buffer[count++] = c;
                    776:       c = getc(finput);
                    777:     }
                    778:   buffer[count] = 0;
                    779: 
                    780:   ungetc (c, finput);
                    781: 
                    782:   expected_conflicts = atoi (buffer);
                    783: }
                    784: 
                    785: /* that's all of parsing the declaration section */
                    786: 
                    787: /* Get the data type (alternative in the union) of the value for symbol n in rule rule.  */
                    788: 
                    789: char *
                    790: get_type_name(n, rule)
                    791: int n;
                    792: symbol_list *rule;
                    793: {
                    794:   static char *msg = "invalid $ value";
                    795: 
                    796:   register int i;
                    797:   register symbol_list *rp;
                    798: 
                    799:   if (n < 0)
                    800:     fatal(msg);
                    801: 
                    802:   rp = rule;
                    803:   i = 0;
                    804: 
                    805:   while (i < n)
                    806:     {
                    807:       rp = rp->next;
                    808:       if (rp == NULL || rp->sym == NULL)
                    809:        fatal(msg);
                    810:       i++;
                    811:     }
                    812: 
                    813:   return (rp->sym->type_name);
                    814: }
                    815: 
                    816: 
                    817: 
                    818: /* after %guard is seen in the input file,
                    819: copy the actual guard into the guards file.
                    820: If the guard is followed by an action, copy that into the actions file.
                    821: stack_offset is the number of values in the current rule so far,
                    822: which says where to find $0 with respect to the top of the stack,
                    823: for the simple parser in which the stack is not popped until after the guard is run.  */
                    824: 
                    825: void
                    826: copy_guard(rule, stack_offset)
                    827: symbol_list *rule;
                    828: int stack_offset;
                    829: {
                    830:   register int c;
                    831:   register int n;
                    832:   register int count;
                    833:   register int match;
                    834:   register int ended;
                    835:   register char *type_name;
                    836:   int brace_flag = 0;
                    837:   int cplus_comment;
                    838: 
                    839:   /* offset is always 0 if parser has already popped the stack pointer */
                    840:   if (semantic_parser) stack_offset = 0;
                    841: 
                    842:   fprintf(fguard, "\ncase %d:\n", nrules);
                    843:   if (!nolinesflag)
                    844:     fprintf(fguard, "#line %d \"%s\"\n", lineno, infile);
                    845:   putc('{', fguard);
                    846: 
                    847:   count = 0;
                    848:   c = getc(finput);
                    849: 
                    850:   while (brace_flag ? (count > 0) : (c != ';'))
                    851:     {
                    852:       switch (c)
                    853:        {
                    854:        case '\n':
                    855:          putc(c, fguard);
                    856:          lineno++;
                    857:          break;
                    858: 
                    859:        case '{':
                    860:          putc(c, fguard);
                    861:          brace_flag = 1;
                    862:          count++;
                    863:          break;
                    864: 
                    865:        case '}':
                    866:          putc(c, fguard);
                    867:          if (count > 0)
                    868:            count--;
                    869:          else
                    870:            fatal("unmatched right brace ('}')");
                    871:           break;
                    872: 
                    873:        case '\'':
                    874:        case '"':
                    875:          match = c;
                    876:          putc(c, fguard);
                    877:          c = getc(finput);
                    878: 
                    879:          while (c != match)
                    880:            {
                    881:              if (c == EOF || c == '\n')
                    882:                fatal("unterminated string");
                    883: 
                    884:              putc(c, fguard);
                    885:              
                    886:              if (c == '\\')
                    887:                {
                    888:                  c = getc(finput);
                    889:                  if (c == EOF)
                    890:                    fatal("unterminated string");
                    891:                  putc(c, fguard);
                    892:                  if (c == '\n')
                    893:                    lineno++;
                    894:                }
                    895: 
                    896:              c = getc(finput);
                    897:            }
                    898: 
                    899:          putc(c, fguard);
                    900:          break;
                    901: 
                    902:        case '/':
                    903:          putc(c, fguard);
                    904:          c = getc(finput);
                    905:          if (c != '*' && c != '/')
                    906:            continue;
                    907: 
                    908:          cplus_comment = (c == '/');
                    909:          putc(c, fguard);
                    910:          c = getc(finput);
                    911: 
                    912:          ended = 0;
                    913:          while (!ended)
                    914:            {
                    915:              if (!cplus_comment && c == '*')
                    916:                {
                    917:                  while (c == '*')
                    918:                    {
                    919:                      putc(c, fguard);
                    920:                      c = getc(finput);
                    921:                    }
                    922: 
                    923:                  if (c == '/')
                    924:                    {
                    925:                      putc(c, fguard);
                    926:                      ended = 1;
                    927:                    }
                    928:                }
                    929:              else if (c == '\n')
                    930:                {
                    931:                  lineno++;
                    932:                  putc(c, fguard);
                    933:                  if (cplus_comment)
                    934:                    ended = 1;
                    935:                  else
                    936:                    c = getc(finput);
                    937:                }
                    938:              else if (c == EOF)
                    939:                fatal("unterminated comment");
                    940:              else
                    941:                {
                    942:                  putc(c, fguard);
                    943:                  c = getc(finput);
                    944:                }
                    945:            }
                    946: 
                    947:          break;
                    948: 
                    949:        case '$':
                    950:          c = getc(finput);
                    951:          type_name = NULL;
                    952: 
                    953:          if (c == '<')
                    954:            {
                    955:              register char *cp = token_buffer;
                    956: 
                    957:              while ((c = getc(finput)) != '>' && c > 0)
                    958:                *cp++ = c;
                    959:              *cp = 0;
                    960:              type_name = token_buffer;
                    961: 
                    962:              c = getc(finput);
                    963:            }
                    964: 
                    965:          if (c == '$')
                    966:            {
                    967:              fprintf(fguard, "yyval");
                    968:              if (!type_name) type_name = rule->sym->type_name;
                    969:              if (type_name)
                    970:                fprintf(fguard, ".%s", type_name);
                    971:              if(!type_name && typed)   /* JF */
                    972:                fprintf(stderr,"%s:%d:  warning:  $$ of '%s' has no declared type.\n",infile,lineno,rule->sym->tag);
                    973:            }
                    974: 
                    975:          else if (isdigit(c) || c == '-')
                    976:            {
                    977:              ungetc (c, finput);
                    978:              n = read_signed_integer(finput);
                    979:              c = getc(finput);
                    980: 
                    981:              if (!type_name && n > 0)
                    982:                type_name = get_type_name(n, rule);
                    983: 
                    984:              fprintf(fguard, "yyvsp[%d]", n - stack_offset);
                    985:              if (type_name)
                    986:                fprintf(fguard, ".%s", type_name);
                    987:              if(!type_name && typed)   /* JF */
                    988:                fprintf(stderr,"%s:%d:  warning:  $%d of '%s' has no declared type.\n",infile,lineno,n,rule->sym->tag);
                    989:              continue;
                    990:            }
                    991:          else
                    992:            fatals("$%c is invalid",c); /* JF changed style */
                    993: 
                    994:          break;
                    995: 
                    996:        case '@':
                    997:          c = getc(finput);
                    998:          if (isdigit(c) || c == '-')
                    999:            {
                   1000:              ungetc (c, finput);
                   1001:              n = read_signed_integer(finput);
                   1002:              c = getc(finput);
                   1003:            }
                   1004:          else
                   1005:            fatals("@%c is invalid",c); /* JF changed style */
                   1006: 
                   1007:          fprintf(fguard, "yylsp[%d]", n - stack_offset);
                   1008:          yylsp_needed = 1;
                   1009: 
                   1010:          continue;
                   1011: 
                   1012:        case EOF:
                   1013:          fatal("unterminated %guard clause");
                   1014: 
                   1015:        default:
                   1016:          putc(c, fguard);
                   1017:        }
                   1018: 
                   1019:       if (c != '}' || count != 0)
                   1020:        c = getc(finput);
                   1021:     }
                   1022: 
                   1023:   c = skip_white_space();
                   1024: 
                   1025:   fprintf(fguard, ";\n    break;}");
                   1026:   if (c == '{')
                   1027:     copy_action(rule, stack_offset);
                   1028:   else if (c == '=')
                   1029:     {
                   1030:       c = getc(finput);
                   1031:       if (c == '{')
                   1032:        copy_action(rule, stack_offset);
                   1033:     }
                   1034:   else
                   1035:     ungetc(c, finput);
                   1036: }
                   1037: 
                   1038: 
                   1039: 
                   1040: /* Assuming that a { has just been seen, copy everything up to the matching }
                   1041: into the actions file.
                   1042: stack_offset is the number of values in the current rule so far,
                   1043: which says where to find $0 with respect to the top of the stack.  */
                   1044: 
                   1045: void
                   1046: copy_action(rule, stack_offset)
                   1047: symbol_list *rule;
                   1048: int stack_offset;
                   1049: {
                   1050:   register int c;
                   1051:   register int n;
                   1052:   register int count;
                   1053:   register int match;
                   1054:   register int ended;
                   1055:   register char *type_name;
                   1056:   int cplus_comment;
                   1057: 
                   1058:   /* offset is always 0 if parser has already popped the stack pointer */
                   1059:   if (semantic_parser) stack_offset = 0;
                   1060: 
                   1061:   fprintf(faction, "\ncase %d:\n", nrules);
                   1062:   if (!nolinesflag)
                   1063:     fprintf(faction, "#line %d \"%s\"\n", lineno, infile);
                   1064:   putc('{', faction);
                   1065: 
                   1066:   count = 1;
                   1067:   c = getc(finput);
                   1068: 
                   1069:   while (count > 0)
                   1070:     {
                   1071:       while (c != '}')
                   1072:         {
                   1073:           switch (c)
                   1074:            {
                   1075:            case '\n':
                   1076:              putc(c, faction);
                   1077:              lineno++;
                   1078:              break;
                   1079: 
                   1080:            case '{':
                   1081:              putc(c, faction);
                   1082:              count++;
                   1083:              break;
                   1084: 
                   1085:            case '\'':
                   1086:            case '"':
                   1087:              match = c;
                   1088:              putc(c, faction);
                   1089:              c = getc(finput);
                   1090: 
                   1091:              while (c != match)
                   1092:                {
                   1093:                  if (c == EOF || c == '\n')
                   1094:                    fatal("unterminated string");
                   1095: 
                   1096:                  putc(c, faction);
                   1097: 
                   1098:                  if (c == '\\')
                   1099:                    {
                   1100:                      c = getc(finput);
                   1101:                      if (c == EOF)
                   1102:                        fatal("unterminated string");
                   1103:                      putc(c, faction);
                   1104:                      if (c == '\n')
                   1105:                        lineno++;
                   1106:                    }
                   1107: 
                   1108:                  c = getc(finput);
                   1109:                }
                   1110: 
                   1111:              putc(c, faction);
                   1112:              break;
                   1113: 
                   1114:            case '/':
                   1115:              putc(c, faction);
                   1116:              c = getc(finput);
                   1117:              if (c != '*' && c != '/')
                   1118:                continue;
                   1119: 
                   1120:              cplus_comment = (c == '/');
                   1121:              putc(c, faction);
                   1122:              c = getc(finput);
                   1123: 
                   1124:              ended = 0;
                   1125:              while (!ended)
                   1126:                {
                   1127:                  if (!cplus_comment && c == '*')
                   1128:                    {
                   1129:                      while (c == '*')
                   1130:                        {
                   1131:                          putc(c, faction);
                   1132:                          c = getc(finput);
                   1133:                        }
                   1134: 
                   1135:                      if (c == '/')
                   1136:                        {
                   1137:                          putc(c, faction);
                   1138:                          ended = 1;
                   1139:                        }
                   1140:                    }
                   1141:                  else if (c == '\n')
                   1142:                    {
                   1143:                      lineno++;
                   1144:                      putc(c, faction);
                   1145:                      if (cplus_comment)
                   1146:                        ended = 1;
                   1147:                      else
                   1148:                        c = getc(finput);
                   1149:                    }
                   1150:                  else if (c == EOF)
                   1151:                    fatal("unterminated comment");
                   1152:                  else
                   1153:                    {
                   1154:                      putc(c, faction);
                   1155:                      c = getc(finput);
                   1156:                    }
                   1157:                }
                   1158: 
                   1159:              break;
                   1160: 
                   1161:            case '$':
                   1162:              c = getc(finput);
                   1163:              type_name = NULL;
                   1164: 
                   1165:              if (c == '<')
                   1166:                {
                   1167:                  register char *cp = token_buffer;
                   1168: 
                   1169:                  while ((c = getc(finput)) != '>' && c > 0)
                   1170:                    *cp++ = c;
                   1171:                  *cp = 0;
                   1172:                  type_name = token_buffer;
                   1173:                  value_components_used = 1;
                   1174: 
                   1175:                  c = getc(finput);
                   1176:                }
                   1177:              if (c == '$')
                   1178:                {
                   1179:                  fprintf(faction, "yyval");
                   1180:                  if (!type_name) type_name = get_type_name(0, rule);
                   1181:                  if (type_name)
                   1182:                    fprintf(faction, ".%s", type_name);
                   1183:                  if(!type_name && typed)       /* JF */
                   1184:                    fprintf(stderr,"%s:%d:  warning:  $$ of '%s' has no declared type.\n",infile,lineno,rule->sym->tag);
                   1185:                }
                   1186:              else if (isdigit(c) || c == '-')
                   1187:                {
                   1188:                  ungetc (c, finput);
                   1189:                  n = read_signed_integer(finput);
                   1190:                  c = getc(finput);
                   1191: 
                   1192:                  if (!type_name && n > 0)
                   1193:                    type_name = get_type_name(n, rule);
                   1194: 
                   1195:                  fprintf(faction, "yyvsp[%d]", n - stack_offset);
                   1196:                  if (type_name)
                   1197:                    fprintf(faction, ".%s", type_name);
                   1198:                  if(!type_name && typed)       /* JF */
                   1199:                    fprintf(stderr,"%s:%d:  warning:  $%d of '%s' has no declared type.\n",infile,lineno,n,rule->sym->tag);
                   1200:                  continue;
                   1201:                }
                   1202:              else
                   1203:                fatals("$%c is invalid",c);     /* JF changed format */
                   1204: 
                   1205:              break;
                   1206: 
                   1207:            case '@':
                   1208:              c = getc(finput);
                   1209:              if (isdigit(c) || c == '-')
                   1210:                {
                   1211:                  ungetc (c, finput);
                   1212:                  n = read_signed_integer(finput);
                   1213:                  c = getc(finput);
                   1214:                }
                   1215:              else
                   1216:                fatal("invalid @-construct");
                   1217: 
                   1218:              fprintf(faction, "yylsp[%d]", n - stack_offset);
                   1219:              yylsp_needed = 1;
                   1220: 
                   1221:              continue;
                   1222: 
                   1223:            case EOF:
                   1224:              fatal("unmatched '{'");
                   1225: 
                   1226:            default:
                   1227:              putc(c, faction);
                   1228:            }
                   1229: 
                   1230:           c = getc(finput);
                   1231:         }
                   1232: 
                   1233:       /* above loop exits when c is '}' */
                   1234: 
                   1235:       if (--count)
                   1236:         {
                   1237:          putc(c, faction);
                   1238:          c = getc(finput);
                   1239:        }
                   1240:     }
                   1241: 
                   1242:   fprintf(faction, ";\n    break;}");
                   1243: }
                   1244: 
                   1245: 
                   1246: 
                   1247: /* generate a dummy symbol, a nonterminal,
                   1248: whose name cannot conflict with the user's names. */
                   1249: 
                   1250: bucket *
                   1251: gensym()
                   1252: {
                   1253:   register bucket *sym;
                   1254: 
                   1255:   sprintf (token_buffer, "@%d", ++gensym_count);
                   1256:   sym = getsym(token_buffer);
                   1257:   sym->class = SNTERM;
                   1258:   sym->value = nvars++;
                   1259:   return (sym);
                   1260: }
                   1261: 
                   1262: /* Parse the input grammar into a one symbol_list structure.
                   1263: Each rule is represented by a sequence of symbols: the left hand side
                   1264: followed by the contents of the right hand side, followed by a null pointer
                   1265: instead of a symbol to terminate the rule.
                   1266: The next symbol is the lhs of the following rule.
                   1267: 
                   1268: All guards and actions are copied out to the appropriate files,
                   1269: labelled by the rule number they apply to.  */
                   1270: 
                   1271: void
                   1272: readgram()
                   1273: {
                   1274:   register int t;
                   1275:   register bucket *lhs;
                   1276:   register symbol_list *p;
                   1277:   register symbol_list *p1;
                   1278:   register bucket *bp;
                   1279: 
                   1280:   symbol_list *crule;  /* points to first symbol_list of current rule.  */
                   1281:                        /* its symbol is the lhs of the rule.   */
                   1282:   symbol_list *crule1;  /* points to the symbol_list preceding crule.  */
                   1283: 
                   1284:   p1 = NULL;
                   1285: 
                   1286:   t = lex();
                   1287: 
                   1288:   while (t != TWO_PERCENTS && t != ENDFILE)
                   1289:     {
                   1290:       if (t == IDENTIFIER || t == BAR)
                   1291:        {
                   1292:          register int actionflag = 0;
                   1293:          int rulelength = 0;  /* number of symbols in rhs of this rule so far  */
                   1294:          int xactions = 0;     /* JF for error checking */
                   1295:          bucket *first_rhs = 0;
                   1296: 
                   1297:          if (t == IDENTIFIER)
                   1298:            {
                   1299:              lhs = symval;
                   1300:     
                   1301:              t = lex();
                   1302:              if (t != COLON)
                   1303:                fatal("ill-formed rule");
                   1304:            }
                   1305: 
                   1306:          if (nrules == 0)
                   1307:            {
                   1308:              if (t == BAR)
                   1309:                fatal("grammar starts with vertical bar");
                   1310: 
                   1311:              if (!start_flag)
                   1312:                startval = lhs;
                   1313:            }
                   1314: 
                   1315:          /* start a new rule and record its lhs.  */
                   1316: 
                   1317:          nrules++;
                   1318:          nitems++;
                   1319: 
                   1320:          record_rule_line ();
                   1321: 
                   1322:          p = NEW(symbol_list);
                   1323:          p->sym = lhs;
                   1324: 
                   1325:          crule1 = p1;
                   1326:          if (p1)
                   1327:            p1->next = p;
                   1328:          else
                   1329:            grammar = p;
                   1330: 
                   1331:          p1 = p;
                   1332:          crule = p;
                   1333: 
                   1334:          /* mark the rule's lhs as a nonterminal if not already so.  */
                   1335: 
                   1336:          if (lhs->class == SUNKNOWN)
                   1337:            {
                   1338:              lhs->class = SNTERM;
                   1339:              lhs->value = nvars;
                   1340:              nvars++;
                   1341:            }
                   1342:          else if (lhs->class == STOKEN)
                   1343:            fatals("rule given for %s, which is a token", lhs->tag);
                   1344: 
                   1345:          /* read the rhs of the rule.  */
                   1346: 
                   1347:          for (;;)
                   1348:            {
                   1349:              t = lex();
                   1350: 
                   1351:              if (! (t == IDENTIFIER || t == LEFT_CURLY)) break;
                   1352: 
                   1353:              /* If next token is an identifier, see if a colon follows it.
                   1354:                 If one does, exit this rule now.  */
                   1355:              if (t == IDENTIFIER)
                   1356:                {
                   1357:                  register bucket *ssave;
                   1358:                  register int t1;
                   1359: 
                   1360:                  ssave = symval;
                   1361:                  t1 = lex();
                   1362:                  unlex(t1);
                   1363:                  symval = ssave;
                   1364:                  if (t1 == COLON) break;
                   1365: 
                   1366:                  if(!first_rhs)        /* JF */
                   1367:                    first_rhs = symval;
                   1368:                  /* Not followed by colon =>
                   1369:                     process as part of this rule's rhs.  */
                   1370:                }
                   1371: 
                   1372:              /* If we just passed an action, that action was in the middle
                   1373:                 of a rule, so make a dummy rule to reduce it to a
                   1374:                 non-terminal.  */
                   1375:              if (actionflag)
                   1376:                {
                   1377:                  register bucket *sdummy;
                   1378: 
                   1379:                  /* Since the action was written out with this rule's */
                   1380:                  /* number, we must write give the new rule this number */
                   1381:                  /* by inserting the new rule before it.  */
                   1382: 
                   1383:                  /* Make a dummy nonterminal, a gensym.  */
                   1384:                  sdummy = gensym();
                   1385: 
                   1386:                  /* Make a new rule, whose body is empty,
                   1387:                     before the current one, so that the action
                   1388:                     just read can belong to it.  */
                   1389:                  nrules++;
                   1390:                  nitems++;
                   1391:                  record_rule_line ();
                   1392:                  p = NEW(symbol_list);
                   1393:                  if (crule1)
                   1394:                    crule1->next = p;
                   1395:                  else grammar = p;
                   1396:                  p->sym = sdummy;
                   1397:                  crule1 = NEW(symbol_list);
                   1398:                  p->next = crule1;
                   1399:                  crule1->next = crule;
                   1400: 
                   1401:                  /* insert the dummy generated by that rule into this rule.  */
                   1402:                  nitems++;
                   1403:                  p = NEW(symbol_list);
                   1404:                  p->sym = sdummy;
                   1405:                  p1->next = p;
                   1406:                  p1 = p;
                   1407: 
                   1408:                  actionflag = 0;
                   1409:                }
                   1410: 
                   1411:              if (t == IDENTIFIER)
                   1412:                {
                   1413:                  nitems++;
                   1414:                  p = NEW(symbol_list);
                   1415:                  p->sym = symval;
                   1416:                  p1->next = p;
                   1417:                  p1 = p;
                   1418:                }
                   1419:              else /* handle an action.  */
                   1420:                {
                   1421:                  copy_action(crule, rulelength);
                   1422:                  actionflag = 1;
                   1423:                  xactions++;   /* JF */
                   1424:                }
                   1425:              rulelength++;
                   1426:            }
                   1427: 
                   1428:          /* Put an empty link in the list to mark the end of this rule  */
                   1429:          p = NEW(symbol_list);
                   1430:          p1->next = p;
                   1431:          p1 = p;
                   1432: 
                   1433:          if (t == PREC)
                   1434:            {
                   1435:              t = lex();
                   1436:              crule->ruleprec = symval;
                   1437:              t = lex();
                   1438:            }
                   1439:          if (t == GUARD)
                   1440:            {
                   1441:              if (! semantic_parser)
                   1442:                fatal("%guard present but %semantic_parser not specified");
                   1443: 
                   1444:              copy_guard(crule, rulelength);
                   1445:              t = lex();
                   1446:            }
                   1447:          else if (t == LEFT_CURLY)
                   1448:            {
                   1449:              if (actionflag) fatal("two actions at end of one rule");
                   1450:              copy_action(crule, rulelength);
                   1451:              t = lex();
                   1452:            }
                   1453:          /* If $$ is being set in default way,
                   1454:             warn if any type mismatch.  */
                   1455:          else if (!xactions && first_rhs && lhs->type_name != first_rhs->type_name)
                   1456:            {
                   1457:              if (lhs->type_name == 0 || first_rhs->type_name == 0
                   1458:                  || strcmp(lhs->type_name,first_rhs->type_name))
                   1459:                fprintf(stderr, "%s:%d:  warning:  type clash ('%s' '%s') on default action\n",
                   1460:                        infile,
                   1461:                        lineno,
                   1462:                        lhs->type_name ? lhs->type_name : "",
                   1463:                        first_rhs->type_name ? first_rhs->type_name : "");
                   1464:            }
                   1465:          /* Warn if there is no default for $$ but we need one.  */
                   1466:          else if (!xactions && !first_rhs && lhs->type_name != 0)
                   1467:            fprintf(stderr,
                   1468:                    "%s:%d:  warning: empty rule for typed nonterminal, and no action\n",
                   1469:                    infile,
                   1470:                    lineno);
                   1471:          if (t == SEMICOLON)
                   1472:            t = lex();
                   1473:        }
                   1474:       /* these things can appear as alternatives to rules.  */
                   1475:       else if (t == TOKEN)
                   1476:        {
                   1477:          parse_token_decl(STOKEN, SNTERM);
                   1478:          t = lex();
                   1479:        }
                   1480:       else if (t == NTERM)
                   1481:        {
                   1482:          parse_token_decl(SNTERM, STOKEN);
                   1483:          t = lex();
                   1484:        }
                   1485:       else if (t == TYPE)
                   1486:        {
                   1487:          t = get_type();
                   1488:        }
                   1489:       else if (t == UNION)
                   1490:        {
                   1491:          parse_union_decl();
                   1492:          t = lex();
                   1493:        }
                   1494:       else if (t == EXPECT)
                   1495:        {
                   1496:          parse_expect_decl();
                   1497:          t = lex();
                   1498:        }
                   1499:       else if (t == START)
                   1500:        {
                   1501:          parse_start_decl();
                   1502:          t = lex();
                   1503:        }
                   1504:       else
                   1505:        fatal("invalid input");
                   1506:     }
                   1507: 
                   1508:   if (nsyms > MAXSHORT)
                   1509:     fatals("too many symbols (tokens plus nonterminals); maximum %d",
                   1510:           MAXSHORT);
                   1511:   if (nrules == 0)
                   1512:     fatal("no input grammar");
                   1513: 
                   1514:   if (typed == 0       /* JF put out same default YYSTYPE as YACC does */
                   1515:       && !value_components_used)
                   1516:     {
                   1517:       /* We used to use `unsigned long' as YYSTYPE on MSDOS,
                   1518:         but it seems better to be consistent.
                   1519:         Most programs should declare their own type anyway.  */
                   1520:       fprintf(fattrs, "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n");
                   1521:       if (fdefines)
                   1522:        fprintf(fdefines, "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n");
                   1523:     }
                   1524: 
                   1525:   /* Report any undefined symbols and consider them nonterminals.  */
                   1526: 
                   1527:   for (bp = firstsymbol; bp; bp = bp->next)
                   1528:     if (bp->class == SUNKNOWN)
                   1529:       {
                   1530:        fprintf(stderr, "symbol %s used, not defined as token, and no rules for it\n",
                   1531:                        bp->tag);
                   1532:        failure = 1;
                   1533:        bp->class = SNTERM;
                   1534:        bp->value = nvars++;
                   1535:       }
                   1536: 
                   1537:   ntokens = nsyms - nvars;
                   1538: }
                   1539: 
                   1540: 
                   1541: void
                   1542: record_rule_line ()
                   1543: {
                   1544:   /* Record each rule's source line number in rline table.  */
                   1545: 
                   1546:   if (nrules >= rline_allocated)
                   1547:     {
                   1548:       rline_allocated = nrules * 2;
                   1549:       rline = (short *) xrealloc (rline,
                   1550:                                  rline_allocated * sizeof (short));
                   1551:     }
                   1552:   rline[nrules] = lineno;
                   1553: }
                   1554: 
                   1555: 
                   1556: /* read in a %type declaration and record its information for get_type_name to access */
                   1557: 
                   1558: int
                   1559: get_type()
                   1560: {
                   1561:   register int k;
                   1562:   register int t;
                   1563:   register char *name;
                   1564: 
                   1565:   t = lex();
                   1566: 
                   1567:   if (t != TYPENAME)
                   1568:     fatal("ill-formed %type declaration");
                   1569: 
                   1570:   k = strlen(token_buffer);
                   1571:   name = NEW2(k + 1, char);
                   1572:   strcpy(name, token_buffer);
                   1573: 
                   1574:   for (;;)
                   1575:     {
                   1576:       t = lex();
                   1577: 
                   1578:       switch (t)
                   1579:        {
                   1580:        case SEMICOLON:
                   1581:          return (lex());
                   1582: 
                   1583:        case COMMA:
                   1584:          break;
                   1585: 
                   1586:        case IDENTIFIER:
                   1587:          if (symval->type_name == NULL)
                   1588:            symval->type_name = name;
                   1589:          else
                   1590:            fatals("type redeclaration for %s", symval->tag);
                   1591: 
                   1592:          break;
                   1593: 
                   1594:        default:
                   1595:          return (t);
                   1596:        }
                   1597:     }
                   1598: }
                   1599: 
                   1600: 
                   1601: 
                   1602: /* assign symbol numbers, and write definition of token names into fdefines.
                   1603: Set up vectors tags and sprec of names and precedences of symbols.  */
                   1604: 
                   1605: void
                   1606: packsymbols()
                   1607: {
                   1608:   register bucket *bp;
                   1609:   register int tokno = 1;
                   1610:   register int i;
                   1611:   register int last_user_token_number;
                   1612: 
                   1613:   /* int lossage = 0; JF set but not used */
                   1614: 
                   1615:   tags = NEW2(nsyms + 1, char *);
                   1616:   tags[0] = "$";
                   1617: 
                   1618:   sprec = NEW2(nsyms, short);
                   1619:   sassoc = NEW2(nsyms, short);
                   1620: 
                   1621:   max_user_token_number = 256;
                   1622:   last_user_token_number = 256;
                   1623: 
                   1624:   for (bp = firstsymbol; bp; bp = bp->next)
                   1625:     {
                   1626:       if (bp->class == SNTERM)
                   1627:        {
                   1628:          bp->value += ntokens;
                   1629:        }
                   1630:       else
                   1631:        {
                   1632:          if (translations && !(bp->user_token_number))
                   1633:            bp->user_token_number = ++last_user_token_number;
                   1634:          if (bp->user_token_number > max_user_token_number)
                   1635:            max_user_token_number = bp->user_token_number;
                   1636:          bp->value = tokno++;
                   1637:        }
                   1638: 
                   1639:       tags[bp->value] = bp->tag;
                   1640:       sprec[bp->value] = bp->prec;
                   1641:       sassoc[bp->value] = bp->assoc;
                   1642: 
                   1643:     }
                   1644: 
                   1645:   if (translations)
                   1646:     {
                   1647:       register int i;
                   1648: 
                   1649:       token_translations = NEW2(max_user_token_number+1, short);
                   1650: 
                   1651:       /* initialize all entries for literal tokens to 2,
                   1652:         the internal token number for $illegal., which represents all invalid inputs.  */
                   1653:       for (i = 0; i <= max_user_token_number; i++)
                   1654:         token_translations[i] = 2;      
                   1655:     }
                   1656: 
                   1657:   for (bp = firstsymbol; bp; bp = bp->next)
                   1658:     {
                   1659:       if (bp->value >= ntokens) continue;
                   1660:       if (translations)
                   1661:        {
                   1662:          if (token_translations[bp->user_token_number] != 2)
                   1663:            {
                   1664:                /* JF made this a call to fatals() */
                   1665:              fatals( "tokens %s and %s both assigned number %d",
                   1666:                              tags[token_translations[bp->user_token_number]],
                   1667:                              bp->tag,
                   1668:                              bp->user_token_number);
                   1669:            }
                   1670:          token_translations[bp->user_token_number] = bp->value;
                   1671:        }
                   1672:     }
                   1673: 
                   1674:   error_token_number = errtoken->value;
                   1675: 
                   1676:   output_token_defines(ftable);
                   1677: 
                   1678:   if (startval->class == SUNKNOWN)
                   1679:     fatals("the start symbol %s is undefined", startval->tag);
                   1680:   else if (startval->class == STOKEN)
                   1681:     fatals("the start symbol %s is a token", startval->tag);
                   1682: 
                   1683:   start_symbol = startval->value;
                   1684: 
                   1685:   if (definesflag)
                   1686:     {
                   1687:       output_token_defines(fdefines);
                   1688: 
                   1689:       if (!pure_parser)
                   1690:        {
                   1691:          if (spec_name_prefix)
                   1692:            fprintf(fdefines, "\nextern YYSTYPE %slval;\n", spec_name_prefix);
                   1693:          else
                   1694:            fprintf(fdefines, "\nextern YYSTYPE yylval;\n");
                   1695:        }
                   1696: 
                   1697:       if (semantic_parser)
                   1698:        for (i = ntokens; i < nsyms; i++)
                   1699:          {
                   1700:            /* don't make these for dummy nonterminals made by gensym.  */
                   1701:            if (*tags[i] != '@')
                   1702:              fprintf(fdefines, "#define\tNT%s\t%d\n", tags[i], i);
                   1703:          }
                   1704: #if 0
                   1705:       /* `fdefines' is now a temporary file, so we need to copy its
                   1706:          contents in `done', so we can't close it here.  */
                   1707:       fclose(fdefines);
                   1708:       fdefines = NULL;
                   1709: #endif
                   1710:     }
                   1711: }
                   1712:       
                   1713: 
                   1714: void
                   1715: output_token_defines(file)
                   1716: FILE *file;
                   1717: {
                   1718:   bucket *bp;
                   1719: 
                   1720:   for (bp = firstsymbol; bp; bp = bp->next)
                   1721:     {
                   1722:       if (bp->value >= ntokens) continue;
                   1723: 
                   1724:       /* For named tokens, but not literal ones, define the name.  */
                   1725:       /* The value is the user token number.  */
                   1726: 
                   1727:       if ('\'' != *tags[bp->value] && bp != errtoken)
                   1728:        {
                   1729:          register char *cp = tags[bp->value];
                   1730:          register char c;
                   1731: 
                   1732:          /* Don't #define nonliteral tokens whose names contain periods.  */
                   1733: 
                   1734:          while ((c = *cp++) && c != '.');
                   1735:          if (!c)
                   1736:            {
                   1737:               fprintf(file, "#define\t%s\t%d\n", tags[bp->value],
                   1738:                            (translations ? bp->user_token_number : bp->value));
                   1739:              if (semantic_parser)
                   1740:                 fprintf(file, "#define\tT%s\t%d\n", tags[bp->value],
                   1741:                              bp->value);
                   1742:            }
                   1743:        }
                   1744:     }
                   1745: 
                   1746:   putc('\n', file);
                   1747: }
                   1748: 
                   1749: 
                   1750: 
                   1751: /* convert the rules into the representation using rrhs, rlhs and ritems.  */
                   1752: 
                   1753: void
                   1754: packgram()
                   1755: {
                   1756:   register int itemno;
                   1757:   register int ruleno;
                   1758:   register symbol_list *p;
                   1759: /*  register bucket *bp; JF unused */
                   1760: 
                   1761:   bucket *ruleprec;
                   1762: 
                   1763:   ritem = NEW2(nitems + 1, short);
                   1764:   rlhs = NEW2(nrules, short) - 1;
                   1765:   rrhs = NEW2(nrules, short) - 1;
                   1766:   rprec = NEW2(nrules, short) - 1;
                   1767:   rprecsym = NEW2(nrules, short) - 1;
                   1768:   rassoc = NEW2(nrules, short) - 1;
                   1769: 
                   1770:   itemno = 0;
                   1771:   ruleno = 1;
                   1772: 
                   1773:   p = grammar;
                   1774:   while (p)
                   1775:     {
                   1776:       rlhs[ruleno] = p->sym->value;
                   1777:       rrhs[ruleno] = itemno;
                   1778:       ruleprec = p->ruleprec;
                   1779: 
                   1780:       p = p->next;
                   1781:       while (p && p->sym)
                   1782:        {
                   1783:          ritem[itemno++] = p->sym->value;
                   1784:          /* A rule gets by default the precedence and associativity
                   1785:             of the last token in it.  */
                   1786:           if (p->sym->class == STOKEN)
                   1787:            {
                   1788:              rprec[ruleno] = p->sym->prec;
                   1789:              rassoc[ruleno] = p->sym->assoc;
                   1790:            }
                   1791:          if (p) p = p->next;
                   1792:        }
                   1793: 
                   1794:       /* If this rule has a %prec,
                   1795:         the specified symbol's precedence replaces the default.  */
                   1796:       if (ruleprec)
                   1797:        {
                   1798:           rprec[ruleno] = ruleprec->prec;
                   1799:           rassoc[ruleno] = ruleprec->assoc;
                   1800:          rprecsym[ruleno] = ruleprec->value;
                   1801:        }
                   1802: 
                   1803:       ritem[itemno++] = -ruleno;
                   1804:       ruleno++;
                   1805: 
                   1806:       if (p) p = p->next;
                   1807:     }
                   1808: 
                   1809:   ritem[itemno] = 0;
                   1810: }
                   1811: 
                   1812: /* Read a signed integer from STREAM and return its value.  */
                   1813: 
                   1814: int
                   1815: read_signed_integer (stream)
                   1816:      FILE *stream;
                   1817: {
                   1818:   register int c = getc(stream);
                   1819:   register int sign = 1;
                   1820:   register int n;
                   1821: 
                   1822:   if (c == '-')
                   1823:     {
                   1824:       c = getc(stream);
                   1825:       sign = -1;
                   1826:     }
                   1827:   n = 0;
                   1828:   while (isdigit(c))
                   1829:     {
                   1830:       n = 10*n + (c - '0');
                   1831:       c = getc(stream);
                   1832:     }
                   1833: 
                   1834:   ungetc(c, stream);
                   1835: 
                   1836:   return n * sign;
                   1837: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.