42 #include <type_traits>
55 static bool const plaintext =
false;
57 static bool const cxxtext =
true;
84 static text_type
const id = text_type::whitespace;
91 static text_type
const id = text_type::greyspace;
98 static text_type
const id = text_type::continuation;
105 static text_type
const id = text_type::cxx_comment;
113 static text_type
const id = text_type::c_comment;
121 static text_type
const id = text_type::string_literal;
129 static text_type
const id = text_type::character_literal;
137 static text_type
const id = text_type::raw_string_literal;
145 static text_type
const id = text_type::header_name;
153 static text_type
const id = text_type::code;
161 static text_type
const id = text_type::name;
169 static text_type
const id = text_type::literal_space;
177 static text_type
const id = text_type::punctuation;
185 static text_type
const id = text_type::number_space;
193 static text_type
const id = text_type::stringify;
201 static text_type
const id = text_type::token_paste;
247 template<
class CharSeq>
257 template<
class Mode1,
class Mode2>
259 typename std::enable_if<std::is_same<Mode1,Mode2>::value>::type;
306 void scan(Mode mode,
size_t off) {
323 template<
class FirstMode,
class ...OtherModes>
325 FirstMode first_mode, OtherModes... other_modes) {
326 adjust >= 0 ?
on(adjust) :
back(-adjust);
327 scan<FirstMode,OtherModes...>();
336 template<
class FirstMode,
class ...OtherModes>
339 consume<FirstMode,OtherModes...>();
407 explicit operator size_t ()
const {
431 explicit operator bool ()
const {
486 template<
class FirstMode,
class ...OtherModes>
488 std::enable_if<!std::is_arithmetic<FirstMode>::value,
chewer &>::type
489 operator()(FirstMode first_mode, OtherModes... other_modes) {
490 scan<FirstMode,OtherModes...>();
500 std::enable_if<traits::has_extend_method<U>::value>::type;
506 std::enable_if<!traits::has_extend_method<U>::value>::type;
510 template<
typename U = sequence_type>
515 template<
typename U = sequence_type>
516 void extend(if_sequence_is_not_extensible<U> * =
nullptr) {}
523 template<
typename U = sequence_type>
528 template<
typename U = sequence_type>
532 if_sequence_is_not_extensible<U> * =
nullptr) {}
542 unsigned eol(
size_t off = 0) {
551 return atoff(off) ==
'\\' &&
eol(off + 1);
560 for ( ;
curch() ==
'\\' && (nl_len =
eol(1));
on(nl_len + 1)) {
568 void_if<Mode,chew_mode::whitespace>
consume() {
569 consume<chew_mode::continuation>();
571 ++
_cur,consume<chew_mode::continuation>()) {}
575 void_if<Mode,chew_mode::number_space>
consume() {
576 consume<chew_mode::continuation>();
588 ++
_cur,consume<chew_mode::continuation>()) {}
592 void_if<Mode,chew_mode::name>
consume() {
593 consume<chew_mode::continuation>();
596 ++
_cur,consume<chew_mode::continuation>()){}
602 void_if<Mode,chew_mode::punctuation>
consume() {
603 consume<chew_mode::continuation>();
606 ++
_cur,consume<chew_mode::continuation>()) {}
610 void_if<Mode,chew_mode::stringify>
consume() {
611 consume<chew_mode::continuation>();
616 void_if<Mode,chew_mode::token_paste>
consume() {
618 consume<chew_mode::continuation>();
620 consume<chew_mode::continuation>();
630 void_if<Mode,chew_mode::cxx_comment>
consume() {
631 consume<chew_mode::continuation>();
635 consume<chew_mode::continuation>();
642 ++
_cur,consume<chew_mode::continuation>()){};
647 void_if<Mode,chew_mode::c_comment>
consume() {
648 consume<chew_mode::continuation>();
654 consume<chew_mode::continuation>();
659 bool closing =
false;
661 consume<chew_mode::continuation>();
663 closing = (
curch() ==
'*'),
664 ++
_cur,consume<chew_mode::continuation>()) {
665 if (
curch() ==
'/') {
671 size_t nl_len =
eol();
681 void_if<Mode,chew_mode::string_literal>
consume() {
682 consume<chew_mode::continuation>();
687 void_if<Mode,chew_mode::header_name>
consume() {
688 consume<chew_mode::continuation>();
690 consume_enclosed_string<'<','>
'>();
692 consume_enclosed_string<'\
"','\"'>();
697 void_if<Mode,chew_mode::character_literal> consume() {
698 consume<chew_mode::continuation>();
699 if (overshoot() || curch() != '\'') {
704 consume<chew_mode::continuation>();
706 for ( ; !overshoot(); ++_cur,consume<chew_mode::continuation>()) {
707 if (curch() == '\'') {
713 } else if (curch() == '\\') {
723 void_if<Mode,chew_mode::raw_string_literal> consume() {
724 consume<chew_mode::continuation>();
725 if (overshoot() || curch() != 'R') {
730 consume<chew_mode::continuation>();
731 if (overshoot() || curch() != '\"') {
736 consume<chew_mode::continuation>();
737 for ( ; !overshoot(); ++_cur,consume<chew_mode::continuation>()) {
738 if (!isgraph(curch()) || curch() == '\\') {
742 if (curch() == '(') {
747 consume<chew_mode::continuation>();
748 for ( ; !overshoot(); ++_cur,consume<chew_mode::continuation>()) {
749 if (curch() == ')') {
752 size_t nl_len = eol();
758 consume<chew_mode::continuation>();
759 for (; !overshoot(); ++_cur,consume<chew_mode::continuation>()) {
760 if (!isgraph(curch()) || curch() == '\\') {
763 if (curch() == '\"') {
768 missing_terminator(mark,'\"');
772 void_if<Mode,chew_mode::greyspace> consume() {
774 consume<chew_mode::whitespace>();
777 for ( ;!overshoot(); ) {
778 consume<chew_mode::whitespace>();
780 consume<chew_mode::cxx_comment>();
784 consume<chew_mode::c_comment>();
792 void_if<Mode,chew_mode::code> consume() {
793 for ( ;!overshoot(); ++_cur) {
794 consume<chew_mode::greyspace>();
795 consume<chew_mode::character_literal>();
796 consume<chew_mode::string_literal>();
797 consume<chew_mode::raw_string_literal>();
802 void_if<Mode,chew_mode::literal_space> consume() {
803 consume<chew_mode::character_literal,
804 chew_mode::string_literal,
805 chew_mode::raw_string_literal>();
812 template<class First, class Next, class ...Rest>
813 typename std::enable_if<sizeof ...(Rest) == 0>::type
816 template<class First, class Next, class ...Rest>
817 typename std::enable_if<sizeof ...(Rest) != 0>::type
823 template<char_type Opener, char_type Closer>
824 void consume_enclosed_string();
827 void missing_terminator(size_t off, char_type missing);
829 void eof_in_comment();
834 sequence_type & _seq;
844 template<class CharSeq>
846 typename chewer<CharSeq>::char_type Opener,
847 typename chewer<CharSeq>::char_type Closer
849 void chewer<CharSeq>::consume_enclosed_string()
851 if (overshoot() || curch() != Opener) {
854 size_t mark = _cur++;
855 consume<chew_mode::continuation>();
857 for ( ; !overshoot(); ++_cur,consume<chew_mode::continuation>()) {
858 if (curch() == Closer) {
864 } else if (curch() == '\\') {
871 missing_terminator(mark,Closer);
875 template<class CharSeq>
876 template<class First, class Next, class ...Rest>
877 typename std::enable_if<sizeof ...(Rest) == 0>::type
878 chewer<CharSeq>::consume() {
879 for ( ;!overshoot(); ) {
889 template<class CharSeq>
890 template<class First, class Next, class ...Rest>
891 typename std::enable_if<sizeof ...(Rest) != 0>::type
892 chewer<CharSeq>::consume() {
893 for ( ;!overshoot(); ) {
896 consume<Next,Rest...>();
template struct traits::is_random_access_char_sequence<T> exports a static const boolean member value...
unsigned eol(CharSeq const &seq, size_t off)
Test for a newline-sequence at an offset in a character sequence.
A tag class for selecting a chew mode.
A tag class for selecting a chew mode.
void back(size_t n)
Retreat the scanning position an amount.
chewer & operator()(ptrdiff_t move, Mode mode)
operator()(move,mode) calls scan(move,mode) returning *this
char_type * _buf
Pointer to the data controlled by _seq
chew_mode::character_literal const character_literal
An exemplar chew_mode::character_literal
A tag class for selecting a chew mode.
chewer(bool cxx, sequence_type &seq, size_t off=0)
Construct from a sequence_type and initial offset.
A tag class for selecting a chew mode.
void_if< Mode, chew_mode::continuation > consume()
Consume characters satisfying a given mode, without preliminary snyc()
void scan()
Scan in a sequence of modes.
A tag class for selecting a chew mode.
bool cxx() const
Say whether scanning as C/C++ source.
A utility class to prevent assignment of containing class.
chewer(bool cxx, Mode mode, sequence_type &seq, size_t off=0)
Construct, scanning a given a sequence_type from a given offset.
typename std::enable_if< traits::has_extend_method< U >::value >::type if_sequence_is_extensible
SFINAE type equating to void if sequence_type has an extend method.
chew_mode::string_literal const string_literal
An exemplar chew_mode::string_literal
chew_mode::token_paste const token_paste
An exemplar chew_mode::token_paste
void scan(ptrdiff_t adjust, FirstMode first_mode, OtherModes...other_modes)
Adjust position and then scan in a sequence of modes.
chewer & operator=(size_t off)
Assign the scanning position, returning *this
chew_mode::c_comment const c_comment
An exemplar chew_mode::c_comment
CharSeq sequence_type
Type of the character-sequence consumed.
void cursor(size_t off)
Set the scanning position.
bool overshoot(size_t off=0) const
Say whether the scanning position is past the end of the associated sequence_type ...
chew_mode::raw_string_literal const raw_string_literal
An exemplar chew_mode::raw_string_literal
unsigned eol(size_t off=0)
Test for a newline-sequence at an offset from the scanning position.
A tag class for selecting a chew mode.
chewer & operator--()
Decrement the scanning position, returning *this
char_type operator*() const
operator*() const is an alias for curch() const.
A tag class for selecting a chew mode.
chew_mode::whitespace const whitespace
An exemplar chew_mode::whitespace
sequence_type & buf()
Get a [const] reference to the associated sequence_type
void extend(size_t skip, if_sequence_is_extensible< U > *=nullptr)
Extend the associated sequence_type by reading more input, possibly replacing skip characters ahead o...
size_t remaining() const
Get the remaining length of the associated sequence_type from the scanning position.
char_type curch() const
Get the character at the scanning position.
chew_mode::continuation const continuation
An exemplar chew_mode::continuation
A tag class for selecting a chew mode.
chew_mode::name const name
An exemplar chew_mode::name
chew_mode::number_space const number_space
An exemplar chew_mode::number_space
char_type & atoff(size_t off)
Get a reference to the character at an offset from the scanning position.
bool _cxx
Scanning C/C++ source?
chew_mode::cxx_comment const cxx_comment
An exemplar chew_mode::cxx_comment
void sync()
Synchronise the object with the associated sequence_type
void on(size_t n)
Advance the scanning position an amount.
char_type & operator[](size_t off)
operator[]() is an alias for atoff()
void eof_in_comment()
Diagnose end of file in C-comment.
chew_mode::greyspace const greyspace
An exemplar chew_mode::greyspace
size_t _cur
The scanning position in _buf.
chew_mode::header_name const header_name
An exemplar chew_mode::header_name
chewer & operator++()
Increment the scanning position, returning *this
chew_mode::code const code
An exemplar chew_mode::code
std::enable_if<!std::is_arithmetic< FirstMode >::value, chewer & >::type operator()(FirstMode first_mode, OtherModes...other_modes)
operator()(mode) calls scan(mode) returning *this
`template struct chewer<CharSeq> is a cursor-like type that is associated with a character-sequence t...
typename std::enable_if< std::is_same< Mode1, Mode2 >::value >::type void_if
SFINAE type equating to void if enabled.
sequence_type & _seq
The sequence that is consumed.
size_t _len
The length of the data at `_buf'.
A tag class for selecting a chew mode.
A tag class for selecting a chew mode.
typename sequence_type::value_type char_type
Value-type of the character-sequence.
chewer & operator+=(size_t n)
Advance the scanning position an amount, returning *this
void scan(Mode mode, size_t off)
Scan the associated sequence_type in a given mode from a given offset.
char_type operator[](size_t off) const
operator[]() const is an alias for atoff() const
A tag class for selecting a chew mode.
void extend(if_sequence_is_extensible< U > *=nullptr)
Extend the associated sequence_type by reading more input.
char_type & curch()
Get a reference to the character at the scanning position.
void consume_enclosed_string()
Consume characters between delimiting characters.
A tag class for selecting a chew mode.
typename std::enable_if<!traits::has_extend_method< U >::value >::type if_sequence_is_not_extensible
SFINAE type equating to void if sequence_type lacks an extend method.
chew_mode::punctuation const punctuation
An exemplar chew_mode::punctuation
size_t cursor() const
Get the scanning position.
char_type atoff(ptrdiff_t off) const
Get the character at an offset from the scanning position.
A tag class for selecting a chew mode.
bool line_continues(size_t off=0)
Say whether there is a line-continuation at an offset.
chewer & operator-=(size_t n)
Retreat the scanning position an amount, returning *this
chew_mode::literal_space const literal_space
An exemplar chew_mode::literal_space
chew_mode::stringify const stringify
An exemplar chew_mode::stringify