diff --git a/xo-arena/include/xo/arena/DArena.hpp b/xo-arena/include/xo/arena/DArena.hpp index 8d9372a0..ffd710f0 100644 --- a/xo-arena/include/xo/arena/DArena.hpp +++ b/xo-arena/include/xo/arena/DArena.hpp @@ -64,8 +64,9 @@ namespace xo { /** @brief Checkpoint for unwinding arena state **/ struct Checkpoint { + Checkpoint() = default; explicit Checkpoint(std::byte * x) : free_{x} {} - std::byte * free_; + std::byte * free_ = nullptr; }; ///@} diff --git a/xo-reader2/include/xo/reader2/DExprSeqState.hpp b/xo-reader2/include/xo/reader2/DExprSeqState.hpp index f1faed86..f081691a 100644 --- a/xo-reader2/include/xo/reader2/DExprSeqState.hpp +++ b/xo-reader2/include/xo/reader2/DExprSeqState.hpp @@ -38,11 +38,11 @@ namespace xo { explicit DExprSeqState(exprseqtype ty); /** start interactive top-level session **/ - static void start_interactive(obj mm, - ParserStateMachine * p_psm); + static void establish_interactive(obj mm, + ParserStateMachine * p_psm); /** start non-interactive top-level session **/ - static void start_batch(obj mm, - ParserStateMachine * p_psm); + static void establish_batch(obj mm, + ParserStateMachine * p_psm); public: /** @defgroup scm-exprseq-ssm-facet syntaxstatemachine facet methods **/ diff --git a/xo-reader2/include/xo/reader2/ParserStack.hpp b/xo-reader2/include/xo/reader2/ParserStack.hpp index 424be42b..4a87de7f 100644 --- a/xo-reader2/include/xo/reader2/ParserStack.hpp +++ b/xo-reader2/include/xo/reader2/ParserStack.hpp @@ -28,8 +28,9 @@ namespace xo { /** create new top of stack for syntax @p ssm, using memory from @p mm. * previous stack given by @p parent **/ - ParserStack * push(obj mm, - obj ssm); + static ParserStack * push(ParserStack * stack, + obj mm, + obj ssm); obj top() const noexcept { return ssm_; } ParserStack * parent() const noexcept { return parent_; } diff --git a/xo-reader2/include/xo/reader2/ParserStateMachine.hpp b/xo-reader2/include/xo/reader2/ParserStateMachine.hpp index cae4a551..c3c179ad 100644 --- a/xo-reader2/include/xo/reader2/ParserStateMachine.hpp +++ b/xo-reader2/include/xo/reader2/ParserStateMachine.hpp @@ -41,16 +41,28 @@ namespace xo { const ParserResult & result() const noexcept { return result_; } obj expr_alloc() const noexcept { return expr_alloc_; } + /** true iff state machine is currently idle (at top-level) **/ + bool is_at_toplevel() const noexcept; + + /** true iff state machine currently has incomplete expression **/ + bool has_incomplete_expr() const noexcept; + ///@} /** @defgroup scm-parserstatemachine-bookkeeping bookkeeping methods **/ ///@{ + /** establish toplevel @p ssm. Must have empty stack **/ + void establish_toplevel_ssm(obj ssm); + /** push syntax @p ssm onto @ref stack_ **/ void push_ssm(obj ssm); /** reset result to none **/ - void reset_result() { result_ = ParserResult(); } + void reset_result(); + + /** reset after reporting error **/ + void clear_error_reset(); ///@} @@ -89,6 +101,7 @@ namespace xo { ///@} private: + /** Arena for internal parsing stack. * Must be owned exclusively because destructively * modified as parser completes parsing of each sub-expression @@ -97,6 +110,12 @@ namespace xo { **/ DArena parser_alloc_; + /** Checkpoint of toplevel parser allocator. + * Retore parser_alloc to this checkpoint to proceed + * after encountering a parsing error. + **/ + DArena::Checkpoint parser_alloc_ckp_; + /** parser stack. Memory from @ref parser_alloc_ **/ ParserStack * stack_ = nullptr; diff --git a/xo-reader2/src/reader2/DExprSeqState.cpp b/xo-reader2/src/reader2/DExprSeqState.cpp index 7d2368e5..4d6ae613 100644 --- a/xo-reader2/src/reader2/DExprSeqState.cpp +++ b/xo-reader2/src/reader2/DExprSeqState.cpp @@ -30,25 +30,21 @@ namespace xo { } void - DExprSeqState::start_interactive(obj mm, - ParserStateMachine * p_psm) + DExprSeqState::establish_interactive(obj mm, + ParserStateMachine * p_psm) { - - - p_psm->push_ssm(make_exprseq_ssm(mm, - exprseqtype::toplevel_interactive)); + p_psm->establish_toplevel_ssm(make_exprseq_ssm + (mm, + exprseqtype::toplevel_interactive)); } void - DExprSeqState::start_batch(obj mm, - ParserStateMachine * p_psm) + DExprSeqState::establish_batch(obj mm, + ParserStateMachine * p_psm) { - (void)mm; - (void)p_psm; -#ifdef NOT_YET - p_psm->push_ssm(make_exprseq_ssm(mm, - exprseqtype::toplevel_batch)); -#endif + p_psm->establish_toplevel_ssm(make_exprseq_ssm + (mm, + exprseqtype::toplevel_batch)); } // SyntaxStateMachine facet methods diff --git a/xo-reader2/src/reader2/ParserStack.cpp b/xo-reader2/src/reader2/ParserStack.cpp index 3648cb4d..5b416c54 100644 --- a/xo-reader2/src/reader2/ParserStack.cpp +++ b/xo-reader2/src/reader2/ParserStack.cpp @@ -16,14 +16,15 @@ namespace xo { {} ParserStack * - ParserStack::push(obj mm, + ParserStack::push(ParserStack * stack, + obj mm, obj ssm) { void * mem = mm.alloc(typeseq::id(), sizeof(ParserStack)); - return new (mem) ParserStack(ssm, parent_); + return new (mem) ParserStack(ssm, stack); } } /*namespace scm*/ diff --git a/xo-reader2/src/reader2/ParserStateMachine.cpp b/xo-reader2/src/reader2/ParserStateMachine.cpp index c2297da4..4f54a584 100644 --- a/xo-reader2/src/reader2/ParserStateMachine.cpp +++ b/xo-reader2/src/reader2/ParserStateMachine.cpp @@ -23,6 +23,35 @@ namespace xo { { } + bool + ParserStateMachine::is_at_toplevel() const noexcept + { + return ((stack_ == nullptr) + || (stack_->parent() == nullptr)); + } + + bool + ParserStateMachine::has_incomplete_expr() const noexcept + { + // don't count toplevel expression + + return !(this->is_at_toplevel()); + } + + void + ParserStateMachine::establish_toplevel_ssm(obj ssm) + { + scope log(XO_DEBUG(debug_flag_)); + + assert(stack_ == nullptr); + + auto alloc = with_facet::mkobj(&parser_alloc_); + + this->stack_ = ParserStack::push(nullptr /*stack*/, + alloc, ssm); + this->parser_alloc_ckp_ = parser_alloc_.checkpoint(); + } + void ParserStateMachine::push_ssm(obj ssm) { @@ -32,7 +61,24 @@ namespace xo { auto alloc = with_facet::mkobj(&parser_alloc_); - this->stack_ = stack_->push(alloc, ssm); + this->stack_ = ParserStack::push(stack_, alloc, ssm); + } + + void + ParserStateMachine::reset_result() + { + this->result_ = ParserResult(); + } + + void + ParserStateMachine::clear_error_reset() + { + this->reset_result(); + + while (stack_ && stack_->parent()) + stack_ = stack_->parent(); + + this->parser_alloc_.restore(parser_alloc_ckp_); } void diff --git a/xo-reader2/src/reader2/SchematikaParser.cpp b/xo-reader2/src/reader2/SchematikaParser.cpp index 712c55d8..2e607e77 100644 --- a/xo-reader2/src/reader2/SchematikaParser.cpp +++ b/xo-reader2/src/reader2/SchematikaParser.cpp @@ -25,26 +25,23 @@ namespace xo { bool SchematikaParser::is_at_toplevel() const { - return psm_.stack() == nullptr; + return psm_.is_at_toplevel(); } bool SchematikaParser::has_incomplete_expr() const { - /* (don't count toplevel exprseq) */ - ParserStack * stack = psm_.stack(); - if (!stack) - return false; - return stack->parent() != nullptr; + return !(this->is_at_toplevel()); } void SchematikaParser::begin_interactive_session() { - DExprSeqState::start_interactive(psm_.expr_alloc(), &psm_); + DExprSeqState::establish_interactive(psm_.expr_alloc(), &psm_); + } void SchematikaParser::begin_translation_unit() { - DExprSeqState::start_batch(psm_.expr_alloc(), &psm_); + DExprSeqState::establish_batch(psm_.expr_alloc(), &psm_); } const ParserResult & @@ -75,8 +72,7 @@ namespace xo { void SchematikaParser::reset_to_idle_toplevel() { - psm_.reset_stack(); - psm_.reset_result(); + psm_.clear_error_reset(); } /*reset_to_idle_toplevel*/ void