X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/ab7f29f8f9a7ad89b6a3163f913e1ee2b7889223..d4fe9e88f33f622f86907feb7b2690d354d92945:/src/parse-gram.y diff --git a/src/parse-gram.y b/src/parse-gram.y index 72f5eefa..5f77a5bd 100644 --- a/src/parse-gram.y +++ b/src/parse-gram.y @@ -1,7 +1,6 @@ %{/* Bison Grammar Parser -*- C -*- - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software - Foundation, Inc. + Copyright (C) 2002-2012 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -21,19 +20,20 @@ #include #include "system.h" -#include - +#include "c-ctype.h" #include "complain.h" #include "conflicts.h" #include "files.h" #include "getargs.h" #include "gram.h" -#include "muscle_tab.h" +#include "muscle-tab.h" +#include "named-ref.h" #include "quotearg.h" #include "reader.h" #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); @@ -63,10 +63,30 @@ static void add_param (char const *type, char *decl, location loc); static symbol_class current_class = unknown_sym; static uniqstr current_type = NULL; -static symbol *current_lhs; +static symbol *current_lhs_symbol; static location current_lhs_location; +static named_ref *current_lhs_named_ref; static int current_prec = 0; +/** 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 @@ -74,13 +94,14 @@ static int current_prec = 0; %} %debug -%verbose +%define api.prefix "gram_" +%define api.pure +%define parse.lac full %defines -%locations -%pure-parser %error-verbose -%name-prefix="gram_" %expect 0 +%locations +%verbose %initial-action { @@ -100,6 +121,7 @@ static int current_prec = 0; assoc assoc; uniqstr uniqstr; unsigned char character; + named_ref *named_ref; }; /* Define the tokens together with their human representation. */ @@ -159,6 +181,7 @@ static int current_prec = 0; ; %token BRACED_CODE "{...}" +%token BRACKETED_ID "[identifier]" %token CHAR "char" %token EPILOGUE "epilogue" %token EQUAL "=" @@ -184,20 +207,23 @@ static int current_prec = 0; %printer { fprintf (stderr, "{\n%s\n}", $$); } braceless content.opt "{...}" "%{...%}" EPILOGUE -%type TYPE ID ID_COLON variable -%printer { fprintf (stderr, "<%s>", $$); } TYPE -%printer { fputs ($$, stderr); } ID variable +%type BRACKETED_ID ID ID_COLON TYPE variable +%printer { fputs ($$, stderr); } +%printer { fprintf (stderr, "[%s]", $$); } BRACKETED_ID %printer { fprintf (stderr, "%s:", $$); } ID_COLON +%printer { fprintf (stderr, "<%s>", $$); } TYPE %type INT -%printer { fprintf (stderr, "%d", $$); } INT +%printer { fprintf (stderr, "%d", $$); } -%type id id_colon symbol symbol.prec string_as_id -%printer { fprintf (stderr, "%s", $$->tag); } id symbol string_as_id +%type id id_colon string_as_id symbol symbol.prec +%printer { fprintf (stderr, "%s", $$->tag); } %printer { fprintf (stderr, "%s:", $$->tag); } id_colon %type precedence_declarator %type symbols.1 symbols.prec generic_symlist generic_symlist_item +%type named_ref.opt + %% input: @@ -226,10 +252,11 @@ prologue_declaration: plain_code.code, @1); code_scanner_last_string_free (); } -| "%debug" { debug_flag = true; } +| "%debug" { debug = true; } | "%define" variable content.opt { - muscle_percent_define_insert ($2, @2, $3); + muscle_percent_define_insert ($2, @2, $3, + MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); } | "%defines" { defines_flag = true; } | "%defines" STRING @@ -256,7 +283,7 @@ prologue_declaration: muscle_code_grow ("initial_action", action.code, @2); code_scanner_last_string_free (); } -| "%language" STRING { language_argmatch ($2, 1, &@1); } +| "%language" STRING { language_argmatch ($2, grammar_prio, @1); } | "%lex-param" "{...}" { add_param ("lex_param", $2, @2); } | "%locations" { locations_flag = true; } | "%name-prefix" STRING { spec_name_prefix = $2; } @@ -272,18 +299,20 @@ prologue_declaration: `%define api.pure' in a backward-compatible manner here. First, don't complain if %pure-parser is specified multiple times. */ if (!muscle_find_const ("percent_define(api.pure)")) - muscle_percent_define_insert ("api.pure", @1, ""); + muscle_percent_define_insert ("api.pure", @1, "", + MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); /* In all cases, use api.pure now so that the backend doesn't complain if the skeleton ignores api.pure, but do warn now if there's a previous conflicting definition from an actual %define. */ if (!muscle_percent_define_flag_if ("api.pure")) - muscle_percent_define_insert ("api.pure", @1, ""); + muscle_percent_define_insert ("api.pure", @1, "", + MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); } | "%require" STRING { version_check (&@2, $2); } | "%skeleton" STRING { char const *skeleton_user = $2; - if (strchr (skeleton_user, '/')) + if (mbschr (skeleton_user, '/')) { size_t dir_length = strlen (current_file); char *skeleton_build; @@ -295,14 +324,14 @@ prologue_declaration: 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); skeleton_user = uniqstr_new (skeleton_build); free (skeleton_build); } - skeleton_arg (skeleton_user, 1, &@1); + skeleton_arg (skeleton_user, grammar_prio, @1); } | "%token-table" { token_table_flag = true; } | "%verbose" { report_flag |= report_states; } @@ -319,17 +348,27 @@ grammar_declaration: } | "%destructor" "{...}" generic_symlist { - symbol_list *list; - for (list = $3; list; list = list->next) - symbol_list_destructor_set (list, $2, @2); - symbol_list_free ($3); + code_props code; + code_props_symbol_action_init (&code, $2, @2); + code_props_translate_code (&code); + { + symbol_list *list; + for (list = $3; list; list = list->next) + symbol_list_destructor_set (list, &code); + 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_free ($3); + code_props code; + code_props_symbol_action_init (&code, $2, @2); + code_props_translate_code (&code); + { + symbol_list *list; + for (list = $3; list; list = list->next) + symbol_list_printer_set (list, &code); + symbol_list_free ($3); + } } | "%default-prec" { @@ -518,7 +557,11 @@ rules_or_grammar_declaration: ; rules: - id_colon { current_lhs = $1; current_lhs_location = @1; } 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: @@ -529,11 +572,12 @@ rhses.1: rhs: /* Nothing. */ - { grammar_current_rule_begin (current_lhs, current_lhs_location); } -| rhs symbol - { grammar_current_rule_symbol_append ($2, @2); } -| rhs "{...}" - { grammar_current_rule_action_append ($2, @2); } + { 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); } | rhs "%prec" symbol { grammar_current_rule_prec_set ($3, @3); } | rhs "%dprec" INT @@ -542,22 +586,28 @@ rhs: { grammar_current_rule_merge_set ($3, @3); } ; +named_ref.opt: + /* Nothing. */ { $$ = 0; } +| + BRACKETED_ID { $$ = named_ref_new($1, @1); } +; + /*----------------------------* | variable and content.opt. | *---------------------------*/ +/* The STRING form of variable is deprecated and is not M4-friendly. + For example, M4 fails for `%define "[" "value"'. */ variable: ID - | STRING { $$ = uniqstr_new ($1); } /* deprecated and not M4-friendly */ - ; +| STRING { $$ = uniqstr_new ($1); } +; /* Some content or empty by default. */ content.opt: - /* Nothing. */ - { - $$ = ""; - } + /* Nothing. */ { $$ = ""; } +| ID { $$ = $1; } | STRING ; @@ -648,7 +698,7 @@ lloc_default (YYLTYPE const *rhs, int n) 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++) @@ -685,27 +735,19 @@ add_param (char const *type, char *decl, location loc) /* Strip the surrounding '{' and '}', and any blanks just inside the braces. */ - while (*--p == ' ' || *p == '\t') - continue; + --p; + while (c_isspace ((unsigned char) *p)) + --p; p[1] = '\0'; - while (*++decl == ' ' || *decl == '\t') - continue; + ++decl; + while (c_isspace ((unsigned char) *decl)) + ++decl; if (! name_start) 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)); muscle_pair_list_grow (type, decl, name); free (name); } @@ -720,8 +762,8 @@ version_check (location const *loc, char const *version) 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); } }