/* Input parser for bison
- Copyright (C) 1984, 1986, 1989 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1986, 1989, 1992, 1998 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
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. */
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
/* read in the grammar specification and record it in the format described in gram.h.
The entry point is reader(). */
#include <stdio.h>
-#include <ctype.h>
#include "system.h"
#include "files.h"
-#include "new.h"
+#include "alloc.h"
#include "symtab.h"
#include "lex.h"
#include "gram.h"
extern char *program_name;
extern int definesflag;
extern int nolinesflag;
+extern int noparserflag;
+extern int rawtoknumflag;
extern bucket *symval;
extern int numval;
-extern int failure;
extern int expected_conflicts;
extern char *token_buffer;
-
-extern void init_lex();
-extern void tabinit();
-extern void output_headers();
-extern void output_trailers();
-extern void free_symtab();
-extern void open_extra_files();
-extern void fatal();
-extern void fatals();
-extern void unlex();
-extern void done();
-
-extern int skip_white_space();
-extern int parse_percent_token();
-extern int lex();
-
-void read_declarations();
-void copy_definition();
-void parse_token_decl();
-void parse_start_decl();
-void parse_type_decl();
-void parse_assoc_decl();
-void parse_union_decl();
-void parse_expect_decl();
-void copy_action();
-void readgram();
-void record_rule_line();
-void packsymbols();
-void output_token_defines();
-void packgram();
-int read_signed_integer();
-int get_type();
+extern int maxtoken;
+
+extern void init_lex PARAMS((void));
+extern char *grow_token_buffer PARAMS((char *));
+extern void tabinit PARAMS((void));
+extern void output_headers PARAMS((void));
+extern void output_trailers PARAMS((void));
+extern void free_symtab PARAMS((void));
+extern void open_extra_files PARAMS((void));
+extern char *int_to_string PARAMS((int));
+extern char *printable_version PARAMS((int));
+extern void fatal PARAMS((char *));
+extern void fatals PARAMS((char *, char *));
+extern void warn PARAMS((char *));
+extern void warni PARAMS((char *, int));
+extern void warns PARAMS((char *, char *));
+extern void warnss PARAMS((char *, char *, char *));
+extern void warnsss PARAMS((char *, char *, char *, char *));
+extern void unlex PARAMS((int));
+extern void done PARAMS((int));
+
+extern int skip_white_space PARAMS((void));
+extern int parse_percent_token PARAMS((void));
+extern int lex PARAMS((void));
typedef
struct symbol_list
symbol_list;
+void reader PARAMS((void));
+void reader_output_yylsp PARAMS((FILE *));
+void read_declarations PARAMS((void));
+void copy_definition PARAMS((void));
+void parse_token_decl PARAMS((int, int));
+void parse_start_decl PARAMS((void));
+void parse_type_decl PARAMS((void));
+void parse_assoc_decl PARAMS((int));
+void parse_union_decl PARAMS((void));
+void parse_expect_decl PARAMS((void));
+char *get_type_name PARAMS((int, symbol_list *));
+void copy_guard PARAMS((symbol_list *, int));
+void parse_thong_decl PARAMS((void));
+void copy_action PARAMS((symbol_list *, int));
+bucket *gensym PARAMS((void));
+void readgram PARAMS((void));
+void record_rule_line PARAMS((void));
+void packsymbols PARAMS((void));
+void output_token_defines PARAMS((FILE *));
+void packgram PARAMS((void));
+int read_signed_integer PARAMS((FILE *));
+
+#if 0
+static int get_type PARAMS((void));
+#endif
int lineno;
symbol_list *grammar;
int start_flag;
bucket *startval;
char **tags;
+int *user_toknums;
/* Nonzero if components of semantic values are used, implying
they must be unions. */
static int gensym_count; /* incremented for each generated symbol */
static bucket *errtoken;
+static bucket *undeftoken;
/* Nonzero if any action or guard uses the @n construct. */
static int yylsp_needed;
extern char *version_string;
+
+static void
+skip_to_char (int target)
+{
+ int c;
+ if (target == '\n')
+ warn(_(" Skipping to next \\n"));
+ else
+ warni(_(" Skipping to next %c"), target);
+
+ do
+ c = skip_white_space();
+ while (c != target && c != EOF);
+ if (c != EOF)
+ ungetc(c, finput);
+}
+
+
void
-reader()
+reader (void)
{
start_flag = 0;
startval = NULL; /* start symbol not specified yet. */
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("$undefined.")->class = STOKEN;
+ undeftoken = getsym("$undefined.");
+ undeftoken->class = STOKEN;
+ undeftoken->user_token_number = 2;
/* Read the declaration section. Copy %{ ... %} groups to ftable and fdefines file.
Also notice any %token, %left, etc. found there. */
- fprintf(ftable, "\n/* A Bison parser, made from %s", infile);
- fprintf(ftable, " with Bison version %s */\n\n", version_string);
+ if (noparserflag)
+ fprintf(ftable, "\n/* Bison-generated parse tables, made from %s\n",
+ infile);
+ else
+ fprintf(ftable, "\n/* A Bison parser, made from %s\n", infile);
+ fprintf(ftable, " by %s */\n\n", version_string);
fprintf(ftable, "#define YYBISON 1 /* Identify Bison output. */\n\n");
read_declarations();
- /* output the definition of YYLTYPE into the fattrs and fdefines files. */
- /* fattrs winds up in the .tab.c file, before bison.simple. */
- fprintf(fattrs, LTYPESTR);
/* start writing the guard and action files, if they are needed. */
output_headers();
/* read in the grammar, build grammar in list form. write out guards and actions. */
readgram();
/* Now we know whether we need the line-number stack.
If we do, write its type into the .tab.h file. */
- if (yylsp_needed)
- {
- if (fdefines)
- fprintf(fdefines, LTYPESTR);
- }
+ if (fdefines)
+ reader_output_yylsp(fdefines);
/* write closing delimiters for actions and guards. */
output_trailers();
if (yylsp_needed)
free_symtab();
}
-
+void
+reader_output_yylsp (FILE *f)
+{
+ if (yylsp_needed)
+ fprintf(f, LTYPESTR);
+}
/* read from finput until %% is seen. Discard the %%.
Handle any % declarations,
and copy the contents of any %{ ... %} groups to fattrs. */
void
-read_declarations ()
+read_declarations (void)
{
register int c;
register int tok;
case TOKEN:
parse_token_decl (STOKEN, SNTERM);
break;
-
+
case NTERM:
parse_token_decl (SNTERM, STOKEN);
break;
-
+
case TYPE:
parse_type_decl();
break;
-
+
case START:
parse_start_decl();
break;
-
+
case UNION:
parse_union_decl();
break;
-
+
case EXPECT:
parse_expect_decl();
break;
-
+ case THONG:
+ parse_thong_decl();
+ break;
case LEFT:
parse_assoc_decl(LEFT_ASSOC);
break;
pure_parser = 1;
break;
+ case NOOP:
+ break;
+
default:
- fatal("junk after `%%' in definition section");
- }
+ warns(_("unrecognized: %s"), token_buffer);
+ skip_to_char('%');
+ }
}
else if (c == EOF)
- fatal("no input grammar");
- else if (c >= 040 && c <= 0177)
- fatals ("unknown character `%c' in declaration section", c);
+ fatal(_("no input grammar"));
else
- fatals ("unknown character with code 0x%x in declaration section", c);
+ {
+ char buff[100];
+ sprintf(buff, _("unknown character: %s"), printable_version(c));
+ warn(buff);
+ skip_to_char('%');
+ }
}
}
The %{ has already been read. Return after reading the %}. */
void
-copy_definition ()
+copy_definition (void)
{
register int c;
register int match;
case '%':
after_percent = -1;
break;
-
+
case '\'':
case '"':
match = c;
while (c != match)
{
- if (c == EOF || c == '\n')
- fatal("unterminated string");
+ if (c == EOF)
+ fatal(_("unterminated string at end of file"));
+ if (c == '\n')
+ {
+ warn(_("unterminated string"));
+ ungetc(c, finput);
+ c = match;
+ continue;
+ }
putc(c, fattrs);
-
+
if (c == '\\')
{
c = getc(finput);
if (c == EOF)
- fatal("unterminated string");
+ fatal(_("unterminated string at end of file"));
putc(c, fattrs);
if (c == '\n')
lineno++;
c = getc(finput);
}
else if (c == EOF)
- fatal("unterminated comment in `%{' definition");
+ fatal(_("unterminated comment in `%{' definition"));
else
{
putc(c, fattrs);
break;
case EOF:
- fatal("unterminated `%{' definition");
+ fatal(_("unterminated `%{' definition"));
default:
putc(c, fattrs);
For %nterm, the arguments are reversed. */
void
-parse_token_decl (what_is, what_is_not)
- int what_is, what_is_not;
+parse_token_decl (int what_is, int what_is_not)
{
-/* register int start_lineno; JF */
register int token = 0;
- register int prev;
register char *typename = 0;
+ register struct bucket *symbol = NULL; /* pts to symbol being defined */
int k;
-/* start_lineno = lineno; JF */
-
for (;;)
{
- if(ungetc(skip_white_space(), finput) == '%')
- return;
+ int tmp_char = ungetc (skip_white_space (), finput);
-/* if (lineno != start_lineno)
- return; JF */
-
- /* we have not passed a newline, so the token now starting is in this declaration */
- prev = token;
+ if (tmp_char == '%')
+ return;
+ if (tmp_char == EOF)
+ fatals ("Premature EOF after %s", token_buffer);
token = lex();
if (token == COMMA)
- continue;
+ {
+ symbol = NULL;
+ continue;
+ }
if (token == TYPENAME)
{
k = strlen(token_buffer);
typename = NEW2(k + 1, char);
strcpy(typename, token_buffer);
value_components_used = 1;
+ symbol = NULL;
+ }
+ else if (token == IDENTIFIER && *symval->tag == '\"'
+ && symbol)
+ {
+ translations = 1;
+ symval->class = STOKEN;
+ symval->type_name = typename;
+ symval->user_token_number = symbol->user_token_number;
+ symbol->user_token_number = SALIAS;
+
+ symval->alias = symbol;
+ symbol->alias = symval;
+ symbol = NULL;
+
+ nsyms--; /* symbol and symval combined are only one symbol */
}
else if (token == IDENTIFIER)
{
int oldclass = symval->class;
+ symbol = symval;
- if (symval->class == what_is_not)
- fatals("symbol %s redefined", symval->tag);
- symval->class = what_is;
+ if (symbol->class == what_is_not)
+ warns(_("symbol %s redefined"), symbol->tag);
+ symbol->class = what_is;
if (what_is == SNTERM && oldclass != SNTERM)
- symval->value = nvars++;
+ symbol->value = nvars++;
if (typename)
{
- if (symval->type_name == NULL)
- symval->type_name = typename;
- else
- fatals("type redeclaration for %s", symval->tag);
+ if (symbol->type_name == NULL)
+ symbol->type_name = typename;
+ else if (strcmp(typename, symbol->type_name) != 0)
+ warns(_("type redeclaration for %s"), symbol->tag);
}
}
- else if (prev == IDENTIFIER && token == NUMBER)
+ else if (symbol && token == NUMBER)
{
- symval->user_token_number = numval;
+ symbol->user_token_number = numval;
translations = 1;
}
else
- fatal("invalid text in %token or %nterm declaration");
+ {
+ warnss(_("`%s' is invalid in %s"),
+ token_buffer,
+ (what_is == STOKEN) ? "%token" : "%nterm");
+ skip_to_char('%');
+ }
}
}
+/* parse what comes after %thong
+ the full syntax is
+ %thong <type> token number literal
+ the <type> or number may be omitted. The number specifies the
+ user_token_number.
+
+ Two symbols are entered in the table, one for the token symbol and
+ one for the literal. Both are given the <type>, if any, from the declaration.
+ The ->user_token_number of the first is SALIAS and the ->user_token_number
+ of the second is set to the number, if any, from the declaration.
+ The two symbols are linked via pointers in their ->alias fields.
+
+ during output_defines_table, the symbol is reported
+ thereafter, only the literal string is retained
+ it is the literal string that is output to yytname
+*/
+
+void
+parse_thong_decl (void)
+{
+ register int token;
+ register struct bucket *symbol;
+ register char *typename = 0;
+ int k, usrtoknum;
+
+ translations = 1;
+ token = lex(); /* fetch typename or first token */
+ if (token == TYPENAME) {
+ k = strlen(token_buffer);
+ typename = NEW2(k + 1, char);
+ strcpy(typename, token_buffer);
+ value_components_used = 1;
+ token = lex(); /* fetch first token */
+ }
+
+ /* process first token */
+
+ if (token != IDENTIFIER)
+ {
+ warns(_("unrecognized item %s, expected an identifier"),
+ token_buffer);
+ skip_to_char('%');
+ return;
+ }
+ symval->class = STOKEN;
+ symval->type_name = typename;
+ symval->user_token_number = SALIAS;
+ symbol = symval;
+
+ token = lex(); /* get number or literal string */
+
+ if (token == NUMBER) {
+ usrtoknum = numval;
+ token = lex(); /* okay, did number, now get literal */
+ }
+ else usrtoknum = 0;
+
+ /* process literal string token */
+
+ if (token != IDENTIFIER || *symval->tag != '\"')
+ {
+ warns(_("expected string constant instead of %s"),
+ token_buffer);
+ skip_to_char('%');
+ return;
+ }
+ symval->class = STOKEN;
+ symval->type_name = typename;
+ symval->user_token_number = usrtoknum;
+
+ symval->alias = symbol;
+ symbol->alias = symval;
+
+ nsyms--; /* symbol and symval combined are only one symbol */
+}
/* parse what comes after %start */
void
-parse_start_decl ()
+parse_start_decl (void)
{
if (start_flag)
- fatal("multiple %start declarations");
- start_flag = 1;
+ warn(_("multiple %start declarations"));
if (lex() != IDENTIFIER)
- fatal("invalid %start declaration");
- startval = symval;
+ warn(_("invalid %start declaration"));
+ else
+ {
+ start_flag = 1;
+ startval = symval;
+ }
}
/* read in a %type declaration and record its information for get_type_name to access */
void
-parse_type_decl ()
+parse_type_decl (void)
{
register int k;
register char *name;
-/* register int start_lineno; JF */
if (lex() != TYPENAME)
- fatal("ill-formed %type declaration");
+ {
+ warn(_("%type declaration has no <typename>"));
+ skip_to_char('%');
+ return;
+ }
k = strlen(token_buffer);
name = NEW2(k + 1, char);
strcpy(name, token_buffer);
-/* start_lineno = lineno; */
-
for (;;)
{
register int t;
+ int tmp_char = ungetc (skip_white_space (), finput);
- if(ungetc(skip_white_space(), finput) == '%')
+ if (tmp_char == '%')
return;
-
-/* if (lineno != start_lineno)
- return; JF */
-
- /* we have not passed a newline, so the token now starting is in this declaration */
+ if (tmp_char == EOF)
+ fatals ("Premature EOF after %s", token_buffer);
t = lex();
case IDENTIFIER:
if (symval->type_name == NULL)
symval->type_name = name;
- else
- fatals("type redeclaration for %s", symval->tag);
+ else if (strcmp(name, symval->type_name) != 0)
+ warns(_("type redeclaration for %s"), symval->tag);
break;
default:
- fatal("invalid %type declaration");
+ warns(_("invalid %%type declaration due to item: `%s'"), token_buffer);
+ skip_to_char('%');
}
}
}
/* assoc is either LEFT_ASSOC, RIGHT_ASSOC or NON_ASSOC. */
void
-parse_assoc_decl (assoc)
-int assoc;
+parse_assoc_decl (int assoc)
{
register int k;
register char *name = NULL;
-/* register int start_lineno; JF */
- register int prev = 0; /* JF added = 0 to keep lint happy */
+ register int prev = 0;
lastprec++; /* Assign a new precedence level, never 0. */
-/* start_lineno = lineno; */
-
for (;;)
{
register int t;
+ int tmp_char = ungetc (skip_white_space (), finput);
- if(ungetc(skip_white_space(), finput) == '%')
+ if (tmp_char == '%')
return;
-
- /* if (lineno != start_lineno)
- return; JF */
-
- /* we have not passed a newline, so the token now starting is in this declaration */
+ if (tmp_char == EOF)
+ fatals ("Premature EOF after %s", token_buffer);
t = lex();
case IDENTIFIER:
if (symval->prec != 0)
- fatals("redefining precedence of %s", symval->tag);
+ warns(_("redefining precedence of %s"), symval->tag);
symval->prec = lastprec;
symval->assoc = assoc;
if (symval->class == SNTERM)
- fatals("symbol %s redefined", symval->tag);
+ warns(_("symbol %s redefined"), symval->tag);
symval->class = STOKEN;
if (name)
{ /* record the type, if one is specified */
if (symval->type_name == NULL)
symval->type_name = name;
- else
- fatals("type redeclaration for %s", symval->tag);
+ else if (strcmp(name, symval->type_name) != 0)
+ warns(_("type redeclaration for %s"), symval->tag);
}
break;
symval->user_token_number = numval;
translations = 1;
}
- else
- fatal("invalid text in association declaration");
+ else
+ {
+ warns(_("invalid text (%s) - number should be after identifier"),
+ token_buffer);
+ skip_to_char('%');
+ }
break;
case SEMICOLON:
return;
default:
- fatal("malformatted association declaration");
+ warns(_("unexpected item: %s"), token_buffer);
+ skip_to_char('%');
}
prev = t;
definition of YYSTYPE, the type of elements of the parser value stack. */
void
-parse_union_decl()
+parse_union_decl (void)
{
register int c;
register int count;
int cplus_comment;
if (typed)
- fatal("multiple %union declarations");
+ warn(_("multiple %union declarations"));
typed = 1;
}
}
if (c == EOF)
- fatal("unterminated comment");
+ fatal(_("unterminated comment at end of file"));
if (!cplus_comment && c == '*')
{
case '}':
if (count == 0)
- fatal ("unmatched close-brace (`}')");
+ warn (_("unmatched close-brace (`}')"));
count--;
- if (count == 0)
+ if (count <= 0)
{
fprintf(fattrs, " YYSTYPE;\n");
if (fdefines)
shift-reduce conflicts. */
void
-parse_expect_decl()
+parse_expect_decl (void)
{
register int c;
register int count;
ungetc (c, finput);
+ if (count <= 0 || count > 10)
+ warn(_("argument of %expect is not an integer"));
expected_conflicts = atoi (buffer);
}
/* Get the data type (alternative in the union) of the value for symbol n in rule rule. */
char *
-get_type_name(n, rule)
-int n;
-symbol_list *rule;
+get_type_name (int n, symbol_list *rule)
{
- static char *msg = "invalid $ value";
+ static char *msg = N_("invalid $ value");
register int i;
register symbol_list *rp;
if (n < 0)
- fatal(msg);
+ {
+ warn(_(msg));
+ return NULL;
+ }
rp = rule;
i = 0;
{
rp = rp->next;
if (rp == NULL || rp->sym == NULL)
- fatal(msg);
+ {
+ warn(_(msg));
+ return NULL;
+ }
i++;
}
}
-
/* after %guard is seen in the input file,
copy the actual guard into the guards file.
If the guard is followed by an action, copy that into the actions file.
for the simple parser in which the stack is not popped until after the guard is run. */
void
-copy_guard(rule, stack_offset)
-symbol_list *rule;
-int stack_offset;
+copy_guard (symbol_list *rule, int stack_offset)
{
register int c;
register int n;
if (count > 0)
count--;
else
- fatal("unmatched right brace ('}')");
+ {
+ warn(_("unmatched right brace (`}')"));
+ c = getc(finput); /* skip it */
+ }
break;
case '\'':
while (c != match)
{
- if (c == EOF || c == '\n')
- fatal("unterminated string");
+ if (c == EOF)
+ fatal(_("unterminated string at end of file"));
+ if (c == '\n')
+ {
+ warn(_("unterminated string"));
+ ungetc(c, finput);
+ c = match; /* invent terminator */
+ continue;
+ }
putc(c, fguard);
-
+
if (c == '\\')
{
c = getc(finput);
if (c == EOF)
- fatal("unterminated string");
+ fatal(_("unterminated string"));
putc(c, fguard);
if (c == '\n')
lineno++;
c = getc(finput);
}
else if (c == EOF)
- fatal("unterminated comment");
+ fatal(_("unterminated comment"));
else
{
putc(c, fguard);
register char *cp = token_buffer;
while ((c = getc(finput)) != '>' && c > 0)
- *cp++ = c;
+ {
+ if (cp == token_buffer + maxtoken)
+ cp = grow_token_buffer(cp);
+
+ *cp++ = c;
+ }
*cp = 0;
type_name = token_buffer;
if (!type_name) type_name = rule->sym->type_name;
if (type_name)
fprintf(fguard, ".%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);
+ if(!type_name && typed)
+ warns(_("$$ of `%s' has no declared type"), rule->sym->tag);
}
else if (isdigit(c) || c == '-')
fprintf(fguard, "yyvsp[%d]", n - stack_offset);
if (type_name)
fprintf(fguard, ".%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);
+ if(!type_name && typed)
+ warnss(_("$%s of `%s' has no declared type"), int_to_string(n), rule->sym->tag);
continue;
}
else
- fatals("$%c is invalid",c); /* JF changed style */
+ warns(_("$%s is invalid"), printable_version(c));
break;
c = getc(finput);
}
else
- fatals("@%c is invalid",c); /* JF changed style */
+ {
+ warns(_("@%s is invalid"), printable_version(c));
+ n = 1;
+ }
fprintf(fguard, "yylsp[%d]", n - stack_offset);
yylsp_needed = 1;
continue;
case EOF:
- fatal("unterminated %guard clause");
+ fatal(_("unterminated %%guard clause"));
default:
putc(c, fguard);
copy_action(rule, stack_offset);
else if (c == '=')
{
- c = getc(finput);
+ c = getc(finput); /* why not skip_white_space -wjh */
if (c == '{')
copy_action(rule, stack_offset);
}
which says where to find $0 with respect to the top of the stack. */
void
-copy_action(rule, stack_offset)
-symbol_list *rule;
-int stack_offset;
+copy_action (symbol_list *rule, int stack_offset)
{
register int c;
register int n;
while (c != match)
{
- if (c == EOF || c == '\n')
- fatal("unterminated string");
+ if (c == '\n')
+ {
+ warn(_("unterminated string"));
+ ungetc(c, finput);
+ c = match;
+ continue;
+ }
+ else if (c == EOF)
+ fatal(_("unterminated string at end of file"));
putc(c, faction);
{
c = getc(finput);
if (c == EOF)
- fatal("unterminated string");
+ fatal(_("unterminated string"));
putc(c, faction);
if (c == '\n')
lineno++;
c = getc(finput);
}
else if (c == EOF)
- fatal("unterminated comment");
+ fatal(_("unterminated comment"));
else
{
putc(c, faction);
register char *cp = token_buffer;
while ((c = getc(finput)) != '>' && c > 0)
- *cp++ = c;
+ {
+ if (cp == token_buffer + maxtoken)
+ cp = grow_token_buffer(cp);
+
+ *cp++ = c;
+ }
*cp = 0;
type_name = token_buffer;
value_components_used = 1;
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);
+ if(!type_name && typed)
+ warns(_("$$ of `%s' has no declared type"), rule->sym->tag);
}
else if (isdigit(c) || c == '-')
{
fprintf(faction, "yyvsp[%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);
+ if(!type_name && typed)
+ warnss(_("$%s of `%s' has no declared type"),
+ int_to_string(n), rule->sym->tag);
continue;
}
else
- fatals("$%c is invalid",c); /* JF changed format */
+ warns(_("$%s is invalid"), printable_version(c));
break;
c = getc(finput);
}
else
- fatal("invalid @-construct");
+ {
+ warn(_("invalid @-construct"));
+ n = 1;
+ }
fprintf(faction, "yylsp[%d]", n - stack_offset);
yylsp_needed = 1;
continue;
case EOF:
- fatal("unmatched '{'");
+ fatal(_("unmatched `{'"));
default:
putc(c, faction);
whose name cannot conflict with the user's names. */
bucket *
-gensym()
+gensym (void)
{
register bucket *sym;
labelled by the rule number they apply to. */
void
-readgram()
+readgram (void)
{
register int t;
- register bucket *lhs;
+ register bucket *lhs = NULL;
register symbol_list *p;
register symbol_list *p1;
register bucket *bp;
if (t == IDENTIFIER)
{
lhs = symval;
-
+
+ if (!start_flag)
+ {
+ startval = lhs;
+ start_flag = 1;
+ }
+
t = lex();
if (t != COLON)
- fatal("ill-formed rule");
+ {
+ warn(_("ill-formed rule: initial symbol not followed by colon"));
+ unlex(t);
+ }
}
- if (nrules == 0)
+ if (nrules == 0 && t == BAR)
{
- if (t == BAR)
- fatal("grammar starts with vertical bar");
-
- if (!start_flag)
- startval = lhs;
+ warn(_("grammar starts with vertical bar"));
+ lhs = symval; /* BOGUS: use a random symval */
}
-
/* start a new rule and record its lhs. */
nrules++;
nvars++;
}
else if (lhs->class == STOKEN)
- fatals("rule given for %s, which is a token", lhs->tag);
+ warns(_("rule given for %s, which is a token"), lhs->tag);
/* read the rhs of the rule. */
for (;;)
{
t = lex();
+ if (t == PREC)
+ {
+ t = lex();
+ crule->ruleprec = symval;
+ t = lex();
+ }
if (! (t == IDENTIFIER || t == LEFT_CURLY)) break;
register bucket *sdummy;
/* Since the action was written out with this rule's */
- /* number, we must write give the new rule this number */
+ /* number, we must give the new rule this number */
/* by inserting the new rule before it. */
/* Make a dummy nonterminal, a gensym. */
xactions++; /* JF */
}
rulelength++;
- }
+ } /* end of read rhs of rule */
/* Put an empty link in the list to mark the end of this rule */
p = NEW(symbol_list);
if (t == PREC)
{
+ warn(_("two @prec's in a row"));
t = lex();
crule->ruleprec = symval;
t = lex();
if (t == GUARD)
{
if (! semantic_parser)
- fatal("%guard present but %semantic_parser not specified");
+ warn(_("%%guard present but %%semantic_parser not specified"));
copy_guard(crule, rulelength);
t = lex();
}
else if (t == LEFT_CURLY)
{
- if (actionflag) fatal("two actions at end of one rule");
+ /* This case never occurs -wjh */
+ if (actionflag) warn(_("two actions at end of one rule"));
copy_action(crule, rulelength);
+ actionflag = 1;
+ xactions++; /* -wjh */
t = lex();
}
/* If $$ is being set in default way,
{
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,
+ warnss(_("type clash (`%s' `%s') on default action"),
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);
+ warn(_("empty rule for typed nonterminal, and no action"));
if (t == SEMICOLON)
t = lex();
}
- /* these things can appear as alternatives to rules. */
+#if 0
+ /* these things can appear as alternatives to rules. */
+/* NO, they cannot.
+ a) none of the documentation allows them
+ b) most of them scan forward until finding a next %
+ thus they may swallow lots of intervening rules
+*/
else if (t == TOKEN)
{
parse_token_decl(STOKEN, SNTERM);
parse_start_decl();
t = lex();
}
+#endif
+
else
- fatal("invalid input");
+ {
+ warns(_("invalid input: %s"), token_buffer);
+ t = lex();
+ }
}
+ /* grammar has been read. Do some checking */
+
if (nsyms > MAXSHORT)
- fatals("too many symbols (tokens plus nonterminals); maximum %d",
- MAXSHORT);
+ fatals(_("too many symbols (tokens plus nonterminals); maximum %s"),
+ int_to_string(MAXSHORT));
if (nrules == 0)
- fatal("no input grammar");
+ fatal(_("no rules in the input grammar"));
if (typed == 0 /* JF put out same default YYSTYPE as YACC does */
&& !value_components_used)
for (bp = firstsymbol; bp; bp = bp->next)
if (bp->class == SUNKNOWN)
{
- fprintf(stderr, "symbol %s used, not defined as token, and no rules for it\n",
+ warns(_("symbol %s is used, but is not defined as a token and has no rules"),
bp->tag);
- failure = 1;
bp->class = SNTERM;
bp->value = nvars++;
}
void
-record_rule_line ()
+record_rule_line (void)
{
/* Record each rule's source line number in rline table. */
if (nrules >= rline_allocated)
{
rline_allocated = nrules * 2;
- rline = (short *) xrealloc (rline,
+ rline = (short *) xrealloc ((char *) rline,
rline_allocated * sizeof (short));
}
rline[nrules] = lineno;
}
+#if 0
/* read in a %type declaration and record its information for get_type_name to access */
-
-int
-get_type()
+/* this is unused. it is only called from the #if 0 part of readgram */
+static int
+get_type (void)
{
register int k;
register int t;
t = lex();
if (t != TYPENAME)
- fatal("ill-formed %type declaration");
+ {
+ warn(_("ill-formed %type declaration"));
+ return t;
+ }
k = strlen(token_buffer);
name = NEW2(k + 1, char);
case IDENTIFIER:
if (symval->type_name == NULL)
symval->type_name = name;
- else
- fatals("type redeclaration for %s", symval->tag);
+ else if (strcmp(name, symval->type_name) != 0)
+ warns(_("type redeclaration for %s"), symval->tag);
break;
}
}
}
-
+#endif
/* assign symbol numbers, and write definition of token names into fdefines.
Set up vectors tags and sprec of names and precedences of symbols. */
void
-packsymbols()
+packsymbols (void)
{
register bucket *bp;
register int tokno = 1;
tags = NEW2(nsyms + 1, char *);
tags[0] = "$";
+ user_toknums = NEW2(nsyms + 1, int);
+ user_toknums[0] = 0;
sprec = NEW2(nsyms, short);
sassoc = NEW2(nsyms, short);
{
bp->value += ntokens;
}
- else
+ else if (bp->alias)
+ {
+ /* this symbol and its alias are a single token defn.
+ allocate a tokno, and assign to both
+ check agreement of ->prec and ->assoc fields
+ and make both the same
+ */
+ if (bp->value == 0)
+ bp->value = bp->alias->value = tokno++;
+
+ if (bp->prec != bp->alias->prec) {
+ if (bp->prec != 0 && bp->alias->prec != 0
+ && bp->user_token_number == SALIAS)
+ warnss(_("conflicting precedences for %s and %s"),
+ bp->tag, bp->alias->tag);
+ if (bp->prec != 0) bp->alias->prec = bp->prec;
+ else bp->prec = bp->alias->prec;
+ }
+
+ if (bp->assoc != bp->alias->assoc) {
+ if (bp->assoc != 0 && bp->alias->assoc != 0
+ && bp->user_token_number == SALIAS)
+ warnss(_("conflicting assoc values for %s and %s"),
+ bp->tag, bp->alias->tag);
+ if (bp->assoc != 0) bp->alias->assoc = bp->assoc;
+ else bp->assoc = bp->alias->assoc;
+ }
+
+ if (bp->user_token_number == SALIAS)
+ continue; /* do not do processing below for SALIASs */
+
+ }
+ else /* bp->class == STOKEN */
+ {
+ bp->value = tokno++;
+ }
+
+ if (bp->class == STOKEN)
{
if (translations && !(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;
+ user_toknums[bp->value] = bp->user_token_number;
sprec[bp->value] = bp->prec;
sassoc[bp->value] = bp->assoc;
the internal token number for $undefined.,
which represents all invalid inputs. */
for (i = 0; i <= max_user_token_number; i++)
- token_translations[i] = 2;
- }
+ token_translations[i] = 2;
- for (bp = firstsymbol; bp; bp = bp->next)
- {
- if (bp->value >= ntokens) continue;
- if (translations)
- {
- if (token_translations[bp->user_token_number] != 2)
- {
- /* JF made this a call to fatals() */
- fatals( "tokens %s and %s both assigned number %d",
+ for (bp = firstsymbol; bp; bp = bp->next)
+ {
+ if (bp->value >= ntokens) continue; /* non-terminal */
+ if (bp->user_token_number == SALIAS) continue;
+ if (token_translations[bp->user_token_number] != 2)
+ warnsss(_("tokens %s and %s both assigned number %s"),
tags[token_translations[bp->user_token_number]],
bp->tag,
- bp->user_token_number);
- }
- token_translations[bp->user_token_number] = bp->value;
- }
+ int_to_string(bp->user_token_number));
+ token_translations[bp->user_token_number] = bp->value;
+ }
}
error_token_number = errtoken->value;
- output_token_defines(ftable);
+ if (! noparserflag)
+ output_token_defines(ftable);
if (startval->class == SUNKNOWN)
- fatals("the start symbol %s is undefined", startval->tag);
+ fatals(_("the start symbol %s is undefined"), startval->tag);
else if (startval->class == STOKEN)
- fatals("the start symbol %s is a token", startval->tag);
+ fatals(_("the start symbol %s is a token"), startval->tag);
start_symbol = startval->value;
#endif
}
}
-
+/* For named tokens, but not literal ones, define the name.
+ The value is the user token number.
+*/
void
-output_token_defines(file)
-FILE *file;
+output_token_defines (FILE *file)
{
bucket *bp;
+ register char *cp, *symbol;
+ register char c;
for (bp = firstsymbol; bp; bp = bp->next)
{
- if (bp->value >= ntokens) continue;
-
- /* For named tokens, but not literal ones, define the name. */
- /* The value is the user token number. */
+ symbol = bp->tag; /* get symbol */
- if ('\'' != *tags[bp->value] && bp != errtoken)
+ if (bp->value >= ntokens) continue;
+ if (bp->user_token_number == SALIAS) continue;
+ if ('\'' == *symbol) continue; /* skip literal character */
+ if (bp == errtoken) continue; /* skip error token */
+ if ('\"' == *symbol)
{
- register char *cp = tags[bp->value];
- register char c;
+ /* use literal string only if given a symbol with an alias */
+ if (bp->alias)
+ symbol = bp->alias->tag;
+ else
+ continue;
+ }
- /* Don't #define nonliteral tokens whose names contain periods. */
+ /* Don't #define nonliteral tokens whose names contain periods. */
+ cp = symbol;
+ while ((c = *cp++) && c != '.');
+ if (c != '\0') continue;
- while ((c = *cp++) && c != '.');
- if (!c)
- {
- fprintf(file, "#define\t%s\t%d\n", tags[bp->value],
- (translations ? bp->user_token_number : bp->value));
- if (semantic_parser)
- fprintf(file, "#define\tT%s\t%d\n", tags[bp->value],
- bp->value);
- }
- }
+ fprintf(file, "#define\t%s\t%d\n", symbol,
+ ((translations && ! rawtoknumflag)
+ ? bp->user_token_number
+ : bp->value));
+ if (semantic_parser)
+ fprintf(file, "#define\tT%s\t%d\n", symbol, bp->value);
}
putc('\n', file);
/* convert the rules into the representation using rrhs, rlhs and ritems. */
void
-packgram()
+packgram (void)
{
register int itemno;
register int ruleno;
/* Read a signed integer from STREAM and return its value. */
int
-read_signed_integer (stream)
- FILE *stream;
+read_signed_integer (FILE *stream)
{
register int c = getc(stream);
register int sign = 1;