mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
Have Bison grammars parsed by a Bison grammar.
* src/reader.c, src/reader.h (prologue_augment): New. * src/reader.c (copy_definition): Remove. * src/reader.h, src/reader.c (gram_start_symbol_set, prologue_augment) (grammar_symbol_append, grammar_rule_begin, grammar_midrule_action) (grammar_current_rule_prec_set, grammar_current_rule_check) (grammar_current_rule_symbol_append) (grammar_current_rule_action_append): Export. * src/parse-gram.y (symbol_list_new, symbol_list_symbol_append_ (symbol_list_action_append): Remove. Hook the routines from reader. * src/scan-gram.l: In INITIAL, characters and strings are tokens. * src/system.h (ATTRIBUTE_NORETURN, ATTRIBUTE_UNUSED): Now. * src/reader.c (read_declarations): Remove, unused. * src/parse-gram.y: Handle the epilogue. * src/reader.h, src/reader.c (gram_start_symbol_set): Rename as... (grammar_start_symbol_set): this. * src/scan-gram.l: Be sure to ``use'' yycontrol to keep GCC quiet. * src/reader.c (readgram): Remove, unused. (reader): Adjust to insert eoftoken and axiom where appropriate. * src/reader.c (copy_dollar): Replace with... * src/scan-gram.h (handle_dollar): this. * src/parse-gram.y: Remove `%thong'. * src/reader.c (copy_at): Replace with... * src/scan-gram.h (handle_at): this. * src/complain.h, src/complain.c (warn_at, complain_at, fatal_at): New. * src/scan-gram.l (YY_LINES): Keep lineno synchronized for the time being. * src/reader.h, src/reader.c (grammar_rule_end): New. * src/parse.y (current_type, current_class): New. Implement `%nterm', `%token' support. Merge `%term' into `%token'. (string_as_id): New. * src/symtab.h, src/symtab.c (symbol_make_alias): Don't pass the type name. * src/parse-gram.y: Be sure to handle properly the beginning of rules. * src/parse-gram.y: Handle %type. * src/reader.c (grammar_rule_end): Call grammar_current_rule_check. * src/parse-gram.y: More directives support. * src/options.c: No longer handle source directives. * src/parse-gram.y: Fix %output. * src/parse-gram.y: Handle %union. Use the prologue locations. * src/reader.c (parse_union_decl): Remove. * src/reader.h, src/reader.c (epilogue_set): New. * src/parse-gram.y: Use it. * data/bison.simple, data/bison.c++: b4_stype is now either not defined, then default to int, or to the contents of %union, without `union' itself. Adjust. * src/muscle_tab.c (muscle_init): Don't predefine `stype'. * src/output.c (actions_output): Don't output braces, as they are already handled by the scanner. * src/scan-gram.l (SC_CHARACTER): Set the user_token_number of characters to themselves. * tests/reduce.at (Reduced Automaton): End the grammars with %% so that the epilogue has a proper #line. * src/parse-gram.y: Handle precedence/associativity. * src/symtab.c (symbol_precedence_set): Requires the symbol to be a terminal. * src/scan-gram.l (SC_BRACED_CODE): Catch strings and characters. * tests/calc.at: Do not use `%token "foo"' as it makes not sense at all to define terminals that cannot be emitted. * src/scan-gram.l: Escape M4 characters. * src/scan-gram.l: Working properly with escapes in user strings/characters. * tests/torture.at (AT_DATA_TRIANGULAR_GRAMMAR) (AT_DATA_HORIZONTAL_GRAMMAR): Respect the `%token ID NUM STRING' grammar. Use more modest sizes, as for the time being the parser does not release memory, and therefore the process swallows a huge amount of memory. * tests/torture.at (AT_DATA_LOOKAHEADS_GRAMMAR): Adjust to the stricter %token grammar. * src/symtab.h (associativity): Add `undef_assoc'. (symbol_precedence_set): Do nothing when passed an undef_assoc. * src/symtab.c (symbol_check_alias_consistence): Adjust. * tests/regression.at (Invalid %directive): Remove, as it is now meaningless. (Invalid inputs): Adjust to the new error messages. (Token definitions): The new grammar doesn't allow too many eccentricities. * src/lex.h, src/lex.c: Remove. * src/reader.c (lastprec, skip_to_char, read_signed_integer) (copy_character, copy_string2, copy_string, copy_identifier) (copy_comment, parse_token_decl, parse_type_decl, parse_assoc_decl) (parse_muscle_decl, parse_dquoted_param, parse_skel_decl) (parse_action): Remove. * po/POTFILES.in: Adjust.
This commit is contained in:
123
ChangeLog
123
ChangeLog
@@ -1,3 +1,126 @@
|
||||
2002-06-11 Akim Demaille <akim@epita.fr>
|
||||
|
||||
Have Bison grammars parsed by a Bison grammar.
|
||||
|
||||
* src/reader.c, src/reader.h (prologue_augment): New.
|
||||
* src/reader.c (copy_definition): Remove.
|
||||
|
||||
* src/reader.h, src/reader.c (gram_start_symbol_set, prologue_augment)
|
||||
(grammar_symbol_append, grammar_rule_begin, grammar_midrule_action)
|
||||
(grammar_current_rule_prec_set, grammar_current_rule_check)
|
||||
(grammar_current_rule_symbol_append)
|
||||
(grammar_current_rule_action_append): Export.
|
||||
* src/parse-gram.y (symbol_list_new, symbol_list_symbol_append_
|
||||
(symbol_list_action_append): Remove.
|
||||
Hook the routines from reader.
|
||||
* src/scan-gram.l: In INITIAL, characters and strings are tokens.
|
||||
* src/system.h (ATTRIBUTE_NORETURN, ATTRIBUTE_UNUSED): Now.
|
||||
|
||||
* src/reader.c (read_declarations): Remove, unused.
|
||||
|
||||
* src/parse-gram.y: Handle the epilogue.
|
||||
* src/reader.h, src/reader.c (gram_start_symbol_set): Rename as...
|
||||
(grammar_start_symbol_set): this.
|
||||
* src/scan-gram.l: Be sure to ``use'' yycontrol to keep GCC quiet.
|
||||
* src/reader.c (readgram): Remove, unused.
|
||||
(reader): Adjust to insert eoftoken and axiom where appropriate.
|
||||
|
||||
* src/reader.c (copy_dollar): Replace with...
|
||||
* src/scan-gram.h (handle_dollar): this.
|
||||
* src/parse-gram.y: Remove `%thong'.
|
||||
|
||||
* src/reader.c (copy_at): Replace with...
|
||||
* src/scan-gram.h (handle_at): this.
|
||||
|
||||
* src/complain.h, src/complain.c (warn_at, complain_at, fatal_at):
|
||||
New.
|
||||
|
||||
* src/scan-gram.l (YY_LINES): Keep lineno synchronized for the
|
||||
time being.
|
||||
|
||||
* src/reader.h, src/reader.c (grammar_rule_end): New.
|
||||
|
||||
* src/parse.y (current_type, current_class): New.
|
||||
Implement `%nterm', `%token' support.
|
||||
Merge `%term' into `%token'.
|
||||
(string_as_id): New.
|
||||
* src/symtab.h, src/symtab.c (symbol_make_alias): Don't pass the
|
||||
type name.
|
||||
|
||||
* src/parse-gram.y: Be sure to handle properly the beginning of
|
||||
rules.
|
||||
|
||||
* src/parse-gram.y: Handle %type.
|
||||
* src/reader.c (grammar_rule_end): Call grammar_current_rule_check.
|
||||
|
||||
* src/parse-gram.y: More directives support.
|
||||
* src/options.c: No longer handle source directives.
|
||||
|
||||
* src/parse-gram.y: Fix %output.
|
||||
|
||||
* src/parse-gram.y: Handle %union.
|
||||
Use the prologue locations.
|
||||
* src/reader.c (parse_union_decl): Remove.
|
||||
|
||||
* src/reader.h, src/reader.c (epilogue_set): New.
|
||||
* src/parse-gram.y: Use it.
|
||||
|
||||
* data/bison.simple, data/bison.c++: b4_stype is now either not
|
||||
defined, then default to int, or to the contents of %union,
|
||||
without `union' itself.
|
||||
Adjust.
|
||||
* src/muscle_tab.c (muscle_init): Don't predefine `stype'.
|
||||
|
||||
* src/output.c (actions_output): Don't output braces, as they are
|
||||
already handled by the scanner.
|
||||
|
||||
* src/scan-gram.l (SC_CHARACTER): Set the user_token_number of
|
||||
characters to themselves.
|
||||
|
||||
* tests/reduce.at (Reduced Automaton): End the grammars with %% so
|
||||
that the epilogue has a proper #line.
|
||||
|
||||
* src/parse-gram.y: Handle precedence/associativity.
|
||||
|
||||
* src/symtab.c (symbol_precedence_set): Requires the symbol to be
|
||||
a terminal.
|
||||
* src/scan-gram.l (SC_BRACED_CODE): Catch strings and characters.
|
||||
* tests/calc.at: Do not use `%token "foo"' as it makes not sense
|
||||
at all to define terminals that cannot be emitted.
|
||||
|
||||
* src/scan-gram.l: Escape M4 characters.
|
||||
|
||||
* src/scan-gram.l: Working properly with escapes in user
|
||||
strings/characters.
|
||||
|
||||
* tests/torture.at (AT_DATA_TRIANGULAR_GRAMMAR)
|
||||
(AT_DATA_HORIZONTAL_GRAMMAR): Respect the `%token ID NUM STRING'
|
||||
grammar.
|
||||
Use more modest sizes, as for the time being the parser does not
|
||||
release memory, and therefore the process swallows a huge amount
|
||||
of memory.
|
||||
|
||||
* tests/torture.at (AT_DATA_LOOKAHEADS_GRAMMAR): Adjust to the
|
||||
stricter %token grammar.
|
||||
|
||||
* src/symtab.h (associativity): Add `undef_assoc'.
|
||||
(symbol_precedence_set): Do nothing when passed an undef_assoc.
|
||||
* src/symtab.c (symbol_check_alias_consistence): Adjust.
|
||||
|
||||
* tests/regression.at (Invalid %directive): Remove, as it is now
|
||||
meaningless.
|
||||
(Invalid inputs): Adjust to the new error messages.
|
||||
(Token definitions): The new grammar doesn't allow too many
|
||||
eccentricities.
|
||||
|
||||
* src/lex.h, src/lex.c: Remove.
|
||||
* src/reader.c (lastprec, skip_to_char, read_signed_integer)
|
||||
(copy_character, copy_string2, copy_string, copy_identifier)
|
||||
(copy_comment, parse_token_decl, parse_type_decl, parse_assoc_decl)
|
||||
(parse_muscle_decl, parse_dquoted_param, parse_skel_decl)
|
||||
(parse_action): Remove.
|
||||
* po/POTFILES.in: Adjust.
|
||||
|
||||
2002-06-11 Akim Demaille <akim@epita.fr>
|
||||
|
||||
* src/reader.c (parse_action): Don't store directly into the
|
||||
|
||||
@@ -159,11 +159,10 @@ b4_token_defines(b4_tokens)
|
||||
#endif
|
||||
|
||||
#ifndef YYSTYPE
|
||||
m4_ifdef([b4_stype_line],
|
||||
m4_ifdef([b4_stype],
|
||||
[#line b4_stype_line "b4_filename"
|
||||
])dnl
|
||||
typedef b4_stype
|
||||
yystype;
|
||||
typedef union b4_stype yystype;],
|
||||
[typedef int yystype;])
|
||||
# define YYSTYPE yystype
|
||||
#endif
|
||||
|
||||
|
||||
@@ -191,10 +191,10 @@ b4_token_defines(b4_tokens)
|
||||
#endif
|
||||
|
||||
#ifndef YYSTYPE
|
||||
m4_ifdef([b4_stype_line],
|
||||
m4_ifdef([b4_stype],
|
||||
[#line b4_stype_line "b4_filename"
|
||||
])dnl
|
||||
typedef b4_stype yystype;
|
||||
typedef union b4_stype yystype;],
|
||||
[typedef int yystype;])
|
||||
# define YYSTYPE yystype
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
#endif
|
||||
@@ -1238,11 +1238,10 @@ m4_if(b4_defines_flag, 0, [],
|
||||
b4_token_defines(b4_tokens)
|
||||
|
||||
#ifndef YYSTYPE
|
||||
m4_ifdef([b4_stype_line],
|
||||
m4_ifdef([b4_stype],
|
||||
[#line b4_stype_line "b4_filename"
|
||||
])dnl
|
||||
typedef b4_stype
|
||||
yystype;
|
||||
typedef union b4_stype yystype;],
|
||||
[typedef int yystype;])
|
||||
# define YYSTYPE yystype
|
||||
#endif
|
||||
|
||||
|
||||
@@ -4,10 +4,11 @@ src/conflicts.c
|
||||
src/files.c
|
||||
src/getargs.c
|
||||
src/lalr.c
|
||||
src/lex.c
|
||||
src/parse-gram.c
|
||||
src/print.c
|
||||
src/reader.c
|
||||
src/reduce.c
|
||||
src/scan-gram.c
|
||||
|
||||
lib/error.c
|
||||
lib/getopt.c
|
||||
|
||||
@@ -36,8 +36,10 @@ LDADD = $(INTLLIBS) ../lib/libbison.a
|
||||
bin_PROGRAMS = bison
|
||||
|
||||
bison_SOURCES = LR0.c closure.c complain.c conflicts.c \
|
||||
parse-gram.y parse-gram.h \
|
||||
scan-gram.c \
|
||||
derives.c \
|
||||
files.c getargs.c gram.c lalr.c lex.c main.c nullable.c \
|
||||
files.c getargs.c gram.c lalr.c main.c nullable.c \
|
||||
output.h output.c \
|
||||
state.h state.c \
|
||||
print_graph.h print_graph.c \
|
||||
@@ -46,13 +48,13 @@ bison_SOURCES = LR0.c closure.c complain.c conflicts.c \
|
||||
print.c reader.c reduce.c symtab.c vcg.c \
|
||||
scan-skel.l
|
||||
|
||||
BUILT_SOURCES = scan-skel.c
|
||||
BUILT_SOURCES = scan-skel.c scan-gram.c parse-gram.c parse-gram.h
|
||||
|
||||
EXTRA_bison_SOURCES = vmsgetargs.c
|
||||
|
||||
noinst_HEADERS = LR0.h closure.h complain.h conflicts.h \
|
||||
derives.h \
|
||||
files.h getargs.h gram.h lalr.h lex.h nullable.h \
|
||||
files.h getargs.h gram.h lalr.h nullable.h \
|
||||
print.h reader.h reduce.h symtab.h system.h \
|
||||
types.h vcg.h vcg_defaults.h
|
||||
|
||||
|
||||
132
src/complain.c
132
src/complain.c
@@ -114,6 +114,56 @@ unsigned int complain_message_count;
|
||||
| Report a warning, and proceed. |
|
||||
`--------------------------------*/
|
||||
|
||||
void
|
||||
#if defined VA_START && defined __STDC__
|
||||
warn_at (int location, const char *message, ...)
|
||||
#else
|
||||
warn_at (location, message, va_alist)
|
||||
int location
|
||||
char *message;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
#ifdef VA_START
|
||||
va_list args;
|
||||
#endif
|
||||
|
||||
if (error_one_per_line)
|
||||
{
|
||||
static const char *old_infile;
|
||||
static int old_lineno;
|
||||
|
||||
if (old_lineno == location &&
|
||||
(infile == old_infile || !strcmp (old_infile, infile)))
|
||||
/* Simply return and print nothing. */
|
||||
return;
|
||||
|
||||
old_infile = infile;
|
||||
old_lineno = location;
|
||||
}
|
||||
|
||||
fflush (stdout);
|
||||
if (infile != NULL)
|
||||
fprintf (stderr, "%s:%d: ", infile, location);
|
||||
else
|
||||
fprintf (stderr, "%s:", program_name);
|
||||
|
||||
fputs (_("warning: "), stderr);
|
||||
|
||||
#ifdef VA_START
|
||||
VA_START (args, message);
|
||||
vfprintf (stderr, message, args);
|
||||
va_end (args);
|
||||
#else
|
||||
fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||
#endif
|
||||
|
||||
++warn_message_count;
|
||||
putc ('\n', stderr);
|
||||
fflush (stderr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
#if defined VA_START && defined __STDC__
|
||||
warn (const char *message, ...)
|
||||
@@ -166,6 +216,54 @@ warn (message, va_alist)
|
||||
| An error has occurred, but we can proceed, and die later. |
|
||||
`-----------------------------------------------------------*/
|
||||
|
||||
void
|
||||
#if defined VA_START && defined __STDC__
|
||||
complain_at (int location, const char *message, ...)
|
||||
#else
|
||||
complain_at (location, message, va_alist)
|
||||
int location;
|
||||
char *message;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
#ifdef VA_START
|
||||
va_list args;
|
||||
#endif
|
||||
|
||||
if (error_one_per_line)
|
||||
{
|
||||
static const char *old_infile;
|
||||
static int old_lineno;
|
||||
|
||||
if (old_lineno == location &&
|
||||
(infile == old_infile || !strcmp (old_infile, infile)))
|
||||
/* Simply return and print nothing. */
|
||||
return;
|
||||
|
||||
old_infile = infile;
|
||||
old_lineno = location;
|
||||
}
|
||||
|
||||
fflush (stdout);
|
||||
if (infile != NULL)
|
||||
fprintf (stderr, "%s:%d: ", infile, location);
|
||||
else
|
||||
fprintf (stderr, "%s:", program_name);
|
||||
|
||||
#ifdef VA_START
|
||||
VA_START (args, message);
|
||||
vfprintf (stderr, message, args);
|
||||
va_end (args);
|
||||
#else
|
||||
fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||
#endif
|
||||
|
||||
++complain_message_count;
|
||||
putc ('\n', stderr);
|
||||
fflush (stderr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
#if defined VA_START && defined __STDC__
|
||||
complain (const char *message, ...)
|
||||
@@ -216,6 +314,40 @@ complain (message, va_alist)
|
||||
| A severe error has occurred, we cannot proceed. |
|
||||
`-------------------------------------------------*/
|
||||
|
||||
void
|
||||
#if defined VA_START && defined __STDC__
|
||||
fatal_at (int location, const char *message, ...)
|
||||
#else
|
||||
fatal (location, message, va_alist)
|
||||
int location;
|
||||
char *message;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
#ifdef VA_START
|
||||
va_list args;
|
||||
#endif
|
||||
|
||||
fflush (stdout);
|
||||
if (infile != NULL)
|
||||
fprintf (stderr, "%s:%d: ", infile, location);
|
||||
else
|
||||
fprintf (stderr, "%s:", program_name);
|
||||
|
||||
fputs (_("fatal error: "), stderr);
|
||||
|
||||
#ifdef VA_START
|
||||
VA_START (args, message);
|
||||
vfprintf (stderr, message, args);
|
||||
va_end (args);
|
||||
#else
|
||||
fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||
#endif
|
||||
putc ('\n', stderr);
|
||||
fflush (stderr);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
void
|
||||
#if defined VA_START && defined __STDC__
|
||||
fatal (const char *message, ...)
|
||||
|
||||
@@ -27,23 +27,35 @@ extern "C" {
|
||||
|
||||
/* Informative messages, but we proceed. */
|
||||
|
||||
extern void warn (const char *format, ...)
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
void warn (const char *format, ...)
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
|
||||
void warn_at (int location, const char *format, ...)
|
||||
__attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
|
||||
/* Something bad happen, but let's continue and die later. */
|
||||
|
||||
extern void complain (const char *format, ...)
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
void complain (const char *format, ...)
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
|
||||
void complain_at (int location, const char *format, ...)
|
||||
__attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
|
||||
/* Something bad happen and we die now. */
|
||||
|
||||
extern void fatal (const char *format, ...)
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
void fatal (const char *format, ...)
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
|
||||
void fatal_at (int location, const char *format, ...)
|
||||
__attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
|
||||
#else
|
||||
void warn ();
|
||||
void warn_at ();
|
||||
void complain ();
|
||||
void complain_at ();
|
||||
void fatal ();
|
||||
void fatal_at ();
|
||||
#endif
|
||||
|
||||
/* Position in the current input file. */
|
||||
|
||||
@@ -216,6 +216,10 @@ resolve_sr_conflict (state_t *state, int lookahead)
|
||||
/* Record an explicit error for this token. */
|
||||
errp->errs[errp->nerrs++] = i;
|
||||
break;
|
||||
|
||||
case undef_assoc:
|
||||
assert (symbols[i]->assoc != undef_assoc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
604
src/lex.c
604
src/lex.c
@@ -1,604 +0,0 @@
|
||||
/* Token-reader for Bison's input parser,
|
||||
Copyright (C) 1984, 1986, 1989, 1992, 2000, 2001, 2002
|
||||
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, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "system.h"
|
||||
#include "getargs.h"
|
||||
#include "files.h"
|
||||
#include "symtab.h"
|
||||
#include "options.h"
|
||||
#include "lex.h"
|
||||
#include "complain.h"
|
||||
#include "gram.h"
|
||||
#include "quote.h"
|
||||
|
||||
/* Buffer for storing the current token. */
|
||||
static struct obstack token_obstack;
|
||||
const char *token_buffer = NULL;
|
||||
|
||||
symbol_t *symval = NULL;
|
||||
int numval;
|
||||
|
||||
/* A token to be reread, see unlex and lex. */
|
||||
static token_t unlexed = tok_undef;
|
||||
static symbol_t *unlexed_symval = NULL;
|
||||
static const char *unlexed_token_buffer = NULL;
|
||||
|
||||
void
|
||||
lex_init (void)
|
||||
{
|
||||
obstack_init (&token_obstack);
|
||||
unlexed = tok_undef;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lex_free (void)
|
||||
{
|
||||
obstack_free (&token_obstack, NULL);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
skip_white_space (void)
|
||||
{
|
||||
int c;
|
||||
int inside;
|
||||
|
||||
c = getc (finput);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int cplus_comment;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '/':
|
||||
/* FIXME: Should probably be merged with copy_comment. */
|
||||
c = getc (finput);
|
||||
if (c != '*' && c != '/')
|
||||
{
|
||||
complain (_("unexpected `/' found and ignored"));
|
||||
break;
|
||||
}
|
||||
cplus_comment = (c == '/');
|
||||
|
||||
c = getc (finput);
|
||||
|
||||
inside = 1;
|
||||
while (inside)
|
||||
{
|
||||
if (!cplus_comment && c == '*')
|
||||
{
|
||||
while (c == '*')
|
||||
c = getc (finput);
|
||||
|
||||
if (c == '/')
|
||||
{
|
||||
inside = 0;
|
||||
c = getc (finput);
|
||||
}
|
||||
}
|
||||
else if (c == '\n')
|
||||
{
|
||||
lineno++;
|
||||
if (cplus_comment)
|
||||
inside = 0;
|
||||
c = getc (finput);
|
||||
}
|
||||
else if (c == EOF)
|
||||
fatal (_("unterminated comment"));
|
||||
else
|
||||
c = getc (finput);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
lineno++;
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\f':
|
||||
c = getc (finput);
|
||||
break;
|
||||
|
||||
default:
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------.
|
||||
| Do a getc, but give error message if EOF encountered |
|
||||
`-----------------------------------------------------*/
|
||||
|
||||
int
|
||||
xgetc (FILE *f)
|
||||
{
|
||||
int c = getc (f);
|
||||
if (c == EOF)
|
||||
fatal (_("unexpected end of file"));
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------.
|
||||
| Read one literal character from FINPUT, process \-escapes, and |
|
||||
| return the character. |
|
||||
`---------------------------------------------------------------*/
|
||||
|
||||
char
|
||||
literalchar (void)
|
||||
{
|
||||
int c;
|
||||
int res;
|
||||
|
||||
c = xgetc (finput);
|
||||
if (c == '\n')
|
||||
{
|
||||
complain (_("unescaped newline in constant"));
|
||||
ungetc (c, finput);
|
||||
res = '?';
|
||||
}
|
||||
else if (c != '\\')
|
||||
{
|
||||
res = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = xgetc (finput);
|
||||
if (c == 't')
|
||||
res = '\t';
|
||||
else if (c == 'n')
|
||||
res = '\n';
|
||||
else if (c == 'a')
|
||||
res = '\007';
|
||||
else if (c == 'r')
|
||||
res = '\r';
|
||||
else if (c == 'f')
|
||||
res = '\f';
|
||||
else if (c == 'b')
|
||||
res = '\b';
|
||||
else if (c == 'v')
|
||||
res = '\013';
|
||||
else if (c == '\\')
|
||||
res = '\\';
|
||||
else if (c == '\'')
|
||||
res = '\'';
|
||||
else if (c == '\"')
|
||||
res = '\"';
|
||||
else if (c <= '7' && c >= '0')
|
||||
{
|
||||
res = 0;
|
||||
while (c <= '7' && c >= '0')
|
||||
{
|
||||
res = (res * 8) + (c - '0');
|
||||
if (res >= 256 || res < 0)
|
||||
{
|
||||
complain (_("octal value outside range 0...255: `\\%o'"),
|
||||
res);
|
||||
res &= 0xFF;
|
||||
break;
|
||||
}
|
||||
c = xgetc (finput);
|
||||
}
|
||||
ungetc (c, finput);
|
||||
}
|
||||
else if (c == 'x')
|
||||
{
|
||||
c = xgetc (finput);
|
||||
res = 0;
|
||||
while (1)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
res *= 16, res += c - '0';
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
res *= 16, res += c - 'a' + 10;
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
res *= 16, res += c - 'A' + 10;
|
||||
else
|
||||
break;
|
||||
if (res >= 256 || res < 0)
|
||||
{
|
||||
complain (_("hexadecimal value above 255: `\\x%x'"), res);
|
||||
res &= 0xFF;
|
||||
break;
|
||||
}
|
||||
c = xgetc (finput);
|
||||
}
|
||||
ungetc (c, finput);
|
||||
}
|
||||
else
|
||||
{
|
||||
char badchar [] = "c";
|
||||
badchar[0] = c;
|
||||
complain (_("unknown escape sequence: `\\' followed by `%s'"),
|
||||
quote (badchar));
|
||||
res = '?';
|
||||
}
|
||||
} /* has \ */
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
unlex (token_t token)
|
||||
{
|
||||
unlexed = token;
|
||||
unlexed_token_buffer = token_buffer;
|
||||
unlexed_symval = symval;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------.
|
||||
| We just read `<' from FIN. Store in TOKEN_BUFFER, the type name |
|
||||
| specified between the `<...>'. |
|
||||
`-----------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
read_type_name (FILE *fin)
|
||||
{
|
||||
int c = getc (fin);
|
||||
|
||||
while (c != '>')
|
||||
{
|
||||
if (c == EOF)
|
||||
fatal (_("unterminated type name at end of file"));
|
||||
if (c == '\n')
|
||||
{
|
||||
complain (_("unterminated type name"));
|
||||
ungetc (c, fin);
|
||||
break;
|
||||
}
|
||||
|
||||
obstack_1grow (&token_obstack, c);
|
||||
c = getc (fin);
|
||||
}
|
||||
obstack_1grow (&token_obstack, '\0');
|
||||
token_buffer = obstack_finish (&token_obstack);
|
||||
}
|
||||
|
||||
|
||||
token_t
|
||||
lex (void)
|
||||
{
|
||||
int c;
|
||||
|
||||
/* Just to make sure. */
|
||||
token_buffer = NULL;
|
||||
|
||||
if (unlexed != tok_undef)
|
||||
{
|
||||
token_t res = unlexed;
|
||||
symval = unlexed_symval;
|
||||
token_buffer = unlexed_token_buffer;
|
||||
unlexed = tok_undef;
|
||||
return res;
|
||||
}
|
||||
|
||||
c = skip_white_space ();
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case EOF:
|
||||
token_buffer = "EOF";
|
||||
return tok_eof;
|
||||
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E':
|
||||
case 'F': case 'G': case 'H': case 'I': case 'J':
|
||||
case 'K': case 'L': case 'M': case 'N': case 'O':
|
||||
case 'P': case 'Q': case 'R': case 'S': case 'T':
|
||||
case 'U': case 'V': case 'W': case 'X': case 'Y':
|
||||
case 'Z':
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e':
|
||||
case 'f': case 'g': case 'h': case 'i': case 'j':
|
||||
case 'k': case 'l': case 'm': case 'n': case 'o':
|
||||
case 'p': case 'q': case 'r': case 's': case 't':
|
||||
case 'u': case 'v': case 'w': case 'x': case 'y':
|
||||
case 'z':
|
||||
case '.': case '_':
|
||||
|
||||
while (isalnum (c) || c == '_' || c == '.')
|
||||
{
|
||||
obstack_1grow (&token_obstack, c);
|
||||
c = getc (finput);
|
||||
}
|
||||
obstack_1grow (&token_obstack, '\0');
|
||||
token_buffer = obstack_finish (&token_obstack);
|
||||
ungetc (c, finput);
|
||||
symval = getsym (token_buffer);
|
||||
return tok_identifier;
|
||||
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
{
|
||||
numval = 0;
|
||||
|
||||
while (isdigit (c))
|
||||
{
|
||||
obstack_1grow (&token_obstack, c);
|
||||
numval = numval * 10 + c - '0';
|
||||
c = getc (finput);
|
||||
}
|
||||
obstack_1grow (&token_obstack, '\0');
|
||||
token_buffer = obstack_finish (&token_obstack);
|
||||
ungetc (c, finput);
|
||||
return tok_number;
|
||||
}
|
||||
|
||||
case '\'':
|
||||
/* parse the literal token and compute character code in code */
|
||||
|
||||
{
|
||||
int code = literalchar ();
|
||||
|
||||
obstack_1grow (&token_obstack, '\'');
|
||||
obstack_1grow (&token_obstack, code);
|
||||
|
||||
c = getc (finput);
|
||||
if (c != '\'')
|
||||
{
|
||||
complain (_("use \"...\" for multi-character literal tokens"));
|
||||
while (literalchar () != '\'')
|
||||
/* Skip. */;
|
||||
}
|
||||
obstack_1grow (&token_obstack, '\'');
|
||||
obstack_1grow (&token_obstack, '\0');
|
||||
token_buffer = obstack_finish (&token_obstack);
|
||||
symval = getsym (token_buffer);
|
||||
symbol_class_set (symval, token_sym);
|
||||
symbol_user_token_number_set (symval, code);
|
||||
return tok_identifier;
|
||||
}
|
||||
|
||||
case '\"':
|
||||
/* parse the literal string token and treat as an identifier */
|
||||
|
||||
{
|
||||
int code;
|
||||
|
||||
obstack_1grow (&token_obstack, '\"');
|
||||
/* Read up to and including ". */
|
||||
do
|
||||
{
|
||||
code = literalchar ();
|
||||
obstack_1grow (&token_obstack, code);
|
||||
}
|
||||
while (code != '\"');
|
||||
obstack_1grow (&token_obstack, '\0');
|
||||
token_buffer = obstack_finish (&token_obstack);
|
||||
|
||||
symval = getsym (token_buffer);
|
||||
symbol_class_set (symval, token_sym);
|
||||
return tok_identifier;
|
||||
}
|
||||
|
||||
case ',':
|
||||
token_buffer = ",";
|
||||
return tok_comma;
|
||||
|
||||
case ':':
|
||||
token_buffer = ":";
|
||||
return tok_colon;
|
||||
|
||||
case ';':
|
||||
token_buffer = ";";
|
||||
return tok_semicolon;
|
||||
|
||||
case '|':
|
||||
token_buffer = "|";
|
||||
return tok_bar;
|
||||
|
||||
case '{':
|
||||
token_buffer = "{";
|
||||
return tok_left_curly;
|
||||
|
||||
case '=':
|
||||
obstack_1grow (&token_obstack, c);
|
||||
do
|
||||
{
|
||||
c = getc (finput);
|
||||
obstack_1grow (&token_obstack, c);
|
||||
if (c == '\n')
|
||||
lineno++;
|
||||
}
|
||||
while (c == ' ' || c == '\n' || c == '\t');
|
||||
obstack_1grow (&token_obstack, '\0');
|
||||
token_buffer = obstack_finish (&token_obstack);
|
||||
|
||||
if (c == '{')
|
||||
{
|
||||
return tok_left_curly;
|
||||
}
|
||||
else
|
||||
{
|
||||
ungetc (c, finput);
|
||||
return tok_illegal;
|
||||
}
|
||||
|
||||
case '<':
|
||||
read_type_name (finput);
|
||||
return tok_typename;
|
||||
|
||||
case '%':
|
||||
return parse_percent_token ();
|
||||
|
||||
default:
|
||||
obstack_1grow (&token_obstack, c);
|
||||
obstack_1grow (&token_obstack, '\0');
|
||||
token_buffer = obstack_finish (&token_obstack);
|
||||
return tok_illegal;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is a strcmp, which doesn't differentiate `-' and `_'
|
||||
chars. */
|
||||
|
||||
static int
|
||||
option_strcmp (const char *left, const char *right)
|
||||
{
|
||||
const unsigned char *l, *r;
|
||||
int c;
|
||||
|
||||
assert (left);
|
||||
assert (right);
|
||||
l = (const unsigned char *)left;
|
||||
r = (const unsigned char *)right;
|
||||
while (((c = *l - *r++) == 0 && *l != '\0')
|
||||
|| ((*l == '-' || *l == '_') && (*r == '_' || *r == '-')))
|
||||
l++;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Parse a token which starts with %.
|
||||
Assumes the % has already been read and discarded. */
|
||||
|
||||
token_t
|
||||
parse_percent_token (void)
|
||||
{
|
||||
const struct option_table_s *tx = NULL;
|
||||
const char *arg = NULL;
|
||||
/* Where the ARG was found in token_buffer. */
|
||||
size_t arg_offset = 0;
|
||||
|
||||
int c = getc (finput);
|
||||
obstack_1grow (&token_obstack, '%');
|
||||
obstack_1grow (&token_obstack, c);
|
||||
|
||||
if (!isalpha (c))
|
||||
{
|
||||
obstack_1grow (&token_obstack, '\0');
|
||||
token_buffer = obstack_finish (&token_obstack);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '%':
|
||||
return tok_two_percents;
|
||||
|
||||
case '{':
|
||||
return tok_percent_left_curly;
|
||||
|
||||
/* The following guys are here for backward compatibility with
|
||||
very ancient Yacc versions. The paper of Johnson mentions
|
||||
them (as ancient :). */
|
||||
case '<':
|
||||
return tok_left;
|
||||
|
||||
case '>':
|
||||
return tok_right;
|
||||
|
||||
case '2':
|
||||
return tok_nonassoc;
|
||||
|
||||
case '0':
|
||||
return tok_token;
|
||||
|
||||
case '=':
|
||||
return tok_prec;
|
||||
|
||||
default:
|
||||
return tok_illegal;
|
||||
}
|
||||
}
|
||||
|
||||
while (c = getc (finput), isalpha (c) || c == '_' || c == '-')
|
||||
{
|
||||
if (c == '_')
|
||||
c = '-';
|
||||
obstack_1grow (&token_obstack, c);
|
||||
}
|
||||
|
||||
/* %DIRECTIVE="ARG". Separate into
|
||||
TOKEN_BUFFER = `%DIRECTIVE\0ARG\0'.
|
||||
This is a bit hackish, but once we move to a Bison parser,
|
||||
things will be cleaned up. */
|
||||
if (c == '=')
|
||||
{
|
||||
/* End of the directive. We skip the `='. */
|
||||
obstack_1grow (&token_obstack, '\0');
|
||||
/* Fetch the ARG if present. */
|
||||
c = getc (finput);
|
||||
if (c == '"')
|
||||
{
|
||||
int code;
|
||||
arg_offset = obstack_object_size (&token_obstack);
|
||||
/* Read up to and including `"'. Do not append the closing
|
||||
`"' in the output: it's not part of the ARG. */
|
||||
while ((code = literalchar ()) != '"')
|
||||
obstack_1grow (&token_obstack, code);
|
||||
}
|
||||
/* else: should be an error. */
|
||||
}
|
||||
else
|
||||
ungetc (c, finput);
|
||||
|
||||
obstack_1grow (&token_obstack, '\0');
|
||||
token_buffer = obstack_finish (&token_obstack);
|
||||
if (arg_offset)
|
||||
arg = token_buffer + arg_offset;
|
||||
|
||||
/* table lookup % directive */
|
||||
for (tx = option_table; tx->name; tx++)
|
||||
if ((tx->access == opt_percent || tx->access == opt_both)
|
||||
&& option_strcmp (token_buffer + 1, tx->name) == 0)
|
||||
break;
|
||||
|
||||
if (arg && tx->ret_val != tok_stropt)
|
||||
fatal (_("`%s' supports no argument: %s"), token_buffer, quote (arg));
|
||||
|
||||
|
||||
switch (tx->ret_val)
|
||||
{
|
||||
case tok_stropt:
|
||||
assert (tx->flag);
|
||||
if (arg)
|
||||
{
|
||||
char **flag = (char **) tx->flag;
|
||||
/* Keep only the first assignment: command line options have
|
||||
already been processed, and we want them to have
|
||||
precedence. Side effect: if this %-option is used
|
||||
several times, only the first is honored. Bah. */
|
||||
if (!*flag)
|
||||
*flag = xstrdup (arg);
|
||||
}
|
||||
else
|
||||
fatal (_("`%s' requires an argument"), token_buffer);
|
||||
return tok_noop;
|
||||
break;
|
||||
|
||||
case tok_intopt:
|
||||
assert (tx->flag);
|
||||
*((int *) (tx->flag)) = 1;
|
||||
return tok_noop;
|
||||
break;
|
||||
|
||||
case tok_obsolete:
|
||||
fatal (_("`%s' is no longer supported"), token_buffer);
|
||||
return tok_noop;
|
||||
break;
|
||||
|
||||
default:
|
||||
return tx->ret_val;
|
||||
break;
|
||||
}
|
||||
abort ();
|
||||
}
|
||||
82
src/lex.h
82
src/lex.h
@@ -1,82 +0,0 @@
|
||||
/* Token type definitions for bison's input reader,
|
||||
Copyright 1984, 1989, 1992, 2000, 2001 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, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef LEX_H_
|
||||
# define LEX_H_
|
||||
|
||||
/* Token-type codes. */
|
||||
typedef enum token_e
|
||||
{
|
||||
tok_undef, /* Not defined. Used to initial token_t vars. */
|
||||
tok_eof,
|
||||
tok_identifier,
|
||||
tok_comma,
|
||||
tok_colon,
|
||||
tok_semicolon,
|
||||
tok_bar,
|
||||
tok_left_curly,
|
||||
tok_two_percents,
|
||||
tok_percent_left_curly,
|
||||
tok_token,
|
||||
tok_nterm,
|
||||
tok_type,
|
||||
tok_union,
|
||||
tok_start,
|
||||
tok_left,
|
||||
tok_right,
|
||||
tok_nonassoc,
|
||||
tok_prec,
|
||||
tok_typename,
|
||||
tok_number,
|
||||
tok_expect,
|
||||
tok_define,
|
||||
tok_skel,
|
||||
tok_noop,
|
||||
/* A directive that sets to true its associated variable. */
|
||||
tok_intopt,
|
||||
/* A directive that sets its associated variable to the string
|
||||
argument. */
|
||||
tok_stropt,
|
||||
tok_illegal,
|
||||
tok_obsolete
|
||||
} token_t;
|
||||
|
||||
extern const char *token_buffer;
|
||||
extern symbol_t *symval;
|
||||
extern int numval;
|
||||
|
||||
void lex_init PARAMS ((void));
|
||||
void lex_free PARAMS ((void));
|
||||
int skip_white_space PARAMS ((void));
|
||||
void unlex PARAMS ((token_t));
|
||||
void read_type_name PARAMS ((FILE *fin));
|
||||
int xgetc PARAMS ((FILE *fin));
|
||||
|
||||
/* Return one of the token-type codes. When an identifier is seen,
|
||||
the code IDENTIFIER is returned and the name is looked up in the
|
||||
symbol table using symtab.c; symval is set to a pointer to the
|
||||
entry found. */
|
||||
|
||||
token_t lex PARAMS ((void));
|
||||
char literalchar PARAMS ((void));
|
||||
|
||||
token_t parse_percent_token PARAMS ((void));
|
||||
|
||||
#endif /* !LEX_H_ */
|
||||
@@ -38,7 +38,6 @@
|
||||
#include "conflicts.h"
|
||||
#include "print_graph.h"
|
||||
#include "muscle_tab.h"
|
||||
#include "lex.h"
|
||||
|
||||
/* The name this program was run with, for messages. */
|
||||
char *program_name;
|
||||
|
||||
@@ -55,7 +55,6 @@ muscle_init (void)
|
||||
muscle_insert ("filename", infile);
|
||||
|
||||
/* Types. */
|
||||
muscle_insert ("stype", "int");
|
||||
muscle_insert ("ltype", "yyltype");
|
||||
|
||||
/* Default #line formatting. */
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "getargs.h"
|
||||
#include "symtab.h"
|
||||
#include "gram.h"
|
||||
#include "lex.h"
|
||||
#include "output.h"
|
||||
#include "options.h"
|
||||
|
||||
@@ -77,55 +76,33 @@ const struct option_table_s option_table[] =
|
||||
/* Hidden. */
|
||||
OPTN ("trace", no, &trace_flag, 0, 1)
|
||||
|
||||
/*
|
||||
* Percent declarations.
|
||||
*/
|
||||
|
||||
DRTV ("token", no, NULL, tok_token)
|
||||
DRTV ("term", no, NULL, tok_token)
|
||||
DRTV ("nterm", no, NULL, tok_nterm)
|
||||
DRTV ("type", no, NULL, tok_type)
|
||||
DRTV ("union", no, NULL, tok_union)
|
||||
DRTV ("expect", no, NULL, tok_expect)
|
||||
DRTV ("start", no, NULL, tok_start)
|
||||
DRTV ("left", no, NULL, tok_left)
|
||||
DRTV ("right", no, NULL, tok_right)
|
||||
DRTV ("nonassoc", no, NULL, tok_nonassoc)
|
||||
DRTV ("binary", no, NULL, tok_nonassoc)
|
||||
DRTV ("prec", no, NULL, tok_prec)
|
||||
DRTV ("verbose", no, &report_flag, tok_intopt)
|
||||
DRTV ("error-verbose",no, &error_verbose, tok_intopt)
|
||||
|
||||
/* FIXME: semantic parsers will output an `include' of an
|
||||
output file: be sure that the naem included is indeed the name of
|
||||
the output file. */ /* FIXME Should we activate this options ?
|
||||
*/
|
||||
BOTH ("output", required, &spec_outfile, tok_stropt, 'o')
|
||||
BOTH ("file-prefix", required, &spec_file_prefix, tok_stropt, 'b')
|
||||
BOTH ("name-prefix", required, &spec_name_prefix, tok_stropt, 'p')
|
||||
|
||||
DRTV ("define", no, NULL, tok_define)
|
||||
DRTV ("pure-parser", no, &pure_parser, tok_intopt)
|
||||
OPTN ("output", required, &spec_outfile, 0, 'o')
|
||||
OPTN ("file-prefix", required, &spec_file_prefix, 0, 'b')
|
||||
OPTN ("name-prefix", required, &spec_name_prefix, 0, 'p')
|
||||
|
||||
/*
|
||||
* Percent and command line declarations.
|
||||
*/
|
||||
|
||||
/* Output. */
|
||||
BOTH ("defines", optional, &defines_flag, tok_intopt, 'd')
|
||||
OPTN ("defines", optional, &defines_flag, 0, 'd')
|
||||
|
||||
/* Operation modes. */
|
||||
BOTH ("fixed-output-files", no, &yacc_flag, tok_intopt, 'y')
|
||||
BOTH ("yacc", no, &yacc_flag, tok_intopt, 'y')
|
||||
OPTN ("fixed-output-files", no, &yacc_flag, 0, 'y')
|
||||
OPTN ("yacc", no, &yacc_flag, 0, 'y')
|
||||
|
||||
/* Parser. */
|
||||
BOTH ("debug", no, &debug_flag, tok_intopt, 't')
|
||||
BOTH ("locations", no, &locations_flag, tok_intopt, 1)
|
||||
BOTH ("no-lines", no, &no_lines_flag, tok_intopt, 'l')
|
||||
BOTH ("no-parser", no, &no_parser_flag, tok_intopt, 'n')
|
||||
BOTH ("raw", no, 0, tok_obsolete, 0)
|
||||
BOTH ("skeleton", required, 0, tok_skel, 'S')
|
||||
BOTH ("token-table", no, &token_table_flag, tok_intopt, 'k')
|
||||
OPTN ("debug", no, &debug_flag, 0, 't')
|
||||
OPTN ("locations", no, &locations_flag, 0, 1)
|
||||
OPTN ("no-lines", no, &no_lines_flag, 0, 'l')
|
||||
OPTN ("no-parser", no, &no_parser_flag, 0, 'n')
|
||||
OPTN ("raw", no, 0, 0, 0)
|
||||
OPTN ("skeleton", required, 0, 0, 'S')
|
||||
OPTN ("token-table", no, &token_table_flag, 0, 'k')
|
||||
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -548,12 +548,8 @@ actions_output (FILE *out)
|
||||
rules[rule].action_line,
|
||||
quotearg_style (c_quoting_style,
|
||||
muscle_find ("filename")));
|
||||
/* As a Bison extension, add the ending semicolon. Since some
|
||||
Yacc don't do that, help people using bison as a Yacc
|
||||
finding their missing semicolons. */
|
||||
fprintf (out, "{ %s%s }\n break;\n\n",
|
||||
rules[rule].action,
|
||||
yacc_flag ? ";" : "");
|
||||
fprintf (out, " %s\n break;\n\n",
|
||||
rules[rule].action);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1790
src/parse-gram.c
Normal file
1790
src/parse-gram.c
Normal file
File diff suppressed because it is too large
Load Diff
124
src/parse-gram.h
Normal file
124
src/parse-gram.h
Normal file
@@ -0,0 +1,124 @@
|
||||
#ifndef BISON_PARSE_GRAM_H
|
||||
# define BISON_PARSE_GRAM_H
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# if defined (__STDC__) || defined (__cplusplus)
|
||||
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
||||
know about them. */
|
||||
enum yytokentype {
|
||||
GRAM_EOF = 0,
|
||||
STRING = 258,
|
||||
CHARACTER = 259,
|
||||
INT = 260,
|
||||
PERCENT_TOKEN = 261,
|
||||
PERCENT_NTERM = 262,
|
||||
PERCENT_TYPE = 263,
|
||||
PERCENT_UNION = 264,
|
||||
PERCENT_EXPECT = 265,
|
||||
PERCENT_START = 266,
|
||||
PERCENT_LEFT = 267,
|
||||
PERCENT_RIGHT = 268,
|
||||
PERCENT_NONASSOC = 269,
|
||||
PERCENT_PREC = 270,
|
||||
PERCENT_VERBOSE = 271,
|
||||
PERCENT_ERROR_VERBOSE = 272,
|
||||
PERCENT_OUTPUT = 273,
|
||||
PERCENT_FILE_PREFIX = 274,
|
||||
PERCENT_NAME_PREFIX = 275,
|
||||
PERCENT_DEFINE = 276,
|
||||
PERCENT_PURE_PARSER = 277,
|
||||
PERCENT_DEFINES = 278,
|
||||
PERCENT_YACC = 279,
|
||||
PERCENT_DEBUG = 280,
|
||||
PERCENT_LOCATIONS = 281,
|
||||
PERCENT_NO_LINES = 282,
|
||||
PERCENT_SKELETON = 283,
|
||||
PERCENT_TOKEN_TABLE = 284,
|
||||
TYPE = 285,
|
||||
EQUAL = 286,
|
||||
SEMICOLON = 287,
|
||||
COLON = 288,
|
||||
PIPE = 289,
|
||||
ID = 290,
|
||||
PERCENT_PERCENT = 291,
|
||||
PROLOGUE = 292,
|
||||
EPILOGUE = 293,
|
||||
BRACED_CODE = 294
|
||||
};
|
||||
# endif
|
||||
/* POSIX requires `int' for tokens in interfaces. */
|
||||
# define YYTOKENTYPE int
|
||||
#endif /* !YYTOKENTYPE */
|
||||
#define GRAM_EOF 0
|
||||
#define STRING 258
|
||||
#define CHARACTER 259
|
||||
#define INT 260
|
||||
#define PERCENT_TOKEN 261
|
||||
#define PERCENT_NTERM 262
|
||||
#define PERCENT_TYPE 263
|
||||
#define PERCENT_UNION 264
|
||||
#define PERCENT_EXPECT 265
|
||||
#define PERCENT_START 266
|
||||
#define PERCENT_LEFT 267
|
||||
#define PERCENT_RIGHT 268
|
||||
#define PERCENT_NONASSOC 269
|
||||
#define PERCENT_PREC 270
|
||||
#define PERCENT_VERBOSE 271
|
||||
#define PERCENT_ERROR_VERBOSE 272
|
||||
#define PERCENT_OUTPUT 273
|
||||
#define PERCENT_FILE_PREFIX 274
|
||||
#define PERCENT_NAME_PREFIX 275
|
||||
#define PERCENT_DEFINE 276
|
||||
#define PERCENT_PURE_PARSER 277
|
||||
#define PERCENT_DEFINES 278
|
||||
#define PERCENT_YACC 279
|
||||
#define PERCENT_DEBUG 280
|
||||
#define PERCENT_LOCATIONS 281
|
||||
#define PERCENT_NO_LINES 282
|
||||
#define PERCENT_SKELETON 283
|
||||
#define PERCENT_TOKEN_TABLE 284
|
||||
#define TYPE 285
|
||||
#define EQUAL 286
|
||||
#define SEMICOLON 287
|
||||
#define COLON 288
|
||||
#define PIPE 289
|
||||
#define ID 290
|
||||
#define PERCENT_PERCENT 291
|
||||
#define PROLOGUE 292
|
||||
#define EPILOGUE 293
|
||||
#define BRACED_CODE 294
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef YYSTYPE
|
||||
#line 70 "parse-gram.y"
|
||||
typedef union
|
||||
{
|
||||
symbol_t *symbol;
|
||||
int integer;
|
||||
char *string;
|
||||
associativity assoc;
|
||||
}
|
||||
yystype;
|
||||
# define YYSTYPE yystype
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef YYLTYPE
|
||||
typedef struct yyltype
|
||||
{
|
||||
int first_line;
|
||||
int first_column;
|
||||
int last_line;
|
||||
int last_column;
|
||||
} yyltype;
|
||||
# define YYLTYPE yyltype
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif /* not BISON_PARSE_GRAM_H */
|
||||
|
||||
386
src/parse-gram.y
Normal file
386
src/parse-gram.y
Normal file
@@ -0,0 +1,386 @@
|
||||
/* Bison Grammar Parser -*- C -*-
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program 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 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
%debug
|
||||
%defines
|
||||
%locations
|
||||
%pure-parser
|
||||
%error-verbose
|
||||
%defines
|
||||
%name-prefix="gram_"
|
||||
|
||||
%{
|
||||
#include "system.h"
|
||||
#include "muscle_tab.h"
|
||||
#include "files.h"
|
||||
#include "getargs.h"
|
||||
#include "output.h"
|
||||
#include "gram.h"
|
||||
#include "reader.h"
|
||||
#include "conflicts.h"
|
||||
|
||||
/* Pass the control structure to YYPARSE and YYLEX. */
|
||||
#define YYPARSE_PARAM gram_control
|
||||
#define YYLEX_PARAM gram_control
|
||||
/* YYPARSE receives GRAM_CONTROL as a void *. Provide a
|
||||
correctly typed access to it. */
|
||||
#define yycontrol ((gram_control_t *) gram_control)
|
||||
|
||||
/* Request detailed parse error messages, and pass them to
|
||||
GRAM_ERROR. */
|
||||
#undef yyerror
|
||||
#define yyerror(Msg) \
|
||||
gram_error (yycontrol, &yylloc, Msg)
|
||||
|
||||
/* When debugging our pure parser, we want to see values and locations
|
||||
of the tokens. */
|
||||
#define YYPRINT(File, Type, Value) \
|
||||
yyprint (File, &yylloc, Type, &Value)
|
||||
static void yyprint (FILE *file, const yyltype *loc,
|
||||
int type, const yystype *value);
|
||||
|
||||
symbol_class current_class = unknown_sym;
|
||||
char *current_type = 0;
|
||||
symbol_t *current_lhs;
|
||||
associativity current_assoc;
|
||||
int current_prec = 0;
|
||||
%}
|
||||
|
||||
|
||||
/* Only NUMBERS have a value. */
|
||||
%union
|
||||
{
|
||||
symbol_t *symbol;
|
||||
int integer;
|
||||
char *string;
|
||||
associativity assoc;
|
||||
};
|
||||
|
||||
/* Define the tokens together with there human representation. */
|
||||
%token GRAM_EOF 0 "end of string"
|
||||
%token STRING CHARACTER
|
||||
%token INT
|
||||
|
||||
%token PERCENT_TOKEN "%token"
|
||||
%token PERCENT_NTERM "%nterm"
|
||||
%token PERCENT_TYPE "%type"
|
||||
%token PERCENT_UNION "%union"
|
||||
%token PERCENT_EXPECT "%expect"
|
||||
%token PERCENT_START "%start"
|
||||
%token PERCENT_LEFT "%left"
|
||||
%token PERCENT_RIGHT "%right"
|
||||
%token PERCENT_NONASSOC "%nonassoc"
|
||||
%token PERCENT_PREC "%prec"
|
||||
%token PERCENT_VERBOSE "%verbose"
|
||||
%token PERCENT_ERROR_VERBOSE "%error-verbose"
|
||||
|
||||
%token PERCENT_OUTPUT "%output"
|
||||
%token PERCENT_FILE_PREFIX "%file-prefix"
|
||||
%token PERCENT_NAME_PREFIX "%name-prefix"
|
||||
|
||||
%token PERCENT_DEFINE "%define"
|
||||
%token PERCENT_PURE_PARSER "%pure-parser"
|
||||
|
||||
%token PERCENT_DEFINES "%defines"
|
||||
|
||||
%token PERCENT_YACC "%yacc"
|
||||
|
||||
%token PERCENT_DEBUG "%debug"
|
||||
%token PERCENT_LOCATIONS "%locations"
|
||||
%token PERCENT_NO_LINES "%no-lines"
|
||||
%token PERCENT_SKELETON "%skeleton"
|
||||
%token PERCENT_TOKEN_TABLE "%token-table"
|
||||
|
||||
%token TYPE
|
||||
%token EQUAL "="
|
||||
%token SEMICOLON ";"
|
||||
%token COLON ":"
|
||||
%token PIPE "|"
|
||||
%token ID "identifier"
|
||||
%token PERCENT_PERCENT "%%"
|
||||
%token PROLOGUE EPILOGUE
|
||||
%token BRACED_CODE
|
||||
|
||||
%type <string> CHARACTER TYPE BRACED_CODE PROLOGUE EPILOGUE epilogue.opt action STRING string_content
|
||||
%type <integer> INT
|
||||
%type <symbol> ID symbol string_as_id
|
||||
%type <assoc> precedence_directive
|
||||
%%
|
||||
input: { LOCATION_RESET (yylloc); }
|
||||
directives "%%" gram epilogue.opt
|
||||
{
|
||||
yycontrol->errcode = 0;
|
||||
epilogue_set ($5, @5.first_line);
|
||||
}
|
||||
;
|
||||
|
||||
directives:
|
||||
/* Nothing */
|
||||
| directives directive
|
||||
;
|
||||
|
||||
directive:
|
||||
grammar_directives
|
||||
| PROLOGUE { prologue_augment ($1, @1.first_line); }
|
||||
| "%debug" { debug_flag = 1; }
|
||||
| "%define" string_content string_content { muscle_insert ($2, $3); }
|
||||
| "%defines" { defines_flag = 1; }
|
||||
| "%error-verbose" { error_verbose = 1; }
|
||||
| "%expect" INT { expected_conflicts = $2; }
|
||||
| "%file-prefix" "=" string_content { spec_file_prefix = $3; }
|
||||
| "%locations" { locations_flag = 1; }
|
||||
| "%name-prefix" "=" string_content { spec_name_prefix = $3; }
|
||||
| "%no-lines" { no_lines_flag = 1; }
|
||||
| "%output" "=" string_content { spec_outfile = $3; }
|
||||
| "%pure-parser" { pure_parser = 1; }
|
||||
| "%skeleton" string_content { skeleton = $2; }
|
||||
| "%token-table" { token_table_flag = 1; }
|
||||
| "%verbose" { report_flag = 1; }
|
||||
| "%yacc" { yacc_flag = 1; }
|
||||
;
|
||||
|
||||
grammar_directives:
|
||||
precedence_directives
|
||||
| "%nterm" { current_class = nterm_sym; } symbol_defs.1
|
||||
{
|
||||
current_class = unknown_sym;
|
||||
current_type = NULL;
|
||||
}
|
||||
| "%start" symbol
|
||||
{
|
||||
grammar_start_symbol_set ($2);
|
||||
}
|
||||
| "%token" { current_class = token_sym; } symbol_defs.1
|
||||
{
|
||||
current_class = unknown_sym;
|
||||
current_type = NULL;
|
||||
}
|
||||
| "%type" TYPE {current_type = $2; } nterms_to_type.1
|
||||
{
|
||||
current_type = NULL;
|
||||
}
|
||||
| "%union" BRACED_CODE semi_colon_opt
|
||||
{
|
||||
typed = 1;
|
||||
MUSCLE_INSERT_INT ("stype_line", @2.first_line);
|
||||
muscle_insert ("stype", $2);
|
||||
}
|
||||
;
|
||||
|
||||
precedence_directives:
|
||||
precedence_directive type.opt
|
||||
{ current_assoc = $1; ++current_prec; }
|
||||
terms_to_prec.1
|
||||
{ current_assoc = non_assoc; current_type = NULL; }
|
||||
;
|
||||
|
||||
precedence_directive:
|
||||
"%left" { $$ = left_assoc; }
|
||||
| "%right" { $$ = right_assoc; }
|
||||
| "%nonassoc" { $$ = non_assoc; }
|
||||
;
|
||||
|
||||
type.opt:
|
||||
/* Nothing. */ { current_type = NULL;}
|
||||
| TYPE { current_type = $1; }
|
||||
;
|
||||
|
||||
/* One or more nonterminals to be %typed. */
|
||||
nterms_to_type.1:
|
||||
ID { symbol_type_set ($1, current_type); }
|
||||
| nterms_to_type.1 ID { symbol_type_set ($2, current_type); }
|
||||
;
|
||||
|
||||
/* One or more symbols to be given a precedence/associativity. */
|
||||
terms_to_prec.1:
|
||||
symbol
|
||||
{
|
||||
symbol_type_set ($1, current_type);
|
||||
symbol_precedence_set ($1, current_prec, current_assoc);
|
||||
}
|
||||
| terms_to_prec.1 symbol
|
||||
{
|
||||
symbol_type_set ($2, current_type);
|
||||
symbol_precedence_set ($2, current_prec, current_assoc);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
/* One token definition. */
|
||||
symbol_def:
|
||||
TYPE
|
||||
{
|
||||
current_type = $1;
|
||||
}
|
||||
| ID
|
||||
{
|
||||
symbol_class_set ($1, current_class);
|
||||
symbol_type_set ($1, current_type);
|
||||
}
|
||||
| ID INT
|
||||
{
|
||||
symbol_class_set ($1, current_class);
|
||||
symbol_type_set ($1, current_type);
|
||||
symbol_user_token_number_set ($1, $2);
|
||||
}
|
||||
| ID string_as_id
|
||||
{
|
||||
symbol_class_set ($1, current_class);
|
||||
symbol_type_set ($1, current_type);
|
||||
symbol_make_alias ($1, $2);
|
||||
}
|
||||
| ID INT string_as_id
|
||||
{
|
||||
symbol_class_set ($1, current_class);
|
||||
symbol_type_set ($1, current_type);
|
||||
symbol_user_token_number_set ($1, $2);
|
||||
symbol_make_alias ($1, $3);
|
||||
}
|
||||
;
|
||||
|
||||
/* One or more symbol definitions. */
|
||||
symbol_defs.1:
|
||||
symbol_def
|
||||
{;}
|
||||
| symbol_defs.1 symbol_def
|
||||
{;}
|
||||
;
|
||||
|
||||
gram:
|
||||
rules
|
||||
| gram rules
|
||||
;
|
||||
|
||||
rules:
|
||||
ID ":" { current_lhs = $1; } rhses.1 ";"
|
||||
{;}
|
||||
;
|
||||
|
||||
rhses.1:
|
||||
rhs { grammar_rule_end (); }
|
||||
| rhses.1 "|" rhs { grammar_rule_end (); }
|
||||
;
|
||||
|
||||
rhs:
|
||||
/* Nothing. */
|
||||
{ grammar_rule_begin (current_lhs); }
|
||||
| rhs symbol
|
||||
{ grammar_current_rule_symbol_append ($2); }
|
||||
| rhs action
|
||||
{ grammar_current_rule_action_append ($2, @2.first_line); }
|
||||
| rhs "%prec" symbol
|
||||
{ grammar_current_rule_prec_set ($3); }
|
||||
;
|
||||
|
||||
symbol:
|
||||
ID { $$ = $1; }
|
||||
| string_as_id { $$ = $1; }
|
||||
| CHARACTER { $$ = getsym ($1); }
|
||||
;
|
||||
|
||||
action:
|
||||
BRACED_CODE
|
||||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
/* A string used as an ID: we have to keep the quotes. */
|
||||
string_as_id:
|
||||
STRING
|
||||
{
|
||||
$$ = getsym ($1);
|
||||
symbol_class_set ($$, token_sym);
|
||||
}
|
||||
;
|
||||
|
||||
/* A string used for its contents. Strip the quotes. */
|
||||
string_content:
|
||||
STRING
|
||||
{
|
||||
$$ = $1 + 1;
|
||||
$$[strlen ($$) - 1] = '\0';
|
||||
};
|
||||
|
||||
|
||||
epilogue.opt:
|
||||
/* Nothing. */
|
||||
{
|
||||
$$ = xstrdup ("");
|
||||
}
|
||||
| "%%" EPILOGUE
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
;
|
||||
|
||||
semi_colon_opt:
|
||||
/* Nothing. */
|
||||
| ";"
|
||||
;
|
||||
%%
|
||||
/*------------------------------------------------------------------.
|
||||
| When debugging the parser, display tokens' locations and values. |
|
||||
`------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
yyprint (FILE *file,
|
||||
const yyltype *loc, int type, const yystype *value)
|
||||
{
|
||||
fputs (" (", file);
|
||||
LOCATION_PRINT (file, *loc);
|
||||
fputs (")", file);
|
||||
switch (type)
|
||||
{
|
||||
case CHARACTER:
|
||||
fprintf (file, " = '%s'", value->string);
|
||||
break;
|
||||
|
||||
case ID:
|
||||
fprintf (file, " = %s", value->symbol->tag);
|
||||
break;
|
||||
|
||||
case INT:
|
||||
fprintf (file, " = %d", value->integer);
|
||||
break;
|
||||
|
||||
case STRING:
|
||||
fprintf (file, " = \"%s\"", value->string);
|
||||
break;
|
||||
|
||||
case TYPE:
|
||||
fprintf (file, " = <%s>", value->string);
|
||||
break;
|
||||
|
||||
case BRACED_CODE:
|
||||
case PROLOGUE:
|
||||
case EPILOGUE:
|
||||
fprintf (file, " = {{ %s }}", value->string);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gram_error (gram_control_t *control ATTRIBUTE_UNUSED,
|
||||
yyltype *yylloc, const char *msg)
|
||||
{
|
||||
LOCATION_PRINT (stderr, *yylloc);
|
||||
fprintf (stderr, ": %s\n", msg);
|
||||
}
|
||||
1264
src/reader.c
1264
src/reader.c
File diff suppressed because it is too large
Load Diff
89
src/reader.h
89
src/reader.h
@@ -21,13 +21,92 @@
|
||||
#ifndef READER_H_
|
||||
# define READER_H_
|
||||
|
||||
#include "symtab.h"
|
||||
typedef struct symbol_list
|
||||
{
|
||||
struct symbol_list *next;
|
||||
symbol_t *sym;
|
||||
int line;
|
||||
|
||||
/* Read in the grammar specification and record it in the format
|
||||
described in gram.h. */
|
||||
/* The action is attached to the LHS of a rule. */
|
||||
const char *action;
|
||||
int action_line;
|
||||
|
||||
symbol_t *ruleprec;
|
||||
} symbol_list;
|
||||
|
||||
# include "parse-gram.h"
|
||||
|
||||
typedef int location_t;
|
||||
|
||||
/* Initialize LOC. */
|
||||
# define LOCATION_RESET(Loc) \
|
||||
(Loc).first_column = (Loc).first_line = 1; \
|
||||
(Loc).last_column = (Loc).last_line = 1;
|
||||
|
||||
/* Advance of NUM columns. */
|
||||
# define LOCATION_COLUMNS(Loc, Num) \
|
||||
(Loc).last_column += Num;
|
||||
|
||||
/* Advance of NUM lines. */
|
||||
# define LOCATION_LINES(Loc, Num) \
|
||||
(Loc).last_column = 1; \
|
||||
(Loc).last_line += Num;
|
||||
|
||||
/* Restart: move the first cursor to the last position. */
|
||||
# define LOCATION_STEP(Loc) \
|
||||
(Loc).first_column = (Loc).last_column; \
|
||||
(Loc).first_line = (Loc).last_line;
|
||||
|
||||
/* Output LOC on the stream OUT. */
|
||||
# define LOCATION_PRINT(Out, Loc) \
|
||||
fprintf (stderr, "%s:", infile); \
|
||||
if ((Loc).first_line != (Loc).last_line) \
|
||||
fprintf (Out, "%d.%d-%d.%d", \
|
||||
(Loc).first_line, (Loc).first_column, \
|
||||
(Loc).last_line, (Loc).last_column - 1); \
|
||||
else if ((Loc).first_column < (Loc).last_column - 1) \
|
||||
fprintf (Out, "%d.%d-%d", (Loc).first_line, \
|
||||
(Loc).first_column, (Loc).last_column - 1); \
|
||||
else \
|
||||
fprintf (Out, "%d.%d", (Loc).first_line, (Loc).first_column)
|
||||
|
||||
typedef struct gram_control_s
|
||||
{
|
||||
int errcode;
|
||||
} gram_control_t;
|
||||
|
||||
/* From the scanner. */
|
||||
extern FILE *gram_in;
|
||||
extern int gram__flex_debug;
|
||||
|
||||
# define YY_DECL \
|
||||
int gram_lex (yystype *yylval, yyltype *yylloc, \
|
||||
gram_control_t *yycontrol)
|
||||
YY_DECL;
|
||||
|
||||
|
||||
/* From the parser. */
|
||||
extern int gram_debug;
|
||||
void gram_error (gram_control_t *control,
|
||||
yyltype *loc, const char *msg);
|
||||
int gram_parse (void *control);
|
||||
|
||||
char *get_type_name PARAMS ((int n, symbol_list *rule));
|
||||
extern int typed;
|
||||
|
||||
/* From reader.c. */
|
||||
void grammar_start_symbol_set PARAMS ((symbol_t *s));
|
||||
void prologue_augment PARAMS ((const char *prologue, location_t location));
|
||||
void epilogue_set PARAMS ((const char *epilogue, location_t location));
|
||||
void grammar_symbol_append PARAMS ((symbol_t *s));
|
||||
void grammar_rule_begin PARAMS ((symbol_t *lhs));
|
||||
void grammar_rule_end PARAMS ((void));
|
||||
void grammar_midrule_action PARAMS ((void));
|
||||
void grammar_current_rule_prec_set PARAMS ((symbol_t *precsym));
|
||||
void grammar_current_rule_symbol_append PARAMS ((symbol_t *symbol));
|
||||
void grammar_current_rule_action_append PARAMS ((const char *action,
|
||||
int line));
|
||||
extern symbol_list *current_rule;
|
||||
void reader PARAMS ((void));
|
||||
|
||||
extern int lineno;
|
||||
|
||||
#endif /* !READER_H_ */
|
||||
|
||||
46
src/scan-action.l
Normal file
46
src/scan-action.l
Normal file
@@ -0,0 +1,46 @@
|
||||
/* Scan User Actions. -*- C -*-
|
||||
Copyright (C) 2002 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, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
|
||||
%option nodefault noyywrap nounput
|
||||
%option prefix="action_" outfile="lex.yy.c"
|
||||
|
||||
%{
|
||||
#include "system.h"
|
||||
#include "files.h"
|
||||
int skel_lex PARAMS ((void));
|
||||
static int yylineno = 1;
|
||||
%}
|
||||
|
||||
%x DOLLAR
|
||||
|
||||
ID [a-zA-Z]+
|
||||
NUM -?[0-9]+
|
||||
|
||||
%%
|
||||
$(-?[0-9])+ { fprintf (action_out, "yylsp[%s]", yytext + 1) ;}
|
||||
@(-?[0-9])+ { fprintf (action_out, "yylsp[%s]", yytext + 1) ;}
|
||||
$<{ID} { action_type = xstrndup (yytext + 2, yyleng - 2); BEGIN DOLLAR;}
|
||||
$ { BEGIN DOLLAR;}
|
||||
|
||||
<DOLLAR>
|
||||
{
|
||||
{NUM}> { fprintf (action_out, "yyvsp[%s]", NUM }
|
||||
}
|
||||
%%
|
||||
2750
src/scan-gram.c
Normal file
2750
src/scan-gram.c
Normal file
File diff suppressed because it is too large
Load Diff
582
src/scan-gram.l
Normal file
582
src/scan-gram.l
Normal file
@@ -0,0 +1,582 @@
|
||||
/* Bison Grammar Scanner -*- C -*-
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Bison, the GNU Compiler Compiler.
|
||||
|
||||
This program 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 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA
|
||||
*/
|
||||
|
||||
%option debug nodefault noyywrap nounput never-interactive stack
|
||||
%option prefix="gram_" outfile="lex.yy.c"
|
||||
|
||||
%{
|
||||
#include "system.h"
|
||||
#include "complain.h"
|
||||
#include "quote.h"
|
||||
#include "getargs.h"
|
||||
#include "gram.h"
|
||||
#include "reader.h"
|
||||
|
||||
/* Each time we match a string, move the end cursor to its end. */
|
||||
#define YY_USER_ACTION LOCATION_COLUMNS (*yylloc, yyleng)
|
||||
#define YY_LINES LOCATION_LINES (*yylloc, yyleng); lineno += yyleng;
|
||||
#define YY_STEP LOCATION_STEP (*yylloc)
|
||||
|
||||
/* Appending to the STRING_OBSTACK. */
|
||||
#define YY_INIT obstack_init (&string_obstack)
|
||||
#define YY_GROW obstack_grow (&string_obstack, yytext, yyleng)
|
||||
#define YY_FINISH obstack_1grow (&string_obstack, '\0'); yylval->string = obstack_finish (&string_obstack);
|
||||
|
||||
/* This is only to avoid GCC warnings. */
|
||||
#define YY_USER_INIT if (yycontrol) {;};
|
||||
|
||||
static struct obstack string_obstack;
|
||||
static int braces_level = 0;
|
||||
static int percent_percent_count = 0;
|
||||
|
||||
static void handle_dollar PARAMS ((char *cp));
|
||||
static void handle_at PARAMS ((char *cp));
|
||||
|
||||
%}
|
||||
%x SC_COMMENT
|
||||
%x SC_STRING SC_CHARACTER
|
||||
%x SC_ESCAPED_STRING SC_ESCAPED_CHARACTER
|
||||
%x SC_BRACED_CODE SC_PROLOGUE SC_EPILOGUE
|
||||
|
||||
id [.a-zA-Z][.a-zA-Z_0-9]*
|
||||
int [0-9]+
|
||||
eols (\n|\r|\n\r|\r\n)+
|
||||
blanks [ \t\f]+
|
||||
|
||||
%%
|
||||
%{
|
||||
/* At each yylex invocation, mark the current position as the
|
||||
start of the next token. */
|
||||
#define TR_POS 0
|
||||
#if TR_POS
|
||||
fprintf (stderr, "FOO1: ");
|
||||
LOCATION_PRINT (stderr, *yylloc);
|
||||
fprintf (stderr, "\n");
|
||||
#endif
|
||||
YY_STEP;
|
||||
#if TR_POS
|
||||
fprintf (stderr, "BAR1: ");
|
||||
LOCATION_PRINT (stderr, *yylloc);
|
||||
fprintf (stderr, "\n");
|
||||
#endif
|
||||
%}
|
||||
|
||||
|
||||
/*----------------------------.
|
||||
| Scanning Bison directives. |
|
||||
`----------------------------*/
|
||||
<INITIAL>
|
||||
{
|
||||
"%binary" return PERCENT_NONASSOC;
|
||||
"%debug" return PERCENT_DEBUG;
|
||||
"%define" return PERCENT_DEFINE;
|
||||
"%defines" return PERCENT_DEFINES;
|
||||
"%error"[-_]"verbose" return PERCENT_ERROR_VERBOSE;
|
||||
"%expect" return PERCENT_EXPECT;
|
||||
"%file-prefix" return PERCENT_FILE_PREFIX;
|
||||
"%fixed"[-_]"output"[-_]"files" return PERCENT_YACC;
|
||||
"%left" return PERCENT_LEFT;
|
||||
"%locations" return PERCENT_LOCATIONS;
|
||||
"%name"[-_]"prefix" return PERCENT_NAME_PREFIX;
|
||||
"%no"[-_]"lines" return PERCENT_NO_LINES;
|
||||
"%nonassoc" return PERCENT_NONASSOC;
|
||||
"%nterm" return PERCENT_NTERM;
|
||||
"%output" return PERCENT_OUTPUT;
|
||||
"%prec" return PERCENT_PREC;
|
||||
"%pure"[-_]"parser" return PERCENT_PURE_PARSER;
|
||||
"%right" return PERCENT_RIGHT;
|
||||
"%skeleton" return PERCENT_SKELETON;
|
||||
"%start" return PERCENT_START;
|
||||
"%term" return PERCENT_TOKEN;
|
||||
"%token" return PERCENT_TOKEN;
|
||||
"%token"[-_]"table" return PERCENT_TOKEN_TABLE;
|
||||
"%type" return PERCENT_TYPE;
|
||||
"%union" return PERCENT_UNION;
|
||||
"%verbose" return PERCENT_VERBOSE;
|
||||
"%yacc" return PERCENT_YACC;
|
||||
|
||||
"=" return EQUAL;
|
||||
":" return COLON;
|
||||
"|" return PIPE;
|
||||
";" return SEMICOLON;
|
||||
|
||||
{eols} YY_LINES; YY_STEP;
|
||||
{blanks} YY_STEP;
|
||||
{id} {
|
||||
YY_INIT; YY_GROW; YY_FINISH;
|
||||
yylval->symbol = getsym (yylval->string);
|
||||
return ID;
|
||||
}
|
||||
|
||||
{int} yylval->integer = strtol (yytext, 0, 10); return INT;
|
||||
|
||||
/* Characters. We don't check there is only one. */
|
||||
\' YY_INIT; YY_GROW; yy_push_state (SC_ESCAPED_CHARACTER);
|
||||
|
||||
/* Strings. */
|
||||
\" YY_INIT; YY_GROW; yy_push_state (SC_ESCAPED_STRING);
|
||||
|
||||
/* Comments. */
|
||||
"/*" yy_push_state (SC_COMMENT);
|
||||
"//".* YY_STEP;
|
||||
|
||||
/* Prologue. */
|
||||
"%{" YY_INIT; yy_push_state (SC_PROLOGUE);
|
||||
|
||||
/* Code in between braces. */
|
||||
"{" YY_INIT; YY_GROW; ++braces_level; yy_push_state (SC_BRACED_CODE);
|
||||
|
||||
/* A type. */
|
||||
"<"[^>]+">" YY_INIT; obstack_grow (&string_obstack, yytext + 1, yyleng - 2); YY_FINISH; return TYPE;
|
||||
|
||||
"%%" {
|
||||
if (++percent_percent_count == 2)
|
||||
yy_push_state (SC_EPILOGUE);
|
||||
return PERCENT_PERCENT;
|
||||
}
|
||||
|
||||
. {
|
||||
LOCATION_PRINT (stderr, *yylloc);
|
||||
fprintf (stderr, ": invalid character: `%c'\n", *yytext);
|
||||
YY_STEP;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------.
|
||||
| Whatever the start condition (but those which correspond to |
|
||||
| entity `swallowed' by Bison: SC_ESCAPED_STRING and |
|
||||
| SC_ESCAPED_CHARACTER), no M4 character must escape as is. |
|
||||
`------------------------------------------------------------*/
|
||||
|
||||
<SC_COMMENT,SC_STRING,SC_CHARACTER,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
|
||||
{
|
||||
\[ obstack_sgrow (&string_obstack, "@<:@");
|
||||
\] obstack_sgrow (&string_obstack, "@:>@");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------.
|
||||
| Scanning a C comment. The initial `/ *' is already eaten. |
|
||||
`-----------------------------------------------------------*/
|
||||
|
||||
<SC_COMMENT>
|
||||
{
|
||||
"*/" { /* End of the comment. */
|
||||
if (yy_top_state () == INITIAL)
|
||||
{
|
||||
YY_STEP;
|
||||
}
|
||||
else
|
||||
{
|
||||
YY_GROW;
|
||||
}
|
||||
yy_pop_state ();
|
||||
}
|
||||
|
||||
[^\[\]*\n\r]+ if (yy_top_state () != INITIAL) YY_GROW;
|
||||
{eols} if (yy_top_state () != INITIAL) YY_GROW; YY_LINES;
|
||||
. /* Stray `*'. */if (yy_top_state () != INITIAL) YY_GROW;
|
||||
|
||||
<<EOF>> {
|
||||
LOCATION_PRINT (stderr, *yylloc);
|
||||
fprintf (stderr, ": unexpected end of file in a comment\n");
|
||||
yy_pop_state ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------.
|
||||
| Scanning a C string, including its escapes. The initial `"' is |
|
||||
| already eaten. |
|
||||
`----------------------------------------------------------------*/
|
||||
|
||||
<SC_ESCAPED_STRING>
|
||||
{
|
||||
\" {
|
||||
assert (yy_top_state () == INITIAL);
|
||||
YY_GROW;
|
||||
YY_FINISH;
|
||||
yy_pop_state ();
|
||||
return STRING;
|
||||
}
|
||||
|
||||
[^\"\n\r\\]+ YY_GROW;
|
||||
|
||||
{eols} obstack_1grow (&string_obstack, '\n'); YY_LINES;
|
||||
|
||||
<<EOF>> {
|
||||
LOCATION_PRINT (stderr, *yylloc);
|
||||
fprintf (stderr, ": unexpected end of file in a string\n");
|
||||
assert (yy_top_state () == INITIAL);
|
||||
YY_FINISH;
|
||||
yy_pop_state ();
|
||||
return STRING;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------.
|
||||
| Scanning a C character, decoding its escapes. The initial "'" |
|
||||
| is already eaten. |
|
||||
`---------------------------------------------------------------*/
|
||||
|
||||
<SC_ESCAPED_CHARACTER>
|
||||
{
|
||||
\' {
|
||||
YY_GROW;
|
||||
assert (yy_top_state () == INITIAL);
|
||||
{
|
||||
char c;
|
||||
YY_FINISH;
|
||||
c = yylval->string[1];
|
||||
yylval->symbol = getsym (yylval->string);
|
||||
symbol_class_set (yylval->symbol, token_sym);
|
||||
symbol_user_token_number_set (yylval->symbol, (unsigned int) c);
|
||||
yy_pop_state ();
|
||||
return ID;
|
||||
}
|
||||
}
|
||||
|
||||
[^\'\n\r\\] YY_GROW;
|
||||
|
||||
{eols} obstack_1grow (&string_obstack, '\n'); YY_LINES;
|
||||
|
||||
<<EOF>> {
|
||||
LOCATION_PRINT (stderr, *yylloc);
|
||||
fprintf (stderr, ": unexpected end of file in a character\n");
|
||||
assert (yy_top_state () == INITIAL);
|
||||
YY_FINISH;
|
||||
yy_pop_state ();
|
||||
return CHARACTER;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------.
|
||||
| Decode escaped characters. |
|
||||
`----------------------------*/
|
||||
|
||||
<SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>
|
||||
{
|
||||
\\[0-7]{3} {
|
||||
long c = strtol (yytext + 1, 0, 8);
|
||||
if (c > 255)
|
||||
{
|
||||
LOCATION_PRINT (stderr, *yylloc);
|
||||
fprintf (stderr, ": invalid escape: %s\n", yytext);
|
||||
YY_STEP;
|
||||
}
|
||||
else
|
||||
obstack_1grow (&string_obstack, c);
|
||||
}
|
||||
|
||||
\\x[0-9a-fA-F]{2} {
|
||||
obstack_1grow (&string_obstack, strtol (yytext + 2, 0, 16));
|
||||
}
|
||||
|
||||
\\a obstack_1grow (&string_obstack, '\a');
|
||||
\\b obstack_1grow (&string_obstack, '\b');
|
||||
\\f obstack_1grow (&string_obstack, '\f');
|
||||
\\n obstack_1grow (&string_obstack, '\n');
|
||||
\\r obstack_1grow (&string_obstack, '\r');
|
||||
\\t obstack_1grow (&string_obstack, '\t');
|
||||
\\v obstack_1grow (&string_obstack, '\v');
|
||||
\\[\\""] obstack_1grow (&string_obstack, yytext[1]);
|
||||
\\. {
|
||||
LOCATION_PRINT (stderr, *yylloc);
|
||||
fprintf (stderr, ": unrecognized escape: %s\n", yytext);
|
||||
YY_GROW;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------.
|
||||
| Scanning a C character without decoding its escapes. The |
|
||||
| initial "'" is already eaten. |
|
||||
`----------------------------------------------------------*/
|
||||
|
||||
<SC_CHARACTER>
|
||||
{
|
||||
\' {
|
||||
YY_GROW;
|
||||
assert (yy_top_state () != INITIAL);
|
||||
yy_pop_state ();
|
||||
}
|
||||
|
||||
[^\[\]\'\n\r\\] YY_GROW;
|
||||
\\. YY_GROW;
|
||||
|
||||
{eols} YY_GROW; YY_LINES;
|
||||
|
||||
<<EOF>> {
|
||||
LOCATION_PRINT (stderr, *yylloc);
|
||||
fprintf (stderr, ": unexpected end of file in a character\n");
|
||||
assert (yy_top_state () != INITIAL);
|
||||
yy_pop_state ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------.
|
||||
| Scanning a C string, without decoding its escapes. The initial |
|
||||
| `"' is already eaten. |
|
||||
`----------------------------------------------------------------*/
|
||||
|
||||
<SC_STRING>
|
||||
{
|
||||
\" {
|
||||
assert (yy_top_state () != INITIAL);
|
||||
YY_GROW;
|
||||
yy_pop_state ();
|
||||
}
|
||||
|
||||
[^\[\]\"\n\r\\]+ YY_GROW;
|
||||
\\. YY_GROW;
|
||||
|
||||
{eols} YY_GROW; YY_LINES;
|
||||
|
||||
<<EOF>> {
|
||||
LOCATION_PRINT (stderr, *yylloc);
|
||||
fprintf (stderr, ": unexpected end of file in a string\n");
|
||||
assert (yy_top_state () != INITIAL);
|
||||
yy_pop_state ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------.
|
||||
| Strings, comments etc. can be found in user code. |
|
||||
`---------------------------------------------------*/
|
||||
|
||||
<SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
|
||||
{
|
||||
/* Characters. We don't check there is only one. */
|
||||
\' YY_GROW; yy_push_state (SC_CHARACTER);
|
||||
|
||||
/* Strings. */
|
||||
\" YY_GROW; yy_push_state (SC_STRING);
|
||||
|
||||
/* Comments. */
|
||||
"/*" YY_GROW; yy_push_state (SC_COMMENT);
|
||||
"//".* YY_GROW;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------.
|
||||
| Scanning some code in braces (%union and actions). The initial |
|
||||
| "{" is already eaten. |
|
||||
`---------------------------------------------------------------*/
|
||||
|
||||
<SC_BRACED_CODE>
|
||||
{
|
||||
"}" {
|
||||
YY_GROW;
|
||||
if (--braces_level == 0)
|
||||
{
|
||||
yy_pop_state ();
|
||||
YY_FINISH;
|
||||
return BRACED_CODE;
|
||||
}
|
||||
}
|
||||
|
||||
"{" YY_GROW; braces_level++;
|
||||
|
||||
"$"("<".*">")?(-?[0-9]+|"$") { handle_dollar (yytext); }
|
||||
"@"(-?[0-9]+|"$") { handle_at (yytext); }
|
||||
|
||||
[^\[\]$/\'\"@\{\}\n\r]+ YY_GROW;
|
||||
{eols} YY_GROW; YY_LINES;
|
||||
|
||||
/* A lose $, or /, or etc. */
|
||||
. YY_GROW;
|
||||
|
||||
<<EOF>> {
|
||||
LOCATION_PRINT (stderr, *yylloc);
|
||||
fprintf (stderr, ": unexpected end of file in a braced code\n");
|
||||
yy_pop_state ();
|
||||
YY_FINISH;
|
||||
return PROLOGUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------.
|
||||
| Scanning some prologue: from "%{" (already scanned) to "%}". |
|
||||
`--------------------------------------------------------------*/
|
||||
|
||||
<SC_PROLOGUE>
|
||||
{
|
||||
"%}" {
|
||||
yy_pop_state ();
|
||||
YY_FINISH;
|
||||
return PROLOGUE;
|
||||
}
|
||||
|
||||
[^\[\]%\n\r]+ YY_GROW;
|
||||
"%"+[^%\}\n\r]+ YY_GROW;
|
||||
{eols} YY_GROW; YY_LINES;
|
||||
|
||||
<<EOF>> {
|
||||
LOCATION_PRINT (stderr, *yylloc);
|
||||
fprintf (stderr, ": unexpected end of file in a prologue\n");
|
||||
yy_pop_state ();
|
||||
YY_FINISH;
|
||||
return PROLOGUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------.
|
||||
| Scanning the epilogue (everything after the second "%%", which |
|
||||
| has already been eaten. |
|
||||
`---------------------------------------------------------------*/
|
||||
|
||||
<SC_EPILOGUE>
|
||||
{
|
||||
([^\[\]]|{eols})+ YY_GROW;
|
||||
|
||||
<<EOF>> {
|
||||
yy_pop_state ();
|
||||
YY_FINISH;
|
||||
return EPILOGUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
%%
|
||||
|
||||
/*------------------------------------------------------------------.
|
||||
| CP is pointing to a wannabee semantic value (i.e., a `$'). |
|
||||
| |
|
||||
| Possible inputs: $[<TYPENAME>]($|integer) |
|
||||
| |
|
||||
| Output to the STRING_OBSTACK a reference to this semantic value. |
|
||||
`------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
handle_dollar (char *cp)
|
||||
{
|
||||
const char *type_name = NULL;
|
||||
|
||||
/* RULE_LENGTH 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. It is not the same as the rule->length in the case of mid
|
||||
rule actions. */
|
||||
int rule_length = 0;
|
||||
symbol_list *rhs;
|
||||
for (rhs = current_rule->next; rhs; rhs = rhs->next)
|
||||
++rule_length;
|
||||
|
||||
++cp;
|
||||
|
||||
/* Get the type name if explicit. */
|
||||
if (*cp == '<')
|
||||
{
|
||||
type_name = ++cp;
|
||||
while (*cp != '>')
|
||||
++cp;
|
||||
*cp = '\0';
|
||||
++cp;
|
||||
}
|
||||
|
||||
if (*cp == '$')
|
||||
{
|
||||
if (!type_name)
|
||||
type_name = get_type_name (0, current_rule);
|
||||
if (!type_name && typed)
|
||||
complain (_("$$ of `%s' has no declared type"),
|
||||
current_rule->sym->tag);
|
||||
if (!type_name)
|
||||
type_name = "";
|
||||
obstack_fgrow1 (&string_obstack,
|
||||
"]b4_lhs_value([%s])[", type_name);
|
||||
}
|
||||
else if (isdigit (*cp) || *cp == '-')
|
||||
{
|
||||
int n = strtol (cp, &cp, 10);
|
||||
|
||||
if (n > rule_length)
|
||||
complain (_("invalid value: %s%d"), "$", n);
|
||||
else
|
||||
{
|
||||
if (!type_name && n > 0)
|
||||
type_name = get_type_name (n, current_rule);
|
||||
if (!type_name && typed)
|
||||
complain (_("$%d of `%s' has no declared type"),
|
||||
n, current_rule->sym->tag);
|
||||
if (!type_name)
|
||||
type_name = "";
|
||||
obstack_fgrow3 (&string_obstack,
|
||||
"]b4_rhs_value([%d], [%d], [%s])[",
|
||||
rule_length, n, type_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[] = "$c";
|
||||
buf[1] = *cp;
|
||||
complain (_("%s is invalid"), quote (buf));
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------.
|
||||
| CP is pointing to a location (i.e., a `@'). Output to |
|
||||
| STRING_OBSTACK a reference to this location. |
|
||||
`-------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
handle_at (char *cp)
|
||||
{
|
||||
/* RULE_LENGTH 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. It is not the same as the rule->length in the case of mid
|
||||
rule actions. */
|
||||
int rule_length = 0;
|
||||
symbol_list *rhs;
|
||||
for (rhs = current_rule->next; rhs; rhs = rhs->next)
|
||||
++rule_length;
|
||||
|
||||
locations_flag = 1;
|
||||
++cp;
|
||||
|
||||
if (*cp == '$')
|
||||
{
|
||||
obstack_sgrow (&string_obstack, "]b4_lhs_location[");
|
||||
}
|
||||
else if (isdigit (*cp) || *cp == '-')
|
||||
{
|
||||
int n = strtol (cp, &cp, 10);
|
||||
if (n > rule_length)
|
||||
complain (_("invalid value: %s%d"), "@", n);
|
||||
else
|
||||
obstack_fgrow2 (&string_obstack, "]b4_rhs_location([%d], [%d])[",
|
||||
rule_length, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[] = "@c";
|
||||
buf[1] = *cp;
|
||||
complain (_("%s is invalid"), quote (buf));
|
||||
}
|
||||
}
|
||||
49
src/symtab.c
49
src/symtab.c
@@ -54,36 +54,46 @@ symbol_new (const char *tag)
|
||||
res->class = unknown_sym;
|
||||
|
||||
nsyms++;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------.
|
||||
| Set the TYPE_NAME associated to SYMBOL. |
|
||||
`-----------------------------------------*/
|
||||
/*------------------------------------------------------------------.
|
||||
| Set the TYPE_NAME associated to SYMBOL. Does nothing if passed 0 |
|
||||
| as TYPE_NAME. |
|
||||
`------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
symbol_type_set (symbol_t *symbol, char *type_name)
|
||||
{
|
||||
if (symbol->type_name)
|
||||
complain (_("type redeclaration for %s"), symbol->tag);
|
||||
symbol->type_name = type_name;
|
||||
if (type_name)
|
||||
{
|
||||
if (symbol->type_name)
|
||||
complain (_("type redeclaration for %s"), symbol->tag);
|
||||
symbol->type_name = type_name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------.
|
||||
| Set the PRECEDENCE associated to SYMBOL. |
|
||||
`------------------------------------------*/
|
||||
/*------------------------------------------------------------------.
|
||||
| Set the PRECEDENCE associated to SYMBOL. Does nothing if invoked |
|
||||
| with UNDEF_ASSOC as ASSOC. |
|
||||
`------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
symbol_precedence_set (symbol_t *symbol,
|
||||
int prec, associativity assoc)
|
||||
{
|
||||
if (symbol->prec != 0)
|
||||
complain (_("redefining precedence of %s"), symbol->tag);
|
||||
symbol->prec = prec;
|
||||
symbol->assoc = assoc;
|
||||
if (assoc != undef_assoc)
|
||||
{
|
||||
if (symbol->prec != 0)
|
||||
complain (_("redefining precedence of %s"), symbol->tag);
|
||||
symbol->prec = prec;
|
||||
symbol->assoc = assoc;
|
||||
}
|
||||
|
||||
/* Only terminals have a precedence. */
|
||||
symbol_class_set (symbol, token_sym);
|
||||
}
|
||||
|
||||
|
||||
@@ -176,7 +186,7 @@ symbol_check_defined (symbol_t *this)
|
||||
`-------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
symbol_make_alias (symbol_t *symbol, symbol_t *symval, char *typename)
|
||||
symbol_make_alias (symbol_t *symbol, symbol_t *symval)
|
||||
{
|
||||
if (symval->alias)
|
||||
warn (_("symbol `%s' used more than once as a literal string"),
|
||||
@@ -187,7 +197,6 @@ symbol_make_alias (symbol_t *symbol, symbol_t *symval, char *typename)
|
||||
else
|
||||
{
|
||||
symval->class = token_sym;
|
||||
symval->type_name = typename;
|
||||
symval->user_token_number = symbol->user_token_number;
|
||||
symbol->user_token_number = USER_NUMBER_ALIAS;
|
||||
symval->alias = symbol;
|
||||
@@ -226,8 +235,12 @@ symbol_check_alias_consistence (symbol_t *this)
|
||||
|
||||
if (this->assoc != this->alias->assoc)
|
||||
{
|
||||
if (this->assoc != 0 && this->alias->assoc != 0)
|
||||
complain (_("conflicting assoc values for %s and %s"),
|
||||
/* FIXME: For some reason (probably the S/R => keep the S),
|
||||
the right assoc is chosen has the ``not set''. This is
|
||||
not nice, fix this! */
|
||||
if (this->assoc != right_assoc
|
||||
&& this->alias->assoc != right_assoc)
|
||||
complain (_("conflicting associativities for %s and %s"),
|
||||
this->tag, this->alias->tag);
|
||||
if (this->assoc != 0)
|
||||
this->alias->assoc = this->assoc;
|
||||
|
||||
17
src/symtab.h
17
src/symtab.h
@@ -29,6 +29,7 @@
|
||||
/* Associativity values for tokens and rules. */
|
||||
typedef enum
|
||||
{
|
||||
undef_assoc,
|
||||
right_assoc,
|
||||
left_assoc,
|
||||
non_assoc
|
||||
@@ -84,15 +85,15 @@ struct symbol_s
|
||||
/* Fetch (or create) the symbol associated to KEY. */
|
||||
symbol_t *getsym PARAMS ((const char *key));
|
||||
|
||||
/* Declare the new SYMBOL. Make it an alias of SYMVAL, and type */
|
||||
/* them with TYPENAME. */
|
||||
void symbol_make_alias PARAMS ((symbol_t *symbol, symbol_t *symval,
|
||||
char *typename));
|
||||
/* Declare the new SYMBOL. Make it an alias of SYMVAL. */
|
||||
void symbol_make_alias PARAMS ((symbol_t *symbol, symbol_t *symval));
|
||||
|
||||
/* Set the TYPE_NAME associated to SYMBOL. */
|
||||
/* Set the TYPE_NAME associated to SYMBOL. Does nothing if passed 0 as
|
||||
TYPE_NAME. */
|
||||
void symbol_type_set PARAMS ((symbol_t *symbol, char *type_name));
|
||||
|
||||
/* Set the PRECEDENCE associated to SYMBOL. */
|
||||
/* Set the PRECEDENCE associated to SYMBOL. Ensures that SYMBOL is a
|
||||
terminal. Does nothing if invoked with UNDEF_ASSOC as ASSOC. */
|
||||
void symbol_precedence_set PARAMS ((symbol_t *symbol,
|
||||
int prec, associativity assoc));
|
||||
|
||||
@@ -131,8 +132,8 @@ void symbols_do PARAMS ((symbol_processor processor, void *processor_data));
|
||||
/* Free all the memory allocated for symbols. */
|
||||
void symbols_free PARAMS ((void));
|
||||
|
||||
/* Check that all the symbols are defined. Report any undefined */
|
||||
/* symbols and consider them nonterminals. */
|
||||
/* Check that all the symbols are defined. Report any undefined
|
||||
symbols and consider them nonterminals. */
|
||||
void symbols_check_defined PARAMS ((void));
|
||||
|
||||
/* Perform various sanity checks, assign symbol numbers, and set up
|
||||
|
||||
20
src/system.h
20
src/system.h
@@ -144,14 +144,22 @@ void *memrchr PARAMS ((const void *s, int c, size_t n));
|
||||
(__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
|
||||
# define __attribute__(Spec) /* empty */
|
||||
# endif
|
||||
/* The __-protected variants of `format' and `printf' attributes
|
||||
are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
|
||||
# define __format__ format
|
||||
# define __printf__ printf
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The __-protected variants of `format' and `printf' attributes
|
||||
are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
|
||||
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
|
||||
# define __format__ format
|
||||
# define __printf__ printf
|
||||
#endif
|
||||
|
||||
#ifndef ATTRIBUTE_NORETURN
|
||||
# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
|
||||
#endif
|
||||
|
||||
#ifndef ATTRIBUTE_UNUSED
|
||||
# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
|
||||
#endif
|
||||
|
||||
/*------.
|
||||
| NLS. |
|
||||
|
||||
@@ -89,7 +89,7 @@ char quote[] = "@:>@@:>@,";
|
||||
%type <ival> exp
|
||||
|
||||
/* Exercise quotes in strings. */
|
||||
%token "fake @>:@@>:@,"
|
||||
%token FAKE "fake @>:@@>:@,"
|
||||
|
||||
%nonassoc '=' /* comparison */
|
||||
%left '-' '+'
|
||||
|
||||
@@ -204,6 +204,7 @@ not_reachable: useful { /* A not reachable action. */ }
|
||||
non_productive: non_productive useless_token
|
||||
{ /* Another non productive action. */ }
|
||||
;
|
||||
%%
|
||||
]])
|
||||
|
||||
AT_CHECK([[bison not-reduced.y]], 0, [],
|
||||
@@ -244,6 +245,7 @@ exp: useful { /* A useful action. */ }
|
||||
//non_productive: non_productive useless_token
|
||||
// { /* Another non productive action. */ }
|
||||
// ;
|
||||
%%
|
||||
]])
|
||||
|
||||
AT_CHECK([[bison reduced.y]])
|
||||
|
||||
@@ -287,40 +287,23 @@ AT_DATA([input.y],
|
||||
[[%%
|
||||
?
|
||||
default: 'a' }
|
||||
%{
|
||||
%&
|
||||
%a
|
||||
%-
|
||||
%{
|
||||
]])
|
||||
|
||||
AT_CHECK([bison input.y], [1], [],
|
||||
[[input.y:2: invalid input: `?'
|
||||
input.y:3: invalid input: `}'
|
||||
input.y:4: invalid input: `%{'
|
||||
input.y:5: invalid input: `%&'
|
||||
input.y:6: invalid input: `%a'
|
||||
input.y:7: invalid input: `%-'
|
||||
]])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
|
||||
## -------------------- ##
|
||||
## Invalid %directive. ##
|
||||
## -------------------- ##
|
||||
|
||||
|
||||
AT_SETUP([Invalid %directive])
|
||||
|
||||
AT_DATA([input.y],
|
||||
[[%invalid
|
||||
]])
|
||||
|
||||
AT_CHECK([bison input.y], [1], [],
|
||||
[[input.y:1: unrecognized: %invalid
|
||||
input.y:1: Skipping to next %
|
||||
input.y:2: fatal error: no input grammar
|
||||
[[input.y:2.1: invalid character: `?'
|
||||
input.y:3.14: invalid character: `}'
|
||||
input.y:4.1: invalid character: `%'
|
||||
input.y:4.2: invalid character: `&'
|
||||
input.y:5.1: invalid character: `%'
|
||||
input.y:6.1: invalid character: `%'
|
||||
input.y:6.2: invalid character: `-'
|
||||
input.y:7.1-8.0: unexpected end of file in a prologue
|
||||
input.y:7.1-8.0: parse error, unexpected PROLOGUE, expecting ";" or "|"
|
||||
input.y:8: symbol a is used, but is not defined as a token and has no rules
|
||||
]])
|
||||
|
||||
AT_CLEANUP
|
||||
@@ -340,13 +323,11 @@ AT_DATA([input.y],
|
||||
void yyerror (const char *s);
|
||||
int yylex (void);
|
||||
%}
|
||||
[%token "end of file"
|
||||
[%token YYEOF 0 "end of file"
|
||||
%token 'a' "a"
|
||||
%token "b" 'b'
|
||||
%token "c" c
|
||||
%token d "d"
|
||||
%token e 'e'
|
||||
%token 'f' e
|
||||
%token b "b"
|
||||
%token c 'c'
|
||||
%token 'd' d
|
||||
%%
|
||||
exp: "a";
|
||||
]])
|
||||
|
||||
@@ -33,7 +33,7 @@ AT_DATA([[input.y]],
|
||||
[$2])
|
||||
|
||||
AT_CHECK([bison input.y -o input.c])
|
||||
AT_CHECK([$CC $CFLAGS $CPPFLAGS input.c -o input], 1, [], [stderr])
|
||||
AT_CHECK([$CC $CFLAGS $CPPFLAGS input.c -c], 1, [], [stderr])
|
||||
# In case GCC displays column information, strip it down.
|
||||
#
|
||||
# input.y:4:2: #error "4" or input.y:4.2: #error "4"
|
||||
|
||||
@@ -57,7 +57,7 @@ EOF
|
||||
|
||||
for my $size (1 .. $max)
|
||||
{
|
||||
print "%token \"$size\" ", $size, "\n";
|
||||
print "%token t$size $size \"$size\"\n";
|
||||
};
|
||||
|
||||
print <<EOF;
|
||||
@@ -128,7 +128,9 @@ AT_SETUP([Big triangle])
|
||||
|
||||
# I have been able to go up to 2000 on my machine.
|
||||
# I tried 3000, a 29Mb grammar file, but then my system killed bison.
|
||||
AT_DATA_TRIANGULAR_GRAMMAR([input.y], [500])
|
||||
# With 500 and the new parser, which consume far too much memory,
|
||||
# it gets killed too. Of course the parser is to be cleaned.
|
||||
AT_DATA_TRIANGULAR_GRAMMAR([input.y], [200])
|
||||
AT_CHECK([bison input.y -v -o input.c])
|
||||
AT_CHECK([$CC $CFLAGS $CPPFLAGS input.c -o input], 0, [], [ignore])
|
||||
AT_CHECK([./input])
|
||||
@@ -164,7 +166,7 @@ EOF
|
||||
|
||||
for my $size (1 .. $max)
|
||||
{
|
||||
print "%token \"$size\" ", $size, "\n";
|
||||
print "%token t$size $size \"$size\"\n";
|
||||
};
|
||||
|
||||
print <<EOF;
|
||||
@@ -272,12 +274,12 @@ EOF
|
||||
print
|
||||
wrap ("%type <val> ",
|
||||
" ",
|
||||
map { "token$_" } (1 .. $max)),
|
||||
map { "n$_" } (1 .. $max)),
|
||||
"\n";
|
||||
|
||||
for my $count (1 .. $max)
|
||||
{
|
||||
print "%token \"$count\" $count\n";
|
||||
print "%token t$count $count \"$count\"\n";
|
||||
};
|
||||
|
||||
print <<EOF;
|
||||
@@ -288,18 +290,18 @@ input:
|
||||
;
|
||||
|
||||
exp:
|
||||
token1 "1" { assert (\@S|@1 == 1); }
|
||||
n1 "1" { assert (\@S|@1 == 1); }
|
||||
EOF
|
||||
|
||||
for my $count (2 .. $max)
|
||||
{
|
||||
print "| token$count \"$count\" { assert (\@S|@1 == $count); }\n";
|
||||
print "| n$count \"$count\" { assert (\@S|@1 == $count); }\n";
|
||||
};
|
||||
print ";\n";
|
||||
|
||||
for my $count (1 .. $max)
|
||||
{
|
||||
print "token$count: token { \$\$ = $count; };\n";
|
||||
print "n$count: token { \$\$ = $count; };\n";
|
||||
};
|
||||
|
||||
print <<EOF;
|
||||
|
||||
Reference in New Issue
Block a user