%{/* Bison Grammar Parser -*- C -*-
- Copyright (C) 2002-2011 Free Software Foundation, Inc.
+ Copyright (C) 2002-2012 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
#include "symlist.h"
#include "scan-gram.h"
#include "scan-code.h"
+#include "xmemdup0.h"
#define YYLLOC_DEFAULT(Current, Rhs, N) (Current) = lloc_default (Rhs, N)
static YYLTYPE lloc_default (YYLTYPE const *, int);
#define YY_LOCATION_PRINT(File, Loc) \
- location_print (File, Loc)
+ location_print (File, Loc)
static void version_check (location const *loc, char const *version);
FIXME: depends on the undocumented availability of YYLLOC. */
#undef yyerror
#define yyerror(Msg) \
- gram_error (&yylloc, Msg)
+ gram_error (&yylloc, Msg)
static void gram_error (location const *, char const *);
static char const *char_name (char);
static int current_prec = 0;
static location current_lhs_location;
static named_ref *current_lhs_named_ref;
- static symbol *current_lhs;
+ static symbol *current_lhs_symbol;
static symbol_class current_class = unknown_sym;
static uniqstr current_type = NULL;
+ /** Set the new current left-hand side symbol, possibly common
+ * to several right-hand side parts of rule.
+ */
+ static
+ void
+ current_lhs(symbol *sym, location loc, named_ref *ref)
+ {
+ current_lhs_symbol = sym;
+ current_lhs_location = loc;
+ /* In order to simplify memory management, named references for lhs
+ are always assigned by deep copy into the current symbol_list
+ node. This is because a single named-ref in the grammar may
+ result in several uses when the user factors lhs between several
+ rules using "|". Therefore free the parser's original copy. */
+ free (current_lhs_named_ref);
+ current_lhs_named_ref = ref;
+ }
+
#define YYTYPE_INT16 int_fast16_t
#define YYTYPE_INT8 int_fast8_t
#define YYTYPE_UINT16 uint_fast16_t
%type <chars> STRING "%{...%}" EPILOGUE braceless content.opt
%type <code> "{...}" "%?{...}"
%printer { fputs (quotearg_style (c_quoting_style, $$), stderr); }
- STRING
+ STRING
%printer { fprintf (stderr, "{\n%s\n}", $$); }
- braceless content.opt "{...}" "%{...%}" EPILOGUE
+ braceless content.opt "{...}" "%{...%}" EPILOGUE
%type <uniqstr> BRACKETED_ID ID ID_COLON PERCENT_FLAG TAG variable
%printer { fputs ($$, stderr); } <uniqstr>
;
- /*------------------------------------.
- | Declarations: before the first %%. |
- `------------------------------------*/
+ /*------------------------------------.
+ | Declarations: before the first %%. |
+ `------------------------------------*/
prologue_declarations:
/* Nothing */
MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
}
| "%expect" INT { expected_sr_conflicts = $2; }
-| "%expect-rr" INT { expected_rr_conflicts = $2; }
+| "%expect-rr" INT { expected_rr_conflicts = $2; }
| "%file-prefix" STRING { spec_file_prefix = $2; }
| "%file-prefix" "=" STRING { spec_file_prefix = $3; } /* deprecated */
| "%glr-parser"
muscle_code_grow ("initial_action", action.code, @2);
code_scanner_last_string_free ();
}
-| "%language" STRING { language_argmatch ($2, grammar_prio, @1); }
+| "%language" STRING { language_argmatch ($2, grammar_prio, @1); }
| "%name-prefix" STRING { spec_name_prefix = $2; }
| "%name-prefix" "=" STRING { spec_name_prefix = $3; } /* deprecated */
| "%no-lines" { no_lines_flag = true; }
-| "%nondeterministic-parser" { nondeterministic_parser = true; }
+| "%nondeterministic-parser" { nondeterministic_parser = true; }
| "%output" STRING { spec_outfile = $2; }
| "%output" "=" STRING { spec_outfile = $3; } /* deprecated */
| "%param" { current_param = $1; } params { current_param = param_none; }
xmalloc (dir_length + 1 + strlen (skeleton_user) + 1);
if (dir_length > 0)
{
- strncpy (skeleton_build, current_file, dir_length);
+ memcpy (skeleton_build, current_file, dir_length);
skeleton_build[dir_length++] = '/';
}
strcpy (skeleton_build + dir_length, skeleton_user);
{
symbol_list *list;
for (list = $3; list; list = list->next)
- symbol_list_destructor_set (list, $2, @2);
+ symbol_list_code_props_set (list, destructor, @2, $2);
symbol_list_free ($3);
}
| "%printer" "{...}" generic_symlist
{
symbol_list *list;
for (list = $3; list; list = list->next)
- symbol_list_printer_set (list, $2, @2);
+ symbol_list_code_props_set (list, printer, @2, $2);
symbol_list_free ($3);
}
| "%default-prec"
symbol_list *list;
tag_seen = true;
for (list = $3; list; list = list->next)
- symbol_type_set (list->content.sym, $2, @2);
+ symbol_type_set (list->content.sym, $2, @2);
symbol_list_free ($3);
}
;
symbol_list *list;
++current_prec;
for (list = $3; list; list = list->next)
- {
- symbol_type_set (list->content.sym, current_type, @2);
- symbol_precedence_set (list->content.sym, current_prec, $1, @1);
- }
+ {
+ symbol_type_set (list->content.sym, current_type, @2);
+ symbol_precedence_set (list->content.sym, current_prec, $1, @1);
+ }
symbol_list_free ($3);
current_type = NULL;
}
;
- /*------------------------------------------.
- | The grammar section: between the two %%. |
- `------------------------------------------*/
+ /*------------------------------------------.
+ | The grammar section: between the two %%. |
+ `------------------------------------------*/
grammar:
rules_or_grammar_declaration
;
rules:
- id_colon named_ref.opt { current_lhs = $1; current_lhs_location = @1;
- current_lhs_named_ref = $2; } rhses.1
+ id_colon named_ref.opt { current_lhs ($1, @1, $2); } rhses.1
+ {
+ /* Free the current lhs. */
+ current_lhs (0, @1, 0);
+ }
;
rhses.1:
rhs:
/* Nothing. */
- { grammar_current_rule_begin (current_lhs, current_lhs_location,
- current_lhs_named_ref); }
+ { grammar_current_rule_begin (current_lhs_symbol, current_lhs_location,
+ current_lhs_named_ref); }
| rhs symbol named_ref.opt
{ grammar_current_rule_symbol_append ($2, @2, $3); }
| rhs "{...}" named_ref.opt
{ grammar_current_rule_action_append ($2, @2, $3, false); }
-| rhs "%?{...}"
+| rhs "%?{...}"
{ grammar_current_rule_action_append ($2, @2, NULL, true); }
| rhs "%prec" symbol
{ grammar_current_rule_prec_set ($3, @3); }
loc.start = rhs[n].end;
loc.end = rhs[n].end;
- /* Ignore empty nonterminals the start of the the right-hand side.
+ /* Ignore empty nonterminals the start of the right-hand side.
Do not bother to ignore them at the end of the right-hand side,
since empty nonterminals have the same end as their predecessors. */
for (i = 1; i <= n; i++)
if (! equal_boundaries (rhs[i].start, rhs[i].end))
{
- loc.start = rhs[i].start;
- break;
+ loc.start = rhs[i].start;
+ break;
}
return loc;
complain_at (loc, _("missing identifier in parameter declaration"));
else
{
- char *name;
- size_t name_len;
-
- for (name_len = 1;
- memchr (alphanum, name_start[name_len], sizeof alphanum);
- name_len++)
- continue;
-
- name = xmalloc (name_len + 1);
- memcpy (name, name_start, name_len);
- name[name_len] = '\0';
+ char *name = xmemdup0 (name_start, strspn (name_start, alphanum));
if (type & param_lex)
muscle_pair_list_grow ("lex_param", decl, name);
if (type & param_parse)
if (strverscmp (version, PACKAGE_VERSION) > 0)
{
complain_at (*loc, "require bison %s, but have %s",
- version, PACKAGE_VERSION);
- exit (63);
+ version, PACKAGE_VERSION);
+ exit (EX_MISMATCH);
}
}