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 ?.? (????-??-??) [?]
** 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
Csaba Raduly csaba_22@yahoo.co.uk
Dagobert Michelsen dam@baltic-online.de
Daniel Frużyński daniel@poradnik-webmastera.com
Daniel Hagerty hag@gnu.org
David J. MacKenzie djm@gnu.org
David Kastrup dak@gnu.org

View File

@@ -25,8 +25,7 @@ m4_define([b4_position_define],
[[ /// Abstract a position.
class position
{
public:
]m4_ifdef([b4_location_constructors], [[
public:]m4_ifdef([b4_location_constructors], [[
/// Construct a position.
explicit position (]b4_percent_define_get([[filename_type]])[* f = YY_NULL,
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.
void lines (int count = 1)
{
column = ]b4_location_initial_column[u;
line += count;
if (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.
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.
inline position&
operator+= (position& res, const int width)
operator+= (position& res, int width)
{
res.columns (width);
return res;
}
/// Add two position objects.
inline const position
operator+ (const position& begin, const int width)
inline position
operator+ (position res, int width)
{
position res = begin;
return res += width;
}
/// Add and assign a position.
inline position&
operator-= (position& res, const int width)
operator-= (position& res, int width)
{
return res += -width;
}
/// Add two position objects.
inline const position
operator- (const position& begin, const int width)
inline position
operator- (position res, int width)
{
return begin + -width;
return res -= width;
}
]b4_percent_define_flag_if([[define_location_comparison]], [[
/// Compare two position objects.
@@ -186,13 +193,13 @@ m4_define([b4_location_define],
}
/// Extend the current location to the COUNT next columns.
void columns (unsigned int count = 1)
void columns (int count = 1)
{
end += count;
}
/// Extend the current location to the COUNT next lines.
void lines (unsigned int count = 1)
void lines (int count = 1)
{
end.lines (count);
}
@@ -207,26 +214,35 @@ m4_define([b4_location_define],
};
/// 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;
return res;
}
/// Add two location objects.
inline const location operator+ (const location& begin, unsigned int width)
/// Change end position in place.
inline location& operator+= (location& res, int width)
{
location res = begin;
res.columns (width);
return res;
}
/// Add and assign a location.
inline location& operator+= (location& res, unsigned int width)
/// Change end position.
inline location operator+ (location res, int width)
{
res.columns (width);
return res;
return res += width;
}
/// 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]], [[
/// Compare two location objects.

View File

@@ -10591,16 +10591,18 @@ filename_type "@var{type}"}.
The line, starting at 1.
@end deftypeivar
@deftypemethod {position} {uint} lines (int @var{height} = 1)
Advance by @var{height} lines, resetting the column number.
@deftypemethod {position} {void} lines (int @var{height} = 1)
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
@deftypeivar {position} {uint} column
The column, starting at 1.
@end deftypeivar
@deftypemethod {position} {uint} columns (int @var{width} = 1)
Advance by @var{width} columns, without changing the line number.
@deftypemethod {position} {void} columns (int @var{width} = 1)
Advance by @var{width} columns, without changing the line number. The
resulting column number cannot be less than 1.
@end deftypemethod
@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.
@end deftypeivar
@deftypemethod {location} {uint} columns (int @var{width} = 1)
@deftypemethodx {location} {uint} lines (int @var{height} = 1)
Advance the @code{end} position.
@deftypemethod {location} {void} columns (int @var{width} = 1)
@deftypemethodx {location} {void} lines (int @var{height} = 1)
Forwarded to the @code{end} position.
@end deftypemethod
@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})
Various forms of syntactic sugar.
@end deftypemethod

View File

@@ -18,6 +18,68 @@
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. ##
## --------------------------- ##