/* Input parser for bison
   Copyright (C) 1984, 1986, 1989 Free Software Foundation, Inc.

This file is part of Bison, the GNU Compiler Compiler.

Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING.  If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */


/* read in the grammar specification and record it in the format described in gram.h.
  All actions are copied into faction,
  in each case forming the body of a C function (action)
  which contains a switch statement to decide which guard or action to execute.

The entry point is reader().  
*/

#include <ctype.h>
#include <algorithm>

#include "system.h"
#include "new.h"
#include "machine.h"
#include "declarations.h"

using namespace std;


namespace {

    // variables used by readgram() and support functions.
int rulelength;  // number of symbols in rhs of this rule so far
int xactions;
bucket *lhs;
symbol_list *p1;
symbol_list *p;
symbol_list *crule; // points to first symbol_list of current rule.  
symbol_list *crule1;  // points to the symbol_list preceding crule.  
bool actionflag;
bucket *first_rhs;

bool start_flag;
bool value_components_used;

bucket *startval;
int gensym_count;  /* incremented for each generated symbol */

int lastprec;  /* incremented for each %left, %right or %nonassoc seen */

//// Get the data type (alternative in the union) of the value for symbol n in
//// rule rule. 
//char *get_type_name(int n, symbol_list* rule)
//{
//  static char *msg = "invalid $ value";
//
//  register int i;
//  register symbol_list *rp;
//
//  if (n < 0)
//    fatal(msg);
//
//  rp = rule;
//  i = 0;
//
//  while (i < n)
//    {
//      rp = rp->next;
//      if (rp == 0 || rp->sym == 0)
//    fatal(msg);
//      i++;
//    }
//
//  return (rp->sym->type_name);
//}

//
//                                        // *sp is NOT erased first!
//void read_a_name(string *sp, char const *extra = "_")
//{
//    register int c;
//    for
//    (
//        c = skip_white_space(); 
//            isalnum(c) || strchr(extra, c); 
//                c = getc(finput)
//    )
//        *sp += c;
//
//    ungetc(c, finput);
//} 
//
// parse what comes after %token or %nterm.
// For %token, what_is is STOKEN and what_is_not is SNTERM.
// For %nterm, the arguments are reversed. 
//void parse_token_decl(int what_is, int  what_is_not)
//{
//    register int prev = ILLEGAL;
//    char *internalTypename = 0;
//
//    while (true)
//    {
//        if(ungetc(skip_white_space(), finput) == '%')
//            return;
//        
//        int token = lex();
//        switch(token)
//        {
//            case TYPENAME:
//                internalTypename = xstrdup(token_buffer);
//                value_components_used = true;
//            break;
//
//            case IDENTIFIER:
//            {
//                int oldclass = symval->internalClass;
//    
//                if (symval->internalClass == what_is_not)
//                    fatals("symbol %s redefined",  symval->tag);
//
//                symval->internalClass = what_is;
//                if (what_is == SNTERM && oldclass != SNTERM)
//                    symval->value = nvars++;
//        
//                if (internalTypename)
//                {
//                  if (symval->type_name == 0)
//                        symval->type_name = internalTypename;
//                  else
//                        fatals("type redeclaration for %s",  symval->tag);
//                }
//            }
//            break;
//
//            case NUMBER:
//                if (prev == IDENTIFIER)
//                  symval->user_token_number = numval;
//                else
//                    fatal("invalid text in %token or %nterm declaration");
//            break;
//        }            
//        prev = token;
//    }   
//}
//
//// read in a %type declaration and record its information for get_type_name to
//// access 
//void parse_type_decl()
//{
//    if (lex() != TYPENAME)
//      fatal("ill-formed %type declaration");
//  
//    register char *name = xstrdup(token_buffer);
//    while (true)
//    {
//        if(ungetc(skip_white_space(), finput) == '%')
//            return;
//    
//        switch (lex())
//        {
//            case COMMA:
//            case SEMICOLON:
//            break;
//    
//            case IDENTIFIER:
//                if (symval->type_name == 0)
//                    symval->type_name = name;
//                else
//                    fatals("type redeclaration for %s",  symval->tag);
//            break;
//    
//            default:
//                fatal("invalid %type declaration");
//        }
//    }
//}
//
//void parse_start_decl()         // parse what comes after %start
//{
//  if (start_flag)
//    fatal("multiple %start declarations");
//  start_flag = 1;
//  if (lex() != IDENTIFIER)
//    fatal("invalid %start declaration");
//  startval = symval;
//}
//
//void parse_structured_type(char **out)
//{
//    static char ch[2] = "";
//
//    register int c = getc(finput);
//    register int count = 0;
//    register bool in_comment = false;
//    bool cplus_comment;
//
//    while (c != EOF)
//    {
//        ch[0] = c;
//        *out = stringappend(*out, ch);
//
//        switch (c)
//        {
//            case '\n':
//                lineno++;
//            break;
//        
//            case '/':
//                c = getc(finput);
//                if (c != '*' && c != '/')
//                    ungetc(c, finput);
//                else
//                {
//                    ch[0] = c;
//                    *out = stringappend(*out, ch);
//
//                    cplus_comment = (c == '/');
//                    in_comment = true;
//                    c = getc(finput);
//                    while (in_comment)
//                    {
//                        ch[0] = c;
//                        *out = stringappend(*out, ch);
//
//                        if (c == '\n')
//                        {
//                            lineno++;
//                            if (cplus_comment)
//                            {
//                                in_comment = false;
//                                break;
//                            }
//                        }
//                        else if (c == EOF)
//                            fatal("unterminated comment");
//                        if (!cplus_comment && c == '*')
//                        {
//                            c = getc(finput);
//                            if (c == '/')
//                            {
//                                ch[0] = c;
//                                *out = stringappend(*out, ch);
//
//                                in_comment = false;
//                            }
//                        }
//                        else
//                            c = getc(finput);
//                    }
//                }
//            break;
//        
//            case '{':
//                count++;
//            break;
//        
//            case '}':
//                if (count == 0)
//                    fatal ("unmatched close-brace (`}')");
//                count--;
//                if (count == 0)
//                { 
//                    if (generate_baseclass == FORCED)
//                        *out = stringappend(*out, ";\n");
//        
//                    c = skip_white_space();
//                    if (c != ';') 
//                        ungetc(c,finput);
//                  return;
//                }
//        }
//        c = getc(finput);
//    }
//}
//
//// copy the union declaration into ostringstream `union_decl' as the
//// definition of STYPE, the type of elements of the parser value stack.
//void parse_union_decl()
//{
//    if (typed || simple_stype)
//        fatal("%union or STYPE multiply declared");
//
//      typed = 1;
//
//    if (generate_baseclass == FORCED)
//        union_type = stringappend(union_type, "\n"
//                                              "union STYPE");
//    parse_structured_type(&union_type);
//}
//
// copy the location declaration into ostringstream `location_decl' as the
// definition of LSTYPE.
//void parse_location_decl()
//{
//    if (ltyped || simple_ltype)
//        fatal("%location-struct or LTYPE multiply declared");
//
//    ltyped = 1;
//
//    if (generate_baseclass == FORCED)
//        location_type = stringappend(location_type, "\n"
//                                                    "struct LTYPE");
//    parse_structured_type(&location_type);
//}
//
//
//// parse the declaration %expect N which says to expect N shift-reduce
//// conflicts.
//void parse_expect_decl()
//{
//  register int c;
//  register int count;
//  char buffer[20];
//
//  c = getc(finput);
//  while (c == ' ' || c == '\t')
//    c = getc(finput);
//
//  count = 0;
//  while (c >= '0' && c <= '9')
//    {
//      if (count < 20)
//    buffer[count++] = c;
//      c = getc(finput);
//    }
//  buffer[count] = 0;
//
//  ungetc (c, finput);
//
//  expected_conflicts = atoi (buffer);
//}
//
//
//// read in a %left, %right or %nonassoc declaration and record its
//// information.  assoc is either LEFT_ASSOC, RIGHT_ASSOC or NON_ASSOC.
//void parse_assoc_decl(int assoc)
//{
//    register char *name = 0;
//    register int prev = ILLEGAL;
//
//    lastprec++;  /* Assign a new precedence level, never 0.  */
//
//    while (true)
//    {
//        if (ungetc(skip_white_space(), finput) == '%')
//            return;
//
//        register int t = lex();
//
//        switch (t)
//        {
//            case TYPENAME:
//                name = xstrdup(token_buffer);
//            break;
//    
//            case COMMA:
//            break;
//    
//            case IDENTIFIER:
//                if (symval->prec != 0)
//                  fatals("redefining precedence of %s",  symval->tag);
//
//                symval->prec = lastprec;
//                symval->assoc = assoc;
//
//                if (symval->internalClass == SNTERM)
//                  fatals("symbol %s redefined",  symval->tag);
//
//                symval->internalClass = STOKEN;
//
//                if (name)
//                {   // record the type, if one is specified 
//                    if (symval->type_name == 0)
//                        symval->type_name = name;
//                    else
//                        fatals("type redeclaration for %s",  symval->tag);
//                }
//            break;
//    
//            case NUMBER:
//                if (prev == IDENTIFIER)
//                    symval->user_token_number = numval;
//                else    
//                    fatal("invalid text in association declaration");
//            break;
//    
//            case SEMICOLON:
//            return;
//    
//            default:
//                fatal("malformatted association declaration");
//        }
//        prev = t;
//    }
//}

//void set_parser_name(string const &name)
//{
//    if (parser_defined) // redef 
//        fatals(
//            "parser name multiply defined as \"%s\". "
//            "Redefine attempted to \"%s\"\n", parser_name, name.c_str());
//    else
//    {
//        parser_defined++;
//        parser_name = xstrdup(name.c_str());
//    }
//}
//
//void parse_name_declaration()
//{
//    string name;
//    read_a_name(&name);
//    set_parser_name(name.c_str());
//}
//
//void set_debug_flag()
//{
//    debugflag = true;
//}
//
//void set_error_verbose()
//{
//    error_verbose = true;
//}
//
//void set_lsp_needed()
//{
//    lsp_needed = true;
//}
//
//char *pathname()
//{
//    string name;
//    register int c;
//
//    for (c = skip_white_space(); !isspace(c); c = getc(finput))
//        name += c;
//    ungetc(c, finput);
//
//    return xstrdup(name.c_str());
//}

//void definePathname(char **dest)
//{
//    char *path = pathname();
//    if (!*dest)
//        *dest = path;
//    else
//        delete [] path;
//}
//
//
//void set_ltype()
//{
//    string name;
//    read_a_name(&name);
//
//    if (simple_ltype || ltyped)
//        fatal("%locationstruct or LTYPE multiply defined");
//    else
//        simple_ltype = xstrdup(name.c_str());
//}
//
//void set_stype()
//{
//    string name;
//    read_a_name(&name);
//
//    if (simple_stype || typed)
//        fatal("%union or STYPE multiply defined");
//    else
//        simple_stype = xstrdup(name.c_str());
//}
//
//void set_preinclude()
//{
//    definePathname(&baseclass_preinclude);
//}
//
//void set_namespace()
//{
//    string name;
//    read_a_name(&name);
//
//    if (!nameSpace)
//        nameSpace = xstrdup(name.c_str());
//}
//
//void set_baseclass_header()
//{
//    definePathname(&baseclass_header);
//}
//
//void set_class_header()
//{
//    class_header = pathname();
//}
//
//void set_generic_filename()
//{
//    definePathname(&generic_filename);
//}
//
//void set_implementation_header()
//{
//    definePathname(&implementation_header);
//}
//
void set_parsefun_source()
{
    definePathname(&parsefun_source);
}

//void done()
//{
//    throw 0;
//}
//
//void nop()
//{}
//
//void parse_token_nterm()
//{
//    parse_token_decl(STOKEN, SNTERM);
//}
//
//void parse_nterm_token()
//{
//    parse_token_decl(SNTERM, STOKEN);
//}
//
//void parse_left_assoc()
//{
//    parse_assoc_decl(LEFT_ASSOC);
//}
//
//void parse_right_assoc()
//{
//    parse_assoc_decl(RIGHT_ASSOC);
//}
//
//void parse_nonassoc()
//{
//    parse_assoc_decl(NON_ASSOC);
//}
//
//void not_called()
//{
//    fatal("not_called() called from reader.cc");
//}
//
//void junk()
//{
//    fatal("junk after `%%' in definition section");
//}
//
//void (*action[])() = 
//{
//    not_called,                 // BAR,
//    set_baseclass_header,       // BASECLASS_HEADER,
//    set_preinclude,             // BASECLASS_PREINCLUDE,
//    set_class_header,           // CLASS_HEADER,
//    not_called,                 // COLON,                   
//    not_called,                 // COMMA,                   
//    set_debug_flag,             // DEBUGFLAG,
//    not_called,                 // ENDFILE,                 
//    set_error_verbose,          // ERROR_VERBOSE,
//    parse_expect_decl,          // EXPECT,
//    set_generic_filename,       // FILENAMES,
//    not_called,                 // IDENTIFIER,
//    junk,                       // ILLEGAL,
//    set_implementation_header,  // IMPLEMENTATION_HEADER,
//    parse_left_assoc,           // LEFT,
//    not_called,                 // LEFT_CURLY,              
//    parse_location_decl,        // LOCATIONSTRUCT, 
//                                // writes header file fbaseclass_header
//    set_lsp_needed,             // LSP_NEEDED,
//    set_ltype,                  // LTYPE,
//    set_namespace,              // NAMESPACE,             
//    parse_nonassoc,             // NONASSOC,
//    parse_nterm_token,          // NTERM,
//    not_called,                 // NUMBER,                  
//    set_parsefun_source,        // PARSEFUN_SOURCE,         
//    parse_name_declaration,     // CLASS_NAME,
//    not_called,                 // PERCENT,                 
//    not_called,                 // PERCENT_LEFT_CURLY,      
//    not_called,                 // PREC,                    
//    parse_right_assoc,          // RIGHT,
//    not_called,                 // SEMICOLON,               
//    parse_start_decl,           // START,
//    set_stype,                  // STYPE,
//    parse_token_nterm,          // TOKEN,
//    done,                       // TWO_PERCENTS,
//    parse_type_decl,            // TYPE,
//    not_called,                 // TYPENAME,                
//    parse_union_decl,           // UNION, writes header file fbaseclass_header
//};
//
//
//// read from finput until %% is seen.  Discard the %%.
//// Handle any % declarations, 
//void read_declarations()
//{
//    register int c;
//    try
//    {
//        while (true)
//        {
//            c = skip_white_space();
//    
//            if (c == '%')
//                (*action[ parse_percent_token() ])();
//            else if (c == EOF)
//                fatal("no input grammar");
//            else if (isprint(c))
//                fatals("unknown character `%c' in declaration section", c);
//            else
//                fatals(
//                "unknown character with code 0x%x in declaration section",  c);
//        }
//    }
//    catch (...)
//    {
//        return;
//    }
//}

// generate a dummy symbol, a nonterminal, whose name cannot conflict with the
// user's names.
//bucket *gensym()
//{
//  register bucket *sym;
//
//  sprintf (token_buffer, "@%d", ++gensym_count);
//  sym = getsym(token_buffer);
//  sym->internalClass = SNTERM;
//  sym->value = nvars++;
//  return (sym);
//}
//
//// Read a signed integer from STREAM and return its value.
//int read_signed_integer (FILE* stream)
//{
//  register int c = getc(stream);
//  register int sign = 1;
//  register int n;
//
//  if (c == '-')
//    {
//      c = getc(stream);
//      sign = -1;
//    }
//  n = 0;
//  while (isdigit(c))
//    {
//      n = 10 * n + (c - '0');
//      c = getc(stream);
//    }
//
//  ungetc(c, stream);
//
//  return n * sign;
//}
//
//// Assuming that a { has just been seen, copy everything up to the matching }
//// into the actions file.
//// stack_offset is the number of values in the current rule so far,
//// which says where to find $0 with respect to the top of the stack. 
//void copy_action(symbol_list* rule, int stack_offset)
//{
//  register int c;
//  register int n = 0; // to prevent the unitialized use warning
//  register int count;
//  register int match;
//  register int ended;
//  register char *type_name;
//  int cplus_comment;
//
//    fprintf(faction, "\ncase %d:\n", nrules);
//    if (!nolinesflag)
//        fprintf(faction, "#line %d \"%s\"\n", lineno, quoted_filename(infile));
//    putc('{', faction);
//
//  count = 1;
//  c = getc(finput);
//
//  while (count > 0)
//    {
//      while (c != '}')
//        {
//          switch (c)
//        {
//        case '\n':
//          putc(c, faction);
//          lineno++;
//          break;
//
//        case '{':
//          putc(c, faction);
//          count++;
//          break;
//
//        case '\'':
//        case '"':
//          match = c;
//          putc(c, faction);
//          c = getc(finput);
//
//          while (c != match)
//        {
//          if (c == EOF || c == '\n')
//            fatal("unterminated string");
//
//          putc(c, faction);
//
//          if (c == '\\')
//            {
//              c = getc(finput);
//              if (c == EOF)
//            fatal("unterminated string");
//              putc(c, faction);
//              if (c == '\n')
//            lineno++;
//            }
//
//          c = getc(finput);
//        }
//
//          putc(c, faction);
//          break;
//
//        case '/':
//          putc(c, faction);
//          c = getc(finput);
//          if (c != '*' && c != '/')
//        continue;
//
//          cplus_comment = (c == '/');
//          putc(c, faction);
//          c = getc(finput);
//
//          ended = 0;
//          while (!ended)
//        {
//          if (!cplus_comment && c == '*')
//            {
//              while (c == '*')
//                {
//              putc(c, faction);
//              c = getc(finput);
//            }
//
//              if (c == '/')
//            {
//              putc(c, faction);
//              ended = 1;
//            }
//            }
//          else if (c == '\n')
//            {
//              lineno++;
//              putc(c, faction);
//              if (cplus_comment)
//            ended = 1;
//              else
//                c = getc(finput);
//            }
//          else if (c == EOF)
//            fatal("unterminated comment");
//          else
//            {
//              putc(c, faction);
//              c = getc(finput);
//            }
//        }
//
//          break;
//
//        case '$':
//          c = getc(finput);
//          type_name = 0;
//
//          if (c == '<')
//        {
//          register char *cp = token_buffer;
//
//          while ((c = getc(finput)) != '>' && c > 0)
//            *cp++ = c;
//          *cp = 0;
//          type_name = token_buffer;
//          value_components_used = 1;
//
//          c = getc(finput);
//        }
//
//          if (c == '$')
//        {
//          fprintf(faction, "val");
//          if (!type_name) type_name = get_type_name(0, rule);
//          if (type_name)
//            fprintf(faction, ".%s", type_name);
//          if(!type_name && typed)   /* JF */
//            fprintf(stderr,"%s:%d:  warning:  $$ of '%s' has no declared type.\n",infile,lineno,rule->sym->tag);
//        }
//          else if (isdigit(c) || c == '-')
//        {
//          ungetc (c, finput);
//          n = read_signed_integer(finput);
//          c = getc(finput);
//
//          if (!type_name && n > 0)
//            type_name = get_type_name(n, rule);
//
//          fprintf(faction, "vsp[%d]", n - stack_offset);
//          if (type_name)
//            fprintf(faction, ".%s", type_name);
//          if(!type_name && typed)   /* JF */
//            fprintf(stderr,"%s:%d:  warning:  $%d of '%s' has no declared type.\n",infile,lineno,n,rule->sym->tag);
//          continue;
//        }
//          else
//        fatals("$%c is invalid", c); /* JF changed format */
//
//          break;
//
//        case '@':
//          c = getc(finput);
//          if (isdigit(c) || c == '-')
//        {
//          ungetc (c, finput);
//          n = read_signed_integer(finput);
//          c = getc(finput);
//        }
//          else
//        fatal("invalid @-construct");
//
//          fprintf(faction, "lsp[%d]", n - stack_offset);
//          lsp_needed = 1;
//
//          continue;
//
//        case EOF:
//          fatal("unmatched '{'");
//
//        default:
//          putc(c, faction);
//        }
//
//          c = getc(finput);
//        }
//
//      /* above loop exits when c is '}' */
//
//      if (--count)
//        {
//      putc(c, faction);
//      c = getc(finput);
//    }
//    }
//
//  fprintf(faction, ";\n    break;}");
//}

//// read in a %type declaration and record its information for get_type_name to
//// access 
//int get_type()
//{
//    register int t = lex();
//  
//    if (t != TYPENAME)
//      fatal("ill-formed %type declaration");
//  
//    register char *name = xstrdup(token_buffer);
//  
//    while (true)
//    {
//        t = lex();
//  
//        switch (t)
//        {
//            case SEMICOLON:
//            return lex();
//  
//            case COMMA:
//            break;
//  
//            case IDENTIFIER:
//                if (symval->type_name == 0)
//                    symval->type_name = name;
//                else
//                    fatals("type redeclaration for %s",  symval->tag);
//            break;
//  
//            default:
//            return t;
//        }
//    }
//}
//
//
//void readgram_trailer()
//{
//    if (nsyms > MAXSHORT)
//        fatals("too many symbols (tokens plus nonterminals); maximum %d",
//                MAXSHORT);
//    if (nrules == 0)
//        fatal("no input grammar");
//
//    /* Report any undefined symbols and consider them nonterminals.  */
//
//    for (bucket *bp = firstsymbol; bp; bp = bp->next)
//    {
//        if (bp->internalClass == SUNKNOWN)
//        {
//            fprintf(stderr, "symbol %s used, not defined as token, "
//                            "and no rules for it\n",
//                            bp->tag);
//            failure = 1;
//            bp->internalClass = SNTERM;
//            bp->value = nvars++;
//        }
//    }
//    ntokens = nsyms - nvars;
//}
//
//int readgram_rule_rhs()
//{
//    while (true)
//    {
//        int t = lex();
//
//        if (t != IDENTIFIER && t != LEFT_CURLY)
//            return t;
//
//        // If next token is an identifier, see if a colon follows it.
//        // If one does, exit this rule now. 
//        if (t == IDENTIFIER)
//        {
//            register bucket *ssave;
//            register int t1;
//
//            ssave = symval;
//            t1 = lex();
//            unlex(t1);
//            symval = ssave;
//            if (t1 == COLON) 
//                return t;
//
//            if (!first_rhs)    
//                first_rhs = symval;
//            // Not followed by colon =>
//            //   process as part of this rule's rhs. 
//        }
//
//        // If we just passed an action, that action was in the middle
//        // of a rule, so make a dummy rule to reduce it to a
//        // non-terminal.  
//        if (actionflag)
//        {
//            register bucket *sdummy;
//
//            // Since the action was written out with this rule's 
//            // number, we must write give the new rule this number
//            // by inserting the new rule before it.  
//
//            // Make a dummy nonterminal, a gensym. 
//            sdummy = gensym();
//
//            // Make a new rule, whose body is empty,
//            // before the current one, so that the action
//            // just read can belong to it.  
//            nrules++;
//            nitems++;
//            rline.push_back(lineno);
//
//            p = new symbol_list();
//            if (crule1)
//                crule1->next = p;
//            else 
//                grammar = p;
//            p->sym = sdummy;
//            crule1 = new symbol_list();
//            p->next = crule1;
//            crule1->next = crule;
//
//            // insert the dummy generated by that rule into this rule.
//            nitems++;
//            p = new symbol_list();    // just the name of the symbol.
//            p->sym = sdummy;
//            p1->next = p;
//            p1 = p;
//
//            actionflag = false;
//        }
//
//        if (t == IDENTIFIER)
//        {
//            nitems++;
//            p = new symbol_list();
//            p->sym = symval;
//            p1->next = p;
//            p1 = p;
//        }
//        else // handle an action.
//        {
//            copy_action(crule, rulelength);
//            actionflag = true;
//            xactions++;   
//        }
//        rulelength++;
//    }
//}
//
//int readgram_identifier_or_bar(int t)  // t: token just read
//{
//    actionflag = false;
//    rulelength = 0;
//    xactions = 0;
//    first_rhs = 0;
//
//    if (t == IDENTIFIER)
//    {
//        lhs = symval;
//    
//        t = lex();
//        if (t != COLON)
//            fatal("ill-formed rule");
//    }
//
//    if (nrules == 0)
//    {
//        if (t == BAR)
//            fatal("grammar starts with vertical bar");
//
//        if (!start_flag)
//            startval = lhs;
//    }
//
//    // start a new rule and record its lhs.  
//    nitems++;
//    ++nrules;
//    rline.push_back(lineno);
//
//    p = new symbol_list();
//    p->sym = lhs;
//    if (p1)
//        p1->next = p;
//    else
//        grammar = p;
//
//    p1 = p;
//    crule = p;              // points to first symbol_list of current rule.  
//                            // its symbol is the lhs of the rule.   
//
//    // mark the rule's lhs as a nonterminal if not already so.  
//    if (lhs->internalClass == SUNKNOWN)
//    {
//        lhs->internalClass = SNTERM;
//        lhs->value = nvars;
//        nvars++;
//    }
//    else if (lhs->internalClass == STOKEN)
//        fatals("rule given for %s, which is a token",   lhs->tag);
//
//    t = readgram_rule_rhs();
//
//    // Put an empty link in the list to mark the end of this rule  
//    p = new symbol_list();
//    p1->next = p;
//    p1 = p;
//
//    if (t == PREC)
//    {
//        t = lex();
//        crule->ruleprec = symval;
//        t = lex();
//    }
//    if (t == LEFT_CURLY)
//    {
//        if (actionflag) fatal("two actions at end of one rule");
//        copy_action(crule, rulelength);
//        t = lex();
//    }
//    // If $$ is being set in default way, warn if any type mismatch.  
//    else if (!xactions && first_rhs && lhs->type_name != first_rhs->type_name)
//    {
//        if 
//        (
//            lhs->type_name == 0 || first_rhs->type_name == 0
//            || 
//            strcmp(lhs->type_name,first_rhs->type_name)
//        )
//            fprintf(stderr, "%s:%d:  warning:  "
//                            "type clash ('%s' '%s') on default action\n",
//                            infile,
//                            lineno,
//                            lhs->type_name ? lhs->type_name : "",
//                            first_rhs->type_name ? first_rhs->type_name : "");
//    }
//    // Warn if there is no default for $$ but we need one.  
//    else if (!xactions && !first_rhs && lhs->type_name != 0)
//      fprintf(stderr,
//          "%s:%d:  warning: empty rule for typed nonterminal, and no action\n",
//          infile,
//          lineno);
//
//    if (t == SEMICOLON)
//      t = lex();
//
//    return t;
//}

// Parse the input grammar into a one symbol_list structure.
//Each rule is represented by a sequence of symbols: the left hand side
//followed by the contents of the right hand side, followed by a null pointer
//instead of a symbol to terminate the rule.
//The next symbol is the lhs of the following rule.
//
//All guards and actions are copied out to the appropriate files,
//labelled by the rule number they apply to.  
//void readgram()
//{
//    register int t = lex();
//    while (true)
//    {
//        switch (t)
//        {
//            case TWO_PERCENTS:
//            case ENDFILE:
//                readgram_trailer();
//            return;
//
//            case IDENTIFIER:
//            case BAR:
//                t = readgram_identifier_or_bar(t);
//            continue;
//
//
//???
//volgens de manual niet: alleen rules hier.
//            // these things can appear as alternatives to rules.
//            case TOKEN:
//                parse_token_decl(STOKEN, SNTERM);
//            break;
//    
//            case NTERM:
//                parse_token_decl(SNTERM, STOKEN);
//            break;
//
//            case TYPE:
//                t = get_type();
//            continue;
//
//            case UNION:
//                parse_union_decl();
//            break;
//
//            case EXPECT:
//                parse_expect_decl();
//            break;
//
//            case START:
//                parse_start_decl();
//            break;
//            
//            default:
//                fatal("invalid input");
//        }
//        t = lex();
//    } 
}


/* assign symbol numbers, and write definition of token names into fbaseclass_header.
Set up vectors tags and sprec of names and precedences of symbols.  */

//void packsymbols()
//{
//    register bucket *bp;
//    register int tokno = 1;
//    register int last_user_token_number;
//
//    tags = Zero<char *>::array(nsyms + 1);
//    tags[0] = "$";
//
//    sprec.resize(nsyms);
//    sassoc.resize(nsyms);
//
//    max_user_token_number = 256;
//    last_user_token_number = 256;
//
//    for (bp = firstsymbol; bp; bp = bp->next)
//    {
//        if (bp->internalClass == SNTERM)
//            bp->value += ntokens;
//        else
//        {
//            if (!(bp->user_token_number))
//                bp->user_token_number = ++last_user_token_number;
//            if (bp->user_token_number > max_user_token_number)
//                max_user_token_number = bp->user_token_number;
//            bp->value = tokno++;
//        }
//
//        tags[bp->value] = bp->tag;
//        sprec[bp->value] = bp->prec;
//        sassoc[bp->value] = bp->assoc;
//    }
//
//    token_translations.resize(max_user_token_number + 1);
//
//    // initialize all entries for literal tokens to 2,
//    // the internal token number for $illegal., which represents all invalid
//    // inputs. 
//    for (register int i = 0; i <= max_user_token_number; i++)
//        token_translations[i] = 2;      
//
//    for (bp = firstsymbol; bp; bp = bp->next)
//    {
//        if (bp->value >= ntokens) 
//            continue;
//
//        if (token_translations[bp->user_token_number] != 2)
//            fatals( "tokens %s and %s both assigned number %d",
//                  tags[token_translations[bp->user_token_number]],
//                  bp->tag,
//                  bp->user_token_number);
//
//        token_translations[bp->user_token_number] = bp->value;
//    }
//
//    error_token_number = errtoken->value;
//  
//    if (startval->internalClass == SUNKNOWN)
//        fatals("the start symbol %s is undefined",  startval->tag);
//    else if (startval->internalClass == STOKEN)
//        fatals("the start symbol %s is a token",  startval->tag);
//
//    start_symbol = startval->value;
//}

/* convert the rules into the representation using rrhs, rlhs and ritems.  */

void packgram()
{
  register int itemno;
  register int ruleno;
  register symbol_list *p;
  bucket *ruleprec;

  ritem.resize(nitems + 1);
  rlhs.resize(nrules + 1);      // 1 too many: [0] apparently not used
  rrhs.resize(nrules + 1);      // same
  rprec.resize(nrules + 1);     // same
  rprecsym.resize(nrules + 1);  // same
  rassoc.resize(nrules + 1);    // same

  itemno = 0;
  ruleno = 1;

  p = grammar;
  while (p)
    {
      rlhs[ruleno] = p->sym->value; // lhs beginpoint is symbol's value
      rrhs[ruleno] = itemno;        // rrhs's value is location in rlhs
      ruleprec = p->ruleprec;       // remember the current precedence

      p = p->next;                  // next
      while (p && p->sym)           // while there are symbols
    {
      ritem[itemno++] = p->sym->value;  // store the symbol's value
      /* A rule gets by default the precedence and associativity
         of the last token in it.  */
          if (p->sym->internalClass == STOKEN)
        {
          rprec[ruleno] = p->sym->prec;
          rassoc[ruleno] = p->sym->assoc;
        }
      if (p) p = p->next;
    }

      /* If this rule has a %prec,
     the specified symbol's precedence replaces the default.  */
      if (ruleprec)
    {
          rprec[ruleno] = ruleprec->prec;
          rassoc[ruleno] = ruleprec->assoc;
      rprecsym[ruleno] = ruleprec->value;
    }

      ritem[itemno++] = -ruleno;
      ruleno++;

      if (p) p = p->next;
    }

  ritem[itemno] = 0;
}


} // Anonymous namespace ends


void reader()
{
//  start_flag = 0;
//  startval = 0;  /* start symbol not specified yet. */
//
//  nsyms = 1;
//  nvars = 0;
//  nrules = 0;
//  nitems = 0;
//
//  typed = 0;
//  lastprec = 0;
//  gensym_count = 0;
//  lsp_needed = 0;
//  grammar = 0;
//
//  faction = tmpfile();          // we need this to write the actions.
//                                // it's a temp. file, so it needs no name.
//
//  finput = try_open(infile, "r");// we also need the input stream to analyze
//                                // the specifications
//
//  init_lex();
//  lineno = 1;
//
//  /* initialize the symbol table.  */
//  tabinit();
//
//  /* construct the error token */
//  errtoken = getsym("error");
//  errtoken->internalClass = STOKEN;
//  errtoken->user_token_number = 256; /* Value specified by posix.  */
//
//  /* construct a token that represents all undefined literal tokens. */
//  /* it is always token number 2.  */
//
//  getsym("$illegal.")->internalClass = STOKEN;
//
//  // Read the declaration section: process all until the %% line
//  // Also notice any %token, %left, etc. found there.
//
//
//  read_declarations();
//
//
//    // read in the grammar, build grammar in list form.  write out actions.
//    // nothing is written to the output files.
//  readgram();
//
//  // assign the symbols their symbol numbers. This function does not produce
//  // any output
//  packsymbols();

    // this function doesn't write anything to the output files either
  packgram();

  // free the symbol table data structure
  // since symbols are now all referred to by symbol number.
  free_symtab();


    // up to here nothing is generated. Except for done() writing the
    // redundant include guard to the parserbase.h file.
}





