From c2729758f299eced966df137913fa5cab195ad47 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Mon, 9 Feb 2004 21:31:42 +0000 Subject: [PATCH] Support %destructor and merge error locations in lalr1.cc. * data/lalr1.cc (b4_cxx_destruct_def): New macro. (Parser::stos_): Define unconditionally. (Parser::destruct_): New method. Generate its body with b4_yydestruct_generate. (Parser::error_start_): New attribute. (Parser::parse) : Call destruct_ on erroneous token which are discarded. (Parser::parse) : Update error_start_ when erroneous token are discarded. (Parser::parse) : Compute the location of the error token so that it covers all the discarded tokens. * tests/actions.at (_AT_CHECK_PRINTER_AND_DESTRUCTOR): Adjust so it can be called with `%skeleton "lalr1.cc"', and do that. --- ChangeLog | 18 +++++++++++++ data/lalr1.cc | 41 +++++++++++++++++++++++------ tests/actions.at | 67 +++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 106 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5f0d4aee..2020cdd0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2004-02-09 Alexandre Duret-Lutz + + Support %destructor and merge error locations in lalr1.cc. + + * data/lalr1.cc (b4_cxx_destruct_def): New macro. + (Parser::stos_): Define unconditionally. + (Parser::destruct_): New method. Generate its body with + b4_yydestruct_generate. + (Parser::error_start_): New attribute. + (Parser::parse) : Call destruct_ on erroneous + token which are discarded. + (Parser::parse) : Update + error_start_ when erroneous token are discarded. + (Parser::parse) : Compute the location of the error + token so that it covers all the discarded tokens. + * tests/actions.at (_AT_CHECK_PRINTER_AND_DESTRUCTOR): Adjust so + it can be called with `%skeleton "lalr1.cc"', and do that. + 2004-02-02 Paul Eggert * src/Makefile.am (AM_CPPFLAGS): New macro. It mentions diff --git a/data/lalr1.cc b/data/lalr1.cc index 4fe3c2ad..3585cd19 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -114,6 +114,14 @@ m4_define([b4_cc_var_decls], m4_define([b4_cc_var_decl], [ $1;]) +# b4_cxx_destruct_def(IGNORED-ARGUMENTS) +# -------------------------------------- +# Declare the destruct_ method. +m4_define([b4_cxx_destruct_def], +[void +yy::b4_parser_class_name::destruct_ (int yytype, SemanticType *yyvaluep, LocationType *yylocationp)[]dnl +]) + # We do want M4 expansion after # for CPP macros. m4_changecom() m4_divert(0)dnl @@ -250,6 +258,7 @@ namespace yy static const ]b4_int_type_for([b4_table])[ table_[]; static const ]b4_int_type(b4_table_ninf, b4_table_ninf)[ table_ninf_; static const ]b4_int_type_for([b4_check])[ check_[]; + static const ]b4_int_type_for([b4_stos])[ stos_[]; static const ]b4_int_type_for([b4_r1])[ r1_[]; static const ]b4_int_type_for([b4_r2])[ r2_[]; @@ -262,7 +271,6 @@ namespace yy static const RhsNumberType rhs_[]; static const ]b4_int_type_for([b4_prhs])[ prhs_[]; static const ]b4_int_type_for([b4_rline])[ rline_[]; - static const ]b4_int_type_for([b4_stos])[ stos_[]; static const ]b4_int_type_for([b4_toknum])[ token_number_[]; virtual void reduce_print_ (int yyrule); virtual void stack_print_ (); @@ -270,6 +278,8 @@ namespace yy /* Even more tables. */ static inline TokenNumberType translate_ (int token); + static inline void destruct_ (int yytype, SemanticType *yyvaluep, + LocationType *yylocationp); /* Constants. */ static const int eof_; @@ -307,6 +317,8 @@ namespace yy /* Semantic value and location of lookahead token. */ SemanticType value; LocationType location; + /* Beginning of the last erroneous token popped off. */ + Position error_start_; /* @@$ and $$. */ SemanticType yyval; @@ -349,6 +361,7 @@ do { \ #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab +]b4_yydestruct_generate([b4_cxx_destruct_def])[ int yy::]b4_parser_class_name[::parse () @@ -530,6 +543,7 @@ b4_syncline([@oline@], [@ofile@])[ /* If not already recovering from an error, report this error. */ report_syntax_error_ (); + error_start_ = location.begin; if (errstatus_ == 3) { /* If just tried and failed to reuse lookahead token after an @@ -543,23 +557,26 @@ b4_syncline([@oline@], [@ofile@])[ if (looka_ == eof_) for (;;) { + error_start_ = location_stack_[0].begin; state_stack_.pop (); semantic_stack_.pop (); location_stack_.pop (); if (state_stack_.height () == 1) YYABORT; // YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); -// FIXME: yydestruct (yystos[*yyssp], yyvsp]b4_location_if([, yylsp])[); + destruct_ (stos_[state_stack_[0]], + &semantic_stack_[0], + &location_stack_[0]); } } else { #if YYDEBUG - YYCDEBUG << "Discarding token " << looka_ - << " (" << name_[ilooka_] << ")." << std::endl; -// yydestruct (yytoken, &yylval]b4_location_if([, &yylloc])[); + YYCDEBUG << "Discarding token " << looka_ + << " (" << name_[ilooka_] << ")." << std::endl; #endif - looka_ = empty_; + destruct_ (ilooka_, &value, &location); + looka_ = empty_; } } @@ -582,6 +599,7 @@ yyerrorlab: state_stack_.pop (len_); semantic_stack_.pop (len_); + error_start_ = location_stack_[len_ - 1].begin; location_stack_.pop (len_); state_ = state_stack_[0]; goto yyerrlab1; @@ -631,6 +649,8 @@ yyerrlab1: } } #endif + destruct_ (stos_[state_], &semantic_stack_[0], &location_stack_[0]); + error_start_ = location_stack_[0].begin; state_stack_.pop (); semantic_stack_.pop (); @@ -644,8 +664,13 @@ yyerrlab1: YYCDEBUG << "Shifting error token, "; - semantic_stack_.push (value); - location_stack_.push (location); + { + Location errloc; + errloc.begin = error_start_; + errloc.end = location.end; + semantic_stack_.push (value); + location_stack_.push (errloc); + } state_ = n_; goto yynewstate; diff --git a/tests/actions.at b/tests/actions.at index 9078f9ba..29674273 100644 --- a/tests/actions.at +++ b/tests/actions.at @@ -1,5 +1,5 @@ # Executing Actions. -*- Autotest -*- -# Copyright (C) 2001, 2002 Free Software Foundation, Inc. +# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. # 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 @@ -314,15 +314,16 @@ AT_SETUP([Printers and Destructors: $5]) # Make sure complex $n work. +AT_BISON_OPTION_PUSHDEFS([$5]) AT_DATA_GRAMMAR([[input.y]], [[$5 %{ #include #include -#define RANGE(Location) (Location).first_line, (Location).last_line -static int yylex (void); -static void yyerror (const char *msg); -%} +]AT_LALR1_CC_IF( + [#define RANGE(Location) (Location).begin.line, (Location).end.line], + [#define RANGE(Location) (Location).first_line, (Location).last_line]) +[%} %error-verbose %debug %verbose @@ -331,6 +332,13 @@ static void yyerror (const char *msg); { int ival; } + +%{ +]AT_LALR1_CC_IF([typedef yy::Location YYLTYPE;]) +[static int yylex (]AT_LEX_FORMALS[); +static void yyerror (const char *msg); +%} + %type 'x' ';' thing line input %printer { fprintf (yyoutput, "%d@%d-%d", $$, RANGE (@$)); } @@ -406,7 +414,7 @@ thing: ; %% static int -yylex (void) +yylex (]AT_LEX_FORMALS[) { static const unsigned int input[] = { @@ -424,13 +432,23 @@ yylex (void) if (counter < (sizeof(input) / sizeof (input[0]))) { - yylval.ival = counter; +]AT_LALR1_CC_IF( +[ yylval->ival = counter; + /* As in BASIC, line numbers go from 10 to 10. */ + yylloc->begin.line = yylloc->begin.column = 10 * counter; + yylloc->end.line = yylloc->end.column = yylloc->begin.line + 9; + printf ("sending: '%c' (%d@%d-%d)\n", + input[[counter]], yylval->ival, RANGE (*yylloc)); + return (int) input[[counter++]]; +], +[ yylval.ival = counter; /* As in BASIC, line numbers go from 10 to 10. */ yylloc.first_line = yylloc.first_column = 10 * counter; yylloc.last_line = yylloc.last_column = yylloc.first_line + 9; printf ("sending: '%c' (%d@%d-%d)\n", - input[counter], yylval.ival, RANGE (yylloc)); - return (int) input[counter++]; + input[[counter]], yylval.ival, RANGE (yylloc)); + return (int) input[[counter++]]; +])[ } else { @@ -439,11 +457,34 @@ yylex (void) } } -static void +]AT_LALR1_CC_IF( +[/* Currently, print_ is required in C++. */ +void +yy::Parser::print_ () +{ + std::cerr << location; +} + +/* A C++ error reporting function. */ +void +yy::Parser::error_ () +{ + printf ("%d-%d: %s\n", RANGE (location), message.c_str()); +} + +static bool yydebug; +int +yyparse () +{ + yy::Parser parser (yydebug, yy::Location::Location ()); + return parser.parse (); +} +], +[static void yyerror (const char *msg) { printf ("%d-%d: %s\n", RANGE (yylloc), msg); -} +}])[ int main (void) @@ -460,7 +501,8 @@ main (void) ]]) AT_CHECK([bison -o input.c input.y]) -AT_COMPILE([input]) +AT_LALR1_CC_IF([AT_COMPILE_CXX([input])], + [AT_COMPILE([input])]) AT_PARSER_CHECK([./input], 1, [[sending: 'x' (0@0-9) thing (0@0-9): 'x' (0@0-9) @@ -512,6 +554,7 @@ m4_define([AT_CHECK_PRINTER_AND_DESTRUCTOR], AT_CHECK_PRINTER_AND_DESTRUCTOR() +AT_CHECK_PRINTER_AND_DESTRUCTOR([%locations %defines %skeleton "lalr1.cc"]) # FIXME. This test case fails. #AT_CHECK_PRINTER_AND_DESTRUCTOR([%glr-parser]) -- 2.45.2