xo-reader: + DDefineSsm + utest
This commit is contained in:
parent
301a7c7623
commit
b5d2f3efab
21 changed files with 219 additions and 28 deletions
|
|
@ -44,6 +44,18 @@ xo_add_genfacetimpl(
|
|||
OUTPUT_CPP_DIR src/reader2
|
||||
)
|
||||
|
||||
# note: manual target; generated code committed to git
|
||||
xo_add_genfacetimpl(
|
||||
TARGET xo-reader2-facetimpl-syntaxstatemachine-definessm
|
||||
FACET_PKG xo_reader2
|
||||
FACET SyntaxStateMachine
|
||||
REPR DefineSsm
|
||||
INPUT idl/ISyntaxStateMachine_DDefineSsm.json5
|
||||
OUTPUT_HPP_DIR include/xo/reader2
|
||||
OUTPUT_IMPL_SUBDIR ssm
|
||||
OUTPUT_CPP_DIR src/reader2
|
||||
)
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# shared library
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,15 @@
|
|||
},
|
||||
],
|
||||
nonconst_methods: [
|
||||
{
|
||||
name: "on_def_token",
|
||||
doc: ["update state machine for incoming define-keyworkd-token @p tk"],
|
||||
return_type: "void",
|
||||
args: [
|
||||
{type: "const Token &", name: "tk"},
|
||||
{type: "ParserStateMachine *", name: "ps_psm"},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "on_if_token",
|
||||
doc: ["update state machine for incoming if-keyword-token @p tk"],
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
* @author Roland Conybeare, Jan 2026
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ParserStateMachine.hpp"
|
||||
#include "SyntaxStateMachine.hpp"
|
||||
#include "syntaxstatetype.hpp"
|
||||
|
|
@ -67,8 +69,24 @@ namespace xo {
|
|||
**/
|
||||
class DDefineSsm {
|
||||
public:
|
||||
using DArena = xo::mm::DArena;
|
||||
|
||||
public:
|
||||
/** @defgroup scm-define-ssm-facet constructors **/
|
||||
///@{
|
||||
|
||||
DDefineSsm();
|
||||
|
||||
/** create instance using memory from @p parser_mm **/
|
||||
static DDefineSsm * make(DArena & parser_mm);
|
||||
|
||||
/** start nested parser for a define-expression,
|
||||
* on top of parser state machine @p p_psm
|
||||
**/
|
||||
static void start(DArena & parser_mm,
|
||||
ParserStateMachine * p_psm);
|
||||
|
||||
///@}
|
||||
/** @defgroup scm-define-ssm-facet syntaxstatemachine facet methods **/
|
||||
///@{
|
||||
|
||||
|
|
@ -83,7 +101,14 @@ namespace xo {
|
|||
/** update state for this syntax on incoming token @p tk,
|
||||
* overall parser state in @p p_psm
|
||||
**/
|
||||
void on_if_token(const Token & tk, ParserStateMachine * p_psm);
|
||||
void on_def_token(const Token & tk,
|
||||
ParserStateMachine * p_psm);
|
||||
|
||||
/** update state for this syntax on incoming token @p tk,
|
||||
* overall parser state in @p p_psm
|
||||
**/
|
||||
void on_if_token(const Token & tk,
|
||||
ParserStateMachine * p_psm);
|
||||
|
||||
///@}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,11 @@ namespace xo {
|
|||
**/
|
||||
std::string_view get_expect_str() const noexcept;
|
||||
|
||||
/** update state for this syntax on incoming token @p tk,
|
||||
* overall parser state in @p p_psm
|
||||
**/
|
||||
void on_def_token(const Token & tk, ParserStateMachine * p_psm);
|
||||
|
||||
/** update state for this syntax on incoming token @p tk,
|
||||
* overall parser state in @p p_psm
|
||||
**/
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@ namespace xo {
|
|||
obj<AExpression> result_expr() const { return result_expr_; }
|
||||
const DString * error_description() const { return error_description_; }
|
||||
|
||||
bool is_incomplete() const { return result_type_ == parser_result_type::none; }
|
||||
bool is_expression() const { return result_type_ == parser_result_type::expression; }
|
||||
bool is_error() const { return result_type_ == parser_result_type::error; }
|
||||
|
||||
private:
|
||||
parser_result_type result_type_ = parser_result_type::none;
|
||||
obj<AExpression> result_expr_;
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ namespace xo {
|
|||
/** @defgroup scm-parserstatemachine-bookkeeping bookkeeping methods **/
|
||||
///@{
|
||||
|
||||
/** allocator for parsing stack and ssm's **/
|
||||
DArena & parser_alloc() noexcept { return parser_alloc_; }
|
||||
|
||||
/** establish toplevel @p ssm. Must have empty stack **/
|
||||
void establish_toplevel_ssm(obj<ASyntaxStateMachine> ssm);
|
||||
|
||||
|
|
@ -75,6 +78,9 @@ namespace xo {
|
|||
**/
|
||||
void on_token(const Token & tk);
|
||||
|
||||
/** update state for incoming define-token @p tk **/
|
||||
void on_def_token(const Token & tk);
|
||||
|
||||
/** update state for incoming if-token @p tk **/
|
||||
void on_if_token(const Token & tk);
|
||||
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ namespace xo {
|
|||
/** put parser into state for beginning of a translation unit
|
||||
* (i.e. input stream)
|
||||
**/
|
||||
void begin_translation_unit();
|
||||
void begin_batch_session();
|
||||
|
||||
/** include next token @p tk and increment parser state.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* Generated automagically from ingredients:
|
||||
* 1. code generator:
|
||||
* [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet]
|
||||
* [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
|
||||
* arguments:
|
||||
* --input [idl/SyntaxStateMachine.json5]
|
||||
* 2. jinja2 template for facet .hpp file:
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* Generated automagically from ingredients:
|
||||
* 1. code generator:
|
||||
* [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet]
|
||||
* [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
|
||||
* arguments:
|
||||
* --input [idl/SyntaxStateMachine.json5]
|
||||
* 2. jinja2 template for abstract facet .hpp file:
|
||||
|
|
@ -54,6 +54,8 @@ public:
|
|||
virtual std::string_view get_expect_str(Copaque data) const noexcept = 0;
|
||||
|
||||
// nonconst methods
|
||||
/** update state machine for incoming define-keyworkd-token @p tk **/
|
||||
virtual void on_def_token(Opaque data, const Token & tk, ParserStateMachine * ps_psm) = 0;
|
||||
/** update state machine for incoming if-keyword-token @p tk **/
|
||||
virtual void on_if_token(Opaque data, const Token & tk, ParserStateMachine * p_psm) = 0;
|
||||
///@}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* Generated automagically from ingredients:
|
||||
* 1. code generator:
|
||||
* [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet]
|
||||
* [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
|
||||
* arguments:
|
||||
* --input [idl/SyntaxStateMachine.json5]
|
||||
* 2. jinja2 template for abstract facet .hpp file:
|
||||
|
|
@ -59,6 +59,7 @@ namespace scm {
|
|||
[[noreturn]] std::string_view get_expect_str(Copaque) const noexcept override { _fatal(); }
|
||||
|
||||
// nonconst methods
|
||||
[[noreturn]] void on_def_token(Opaque, const Token &, ParserStateMachine *) override;
|
||||
[[noreturn]] void on_if_token(Opaque, const Token &, ParserStateMachine *) override;
|
||||
|
||||
///@}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* Generated automagically from ingredients:
|
||||
* 1. code generator:
|
||||
* [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet]
|
||||
* [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
|
||||
* arguments:
|
||||
* --input [idl/ISyntaxStateMachine_DExprSeqState.json5]
|
||||
* 2. jinja2 template for abstract facet .hpp file:
|
||||
|
|
@ -53,6 +53,8 @@ namespace xo {
|
|||
static std::string_view get_expect_str(const DExprSeqState & self) noexcept;
|
||||
|
||||
// non-const methods
|
||||
/** update state machine for incoming define-keyworkd-token @p tk **/
|
||||
static void on_def_token(DExprSeqState & self, const Token & tk, ParserStateMachine * ps_psm);
|
||||
/** update state machine for incoming if-keyword-token @p tk **/
|
||||
static void on_if_token(DExprSeqState & self, const Token & tk, ParserStateMachine * p_psm);
|
||||
///@}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* Generated automagically from ingredients:
|
||||
* 1. code generator:
|
||||
* [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet]
|
||||
* [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
|
||||
* arguments:
|
||||
* --input [idl/SyntaxStateMachine.json5]
|
||||
* 2. jinja2 template for abstract facet .hpp file:
|
||||
|
|
@ -50,6 +50,9 @@ namespace scm {
|
|||
}
|
||||
|
||||
// non-const methods
|
||||
void on_def_token(Opaque data, const Token & tk, ParserStateMachine * ps_psm) override {
|
||||
return I::on_def_token(_dcast(data), tk, ps_psm);
|
||||
}
|
||||
void on_if_token(Opaque data, const Token & tk, ParserStateMachine * p_psm) override {
|
||||
return I::on_if_token(_dcast(data), tk, p_psm);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* Generated automagically from ingredients:
|
||||
* 1. code generator:
|
||||
* [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet]
|
||||
* [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
|
||||
* arguments:
|
||||
* --input [idl/SyntaxStateMachine.json5]
|
||||
* 2. jinja2 template for abstract facet .hpp file:
|
||||
|
|
@ -55,6 +55,9 @@ public:
|
|||
}
|
||||
|
||||
// non-const methods (still const in router!)
|
||||
void on_def_token(const Token & tk, ParserStateMachine * ps_psm) {
|
||||
return O::iface()->on_def_token(O::data(), tk, ps_psm);
|
||||
}
|
||||
void on_if_token(const Token & tk, ParserStateMachine * p_psm) {
|
||||
return O::iface()->on_if_token(O::data(), tk, p_psm);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ set(SELF_SRCS
|
|||
ISyntaxStateMachine_DExprSeqState.cpp
|
||||
|
||||
DDefineSsm.cpp
|
||||
ISyntaxStateMachine_DDefineSsm.cpp
|
||||
|
||||
reader2_register_facets.cpp
|
||||
reader2_register_types.cpp
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
**/
|
||||
|
||||
#include "DDefineSsm.hpp"
|
||||
#include "ssm/ISyntaxStateMachine_DDefineSsm.hpp"
|
||||
|
||||
#ifdef NOT_YET
|
||||
#include "parserstatemachine.hpp"
|
||||
#include "expect_symbol_xs.hpp"
|
||||
|
|
@ -13,6 +15,9 @@
|
|||
#endif
|
||||
|
||||
namespace xo {
|
||||
using xo::facet::with_facet;
|
||||
using xo::facet::typeseq;
|
||||
|
||||
namespace scm {
|
||||
// ----- defexprstatetype -----
|
||||
|
||||
|
|
@ -46,16 +51,11 @@ namespace xo {
|
|||
define_xs::make() {
|
||||
return std::make_unique<define_xs>(define_xs(DefineExprAccess::make_empty()));
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
define_xs::start(parserstatemachine * p_psm)
|
||||
{
|
||||
scope log(XO_DEBUG(p_psm->debug_flag()));
|
||||
|
||||
p_psm->push_exprstate(define_xs::make());
|
||||
p_psm->top_exprstate().on_def_token(token_type::def(), p_psm);
|
||||
}
|
||||
// DDefineSsm::start
|
||||
|
||||
#ifdef NOT_YET
|
||||
define_xs::define_xs(rp<DefineExprAccess> def_expr)
|
||||
: exprstate(exprstatetype::defexpr),
|
||||
defxs_type_{defexprstatetype::def_0},
|
||||
|
|
@ -333,6 +333,36 @@ namespace xo {
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
DDefineSsm::DDefineSsm()
|
||||
: defstate_{defexprstatetype::def_0}
|
||||
{}
|
||||
|
||||
DDefineSsm *
|
||||
DDefineSsm::make(DArena & mm)
|
||||
{
|
||||
void * mem = mm.alloc(typeseq::id<DDefineSsm>(),
|
||||
sizeof(DDefineSsm));
|
||||
|
||||
return new (mem) DDefineSsm();
|
||||
}
|
||||
|
||||
void
|
||||
DDefineSsm::start(DArena & mm,
|
||||
ParserStateMachine * p_psm)
|
||||
{
|
||||
//scope log(XO_DEBUG(p_psm->debug_flag()));
|
||||
|
||||
assert(p_psm->stack());
|
||||
|
||||
DDefineSsm * define_ssm = DDefineSsm::make(mm);
|
||||
|
||||
obj<ASyntaxStateMachine> ssm
|
||||
= with_facet<ASyntaxStateMachine>::mkobj(define_ssm);
|
||||
|
||||
p_psm->push_ssm(ssm);
|
||||
p_psm->on_def_token(Token::def_token());
|
||||
}
|
||||
|
||||
syntaxstatetype
|
||||
DDefineSsm::ssm_type() const noexcept
|
||||
{
|
||||
|
|
@ -380,6 +410,21 @@ namespace xo {
|
|||
return "?expect";
|
||||
}
|
||||
|
||||
void
|
||||
DDefineSsm::on_def_token(const Token & tk,
|
||||
ParserStateMachine * p_psm)
|
||||
{
|
||||
if (this->defstate_ == defexprstatetype::def_0) {
|
||||
this->defstate_ = defexprstatetype::def_1;
|
||||
|
||||
// expect_symbol_xs::start(p_psm->parser_alloc(), p_psm);
|
||||
}
|
||||
|
||||
p_psm->illegal_input_on_token("DDefineSsm::on_define_token",
|
||||
tk,
|
||||
this->get_expect_str());
|
||||
}
|
||||
|
||||
void
|
||||
DDefineSsm::on_if_token(const Token & tk,
|
||||
ParserStateMachine * p_psm)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
**/
|
||||
|
||||
#include "DExprSeqState.hpp"
|
||||
#include "DDefineSsm.hpp"
|
||||
#include "ssm/ISyntaxStateMachine_DExprSeqState.hpp"
|
||||
|
||||
namespace xo {
|
||||
|
|
@ -73,13 +74,30 @@ namespace xo {
|
|||
return "impossible-DExprSeqState::get_expr_str";
|
||||
}
|
||||
|
||||
void
|
||||
DExprSeqState::on_def_token(const Token & tk,
|
||||
ParserStateMachine * p_psm)
|
||||
{
|
||||
(void)tk;
|
||||
|
||||
DDefineSsm::start(p_psm->parser_alloc(), p_psm);
|
||||
|
||||
/* keyword 'def' introduces a definition:
|
||||
* def pi : f64 = 3.14159265
|
||||
* def sq(x : f64) -> f64 { (x * x) }
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
DExprSeqState::on_if_token(const Token & tk,
|
||||
ParserStateMachine * p_psm)
|
||||
{
|
||||
switch (seqtype_) {
|
||||
case exprseqtype::toplevel_interactive:
|
||||
assert(false); // DfElseState::start(p_psm);
|
||||
p_psm->illegal_input_on_token("DExprSeqState::on_if_token",
|
||||
tk,
|
||||
this->get_expect_str());
|
||||
//assert(false); // DfElseState::start(p_psm);
|
||||
break;
|
||||
case exprseqtype::toplevel_batch:
|
||||
p_psm->illegal_input_on_token("DExprSeqState::on_if_token",
|
||||
|
|
|
|||
|
|
@ -34,6 +34,12 @@ ISyntaxStateMachine_Any::_valid
|
|||
|
||||
// nonconst methods
|
||||
|
||||
auto
|
||||
ISyntaxStateMachine_Any::on_def_token(Opaque, const Token &, ParserStateMachine *) -> void
|
||||
{
|
||||
_fatal();
|
||||
}
|
||||
|
||||
auto
|
||||
ISyntaxStateMachine_Any::on_if_token(Opaque, const Token &, ParserStateMachine *) -> void
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* Generated automagically from ingredients:
|
||||
* 1. code generator:
|
||||
* [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet]
|
||||
* [/Users/roland/proj/xo-umbrella2/xo-facet/codegen/genfacet]
|
||||
* arguments:
|
||||
* --input [idl/ISyntaxStateMachine_DExprSeqState.json5]
|
||||
* 2. jinja2 template for abstract facet .hpp file:
|
||||
|
|
@ -28,7 +28,16 @@ namespace xo {
|
|||
}
|
||||
|
||||
auto
|
||||
ISyntaxStateMachine_DExprSeqState::on_if_token(DExprSeqState & self, const Token & tk, ParserStateMachine * p_psm) -> void
|
||||
ISyntaxStateMachine_DExprSeqState::on_def_token(DExprSeqState & self,
|
||||
const Token & tk,
|
||||
ParserStateMachine * p_psm) -> void
|
||||
{
|
||||
self.on_def_token(tk, p_psm);
|
||||
}
|
||||
auto
|
||||
ISyntaxStateMachine_DExprSeqState::on_if_token(DExprSeqState & self,
|
||||
const Token & tk,
|
||||
ParserStateMachine * p_psm) -> void
|
||||
{
|
||||
self.on_if_token(tk, p_psm);
|
||||
}
|
||||
|
|
@ -36,4 +45,4 @@ namespace xo {
|
|||
} /*namespace scm*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end ISyntaxStateMachine_DExprSeqState.cpp */
|
||||
/* end ISyntaxStateMachine_DExprSeqState.cpp */
|
||||
|
|
|
|||
|
|
@ -48,8 +48,7 @@ namespace xo {
|
|||
|
||||
auto alloc = with_facet<AAllocator>::mkobj(&parser_alloc_);
|
||||
|
||||
this->stack_ = ParserStack::push(nullptr /*stack*/,
|
||||
alloc, ssm);
|
||||
this->stack_ = ParserStack::push(nullptr /*stack*/, alloc, ssm);
|
||||
this->parser_alloc_ckp_ = parser_alloc_.checkpoint();
|
||||
}
|
||||
|
||||
|
|
@ -96,11 +95,14 @@ namespace xo {
|
|||
}
|
||||
|
||||
switch (tk.tk_type()) {
|
||||
case tokentype::tk_def:
|
||||
this->on_def_token(tk);
|
||||
break;
|
||||
|
||||
case tokentype::tk_if:
|
||||
this->on_if_token(tk);
|
||||
break;
|
||||
|
||||
|
||||
// all the not-yet handled cases
|
||||
case tokentype::tk_invalid:
|
||||
case tokentype::tk_bool:
|
||||
|
|
@ -133,7 +135,6 @@ namespace xo {
|
|||
case tokentype::tk_cmpeq:
|
||||
case tokentype::tk_cmpne:
|
||||
case tokentype::tk_type:
|
||||
case tokentype::tk_def:
|
||||
case tokentype::tk_lambda:
|
||||
case tokentype::tk_then:
|
||||
case tokentype::tk_else:
|
||||
|
|
@ -141,12 +142,21 @@ namespace xo {
|
|||
case tokentype::tk_in:
|
||||
case tokentype::tk_end:
|
||||
case tokentype::N:
|
||||
throw std::runtime_error(tostr("NOT IMPLEMENTED",
|
||||
throw std::runtime_error(tostr("ParserStateMachin::on_token:",
|
||||
"NOT IMPLEMENTED",
|
||||
xtag("token", tk)));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ParserStateMachine::on_def_token(const Token & tk)
|
||||
{
|
||||
scope log(XO_DEBUG(debug_flag_), xtag("tk", tk));
|
||||
|
||||
stack_->top().on_def_token(tk, this);
|
||||
}
|
||||
|
||||
void
|
||||
ParserStateMachine::on_if_token(const Token & tk)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ namespace xo {
|
|||
}
|
||||
|
||||
void
|
||||
SchematikaParser::begin_translation_unit() {
|
||||
SchematikaParser::begin_batch_session() {
|
||||
DExprSeqState::establish_batch(*(psm_.expr_alloc()), &psm_);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,13 +62,38 @@ namespace xo {
|
|||
|
||||
SchematikaParser parser(config, &expr_alloc, false /*debug_flag*/);
|
||||
|
||||
parser.begin_translation_unit();
|
||||
parser.begin_batch_session();
|
||||
|
||||
// after begin_translation_unit, parser has toplevel exprseq
|
||||
// but is still "at toplevel" in the sense of ready for input
|
||||
REQUIRE(parser.has_incomplete_expr() == false);
|
||||
}
|
||||
|
||||
TEST_CASE("SchematikaParser-batch-def", "[reader2][SchematikaParser]")
|
||||
{
|
||||
ArenaConfig config;
|
||||
config.name_ = "test-arena";
|
||||
config.size_ = 16 * 1024;
|
||||
|
||||
DArena expr_arena = DArena::map(config);
|
||||
obj<AAllocator> expr_alloc = with_facet<AAllocator>::mkobj(&expr_arena);
|
||||
|
||||
SchematikaParser parser(config, &expr_alloc, false /*debug_flag*/);
|
||||
|
||||
parser.begin_batch_session();
|
||||
|
||||
auto & result = parser.on_token(Token::def_token());
|
||||
|
||||
// define-expressions not properly implemented
|
||||
|
||||
// after begin_interactive_session, parser has toplevel exprseq
|
||||
// but is still "at toplevel" in the sense of ready for input
|
||||
REQUIRE(parser.has_incomplete_expr() == true);
|
||||
REQUIRE(result.is_error());
|
||||
|
||||
REQUIRE(result.error_description());
|
||||
}
|
||||
|
||||
TEST_CASE("SchematikaParser-interactive-if", "[reader2][SchematikaParser]")
|
||||
{
|
||||
ArenaConfig config;
|
||||
|
|
@ -82,11 +107,16 @@ namespace xo {
|
|||
|
||||
parser.begin_interactive_session();
|
||||
|
||||
parser.on_token(Token::if_token());
|
||||
auto & result = parser.on_token(Token::if_token());
|
||||
|
||||
// after begin_interactive_session, parser has toplevel exprseq
|
||||
// but is still "at toplevel" in the sense of ready for input
|
||||
REQUIRE(parser.has_incomplete_expr() == false);
|
||||
|
||||
REQUIRE(result.is_error());
|
||||
|
||||
// illegal input on token
|
||||
REQUIRE(result.error_description());
|
||||
}
|
||||
|
||||
} /*namespace ut*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue