From 4d7370cb4fe960032afd4a42293b6d55e02237fe Mon Sep 17 00:00:00 2001 From: "Joel E. Denny" Date: Sun, 20 Aug 2006 03:10:18 +0000 Subject: [PATCH] Allow %start after the first rule. * src/reader.c (grammar_current_rule_begin): Don't set the start symbol when parsing the first rule. (check_and_convert_grammar): Search for it here after all grammar declarations have been parsed. Skip midrules, which have dummy LHS nonterminals. * src/symtab.c (symbol_is_dummy): New function. * src/symtab.h (symbol_is_dummy): Declare it. * tests/input.at (%start after first rule): New test. --- ChangeLog | 12 ++++++++++++ src/reader.c | 24 +++++++++++++++++------- src/symtab.c | 5 +++++ src/symtab.h | 3 +++ tests/input.at | 21 +++++++++++++++++++++ 5 files changed, 58 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3cc5679f..f8867cbc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2006-08-19 Joel E. Denny + + Allow %start after the first rule. + * src/reader.c (grammar_current_rule_begin): Don't set the start symbol + when parsing the first rule. + (check_and_convert_grammar): Search for it here after all grammar + declarations have been parsed. Skip midrules, which have dummy LHS + nonterminals. + * src/symtab.c (symbol_is_dummy): New function. + * src/symtab.h (symbol_is_dummy): Declare it. + * tests/input.at (%start after first rule): New test. + 2006-08-18 Joel E. Denny Redo some of the previous commit: add back the ability to use diff --git a/src/reader.c b/src/reader.c index 5084618f..d380d047 100644 --- a/src/reader.c +++ b/src/reader.c @@ -225,13 +225,6 @@ static symbol_list *previous_rule_end = NULL; void grammar_current_rule_begin (symbol *lhs, location loc) { - if (!start_flag) - { - startsymbol = lhs; - startsymbol_location = loc; - start_flag = true; - } - /* Start a new rule and record its lhs. */ ++nrules; previous_rule_end = grammar_end; @@ -607,6 +600,23 @@ check_and_convert_grammar (void) endtoken->user_token_number = 0; } + /* Find the start symbol if no %start. */ + if (!start_flag) + { + symbol_list *node; + for (node = grammar; + node != NULL && symbol_is_dummy (node->sym); + node = node->next) + { + for (node = node->next; + node != NULL && node->sym != NULL; + node = node->next) + ; + } + assert (node != NULL); + grammar_start_symbol_set (node->sym, node->sym->location); + } + /* Insert the initial rule, whose line is that of the first rule (not that of the start symbol): diff --git a/src/symtab.c b/src/symtab.c index 37677ed7..40ba0bee 100644 --- a/src/symtab.c +++ b/src/symtab.c @@ -615,6 +615,11 @@ dummy_symbol_get (location loc) return sym; } +bool +symbol_is_dummy (const symbol *sym) +{ + return sym->tag[0] == '@'; +} /*-------------------. | Free the symbols. | diff --git a/src/symtab.h b/src/symtab.h index 1a3ada4c..647a9e4c 100644 --- a/src/symtab.h +++ b/src/symtab.h @@ -133,6 +133,9 @@ symbol *symbol_get (const char *key, location loc); Its name cannot conflict with the user's names. */ symbol *dummy_symbol_get (location loc); +/** Is this a dummy nonterminal? */ +bool symbol_is_dummy (const symbol *sym); + /** Declare the new symbol \c sym. Make it an alias of \c symval. */ void symbol_make_alias (symbol *sym, symbol *symval, location loc); diff --git a/tests/input.at b/tests/input.at index 0fce2dd1..ce1c777a 100644 --- a/tests/input.at +++ b/tests/input.at @@ -537,3 +537,24 @@ input.y:20.1: syntax error, unexpected end of file, expecting ; ]]) AT_CLEANUP + + +## ------------------------- ## +## %start after first rule. ## +## ------------------------- ## + +AT_SETUP([%start after first rule]) + +# Bison once complained that a %start after the first rule was a redeclaration +# of the start symbol. + +AT_DATA([input.y], +[[%% +false_start: ; +start: false_start ; +%start start; +]]) + +AT_CHECK([bison -o input.c input.y]) + +AT_CLEANUP -- 2.45.2