127 lines
3.1 KiB
C++
127 lines
3.1 KiB
C++
/** @file tokenrepl.cpp **/
|
|
|
|
#include <xo/tokenizer2/Tokenizer.hpp>
|
|
#include <xo/tokenizer2/Token.hpp>
|
|
#include <xo/tokenizer2/tokentype.hpp>
|
|
#include <xo/arena/span.hpp>
|
|
#include <xo/indentlog/log_config.hpp>
|
|
#include <replxx.hxx>
|
|
#include <iostream>
|
|
#include <unistd.h> // for isatty
|
|
|
|
// presumeably replxx assumes input is a tty
|
|
//
|
|
bool replxx_getline(bool interactive,
|
|
std::size_t parser_stack_size,
|
|
replxx::Replxx & rx,
|
|
const char ** p_input)
|
|
{
|
|
using namespace std;
|
|
|
|
char const * prompt = "";
|
|
|
|
if (interactive) {
|
|
if (parser_stack_size <= 1)
|
|
prompt = "> ";
|
|
else
|
|
prompt = ". ";
|
|
}
|
|
|
|
const char * input_cstr = rx.input(prompt);
|
|
|
|
bool retval = (input_cstr != nullptr);
|
|
|
|
if (retval) {
|
|
//cerr << "got reval->true" << endl;
|
|
|
|
*p_input = input_cstr;
|
|
|
|
} else {
|
|
//cerr << "got retval->false" << endl;
|
|
}
|
|
|
|
rx.history_add(input_cstr);
|
|
|
|
return retval;
|
|
}
|
|
|
|
int
|
|
main() {
|
|
using xo::scm::Tokenizer;
|
|
using xo::scm::operator<<;
|
|
using xo::mm::CircularBufferConfig;
|
|
using xo::mm::span;
|
|
using xo::scope;
|
|
using xo::xtag;
|
|
using replxx::Replxx;
|
|
|
|
using namespace std;
|
|
|
|
using span_type = span<const char>;
|
|
|
|
xo::log_config::min_log_level = xo::log_level::severe;
|
|
|
|
bool interactive = isatty(STDIN_FILENO);
|
|
|
|
Replxx rx;
|
|
rx.set_max_history_size(1000);
|
|
rx.history_load("repl_history.txt");
|
|
|
|
constexpr bool c_debug_flag = true;
|
|
scope log(XO_DEBUG(c_debug_flag));
|
|
|
|
Tokenizer tkz(CircularBufferConfig{.name_ = "tokenrepl-input",
|
|
.max_capacity_ = 4*1024,
|
|
.max_captured_span_ = 128},
|
|
c_debug_flag);
|
|
|
|
const char * input_cstr = nullptr;;
|
|
|
|
size_t line_no = 1;
|
|
|
|
constexpr std::size_t c_maxlines = 25;
|
|
|
|
while (replxx_getline(interactive, 0 /*parser_stack_size*/, rx, &input_cstr))
|
|
{
|
|
//cout << "input: " << input << endl;
|
|
|
|
// reminder: input may contain multiple tokens
|
|
if (input_cstr && *input_cstr) {
|
|
auto [error, input] = tkz.buffer_input_line(input_cstr, false /*!eof*/);
|
|
|
|
if (log) {
|
|
log(xtag("msg", "buffered input line"));
|
|
log(xtag("input", input));
|
|
}
|
|
|
|
while (!input.empty())
|
|
{
|
|
auto [tk, consumed, error] = tkz.scan(input);
|
|
|
|
log && log(xtag("consumed", consumed), xtag("tk", tk));
|
|
|
|
if (tk.is_valid()) {
|
|
cout << tk << endl;
|
|
} else if (error.is_error()) {
|
|
cout << "tokenizer error: " << endl;
|
|
error.report(cout);
|
|
|
|
break;
|
|
}
|
|
|
|
input = input.after_prefix(consumed);
|
|
}
|
|
}
|
|
|
|
/* here: input.empty() or error encountered */
|
|
|
|
++line_no;
|
|
|
|
if (line_no > c_maxlines) {
|
|
cout << "always exit after " << c_maxlines << " lines of input" << endl;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/** end tokenrepl.cpp */
|