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.
...
}
+*** 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
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
[[ /// 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,
/// (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[;
}
/** \} */
/// 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.
}
/// 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);
}
};
/// 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.
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})
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
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. ##
## --------------------------- ##