c++: fix several issues with locations

Reported by Daniel Frużyński.
http://lists.gnu.org/archive/html/bug-bison/2013-02/msg00000.html

* data/location.cc (position::columns, position::lines): Check for
underflow.
Fix some weird function signatures.
(location): Accept signed integers as arguments where appropriate.
Add operator- and operator+=.
* doc/bison.texi (C++ position, C++ location): Various fixes
and completion.
* tests/c++.at (C++ Locations): New tests.
This commit is contained in:
Akim Demaille
2013-04-11 09:53:18 +02:00
parent 08cc1a3b18
commit 75ae829984
5 changed files with 119 additions and 31 deletions

5
NEWS
View File

@@ -569,6 +569,11 @@ GNU Bison NEWS
... ...
} }
*** C++ locations
There are operator- and operator-= for 'location'. Negative line/column
increments can no longer underflow the resulting value.
* Noteworthy changes in release ?.? (????-??-??) [?] * Noteworthy changes in release ?.? (????-??-??) [?]
** Bug fixes ** Bug fixes

1
THANKS
View File

@@ -29,6 +29,7 @@ Cris Bailiff c.bailiff+bison@awayweb.com
Cris van Pelt cris@amf03054.office.wxs.nl Cris van Pelt cris@amf03054.office.wxs.nl
Csaba Raduly csaba_22@yahoo.co.uk Csaba Raduly csaba_22@yahoo.co.uk
Dagobert Michelsen dam@baltic-online.de Dagobert Michelsen dam@baltic-online.de
Daniel Frużyński daniel@poradnik-webmastera.com
Daniel Hagerty hag@gnu.org Daniel Hagerty hag@gnu.org
David J. MacKenzie djm@gnu.org David J. MacKenzie djm@gnu.org
David Kastrup dak@gnu.org David Kastrup dak@gnu.org

View File

@@ -25,8 +25,7 @@ m4_define([b4_position_define],
[[ /// Abstract a position. [[ /// Abstract a position.
class position class position
{ {
public: public:]m4_ifdef([b4_location_constructors], [[
]m4_ifdef([b4_location_constructors], [[
/// Construct a position. /// Construct a position.
explicit position (]b4_percent_define_get([[filename_type]])[* f = YY_NULL, explicit position (]b4_percent_define_get([[filename_type]])[* f = YY_NULL,
unsigned int l = ]b4_location_initial_line[u, unsigned int l = ]b4_location_initial_line[u,
@@ -53,14 +52,23 @@ m4_define([b4_position_define],
/// (line related) Advance to the COUNT next lines. /// (line related) Advance to the COUNT next lines.
void lines (int count = 1) void lines (int count = 1)
{ {
column = ]b4_location_initial_column[u; if (count)
line += count; {
column = ]b4_location_initial_column[u;
line =
0 < count || -count < line
? line + count
: ]b4_location_initial_line[;
}
} }
/// (column related) Advance to the COUNT next columns. /// (column related) Advance to the COUNT next columns.
void columns (int count = 1) void columns (int count = 1)
{ {
column = std::max (]b4_location_initial_column[u, column + count); column =
0 < count || -count < column
? column + count
: ]b4_location_initial_column[;
} }
/** \} */ /** \} */
@@ -74,32 +82,31 @@ m4_define([b4_position_define],
/// Add and assign a position. /// Add and assign a position.
inline position& inline position&
operator+= (position& res, const int width) operator+= (position& res, int width)
{ {
res.columns (width); res.columns (width);
return res; return res;
} }
/// Add two position objects. /// Add two position objects.
inline const position inline position
operator+ (const position& begin, const int width) operator+ (position res, int width)
{ {
position res = begin;
return res += width; return res += width;
} }
/// Add and assign a position. /// Add and assign a position.
inline position& inline position&
operator-= (position& res, const int width) operator-= (position& res, int width)
{ {
return res += -width; return res += -width;
} }
/// Add two position objects. /// Add two position objects.
inline const position inline position
operator- (const position& begin, const int width) operator- (position res, int width)
{ {
return begin + -width; return res -= width;
} }
]b4_percent_define_flag_if([[define_location_comparison]], [[ ]b4_percent_define_flag_if([[define_location_comparison]], [[
/// Compare two position objects. /// Compare two position objects.
@@ -186,13 +193,13 @@ m4_define([b4_location_define],
} }
/// Extend the current location to the COUNT next columns. /// Extend the current location to the COUNT next columns.
void columns (unsigned int count = 1) void columns (int count = 1)
{ {
end += count; end += count;
} }
/// Extend the current location to the COUNT next lines. /// Extend the current location to the COUNT next lines.
void lines (unsigned int count = 1) void lines (int count = 1)
{ {
end.lines (count); end.lines (count);
} }
@@ -207,26 +214,35 @@ m4_define([b4_location_define],
}; };
/// Join two location objects to create a location. /// Join two location objects to create a location.
inline const location operator+ (const location& begin, const location& end) inline location operator+ (location res, const location& end)
{ {
location res = begin;
res.end = end.end; res.end = end.end;
return res; return res;
} }
/// Add two location objects. /// Change end position in place.
inline const location operator+ (const location& begin, unsigned int width) inline location& operator+= (location& res, int width)
{ {
location res = begin;
res.columns (width); res.columns (width);
return res; return res;
} }
/// Add and assign a location. /// Change end position.
inline location& operator+= (location& res, unsigned int width) inline location operator+ (location res, int width)
{ {
res.columns (width); return res += width;
return res; }
/// Change end position in place.
inline location& operator-= (location& res, int width)
{
return res += -width;
}
/// Change end position.
inline location operator- (const location& begin, int width)
{
return begin + -width;
} }
]b4_percent_define_flag_if([[define_location_comparison]], [[ ]b4_percent_define_flag_if([[define_location_comparison]], [[
/// Compare two location objects. /// Compare two location objects.

View File

@@ -10591,16 +10591,18 @@ filename_type "@var{type}"}.
The line, starting at 1. The line, starting at 1.
@end deftypeivar @end deftypeivar
@deftypemethod {position} {uint} lines (int @var{height} = 1) @deftypemethod {position} {void} lines (int @var{height} = 1)
Advance by @var{height} lines, resetting the column number. If @var{height} is not null, advance by @var{height} lines, resetting the
column number. The resulting line number cannot be less than 1.
@end deftypemethod @end deftypemethod
@deftypeivar {position} {uint} column @deftypeivar {position} {uint} column
The column, starting at 1. The column, starting at 1.
@end deftypeivar @end deftypeivar
@deftypemethod {position} {uint} columns (int @var{width} = 1) @deftypemethod {position} {void} columns (int @var{width} = 1)
Advance by @var{width} columns, without changing the line number. Advance by @var{width} columns, without changing the line number. The
resulting column number cannot be less than 1.
@end deftypemethod @end deftypemethod
@deftypemethod {position} {position&} operator+= (int @var{width}) @deftypemethod {position} {position&} operator+= (int @var{width})
@@ -10642,14 +10644,16 @@ Reset the location to an empty range at the given values.
The first, inclusive, position of the range, and the first beyond. The first, inclusive, position of the range, and the first beyond.
@end deftypeivar @end deftypeivar
@deftypemethod {location} {uint} columns (int @var{width} = 1) @deftypemethod {location} {void} columns (int @var{width} = 1)
@deftypemethodx {location} {uint} lines (int @var{height} = 1) @deftypemethodx {location} {void} lines (int @var{height} = 1)
Advance the @code{end} position. Forwarded to the @code{end} position.
@end deftypemethod @end deftypemethod
@deftypemethod {location} {location} operator+ (const location& @var{end}) @deftypemethod {location} {location} operator+ (const location& @var{end})
@deftypemethodx {location} {location} operator+ (int @var{width}) @deftypemethodx {location} {location} operator+ (int @var{width})
@deftypemethodx {location} {location} operator+= (int @var{width}) @deftypemethodx {location} {location} operator+= (int @var{width})
@deftypemethodx {location} {location} operator- (int @var{width})
@deftypemethodx {location} {location} operator-= (int @var{width})
Various forms of syntactic sugar. Various forms of syntactic sugar.
@end deftypemethod @end deftypemethod

View File

@@ -18,6 +18,68 @@
AT_BANNER([[C++ Features.]]) AT_BANNER([[C++ Features.]])
## --------------- ##
## C++ Locations. ##
## --------------- ##
AT_SETUP([C++ Locations])
AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "lalr1.cc"])
AT_DATA_GRAMMAR([[input.y]],
[[%code {#include <sstream>}
%locations
%debug
%skeleton "lalr1.cc"
%code
{
]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE[
}
%%
exp: %empty;
%%
]AT_YYERROR_DEFINE[
]AT_YYLEX_DEFINE[
template <typename T>
bool
check (const T& in, const std::string& s)
{
std::stringstream os;
os << in;
if (os.str () != s)
{
std::cerr << "fail: " << os.str () << ", expected: " << s << std::endl;
return false;
}
return true;
}
int
main (void)
{
int fail = 0;
]AT_YYLTYPE[ loc; fail += check (loc, "1.1");
loc += 10; fail += check (loc, "1.1-10");
loc += -5; fail += check (loc, "1.1-5");
loc -= 5; fail += check (loc, "1.1");
// Check that we don't go below.
// http://lists.gnu.org/archive/html/bug-bison/2013-02/msg00000.html
loc -= 10; fail += check (loc, "1.1");
loc.columns (10); loc.lines (10); fail += check (loc, "1.1-11.0");
loc.lines (-2); fail += check (loc, "1.1-9.0");
loc.lines (-10); fail += check (loc, "1.1");
return !fail;
}
]])
AT_FULL_COMPILE([input])
AT_PARSER_CHECK([./input], 0)
AT_BISON_OPTION_POPDEFS
AT_CLEANUP
## --------------------------- ## ## --------------------------- ##
## C++ Variant-based Symbols. ## ## C++ Variant-based Symbols. ##
## --------------------------- ## ## --------------------------- ##