/* @file reader.cpp */ #include "reader.hpp" namespace xo { namespace scm { void reader::begin_translation_unit() { parser_.begin_translation_unit(); } reader_result reader::end_translation_unit() { return this->read_expr(span_type(nullptr, nullptr), true /*eof*/); } reader_result reader::read_expr(const span_type & input_arg, bool eof) { constexpr bool c_debug_flag = true; scope log(XO_DEBUG(c_debug_flag)); span_type input = input_arg; /* input text-span consumed by this call. * Always comprises some number (possibly 0) * of complete tokens, along with any leading * whitespace */ span_type expr_span = input.prefix(0ul); while (!input.empty()) { /* read one token from input */ auto sr = this->tokenizer_.scan2(input, eof); const auto & tk = sr.first; const span_type & used_span = sr.second; log && log(xtag("used_span", used_span)); log && log(xtag("input.pre", input)); input = input.after_prefix(used_span); log && log(xtag("expr_span.pre", expr_span)); expr_span += used_span; if (tk.is_valid()) { /* forward just-read token to parser */ auto expr = this->parser_.include_token(tk); if (expr) { log && log(xtag("outcome", "victory!"), xtag("expr", expr)); /* token completes an expression -> victory */ return reader_result(expr, expr_span); } else { /* token did not complete an expression * (e.g. token for '[') * * input span may contain more tokens -> iterate */ } } else { assert(input.empty()); /* no more tokens in input */ break; } } /* control here: either * 1. input.empty (perhaps ate some whitespace, ok) * 2. missing or incomplete token (ok unless eof) */ if (eof) { if (parser_.has_incomplete_expr()) { throw std::runtime_error ("reader::read_expr" ": eof reached with incomplete expression"); } if (tokenizer_.has_prefix()) { throw std::runtime_error ("reader::read_expr" ": unintelligible input recognized at eof"); } } log && log(xtag("outcome", "noop")); return reader_result(nullptr, expr_span); } } /*namespace scm*/ } /*namespace xo*/ /* end reader.cpp */