diff --git a/include/boost/spirit/home/support/iterators/line_pos_iterator.hpp b/include/boost/spirit/home/support/iterators/line_pos_iterator.hpp index 0b2aec8ce9..10a1c5b768 100644 --- a/include/boost/spirit/home/support/iterators/line_pos_iterator.hpp +++ b/include/boost/spirit/home/support/iterators/line_pos_iterator.hpp @@ -1,6 +1,7 @@ /*============================================================================== Copyright (c) 2001-2011 Joel de Guzman Copyright (c) 2010 Bryce Lelbach + Copyright (c) 2014 Tomoki Imai Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -125,18 +126,35 @@ namespace boost { namespace spirit template inline Iterator get_line_start(Iterator lower_bound, Iterator current) { + // cover LF,CR+LF,CR,LF+RF. + // but if *current == '\r' or *current == '\n', + // result will be something worng. Iterator latest = lower_bound; - + bool prev_was_newline = false; for (Iterator i = lower_bound; i != current; ++i) { - switch (*i) { - case '\r': - case '\n': - latest = i; - } + if (prev_was_newline) { + latest = i; + } + prev_was_newline = (*i == '\r') || (*i == '\n'); + } + if (prev_was_newline) { + latest = current; } - return latest; } + + template + inline Iterator get_line_end(Iterator current, Iterator upper_bound) + { + // if current is at '\r' or '\n',may return something unexpected. + for (Iterator i = current; i != upper_bound; ++i) { + if ((*i == '\n') || (*i == '\r')) { + return i; + } + } + return upper_bound; + } + template inline iterator_range @@ -144,12 +162,9 @@ namespace boost { namespace spirit Iterator current, Iterator upper_bound) { + // if *current is '\r' or '\n', result will something unexpected. Iterator first = get_line_start(lower_bound, current); - Iterator last = get_line_start(current, upper_bound); - - if (last == current) - last = upper_bound; - + Iterator last = get_line_end(current, upper_bound); return iterator_range(first, last); } diff --git a/test/Jamfile b/test/Jamfile index 6da470c2b0..bdc0233831 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -312,6 +312,7 @@ path-constant LEX_DIR : $(BOOST_ROOT)/libs/spirit/test/lex ; [ compile support/regression_multi_pass_position_iterator.cpp : : support_regression_multi_pass_position_iterator ] [ compile support/regression_multi_pass_functor.cpp : : support_regression_multi_pass_functor ] [ compile support/regression_multi_pass_parse.cpp : : support_regression_multi_pass_parse ] + [ run support/regression_line_pos_iterator.cpp : : : : regression_line_pos_iterator ] [ run support/regression_multi_pass_error_handler.cpp : : : : regression_multi_pass_error_handler ] ; diff --git a/test/support/regression_line_pos_iterator.cpp b/test/support/regression_line_pos_iterator.cpp new file mode 100644 index 0000000000..1ff4db8dce --- /dev/null +++ b/test/support/regression_line_pos_iterator.cpp @@ -0,0 +1,45 @@ +// Copyright (c) 2014 Tomoki Imai +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include + +int main() +{ + typedef boost::spirit::line_pos_iterator + pos_iterator_t; + typedef boost::iterator_range + iterator_range; + { + std::string test = "012\n345\n678"; + pos_iterator_t begin(test.begin()), + end(test.end()); + + for (pos_iterator_t iter = begin; iter != end; ++iter) { + // ignore newline because newline's line or column is ambiguous. + if (*iter == '\n') continue; + int n = *iter - '0'; + int line = n / 3 + 1; + int column = n % 3 + 1; + + BOOST_TEST_EQ(line,get_line(iter)); + BOOST_TEST_EQ(column,get_column(begin,iter)); + + iterator_range range = get_current_line(begin,iter,end); + std::string current_line(range.begin(),range.end()); + if (line == 1) { + BOOST_TEST_EQ(current_line,"012"); + } else if(line == 2) { + BOOST_TEST_EQ(current_line,"345"); + } else { + BOOST_TEST_EQ(current_line,"678"); + } + } + } + return 0; +}