Annotation of GNUtools/bison/reader.c, revision 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.