152 lines
4.2 KiB
C++
152 lines
4.2 KiB
C++
/** @file TkInputState.cpp
|
|
*
|
|
* @author Roland Conybeare, Jun 2025
|
|
**/
|
|
|
|
#include "TkInputState.hpp"
|
|
|
|
namespace xo {
|
|
namespace scm {
|
|
using CharT = char;
|
|
|
|
bool
|
|
TkInputState::is_newline(CharT ch) {
|
|
return (ch == '\n');
|
|
}
|
|
|
|
bool
|
|
TkInputState::is_whitespace(CharT ch) {
|
|
switch(ch) {
|
|
case ' ': return true;
|
|
case '\t': return true;
|
|
case '\n': return true;
|
|
case '\r': return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
TkInputState
|
|
TkInputState::rewind(std::size_t n) const
|
|
{
|
|
return TkInputState(this->current_line_,
|
|
(n <= current_pos_) ? current_pos_ - n : 0,
|
|
0 /*whitespace*/);
|
|
}
|
|
|
|
void
|
|
TkInputState::advance(size_t z)
|
|
{
|
|
scope log(XO_DEBUG(debug_flag_));
|
|
|
|
this->current_pos_ += z;
|
|
|
|
log && log(xtag("z", z), xtag("current_pos", current_pos_));
|
|
}
|
|
|
|
void
|
|
TkInputState::advance_until(const CharT * pos)
|
|
{
|
|
scope log(XO_DEBUG(debug_flag_));
|
|
|
|
assert(current_line_.lo() <= pos && pos <= current_line_.hi());
|
|
|
|
this->current_pos_ = pos - current_line_.lo();
|
|
|
|
log && log(xtag("current_pos", current_pos_));
|
|
}
|
|
|
|
auto
|
|
TkInputState::consume_current_line() -> span_type
|
|
{
|
|
span_type retval = current_line_;
|
|
|
|
this->discard_current_line();
|
|
|
|
return retval;
|
|
}
|
|
|
|
void
|
|
TkInputState::discard_current_line()
|
|
{
|
|
this->current_line_ = span_type::make_null();
|
|
this->current_pos_ = 0;
|
|
this->whitespace_ = 0;
|
|
}
|
|
|
|
auto
|
|
TkInputState::capture_current_line(const span_type & input,
|
|
bool eof_flag)
|
|
-> std::pair<input_error, span_type>
|
|
{
|
|
// see also discard_current_line()
|
|
// note: must capture entirety of first line,
|
|
// for example including leading whitespace.
|
|
// See discussion in tokenizer scan() method
|
|
|
|
scope log(XO_DEBUG(debug_flag_),
|
|
xtag("input", input));
|
|
|
|
/* look ahead to {end of line, end of input}, whichever comes first */
|
|
const CharT * sol = input.lo();
|
|
const CharT * eol = sol;
|
|
|
|
if (sol == current_line_.lo()) {
|
|
log && log("short-circuit - current line already stashed");
|
|
|
|
/* nothing to do here */
|
|
return std::make_pair(input_error::ok, current_line_);
|
|
}
|
|
|
|
while ((eol < input.hi()) && (*eol != '\n'))
|
|
++eol;
|
|
|
|
if (*eol == '\n') {
|
|
/* include \n at end-of-line */
|
|
++eol;
|
|
} else {
|
|
if (!eof_flag) {
|
|
/* caller expected to provide complete line of input. complain and ignore */
|
|
return std::make_pair(input_error::incomplete,
|
|
input.prefix(0ul));
|
|
}
|
|
}
|
|
|
|
this->current_line_ = span_type(sol, eol);
|
|
this->current_pos_ = 0;
|
|
this->whitespace_ = 0;
|
|
|
|
log && log(xtag("current_line", print::printspan(current_line_)),
|
|
xtag("current_pos", current_pos_));
|
|
|
|
return std::make_pair(input_error::ok,
|
|
span_type(sol, eol));
|
|
}
|
|
|
|
const CharT *
|
|
TkInputState::skip_leading_whitespace()
|
|
{
|
|
scope log(XO_DEBUG(debug_flag_));
|
|
|
|
const CharT * ix = current_line_.lo() + current_pos_;
|
|
|
|
this->whitespace_ = 0;
|
|
|
|
/* skip whitespace + remember beginning of most recent line */
|
|
while (is_whitespace(*ix) && (ix != current_line_.hi())) {
|
|
++ix;
|
|
|
|
++(this->whitespace_);
|
|
}
|
|
|
|
this->tk_start_ = ix - current_line_.lo();
|
|
this->current_pos_ = ix - current_line_.lo();
|
|
|
|
return ix;
|
|
}
|
|
|
|
|
|
} /*namespace scm*/
|
|
} /*namespace xo*/
|
|
|
|
/* end TkInputState.cpp */
|