X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/95612cfa608188fc323ed3f8560cc6aea953ff32..557962dcffa32e77f7bac052904200f17edc60fd:/src/parse-gram.y diff --git a/src/parse-gram.y b/src/parse-gram.y index 74a6574f..e241b716 100644 --- a/src/parse-gram.y +++ b/src/parse-gram.y @@ -40,39 +40,24 @@ #include "reader.h" #include "conflicts.h" -/* Produce verbose parse errors. */ +/* Produce verbose syntax errors. */ #define YYERROR_VERBOSE 1 -#define YYLLOC_DEFAULT(Current, Rhs, N) \ -do { \ - if (N) \ - { \ - Current.first_column = Rhs[1].first_column; \ - Current.first_line = Rhs[1].first_line; \ - Current.last_column = Rhs[N].last_column; \ - Current.last_line = Rhs[N].last_line; \ - } \ - else \ - { \ - Current = Rhs[0]; \ - } \ -} while (0) - -/* 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. - FIXME: depends on the undocumented availability of YYLLOC.t */ + +#define YYLLOC_DEFAULT(Current, Rhs, N) (Current) = lloc_default (Rhs, N) +static YYLTYPE lloc_default (YYLTYPE const *, int); + +/* Request detailed syntax error messages, and pass them to GRAM_ERROR. + FIXME: depends on the undocumented availability of YYLLOC. */ #undef yyerror #define yyerror(Msg) \ gram_error (&yylloc, Msg) +static void gram_error (location_t const *, char const *); #define YYPRINT(File, Type, Value) \ - yyprint (File, Type, &Value) -static void yyprint (FILE *file, int type, const yystype *value); + print_token_value (File, Type, &Value) +static void print_token_value (FILE *, int, YYSTYPE const *); + +static void add_param (char const *, char const *, location_t); symbol_class current_class = unknown_sym; struniq_t current_type = 0; @@ -147,10 +132,9 @@ braced_code_t current_braced_code = action_braced_code; %token TYPE "type" %token EQUAL "=" %token SEMICOLON ";" -%token COLON ":" -%token COMMA "," %token PIPE "|" %token ID "identifier" +%token ID_COLON "identifier:" %token PERCENT_PERCENT "%%" %token PROLOGUE "%{...%}" %token EPILOGUE "epilogue" @@ -158,20 +142,17 @@ braced_code_t current_braced_code = action_braced_code; %type STRING string_content - BRACED_CODE PROLOGUE EPILOGUE epilogue.opt action + BRACED_CODE code_content action + PROLOGUE EPILOGUE %type TYPE %type INT -%type ID symbol string_as_id +%type ID ID_COLON symbol string_as_id %type precedence_declarator %type symbols.1 %% input: declarations "%%" grammar epilogue.opt - { - yycontrol->errcode = 0; - epilogue_set ($4, @4); - } ; @@ -181,7 +162,7 @@ input: declarations: /* Nothing */ -| declarations declaration semi_colon.opt +| declarations declaration ; declaration: @@ -194,19 +175,18 @@ declaration: | "%expect" INT { expected_conflicts = $2; } | "%file-prefix" "=" string_content { spec_file_prefix = $3; } | "%glr-parser" { glr_parser = 1; } -| "%lex-param" string_content "," string_content - { muscle_pair_list_grow ("lex_param", $2, $4); } +| "%lex-param" code_content { add_param ("lex_param", $2, @2); } | "%locations" { locations_flag = 1; } | "%name-prefix" "=" string_content { spec_name_prefix = $3; } | "%no-lines" { no_lines_flag = 1; } | "%output" "=" string_content { spec_outfile = $3; } -| "%parse-param" string_content "," string_content - { muscle_pair_list_grow ("parse_param", $2, $4); } +| "%parse-param" code_content { add_param ("parse_param", $2, @2); } | "%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_declaration: @@ -219,7 +199,7 @@ grammar_declaration: | "%union" BRACED_CODE { typed = 1; - MUSCLE_INSERT_INT ("stype_line", @2.first_line); + MUSCLE_INSERT_INT ("stype_line", @2.start.line); muscle_insert ("stype", $2); } | "%destructor" @@ -332,9 +312,7 @@ symbol_def: /* One or more symbol definitions. */ symbol_defs.1: symbol_def - {;} | symbol_defs.1 symbol_def - {;} ; @@ -348,11 +326,10 @@ grammar: ; /* As a Bison extension, one can use the grammar declarations in the - body of the grammar. But to remain LALR(1), they must be ended - with a semi-colon. */ + body of the grammar. */ rules_or_grammar_declaration: rules -| grammar_declaration ";" +| grammar_declaration { if (yacc_flag) complain_at (@$, _("POSIX forbids declarations in the grammar")); @@ -361,11 +338,11 @@ rules_or_grammar_declaration: { yyerrok; } +| ";" ; rules: - ID ":" { current_lhs = $1; current_lhs_location = @1; } rhses.1 ";" - {;} + ID_COLON { current_lhs = $1; current_lhs_location = @1; } rhses.1 ; rhses.1: @@ -416,29 +393,104 @@ string_content: }; +/* A BRACED_CODE used for its contents. Strip the braces. */ +code_content: + BRACED_CODE + { + $$ = $1 + 1; + $$[strlen ($$) - 1] = '\0'; + }; + + epilogue.opt: /* Nothing. */ - { - $$ = xstrdup (""); - } | "%%" EPILOGUE { - $$ = $2; + epilogue_augment ($2, @2); + scanner_last_string_free (); } ; -semi_colon.opt: - /* Nothing. */ -| ";" -; %% + + +/* Return the location of the left-hand side of a rule whose + right-hand side is RHS[1] ... RHS[N]. Ignore empty nonterminals in + the right-hand side, and return an empty location equal to the end + boundary of RHS[0] if the right-hand side is empty. */ + +static YYLTYPE +lloc_default (YYLTYPE const *rhs, int n) +{ + int i; + int j; + YYLTYPE r; + r.start = r.end = rhs[n].end; + + for (i = 1; i <= n; i++) + if (! equal_boundaries (rhs[i].start, rhs[i].end)) + { + r.start = rhs[i].start; + + for (j = n; i < j; j--) + if (! equal_boundaries (rhs[j].start, rhs[j].end)) + break; + r.end = rhs[j].end; + + break; + } + + return r; +} + + +/* Add a lex-param or a parse-param (depending on TYPE) with + declaration DECL and location LOC. */ + +static void +add_param (char const *type, char const *decl, location_t loc) +{ + static char const alphanum[] = + "0123456789" + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "_"; + char const *alpha = alphanum + 10; + char const *name_start = NULL; + char const *p; + + for (p = decl; *p; p++) + if ((p == decl || ! strchr (alphanum, p[-1])) && strchr (alpha, p[0])) + name_start = p; + + if (! name_start) + complain_at (loc, _("missing identifier in parameter declaration")); + else + { + char *name; + size_t name_len; + + for (name_len = 1; + name_start[name_len] && strchr (alphanum, name_start[name_len]); + name_len++) + continue; + + name = xmalloc (name_len + 1); + memcpy (name, name_start, name_len); + name[name_len] = '\0'; + muscle_pair_list_grow (type, decl, name); + free (name); + } + + scanner_last_string_free (); +} + /*------------------------------------------------------------------. | When debugging the parser, display tokens' locations and values. | `------------------------------------------------------------------*/ static void -yyprint (FILE *file, - int type, const yystype *value) +print_token_value (FILE *file, int type, YYSTYPE const *value) { fputc (' ', file); switch (type) @@ -464,11 +516,15 @@ yyprint (FILE *file, case EPILOGUE: fprintf (file, " = {{ %s }}", value->string); break; + + default: + fprintf (file, "unknown token type"); + break; } } -void -gram_error (location_t *yylloc, const char *msg) +static void +gram_error (location_t const *loc, char const *msg) { - complain_at (*yylloc, "%s", msg); + complain_at (*loc, "%s", msg); }