Add 'xo-reader/' from commit 'c46c0f1cc4'

git-subtree-dir: xo-reader
git-subtree-mainline: dacdeb2cd7
git-subtree-split: c46c0f1cc4
This commit is contained in:
Roland Conybeare 2025-05-11 01:40:20 -05:00
commit 0ae98c211d
48 changed files with 5184 additions and 0 deletions

View file

@ -0,0 +1,29 @@
# parser/CMakeLists.txt
set(SELF_LIB xo_reader)
set(SELF_SRCS
parser.cpp
parserstatemachine.cpp
reader.cpp
exprstate.cpp
exprstatestack.cpp
define_xs.cpp
progress_xs.cpp
paren_xs.cpp
sequence_xs.cpp
exprseq_xs.cpp
expect_expr_xs.cpp
expect_symbol_xs.cpp
expect_formal_xs.cpp
expect_formal_arglist_xs.cpp
expect_type_xs.cpp
lambda_xs.cpp
let1_xs.cpp
envframestack.cpp
envframe.cpp)
xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS})
xo_dependency(${SELF_LIB} xo_expression)
xo_dependency(${SELF_LIB} xo_tokenizer)
# end CMakeLists.txt

View file

@ -0,0 +1,276 @@
/* @file define_xs.cpp */
#include "define_xs.hpp"
#include "exprstatestack.hpp"
#include "parserstatemachine.hpp"
#include "expect_symbol_xs.hpp"
#include "expect_expr_xs.hpp"
#include "expect_type_xs.hpp"
namespace xo {
namespace scm {
// ----- defexprstatetype -----
const char *
defexprstatetype_descr(defexprstatetype x) {
switch(x) {
case defexprstatetype::invalid: return "invalid";
case defexprstatetype::def_0: return "def_0";
case defexprstatetype::def_1: return "def_1";
case defexprstatetype::def_2: return "def_2";
case defexprstatetype::def_3: return "def_3";
case defexprstatetype::def_4: return "def_4";
case defexprstatetype::def_5: return "def_5";
case defexprstatetype::def_6: return "def_6";
case defexprstatetype::n_defexprstatetype: break;
}
return "???defexprstatetype";
}
std::ostream &
operator<<(std::ostream & os, defexprstatetype x) {
os << defexprstatetype_descr(x);
return os;
}
// ----- define_xs -----
std::unique_ptr<define_xs>
define_xs::make() {
return std::make_unique<define_xs>(define_xs(DefineExprAccess::make_empty()));
}
void
define_xs::start(parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
p_psm->push_exprstate(define_xs::make());
p_psm->top_exprstate().on_def_token(token_type::def(), p_psm);
}
define_xs::define_xs(rp<DefineExprAccess> def_expr)
: exprstate(exprstatetype::defexpr),
defxs_type_{defexprstatetype::def_0},
def_expr_{std::move(def_expr)}
{}
void
define_xs::on_expr(ref::brw<Expression> expr,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("defxs_type", defxs_type_));
if (this->defxs_type_ == defexprstatetype::def_5) {
/* have all the ingredients to create an expression
* representing a definition
*
* 1. if ir_type is a symbol, interpret as variable name.
* Need to be able to locate variable by type
* 2. if ir_type is an expression, adopt as rhs
*/
rp<Expression> rhs_value = expr.promote();
if (this->cvt_expr_)
this->cvt_expr_->assign_arg(rhs_value);
else
this->def_expr_->assign_rhs(rhs_value);;
rp<Expression> def_expr = this->def_expr_;
this->defxs_type_ = defexprstatetype::def_6;
} else {
exprstate::on_expr(expr, p_psm);
}
}
void
define_xs::on_expr_with_semicolon(ref::brw<Expression> expr,
parserstatemachine * p_psm)
{
this->on_expr(expr, p_psm);
/* semicolon is allowed to terminate def expr */
this->on_semicolon_token(token_type::semicolon(), p_psm);
}
void
define_xs::on_symbol(const std::string & symbol_name,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log("defxs_type", defxs_type_);
if (this->defxs_type_ == defexprstatetype::def_1) {
this->defxs_type_ = defexprstatetype::def_2;
this->def_expr_->assign_lhs_name(symbol_name);
return;
} else {
exprstate::on_symbol(symbol_name, p_psm);
}
}
void
define_xs::on_typedescr(TypeDescr td,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log("defxs_type", defxs_type_);
if (this->defxs_type_ == defexprstatetype::def_3) {
this->defxs_type_ = defexprstatetype::def_4;
this->cvt_expr_ = ConvertExprAccess::make(td /*dest_type*/,
nullptr /*source_expr*/);
this->def_expr_->assign_rhs(this->cvt_expr_);
//this->def_lhs_td_ = td;
return;
} else {
exprstate::on_typedescr(td, p_psm);
}
}
void
define_xs::on_def_token(const token_type & tk,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log("defxs_type", defxs_type_);
if (this->defxs_type_ == defexprstatetype::def_0) {
this->defxs_type_ = defexprstatetype::def_1;
expect_symbol_xs::start(p_psm);
} else {
exprstate::on_def_token(tk, p_psm);
}
}
void
define_xs::on_colon_token(const token_type & tk,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log("defxs_type", defxs_type_);
if (this->defxs_type_ == defexprstatetype::def_2) {
this->defxs_type_ = defexprstatetype::def_3;
expect_type_xs::start(p_psm);
} else {
exprstate::on_colon_token(tk, p_psm);
}
}
void
define_xs::on_semicolon_token(const token_type & tk,
parserstatemachine * p_psm)
{
/* def expr consumes semicolon */
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log("defxs_type", defxs_type_);
if (this->defxs_type_ == defexprstatetype::def_6) {
rp<Expression> expr = this->def_expr_;
std::unique_ptr<exprstate> self = p_psm->pop_exprstate();
p_psm->top_exprstate().on_expr(expr, p_psm);
} else {
exprstate::on_semicolon_token(tk, p_psm);
}
}
void
define_xs::on_singleassign_token(const token_type & tk,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * self_name = "define_xs::on_singleassign_token";
log && log("defxs_type", defxs_type_);
/*
* def foo = 1 ;
* def foo : f64 = 1 ;
* ^ ^ ^ ^ ^ ^ ^ ^
* | | | | | | | (done)
* | | | | | | def_6
* | | | | | def_5:expect_rhs_expression
* | | | | def_4
* | | | def_3:expect_type
* | | def_2
* | def_1:expect_symbol
* expect_toplevel_expression_sequence
*
* note that we skip from def_2 -> def_5 if '=' instead of ':'
*/
if ((this->defxs_type_ == defexprstatetype::def_2)
|| (this->defxs_type_ == defexprstatetype::def_4))
{
this->defxs_type_ = defexprstatetype::def_5;
expect_expr_xs::start(p_psm);
} else {
this->illegal_input_error(self_name, tk);
}
}
void
define_xs::on_rightparen_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * self_name = "define_xs::on_rightparen";
this->illegal_input_error(self_name, tk);
}
void
define_xs::on_f64_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * self_name = "define_xs::on_f64";
this->illegal_input_error(self_name, tk);
}
void
define_xs::print(std::ostream & os) const {
os << "<define_xs"
<< xtag("this", (void*)this)
//<< xtag("type", exs_type_)
<< xtag("defxs_type", defxs_type_);
//if (def_expr_)
// os << xtag("def_expr", def_expr_);
//if (cvt_expr_)
// os << xtag("cvt_expr", cvt_expr_);
os << ">";
}
} /*namespace scm*/
} /*namespace xo*/
/* end define_xs.cpp */

View file

@ -0,0 +1,34 @@
/* file envframe.cpp
*
* author: Roland Conybeare
*/
#include "envframe.hpp"
#include "xo/indentlog/print/vector.hpp"
namespace xo {
using xo::ast::Variable;
namespace scm {
rp<Variable>
envframe::lookup(const std::string & x) const {
for (const auto & var : argl_) {
if (x == var->name())
return var;
}
return nullptr;
}
void
envframe::print(std::ostream & os) const {
os << "<envframe"
<< xtag("argl", argl_)
<< ">";
}
} /*namespace scm */
} /*namespace xo*/
/* end envframe.cpp */

View file

@ -0,0 +1,86 @@
/* file envframestack.cpp
*
* author: Roland Conybeare
*/
#include "envframestack.hpp"
namespace xo {
using xo::ast::Variable;
namespace scm {
envframe &
envframestack::top_envframe() {
std::size_t z = stack_.size();
if (z == 0) {
throw std::runtime_error
("parser::top_exprstate: unexpected empty stack");
}
return stack_[z-1];
}
void
envframestack::push_envframe(envframe frame) {
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag),
xtag("frame", frame));
std::size_t z = stack_.size();
stack_.resize(z+1);
stack_[z] = std::move(frame);
}
void
envframestack::pop_envframe() {
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
std::size_t z = stack_.size();
if (z > 0) {
//std::unique_ptr<exprstate> top = std::move(stack_[z-1]);
stack_.resize(z-1);
//return top;
} else {
//return nullptr;
}
}
rp<Variable>
envframestack::lookup(const std::string & x) const {
for (std::size_t i = 0, z = this->size(); i < z; ++i) {
const auto & frame = (*this)[i];
auto retval = frame.lookup(x);
if (retval)
return retval;
}
return nullptr;
}
void
envframestack::print(std::ostream & os) const {
os << "<envframestack"
<< xtag("size", stack_.size())
<< std::endl;
for (std::size_t i = 0, z = stack_.size(); i < z; ++i) {
os << " [" << z-i-1 << "] "
<< stack_[i]
<< std::endl;
}
os << ">" << std::endl;
}
} /*namespace scm*/
} /*namespace xo*/
/* end envframestack.cpp */

View file

@ -0,0 +1,227 @@
/* file expect_expr_xs.cpp
*
* author: Roland Conybeare
*/
#include "expect_expr_xs.hpp"
#include "parserstatemachine.hpp"
#include "exprstatestack.hpp"
#include "lambda_xs.hpp"
#include "define_xs.hpp"
#include "paren_xs.hpp"
#include "sequence_xs.hpp"
#include "progress_xs.hpp"
#include "xo/expression/Lambda.hpp"
#include "xo/expression/Constant.hpp"
namespace xo {
using xo::ast::Constant;
namespace scm {
std::unique_ptr<expect_expr_xs>
expect_expr_xs::make(bool allow_defs,
bool cxl_on_rightbrace)
{
return std::make_unique<expect_expr_xs>(expect_expr_xs(allow_defs,
cxl_on_rightbrace));
}
void
expect_expr_xs::start(bool allow_defs,
bool cxl_on_rightbrace,
parserstatemachine * p_psm)
{
p_psm->push_exprstate(expect_expr_xs::make(allow_defs,
cxl_on_rightbrace));
}
void
expect_expr_xs::start(parserstatemachine * p_psm) {
start(false /*!allow_defs*/,
false /*!cxl_on_rightbrace*/,
p_psm);
}
expect_expr_xs::expect_expr_xs(bool allow_defs,
bool cxl_on_rightbrace)
: exprstate(exprstatetype::expect_rhs_expression),
allow_defs_{allow_defs},
cxl_on_rightbrace_{cxl_on_rightbrace}
{}
void
expect_expr_xs::on_def_token(const token_type & tk,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
if (allow_defs_) {
define_xs::start(p_psm);
} else {
exprstate::on_def_token(tk, p_psm);
}
}
void
expect_expr_xs::on_lambda_token(const token_type & /*tk*/,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
//constexpr const char * self_name = "exprstate::on_leftparen";
lambda_xs::start(p_psm);
}
void
expect_expr_xs::on_leftparen_token(const token_type & /*tk*/,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
//constexpr const char * self_name = "exprstate::on_leftparen";
/* push lparen_0 to remember to look for subsequent rightparen. */
paren_xs::start(p_psm);
}
void
expect_expr_xs::on_leftbrace_token(const token_type & /*tk*/,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
/* push lparen_0 to remember to look for subsequent rightparen. */
sequence_xs::start(p_psm);
}
void
expect_expr_xs::on_rightbrace_token(const token_type & tk,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
if (cxl_on_rightbrace_) {
auto self = p_psm->pop_exprstate();
/* do not call .on_expr(), since '}' cancelled */
p_psm->on_rightbrace_token(tk);
} else {
exprstate::on_rightbrace_token(tk, p_psm);
}
}
void
expect_expr_xs::on_symbol_token(const token_type & tk,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("tk", tk));
/* various possibilities when looking for rhs expression:
*
* x := y // (1)
* x := f(a) // (2)
* x := f(a,b) // (3)
*
* need lookahead token following symbol to distinguish
* between (1) (symbol completes rhs expression)
* and {(2), (3)} (symbol is function call)
*/
rp<Variable> var = p_psm->lookup_var(tk.text());
if (!var) {
throw std::runtime_error
(tostr("expect_expr_xs::on_symbol_token",
": unknown symbol",
xtag("name", tk.text())));
}
/* e.g.
* def pi = 3.14159265;
* def mypi = pi;
* ^
* def pi2 = pi * 2;
* ^
* def y = foo(pi2);
* ^
*/
progress_xs::start(var, p_psm);
#ifdef NOT_YET
p_stack->push_exprstate(exprstate(exprstatetype::expr_progress,
Variable::make(name, type)));
#endif
#ifdef LATER
p_psm->pop_exprstate();
p_psm->top_exprstate().on_symbol(tk.text(),
p_stack, p_emit_expr);
#endif
return;
}
void
expect_expr_xs::on_f64_token(const token_type & tk,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
//constexpr const char * self_name = "exprstate::on_f64_token";
/* e.g.
* def pi = 3.14159265;
* \---tk---/
*/
progress_xs::start
(Constant<double>::make(tk.f64_value()),
p_psm);
}
void
expect_expr_xs::on_expr(ref::brw<Expression> expr,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("exstype", this->exs_type_),
xtag("expr", expr.promote()));
std::unique_ptr<exprstate> self = p_psm->pop_exprstate();
p_psm->on_expr(expr);
} /*on_expr*/
void
expect_expr_xs::on_expr_with_semicolon(ref::brw<Expression> expr,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("exstype", this->exs_type_),
xtag("expr", expr.promote()));
std::unique_ptr<exprstate> self = p_psm->pop_exprstate();
p_psm->on_expr_with_semicolon(expr);
} /*on_expr_with_semicolon*/
} /*namespace scm*/
} /*namespace xo*/
/* end expect_expr_xs.cpp */

View file

@ -0,0 +1,113 @@
/* file expect_formal_arglist_xs.cpp
*
* author: Roland Conybeare
*/
#include "expect_formal_arglist_xs.hpp"
#include "parserstatemachine.hpp"
#include "exprstatestack.hpp"
#include "expect_formal_xs.hpp"
#include "expect_symbol_xs.hpp"
#include "xo/expression/Variable.hpp"
#include "xo/indentlog/print/vector.hpp"
namespace xo {
namespace scm {
const char *
formalarglstatetype_descr(formalarglstatetype x) {
switch (x) {
case formalarglstatetype::invalid:
return "invalid";
case formalarglstatetype::argl_0:
return "argl_0";
case formalarglstatetype::argl_1a:
return "argl_1a";
case formalarglstatetype::argl_1b:
return "argl_1b";
case formalarglstatetype::n_formalarglstatetype:
break;
}
return "?formalarglstatetype";
}
std::unique_ptr<expect_formal_arglist_xs>
expect_formal_arglist_xs::make() {
return std::make_unique<expect_formal_arglist_xs>
(expect_formal_arglist_xs());
}
void
expect_formal_arglist_xs::start(parserstatemachine * p_psm)
{
p_psm->push_exprstate(expect_formal_arglist_xs::make());
}
expect_formal_arglist_xs::expect_formal_arglist_xs()
: exprstate(exprstatetype::expect_formal_arglist),
farglxs_type_{formalarglstatetype::argl_0}
{}
void
expect_formal_arglist_xs::on_leftparen_token(const token_type & tk,
parserstatemachine * p_psm)
{
if (farglxs_type_ == formalarglstatetype::argl_0) {
this->farglxs_type_ = formalarglstatetype::argl_1a;
/* TODO: refactor to have setup method on each exprstate */
expect_formal_xs::start(p_psm);
} else {
exprstate::on_leftparen_token(tk, p_psm);
}
}
void
expect_formal_arglist_xs::on_formal(const rp<Variable> & formal,
parserstatemachine * p_psm)
{
if (farglxs_type_ == formalarglstatetype::argl_1a) {
this->farglxs_type_ = formalarglstatetype::argl_1b;
this->argl_.push_back(formal);
} else {
exprstate::on_formal(formal, p_psm);
}
}
void
expect_formal_arglist_xs::on_comma_token(const token_type & tk,
parserstatemachine * p_psm)
{
if (farglxs_type_ == formalarglstatetype::argl_1b) {
this->farglxs_type_ = formalarglstatetype::argl_1a;
expect_formal_xs::start(p_psm);
} else {
exprstate::on_comma_token(tk, p_psm);
}
}
void
expect_formal_arglist_xs::on_rightparen_token(const token_type & tk,
parserstatemachine * p_psm)
{
if (farglxs_type_ == formalarglstatetype::argl_1b) {
std::unique_ptr<exprstate> self = p_psm->pop_exprstate();
p_psm->top_exprstate().on_formal_arglist(this->argl_, p_psm);
} else {
exprstate::on_rightparen_token(tk, p_psm);
}
}
void
expect_formal_arglist_xs::print(std::ostream & os) const {
os << "<expect_formal_arglist_xs"
<< xtag("type", farglxs_type_);
os << xtag("farglxs_type", farglxs_type_);
os << xtag("argl", argl_);
os << ">";
}
} /*namespace scm*/
} /*namespace xo*/
/* end expect_formal_arglist_xs.cpp */

View file

@ -0,0 +1,109 @@
/* file expect_formal_xs.cpp
*
* author: Roland Conybeare
*/
#include "expect_formal_xs.hpp"
#include "expect_symbol_xs.hpp"
#include "expect_type_xs.hpp"
#include "parserstatemachine.hpp"
#include "exprstatestack.hpp"
#include "xo/expression/Variable.hpp"
namespace xo {
using xo::ast::Variable;
using xo::reflect::TypeDescr;
namespace scm{
const char *
formalstatetype_descr(formalstatetype x) {
switch (x) {
case formalstatetype::invalid:
case formalstatetype::n_formalstatetype:
return "?formalstatetype";
case formalstatetype::formal_0:
return "formal_0";
case formalstatetype::formal_1:
return "formal_1";
case formalstatetype::formal_2:
return "formal_2";
}
return "???formalstatetype";
}
std::unique_ptr<expect_formal_xs>
expect_formal_xs::make() {
return std::make_unique<expect_formal_xs>(expect_formal_xs());
}
void
expect_formal_xs::start(parserstatemachine * p_psm) {
p_psm->push_exprstate(expect_formal_xs::make());
expect_symbol_xs::start(p_psm);
}
expect_formal_xs::expect_formal_xs()
: exprstate(exprstatetype::expect_formal)
{}
void
expect_formal_xs::on_symbol(const std::string & symbol_name,
parserstatemachine * p_psm)
{
if (this->formalxs_type_ == formalstatetype::formal_0) {
this->formalxs_type_ = formalstatetype::formal_1;
this->result_.assign_name(symbol_name);
} else {
exprstate::on_symbol(symbol_name, p_psm);
}
}
void
expect_formal_xs::on_colon_token(const token_type & tk,
parserstatemachine * p_psm)
{
if (this->formalxs_type_ == formalstatetype::formal_1) {
this->formalxs_type_ = formalstatetype::formal_2;
expect_type_xs::start(p_psm);
/* control reenters via expect_formal_xs::on_typedescr() */
} else {
exprstate::on_colon_token(tk,
p_psm);
}
}
void
expect_formal_xs::on_typedescr(TypeDescr td,
parserstatemachine * p_psm)
{
if (this->formalxs_type_ == formalstatetype::formal_2) {
this->result_.assign_td(td);
std::unique_ptr<exprstate> self = p_psm->pop_exprstate();
rp<Variable> var = Variable::make(result_.name(),
result_.td());
p_psm->top_exprstate().on_formal(var, p_psm);
} else {
exprstate::on_typedescr(td, p_psm);
}
}
void
expect_formal_xs::print(std::ostream & os) const {
os << "<expect_formal_xs"
<< xtag("type", formalxs_type_);
if (!result_.name().empty())
os << xtag("result.name", result_.name());
if (result_.td())
os << xtag("result.td", result_.td());
os << ">";
}
} /*namespace scm*/
} /*namespace xo*/
/* end expect_formal_xs.cpp */

View file

@ -0,0 +1,47 @@
/* file expect_symbol_xs.cpp
*
* author: Roland Conybeare
*/
#include "expect_symbol_xs.hpp"
#include "parserstatemachine.hpp"
#include "exprstatestack.hpp"
namespace xo {
namespace scm {
std::unique_ptr<expect_symbol_xs>
expect_symbol_xs::make() {
return std::make_unique<expect_symbol_xs>(expect_symbol_xs());
}
void
expect_symbol_xs::start(parserstatemachine * p_psm)
{
p_psm->push_exprstate(expect_symbol_xs::make());
}
expect_symbol_xs::expect_symbol_xs()
: exprstate(exprstatetype::expect_symbol)
{}
void
expect_symbol_xs::on_symbol_token(const token_type & tk,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("tk", tk));
/* have to do pop first, before sending symbol to
* the o.g. symbol-requester
*/
std::unique_ptr<exprstate> self = p_psm->pop_exprstate();
p_psm->on_symbol(tk.text());
}
} /*namespace scm*/
} /*namespace xo*/
/* end expect_symbol_xs.cpp */

View file

@ -0,0 +1,66 @@
/* file expect_type_xs.cpp
*
* author: Roland Conybeare
*/
#include "expect_type_xs.hpp"
#include "parserstatemachine.hpp"
#include "exprstatestack.hpp"
#include "xo/reflect/Reflect.hpp"
namespace xo {
using xo::reflect::Reflect;
namespace scm {
std::unique_ptr<expect_type_xs>
expect_type_xs::make() {
return std::make_unique<expect_type_xs>(expect_type_xs());
}
void
expect_type_xs::start(parserstatemachine * p_psm) {
p_psm->push_exprstate(expect_type_xs::make());
}
expect_type_xs::expect_type_xs()
: exprstate(exprstatetype::expect_type)
{}
void
expect_type_xs::on_symbol_token(const token_type & tk,
parserstatemachine * p_psm)
{
const char * c_self_name = "expect_type_xs::on_symbol_token";
TypeDescr td = nullptr;
/* TODO: replace with typetable lookup */
if (tk.text() == "f64")
td = Reflect::require<double>();
else if(tk.text() == "f32")
td = Reflect::require<float>();
else if(tk.text() == "i16")
td = Reflect::require<std::int16_t>();
else if(tk.text() == "i32")
td = Reflect::require<std::int32_t>();
else if(tk.text() == "i64")
td = Reflect::require<std::int64_t>();
if (!td) {
throw std::runtime_error
(tostr(c_self_name,
": unknown type name",
" (expecting f64|f32|i16|i32|i64)",
xtag("typename", tk.text())));
}
std::unique_ptr<exprstate> self = p_psm->pop_exprstate();
p_psm->top_exprstate().on_typedescr(td, p_psm);
}
} /*namespace scm*/
} /*namespace xo*/
/* end expect_type_xs.cpp */

View file

@ -0,0 +1,81 @@
/* @file exprseq_xs.cpp */
#include "exprseq_xs.hpp"
#include "parserstatemachine.hpp"
#include "exprstatestack.hpp"
#include "define_xs.hpp"
#include "expect_symbol_xs.hpp"
namespace xo {
namespace scm {
std::unique_ptr<exprseq_xs>
exprseq_xs::make()
{
return std::make_unique<exprseq_xs>(exprseq_xs());
}
void
exprseq_xs::start(parserstatemachine * p_psm)
{
p_psm->push_exprstate(exprseq_xs::make());
}
exprseq_xs::exprseq_xs()
: exprstate(exprstatetype::expect_toplevel_expression_sequence)
{
}
void
exprseq_xs::on_def_token(const token_type & /*tk*/,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
//constexpr const char * c_self_name = "exprseq_xs::on_def_token";
define_xs::start(p_psm);
/* keyword 'def' introduces a definition:
* def pi : f64 = 3.14159265
* def sq(x : f64) -> f64 { (x * x) }
*/
}
void
exprseq_xs::on_symbol_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr const char * c_self_name = "exprseq_xs::on_symbol_token";
this->illegal_input_error(c_self_name, tk);
}
void
exprseq_xs::on_typedescr(TypeDescr /*td*/,
parserstatemachine * /*p_psm*/)
{
/* unreachable - typedescr should never get delivered to exprseq */
assert(false);
return;
}
void
exprseq_xs::on_expr(ref::brw<Expression> expr,
parserstatemachine * p_psm)
{
/* toplevel expression sequence accepts an
* arbitrary number of expressions.
*
* parser::include_token() returns
*/
auto p_emit_expr = p_psm->p_emit_expr_;
*p_emit_expr = expr.promote();
} /*on_expr*/
} /*namespace scm*/
} /*namespace xo*/
/* end exprseq_xs.cpp */

View file

@ -0,0 +1,448 @@
/* @file exprstate.cpp */
#include "exprstate.hpp"
#include "exprstatestack.hpp"
#include "parserstatemachine.hpp"
//#include "formal_arg.hpp"
#include "xo/expression/Variable.hpp"
#include "xo/indentlog/print/vector.hpp"
#include <stdexcept>
//#include "define_xs.hpp"
//#include "progress_xs.hpp"
//#include "paren_xs.hpp"
//#include "expect_expr_xs.hpp"
//#include "xo/expression/Constant.hpp"
//#include "xo/reflect/Reflect.hpp"
namespace xo {
//using xo::ast::Constant;
//using xo::reflect::Reflect;
using xo::reflect::TypeDescr;
namespace scm {
const char *
exprstatetype_descr(exprstatetype x) {
switch (x) {
case exprstatetype::invalid:
return "?invalid";
case exprstatetype::expect_toplevel_expression_sequence:
return "expect_toplevel_expression_sequence";
case exprstatetype::defexpr:
return "defexpr";
case exprstatetype::lambdaexpr:
return "lambdaexpr";
case exprstatetype::parenexpr:
return "parenexpr";
case exprstatetype::sequenceexpr:
return "sequenceexpr";
case exprstatetype::let1expr:
return "let1expr";
case exprstatetype::expect_rhs_expression:
return "expect_rhs_expression";
case exprstatetype::expect_symbol:
return "expect_symbol";
case exprstatetype::expect_type:
return "expect_type";
case exprstatetype::expect_formal_arglist:
return "expect_formal_arglist";
case exprstatetype::expect_formal:
return "expect_formal";
case exprstatetype::expr_progress:
return "expr_progress";
case exprstatetype::n_exprstatetype:
break;
}
return "???";
}
void
exprstate::on_def_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
this->illegal_input_error("exprstate::on_def_token", tk);
}
void
exprstate::on_lambda_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
this->illegal_input_error("exprstate::on_lambda_token", tk);
}
void
exprstate::on_symbol_token(const token_type & tk,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("exstype", p_psm->top_exprstate().exs_type()));
constexpr const char * c_self_name = "exprstate::on_symbol_token";
this->illegal_input_error(c_self_name, tk);
}
void
exprstate::on_typedescr(TypeDescr td,
parserstatemachine * p_psm)
{
/* returning type description to something that wants it */
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("exstype",
p_psm->top_exprstate().exs_type()));
constexpr const char * c_self_name = "exprstate::on_typedescr";
throw std::runtime_error(tostr(c_self_name,
": unexpected typedescr for parsing state",
xtag("td", td),
xtag("state", *this)));
}
void
exprstate::on_formal(const rp<Variable> & formal,
parserstatemachine * p_psm)
{
/* returning type description to something that wants it */
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("exstype",
p_psm->top_exprstate().exs_type()));
constexpr const char * c_self_name = "exprstate::on_formal";
throw std::runtime_error(tostr(c_self_name,
": unexpected formal-arg for parsing state",
xtag("formal", formal.get()),
xtag("state", *this)));
}
void
exprstate::on_formal_arglist(const std::vector<rp<Variable>> & argl,
parserstatemachine * p_psm)
{
/* returning type description to something that wants it */
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("exstype",
p_psm->top_exprstate().exs_type()));
constexpr const char * c_self_name = "exprstate::on_formal_arglist";
throw std::runtime_error(tostr(c_self_name,
": unexpected formal-arg for parsing state",
xtag("argl", argl),
xtag("state", *this)));
}
void
exprstate::on_colon_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * self_name = "exprstate::on_colon";
this->illegal_input_error(self_name, tk);
}
void
exprstate::on_comma_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * self_name = "exprstate::on_comma";
this->illegal_input_error(self_name, tk);
}
void
exprstate::on_semicolon_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * self_name = "exprstate::on_semicolon";
this->illegal_input_error(self_name, tk);
}
void
exprstate::on_singleassign_token(const token_type & tk,
parserstatemachine * /*p_psm*/) {
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * self_name = "exprstate::on_singleassign_token";
this->illegal_input_error(self_name, tk);
}
void
exprstate::on_leftparen_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * self_name = "exprstate::on_leftparen_token";
this->illegal_input_error(self_name, tk);
}
void
exprstate::on_rightparen_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * self_name = "exprstate::on_rightparen";
this->illegal_input_error(self_name, tk);
}
void
exprstate::on_leftbrace_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * self_name = "exprstate::on_leftbrace_token";
this->illegal_input_error(self_name, tk);
}
void
exprstate::on_rightbrace_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * self_name = "exprstate::on_rightbrace_token";
this->illegal_input_error(self_name, tk);
}
void
exprstate::on_operator_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * self_name = "exprstate::on_operator_token";
this->illegal_input_error(self_name, tk);
}
void
exprstate::on_f64_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * self_name = "exprstate::on_f64";
this->illegal_input_error(self_name, tk);
}
void
exprstate::on_input(const token_type & tk,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("tk", tk));
log && log(xtag("state", *this));
log && log(xtag("psm", *p_psm));
switch (tk.tk_type()) {
case tokentype::tk_def:
this->on_def_token(tk, p_psm);
return;
case tokentype::tk_lambda:
this->on_lambda_token(tk, p_psm);
return;
case tokentype::tk_i64:
assert(false);
return;
case tokentype::tk_f64:
this->on_f64_token(tk, p_psm);
return;
case tokentype::tk_string:
assert(false);
return;
case tokentype::tk_symbol:
this->on_symbol_token(tk, p_psm);
return;
case tokentype::tk_leftparen:
this->on_leftparen_token(tk, p_psm);
return;
case tokentype::tk_rightparen:
this->on_rightparen_token(tk, p_psm);
return;
case tokentype::tk_leftbracket:
case tokentype::tk_rightbracket:
assert(false);
break;
case tokentype::tk_leftbrace:
this->on_leftbrace_token(tk, p_psm);
return;
case tokentype::tk_rightbrace:
this->on_rightbrace_token(tk, p_psm);
return;
case tokentype::tk_leftangle:
case tokentype::tk_rightangle:
case tokentype::tk_dot:
assert(false);
return;
case tokentype::tk_comma:
this->on_comma_token(tk, p_psm);
return;
case tokentype::tk_colon:
this->on_colon_token(tk, p_psm);
return;
case tokentype::tk_doublecolon:
assert(false);
return;
case tokentype::tk_semicolon:
this->on_semicolon_token(tk, p_psm);
return;
case tokentype::tk_singleassign:
this->on_singleassign_token(tk, p_psm);
return;
case tokentype::tk_assign:
case tokentype::tk_yields:
case tokentype::tk_plus:
case tokentype::tk_minus:
case tokentype::tk_star:
case tokentype::tk_slash:
this->on_operator_token(tk, p_psm);
return;
case tokentype::tk_type:
case tokentype::tk_if:
case tokentype::tk_let:
case tokentype::tk_in:
case tokentype::tk_end:
assert(false);
return;
case tokentype::tk_invalid:
case tokentype::n_tokentype:
assert(false);
return;
}
assert(false);
}
void
exprstate::on_expr(ref::brw<Expression> expr,
parserstatemachine * /*p_psm*/)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("exstype", this->exs_type_),
xtag("expr", expr));
assert(false);
} /*on_expr*/
void
exprstate::on_expr_with_semicolon(ref::brw<Expression> expr,
parserstatemachine * /*p_psm*/)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
const char * c_self_name = "exprstate::on_expr_with_semicolon";
log && log(xtag("exstype", this->exs_type_),
xtag("expr", expr));
throw std::runtime_error
(tostr(c_self_name,
": unexpected expression for parsing state",
xtag("expr", expr),
xtag("state", *this)));
assert(false);
} /*on_expr_with_semicolon*/
void
exprstate::on_symbol(const std::string & symbol_name,
parserstatemachine * /*p_psm*/)
{
/* unreachable - derived class that can receive
* will override this method
*/
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("exstype", this->exs_type_),
xtag("symbol_name", symbol_name));
assert(false);
}
void
exprstate::print(std::ostream & os) const {
os << "<exprstate"
<< xtag("this", (void*)this)
<< xtag("type", exs_type_);
os << ">";
}
void
exprstate::illegal_input_error(const char * self_name,
const token_type & tk) const
{
throw std::runtime_error
(tostr(self_name,
": unexpected input token for parsing state",
xtag("token", tk),
xtag("state", *this)));
}
} /*namespace scm*/
} /*namespace xo*/
/* end exprstate.cpp */

View file

@ -0,0 +1,71 @@
/* file exprstatestack.cpp
*
* author: Roland Conybeare
*/
#include "exprstatestack.hpp"
namespace xo {
namespace scm {
exprstate &
exprstatestack::top_exprstate() {
std::size_t z = stack_.size();
if (z == 0) {
throw std::runtime_error
("parser::top_exprstate: unexpected empty stack");
}
return *(stack_[z-1]);
}
void
exprstatestack::push_exprstate(std::unique_ptr<exprstate> exs) {
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag),
xtag("exs", exs.get()));
std::size_t z = stack_.size();
stack_.resize(z+1);
stack_[z] = std::move(exs);
}
std::unique_ptr<exprstate>
exprstatestack::pop_exprstate() {
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag),
xtag("top.exstype", top_exprstate().exs_type()));
std::size_t z = stack_.size();
if (z > 0) {
std::unique_ptr<exprstate> top = std::move(stack_[z-1]);
stack_.resize(z-1);
return top;
} else {
return nullptr;
}
}
void
exprstatestack::print(std::ostream & os) const {
os << "<exprstatestack"
<< xtag("size", stack_.size())
<< std::endl;
for (std::size_t i = 0, z = stack_.size(); i < z; ++i) {
os << " [" << z-i-1 << "] "
<< stack_[i].get()
<< std::endl;
}
os << ">" << std::endl;
}
} /*namespace scm*/
} /*namespace xo*/
/* end exprstatestack.cpp */

View file

@ -0,0 +1,128 @@
/* @file lambda_xs.cpp */
#include "lambda_xs.hpp"
#include "parserstatemachine.hpp"
#include "exprstatestack.hpp"
#include "expect_formal_arglist_xs.hpp"
#include "expect_expr_xs.hpp"
#include "xo/expression/Lambda.hpp"
namespace xo {
using xo::ast::Lambda;
namespace scm {
const char *
lambdastatetype_descr(lambdastatetype x) {
switch(x) {
case lambdastatetype::invalid: return "invalid";
case lambdastatetype::lm_0: return "lm_0";
case lambdastatetype::lm_1: return "lm_1";
case lambdastatetype::lm_2: return "lm_2";
case lambdastatetype::lm_3: return "lm_3";
default: break;
}
return "???lambdastatetype";
}
// ----- lambda_xs - ----
std::unique_ptr<lambda_xs>
lambda_xs::make() {
return std::make_unique<lambda_xs>(lambda_xs());
}
void
lambda_xs::start(parserstatemachine * p_psm)
{
p_psm->push_exprstate(lambda_xs::make());
p_psm->top_exprstate()
.on_lambda_token(token_type::lambda(), p_psm);
}
lambda_xs::lambda_xs() : exprstate(exprstatetype::lambdaexpr) {}
void
lambda_xs::on_lambda_token(const token_type & tk,
parserstatemachine * p_psm)
{
if (lmxs_type_ == lambdastatetype::lm_0) {
this->lmxs_type_ = lambdastatetype::lm_1;
expect_formal_arglist_xs::start(p_psm);
} else {
exprstate::on_lambda_token(tk, p_psm);
}
}
void
lambda_xs::on_formal_arglist(const std::vector<rp<Variable>> & argl,
parserstatemachine * p_psm)
{
if (lmxs_type_ == lambdastatetype::lm_1) {
this->lmxs_type_ = lambdastatetype::lm_2;
this->argl_ = argl;
p_psm->push_envframe(envframe(argl));
expect_expr_xs::start(p_psm);
} else {
exprstate::on_formal_arglist(argl, p_psm);
}
}
void
lambda_xs::on_expr(ref::brw<Expression> expr,
parserstatemachine * p_psm)
{
if (lmxs_type_ == lambdastatetype::lm_2) {
this->lmxs_type_ = lambdastatetype::lm_3;
this->body_ = expr.promote();
} else {
exprstate::on_expr(expr, p_psm);
}
}
void
lambda_xs::on_expr_with_semicolon(ref::brw<Expression> expr,
parserstatemachine * p_psm)
{
this->on_expr(expr, p_psm);
this->on_semicolon_token(token_type::semicolon(), p_psm);
}
void
lambda_xs::on_semicolon_token(const token_type & tk,
parserstatemachine * p_psm)
{
if (lmxs_type_ == lambdastatetype::lm_3) {
/* done! */
std::unique_ptr<exprstate> self = p_psm->pop_exprstate();
std::string name = "fixmename";
rp<Lambda> lm = Lambda::make(name, argl_, body_);
p_psm->pop_envframe();
p_psm->top_exprstate().on_expr(lm, p_psm);
p_psm->top_exprstate().on_semicolon_token(tk, p_psm);
return;
}
exprstate::on_semicolon_token(tk, p_psm);
}
void
lambda_xs::print(std::ostream & os) const {
os << "<lambda_xs"
<< xtag("lmxs_type", lmxs_type_)
<< ">";
}
} /*namespace scm*/
} /*namespace xo*/
/* end lambda_xs.cpp */

View file

@ -0,0 +1,119 @@
/* file let1_xs.cpp
*
* author: Roland Conybeare
*/
#include "let1_xs.hpp"
#include "expect_expr_xs.hpp"
#include "parserstatemachine.hpp"
#include "xo/expression/Sequence.hpp"
#include "xo/expression/DefineExpr.hpp"
#include "xo/expression/Apply.hpp"
#include "xo/expression/Lambda.hpp"
namespace xo {
using Sequence = xo::ast::Sequence;
using DefineExpr = xo::ast::DefineExpr;
using Apply = xo::ast::Apply;
using Lambda = xo::ast::Lambda;
using LambdaAccess = xo::ast::LambdaAccess;
using Variable = xo::ast::Variable;
namespace {
std::string gensym() {
return "genanotherxx";
}
}
namespace scm {
std::unique_ptr<let1_xs>
let1_xs::make(std::string lhs_name,
rp<Expression> rhs)
{
return std::make_unique<let1_xs>(let1_xs(std::move(lhs_name),
std::move(rhs)));
}
void
let1_xs::start(const std::string & lhs_name,
const rp<Expression> & rhs,
parserstatemachine * p_psm)
{
p_psm->push_exprstate(let1_xs::make(lhs_name, rhs));
expect_expr_xs::start(true /*allow_defs*/,
true /*cxl_on_rightbrace*/,
p_psm);
}
let1_xs::let1_xs(std::string lhs_name,
rp<Expression> rhs)
: exprstate(),
lhs_name_{std::move(lhs_name)},
rhs_{std::move(rhs)}
{}
void
let1_xs::on_expr(ref::brw<Expression> expr,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
ref::brw<DefineExpr> def_expr = DefineExpr::from(expr);
if (def_expr) {
/** nested_start: control returns via
* .on_expr(x)
* with x something like:
* Apply(Lambda(gensym(),
* [Variable(def_expr->lhs_name(),
* def_expr->valuetype())],
* body...))
* followed immediately by
* .on_rightbrace_token()
**/
let1_xs::start(def_expr->lhs_name(),
def_expr->rhs(),
p_psm);
} else {
this->expr_v_.push_back(expr.promote());
expect_expr_xs::start(true /*allow_defs*/,
true /*cxl_on_rightbrace*/,
p_psm);
}
}
void
let1_xs::on_rightbrace_token(const token_type & tk,
parserstatemachine * p_psm)
{
auto self = p_psm->pop_exprstate();
auto expr = Sequence::make(this->expr_v_);
std::string argname = gensym();
rp<Expression> lambda
= Lambda::make(this->lhs_name_,
{Variable::make(argname,
this->rhs_->valuetype())},
expr);
rp<Expression> result
= Apply::make(lambda, {this->rhs_});
p_psm->top_exprstate().on_expr(result, p_psm);
/* caller of let1_xs expects the same rightbrace '}'
* -- remember we pushed let1_xs to handle an embedded def-expr
* in a sequence
*/
p_psm->on_rightbrace_token(tk);
}
} /*namespace scm*/
} /*namespace xo*/
/* end let1_xs.cpp */

View file

@ -0,0 +1,252 @@
/* @file paren_xs.cpp */
#include "paren_xs.hpp"
#include "parserstatemachine.hpp"
#include "exprstatestack.hpp"
#include "progress_xs.hpp"
#include "expect_expr_xs.hpp"
namespace xo {
namespace scm {
const char *
parenexprstatetype_descr(parenexprstatetype x)
{
switch(x) {
case parenexprstatetype::invalid: return "invalid";
case parenexprstatetype::lparen_0: return "lparen_0";
case parenexprstatetype::lparen_1: return "lparen_1";
case parenexprstatetype::n_parenexprstatetype: break;
}
return "???parenexprstatetype";
}
paren_xs::paren_xs()
: exprstate(exprstatetype::parenexpr),
parenxs_type_{parenexprstatetype::lparen_0}
{}
std::unique_ptr<paren_xs>
paren_xs::make() {
return std::make_unique<paren_xs>(paren_xs());
}
void
paren_xs::start(parserstatemachine * p_psm)
{
p_psm->push_exprstate(paren_xs::make());
expect_expr_xs::start(p_psm);
}
bool
paren_xs::admits_rightparen() const {
switch (parenxs_type_) {
case parenexprstatetype::lparen_0:
/* unreachable */
assert(false);
return false;
case parenexprstatetype::lparen_1:
return true;
case parenexprstatetype::invalid:
case parenexprstatetype::n_parenexprstatetype:
/* unreachable */
assert(false);
return false;
}
return false;
}
bool
paren_xs::admits_f64() const {
switch (parenxs_type_) {
case parenexprstatetype::lparen_0:
return true;
case parenexprstatetype::lparen_1:
return false;
case parenexprstatetype::invalid:
case parenexprstatetype::n_parenexprstatetype:
/* unreachable */
assert(false);
return false;
}
return false;
}
void
paren_xs::on_def_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr const char * c_self_name = "paren_xs::on_def";
this->illegal_input_error(c_self_name, tk);
}
void
paren_xs::on_symbol_token(const token_type & /*tk*/,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("exstype", p_psm->top_exprstate().exs_type()));
//constexpr const char * self_name = "paren_xs::on_symbol";
/* TODO: lparen_0: treat as variable reference */
assert(false);
}
void
paren_xs::on_typedescr(TypeDescr /*td*/,
parserstatemachine * /*p_psm*/)
{
assert(false);
return;
}
void
paren_xs::on_colon_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr const char * c_self_name = "paren_xs::on_colon";
this->illegal_input_error(c_self_name, tk);
}
void
paren_xs::on_semicolon_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr const char * c_self_name = "paren_xs::on_semicolon";
this->illegal_input_error(c_self_name, tk);
}
void
paren_xs::on_singleassign_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr const char * c_self_name = "paren_xs::on_singleassign";
this->illegal_input_error(c_self_name, tk);
}
void
paren_xs::on_leftparen_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr const char * c_self_name = "paren_xs::on_leftparen";
this->illegal_input_error(c_self_name, tk);
}
void
paren_xs::on_rightparen_token(const token_type & tk,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * c_self_name = "paren_xs::on_rightparen";
if (!this->admits_rightparen())
{
this->illegal_input_error(c_self_name, tk);
}
if (this->parenxs_type_ == parenexprstatetype::lparen_1) {
rp<Expression> expr = this->gen_expr_;
std::unique_ptr<exprstate> self = p_psm->pop_exprstate();
p_psm->top_exprstate().on_expr(expr, p_psm);
}
}
void
paren_xs::on_f64_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * c_self_name = "paren_xs::on_f64";
this->illegal_input_error(c_self_name, tk);
}
void
paren_xs::on_expr(ref::brw<Expression> expr,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("exstype", this->exs_type_),
xtag("expr", expr));
switch (this->parenxs_type_) {
case parenexprstatetype::lparen_0: {
this->parenxs_type_ = parenexprstatetype::lparen_1; /* wants on_rightparen */
progress_xs::start(expr.promote(), p_psm);
return;
}
case parenexprstatetype::lparen_1: {
this->gen_expr_ = expr.promote();
/* expect immediate incoming call, this time to on_rightparen() */
return;
}
default:
/* unreachable */
assert(false);
return;
}
} /*on_expr*/
void
paren_xs::on_symbol(const std::string & /*symbol_name*/,
parserstatemachine * /*p_psm*/)
{
switch(this->parenxs_type_) {
case parenexprstatetype::lparen_0:
case parenexprstatetype::lparen_1:
/* NOT IMPLEMENTED */
assert(false);
return;
default:
/* unreachable */
assert(false);
return;
}
}
void
paren_xs::print(std::ostream & os) const {
os << "<paren_xs"
<< xtag("this", (void*)this)
//<< xtag("type", exs_type_);
<< xtag("parenxs_type", parenxs_type_);
if (gen_expr_)
os << xtag("gen_expr", gen_expr_);
os << ">";
}
} /*namespace scm*/
} /*namespace xo*/
/* end paren_xs.cpp */

View file

@ -0,0 +1,81 @@
/* file parser.cpp
*
* author: Roland Conybeare
*/
#include "parser.hpp"
#include "parserstatemachine.hpp"
#include "define_xs.hpp"
#include "exprseq_xs.hpp"
#include "xo/expression/DefineExpr.hpp"
#include "xo/expression/Constant.hpp"
#include "xo/expression/ConvertExpr.hpp"
//#include <regex>
#include <stdexcept>
namespace xo {
using xo::ast::Expression;
//using xo::ast::DefineExpr;
//using xo::ast::ConvertExpr;
//using xo::ast::Constant;
//using xo::reflect::Reflect;
using xo::reflect::TypeDescr;
namespace scm {
// ----- parser -----
bool
parser::has_incomplete_expr() const {
return !xs_stack_.empty();
}
void
parser::begin_translation_unit() {
/* note: not using emit expr here */
parserstatemachine psm(&xs_stack_,
&env_stack_,
nullptr /*p_emit_expr*/);
exprseq_xs::start(&psm);
}
rp<Expression>
parser::include_token(const token_type & tk)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag), xtag("tk", tk));
if (xs_stack_.empty()) {
throw std::runtime_error(tostr("parser::include_token",
": parser not expecting input"
"(call parser.begin_translation_unit()..?)",
xtag("token", tk)));
}
/* stack_ is non-empty */
rp<Expression> retval;
parserstatemachine psm(&xs_stack_, &env_stack_, &retval);
xs_stack_.top_exprstate().on_input(tk, &psm);
log && log(xtag("retval", retval));
return retval;
} /*include_token*/
void
parser::print(std::ostream & os) const {
os << "<parser"
<< std::endl;
xs_stack_.print(os);
os << ">" << std::endl;
}
} /*namespace scm*/
} /*namespace xo*/
/* end parser.cpp */

View file

@ -0,0 +1,154 @@
/* file parserstatemachine.cpp
*
* author: Roland Conybeare
*/
#include "parserstatemachine.hpp"
#include "exprstatestack.hpp"
namespace xo {
using xo::ast::Variable;
namespace scm {
rp<Variable>
parserstatemachine::lookup_var(const std::string & x) const {
return p_env_stack_->lookup(x);
}
std::unique_ptr<exprstate>
parserstatemachine::pop_exprstate() {
return p_stack_->pop_exprstate();
}
exprstate &
parserstatemachine::top_exprstate() {
return p_stack_->top_exprstate();
}
void
parserstatemachine::push_exprstate(std::unique_ptr<exprstate> x) {
p_stack_->push_exprstate(std::move(x));
}
void
parserstatemachine::push_envframe(envframe x) {
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("frame", x));
p_env_stack_->push_envframe(std::move(x));
}
void
parserstatemachine::pop_envframe() {
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
p_env_stack_->pop_envframe();
}
void
parserstatemachine::on_expr(ref::brw<Expression> x)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("x", x),
xtag("psm", *this));
this->p_stack_
->top_exprstate().on_expr(x, this);
}
void
parserstatemachine::on_expr_with_semicolon(ref::brw<Expression> x)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("x", x),
xtag("psm", *this));
this->p_stack_
->top_exprstate().on_expr_with_semicolon(x, this);
}
void
parserstatemachine::on_symbol(const std::string & x)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("x", x),
xtag("psm", *this));
this->p_stack_
->top_exprstate().on_symbol(x, this);
}
void
parserstatemachine::on_semicolon_token(const token_type & tk)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("tk", tk),
xtag("psm", *this));
this->p_stack_
->top_exprstate().on_semicolon_token(tk, this);
}
void
parserstatemachine::on_operator_token(const token_type & tk)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("tk", tk),
xtag("psm", *this));
this->p_stack_
->top_exprstate().on_operator_token(tk, this);
}
void
parserstatemachine::on_leftbrace_token(const token_type & tk)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("tk", tk),
xtag("psm", *this));
this->p_stack_
->top_exprstate().on_leftbrace_token(tk, this);
}
void
parserstatemachine::on_rightbrace_token(const token_type & tk)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("tk", tk),
xtag("psm", *this));
this->p_stack_
->top_exprstate().on_rightbrace_token(tk, this);
}
void
parserstatemachine::print(std::ostream & os) const {
os << "<psm";
os << xtag("stack", p_stack_);
os << xtag("env_stack", p_env_stack_);
os << xtag("emit_expr", p_emit_expr_);
os << ">";
}
} /*namespace scm*/
} /*namespace xo*/
/* end parserstatemachine.cpp */

View file

@ -0,0 +1,439 @@
/* @file progress_xs.cpp */
#include "progress_xs.hpp"
#include "exprstatestack.hpp"
#include "expect_expr_xs.hpp"
#include "parserstatemachine.hpp"
#include "xo/expression/AssignExpr.hpp"
#include "xo/expression/Apply.hpp"
namespace xo {
using xo::ast::Expression;
using xo::ast::AssignExpr;
using xo::ast::Variable;
using xo::ast::Apply;
namespace scm {
const char *
optype_descr(optype x) {
switch (x) {
case optype::invalid:
return "?optype";
case optype::op_assign:
return "op:=";
case optype::op_add:
return "op+";
case optype::op_subtract:
return "op-";
case optype::op_multiply:
return "op*";
case optype::op_divide:
return "op/";
case optype::n_optype:
break;
}
return "???";
}
int
precedence(optype x) {
switch (x) {
case optype::invalid:
case optype::n_optype:
return 0;
case optype::op_assign:
return 1;
case optype::op_add:
case optype::op_subtract:
return 2;
case optype::op_multiply:
case optype::op_divide:
return 3;
}
return 0;
}
std::unique_ptr<progress_xs>
progress_xs::make(rp<Expression> valex, optype op) {
return std::make_unique<progress_xs>(progress_xs(std::move(valex), op));
}
void
progress_xs::start(rp<Expression> valex, optype op, parserstatemachine * p_psm) {
p_psm->push_exprstate(progress_xs::make(valex, op));
}
void
progress_xs::start(rp<Expression> valex, parserstatemachine * p_psm) {
p_psm->push_exprstate(progress_xs::make(valex));
}
progress_xs::progress_xs(rp<Expression> valex, optype op)
: exprstate(exprstatetype::expr_progress),
lhs_{std::move(valex)},
op_type_{op}
{}
bool
progress_xs::admits_f64() const { return false; }
void
progress_xs::on_def_token(const token_type & tk,
parserstatemachine * /*p_stack*/)
{
constexpr const char * self_name = "progress_xs::on_def";
/* nothing here - admits_definition unconditionally false */
this->illegal_input_error(self_name, tk) ;
}
rp<Expression>
progress_xs::assemble_expr() {
/* need to defer building Apply incase expr followed by higher-precedence operator:
* consider input like
* 3.14 + 2.0 * ...
*/
constexpr const char * c_self_name = "progress_xs::assemble_expr";
if ((op_type_ != optype::invalid) && (rhs_.get() == nullptr)) {
throw std::runtime_error(tostr(c_self_name,
": expected expr on rhs of operator",
xtag("lhs", lhs_),
xtag("op", op_type_)));
}
/* consecutive expressions not legal, e.g:
* 3.14 6.28
* but expressions surrounding an infix operators is:
* 3.14 / 6.28
*/
switch (op_type_) {
case optype::invalid:
return this->lhs_;
case optype::op_assign:
{
ref::brw<Variable> lhs = Variable::from(this->lhs_);
if (!lhs) {
throw std::runtime_error
(tostr("progress_xs::assemble_expr",
" expect variable on lhs of assignment operator :=",
xtag("lhs", lhs_),
xtag("rhs", rhs_)));
}
return AssignExpr::make(lhs.promote(),
this->rhs_);
}
case optype::op_add:
return Apply::make_add2_f64(this->lhs_,
this->rhs_);
case optype::op_subtract:
return Apply::make_sub2_f64(this->lhs_,
this->rhs_);
case optype::op_multiply:
return Apply::make_mul2_f64(this->lhs_,
this->rhs_);
case optype::op_divide:
return Apply::make_div2_f64(this->lhs_,
this->rhs_);
case optype::n_optype:
/* unreachable */
assert(false);
return nullptr;
}
return nullptr;
}
void
progress_xs::on_expr(ref::brw<Expression> expr,
parserstatemachine * /*p_psm*/)
{
/* note: previous token probably an operator,
* handled from progress_xs::on_operator_token(),
* which pushes expect_expr_xs::expect_rhs_expression()
*/
constexpr const char * c_self_name = "progress_xs::on_expr";
if (op_type_ == optype::invalid) {
throw std::runtime_error(tostr(c_self_name,
": consecutive unseparated exprs not legal"));
}
#ifdef NOT_QUITE
assert(result.get());
/* this expression complete.. */
std::unique_ptr<exprstate> self = p_psm->pop_exprstate();
/* ..but more operators could follow, so don't commit yet */
p_stack->push_exprstate(progress_xs::make(result));
#endif
this->rhs_ = expr.promote();
}
void
progress_xs::on_symbol_token(const token_type & /*tk*/,
parserstatemachine * /*p_psm*/)
{
/* illegal input, e.g.
* foo bar
*/
assert(false);
}
void
progress_xs::on_typedescr(TypeDescr /*td*/,
parserstatemachine * /*p_psm*/)
{
/* unreachable */
assert(false);
}
void
progress_xs::on_colon_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr const char * self_name = "progress_xs::on_colon";
this->illegal_input_error(self_name, tk);
}
void
progress_xs::on_semicolon_token(const token_type & /*tk*/,
parserstatemachine * p_psm)
{
/* note: implementation parllels .on_rightparen_token() */
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
rp<Expression> expr = this->assemble_expr();
std::unique_ptr<exprstate> self = p_psm->pop_exprstate();
p_psm->on_expr_with_semicolon(expr);
/* control here on input like:
* (1.234;
*
* a. '(' sets up stack [lparen_0:expect_rhs_expression]
* (see exprstate::on_leftparen())
* b. 1.234 pushes (in case operators) [lparen_0:expect_rhs_expression:expr_progress]
* (see exprstate::on_f64())
* c. semicolon completes expr_progress [lparen_0:expect_rhs_expression]
* deliver expresssion to expect_rhs_expression.on_expr_with_semicolon()
* (see exprstate::on_expr_with_semicolon())
* d. expr_rhs_expression forwards expression to [lparen_0]
* e. lparen_0 would advance to [lparen_1], but rejects semicolon
*/
}
void
progress_xs::on_singleassign_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr const char * self_name = "progress_xs::on_singleassign";
this->illegal_input_error(self_name, tk);
}
void
progress_xs::on_leftparen_token(const token_type & tk,
parserstatemachine * /*p_psm*/)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * self_name = "exprstate::on_leftparen";
this->illegal_input_error(self_name, tk);
}
void
progress_xs::on_rightparen_token(const token_type & tk,
parserstatemachine * p_psm)
{
/* note: implementation parallels .on_semicolon_token() */
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * self_name = "progress_xs::on_rightparen";
auto p_stack = p_psm->p_stack_;
/* stack may be something like:
*
* lparen_0
* expect_rhs_expression
* expr_progress
* <-- rightparen
*
* 1. rightparen completes expression-in-progress
* 2. rightparen must then match innermost waiting lparen_0
*/
/* right paren confirms stack expression */
rp<Expression> expr = this->assemble_expr();
std::unique_ptr<exprstate> self = p_psm->pop_exprstate();
if (p_stack->empty()) {
throw std::runtime_error(tostr(self_name,
": expected non-empty parsing stack"));
}
log && log(xtag("stack", p_stack));
p_psm->top_exprstate().on_expr(expr, p_psm);
/* now deliver rightparen */
p_psm->top_exprstate().on_rightparen_token(tk, p_psm);
}
namespace {
optype
tk2op(const tokentype & tktype) {
switch (tktype) {
case tokentype::tk_plus:
return optype::op_add;
case tokentype::tk_minus:
return optype::op_subtract;
case tokentype::tk_star:
return optype::op_multiply;
case tokentype::tk_slash:
return optype::op_divide;
default:
assert(false);
return optype::invalid;
}
return optype::invalid;
}
}
void
progress_xs::on_operator_token(const token_type & tk,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * c_self_name = "progress_xs::on_operator_token";
if (op_type_ == optype::invalid) {
this->op_type_ = tk2op(tk.tk_type());
/* infix operator must be followed by non-empty expression */
expect_expr_xs::start(p_psm);
} else if (rhs_) {
/* already have complete expression stashed.
* behavior depends on operator precedence for tk with stored operator
* this->op_type_
*/
optype op2 = tk2op(tk.tk_type());
if (precedence(op2) <= precedence(this->op_type_)) {
/* e.g.
* 6.2 * 4.9 + ...
*
* in stack:
* 1. progress_xs lhs=6.2, op=*, rhs=4.9
*
* out stack
* 1. progress_xs lhs=apply(*,6.2,4.9), op=+
*/
/* 1. instantiate expression for *this */
auto expr = this->assemble_expr();
/* 2. remove from stack */
std::unique_ptr<exprstate> self = p_psm->pop_exprstate();
/* 3. replace with new progress_xs: */
progress_xs::start(expr, op2, p_psm);
/* infix operator must be followed by non-empty expression */
expect_expr_xs::start(p_psm);
} else {
/* e.g.
* 6.2 + 4.9 * ...
*
* in stack:
* 1. progress_xs lhs=6.2, op=+, rhs=4.9
*
* out stack:
* 1. progress_xs lhs=6.2, op=+
* 2. expect_rhs_expression
* 3. progress_xs lhs=4.9, op=*
* 4. expect_rhs_expression
*/
std::unique_ptr<exprstate> self = p_psm->pop_exprstate();
/* 1. replace with nested incomplete infix exprs */
progress_xs::start(lhs_, op_type_, p_psm);
expect_expr_xs::start(p_psm);
progress_xs::start(rhs_, op2, p_psm);
expect_expr_xs::start(p_psm);
}
} else {
throw std::runtime_error(tostr(c_self_name,
": expected expression following operator",
xtag("tk", tk)));
}
}
void
progress_xs::on_f64_token(const token_type & tk,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * self_name = "progress_xs::on_f64";
if (this->op_type_ == optype::invalid) {
this->illegal_input_error(self_name, tk);
} else {
exprstate::on_f64_token(tk, p_psm);
}
}
void
progress_xs::print(std::ostream & os) const {
os << "<progress_xs"
<< xtag("this", (void*)this)
<< xtag("type", exs_type_);
if (lhs_)
os << xtag("lhs", lhs_);
if (op_type_ != optype::invalid)
os << xtag("op", op_type_);
if (rhs_)
os << xtag("rhs", rhs_);
os << ">";
}
} /*namespace scm*/
} /*namespace xo*/
/* end progress_xs.cpp */

View file

@ -0,0 +1,98 @@
/* @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 */

View file

@ -0,0 +1,113 @@
/* @file sequence_xs.cpp */
#include "sequence_xs.hpp"
#include "parserstatemachine.hpp"
#include "expect_expr_xs.hpp"
#include "let1_xs.hpp"
#include "xo/expression/DefineExpr.hpp"
#include "xo/expression/Sequence.hpp"
namespace xo {
using xo::ast::DefineExpr;
namespace scm {
std::unique_ptr<sequence_xs>
sequence_xs::make() {
return std::make_unique<sequence_xs>(sequence_xs());
}
void
sequence_xs::start(parserstatemachine * p_psm) {
p_psm->push_exprstate(sequence_xs::make());
/* want to accept anything that starts an expression,
* except that } ends it
*/
expect_expr_xs::start(true /*allow_defs*/,
true /*cxl_on_rightbrace*/,
p_psm);
}
sequence_xs::sequence_xs()
: exprstate(exprstatetype::sequenceexpr)
{}
void
sequence_xs::on_expr(ref::brw<Expression> expr,
parserstatemachine * p_psm)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
log && log(xtag("expr", expr.promote()));
/* TODO: if expr is a DefineExpr,
* then need to rewrite...
*
* ...prefix
* DefineExpr(lhs_name, rhs)
* rest...
*
* becomes:
*
* /-- .outer_seq_expr_
* v
* Sequence(
* ...prefix,
*
* /-- .inner_lm_expr_
* v
* Apply(Lambda(gen999,
* [Variable(lhs_name, type(rhs))],
* /-- .expr_v_
* v
* sequencify(rest...)),
* rhs))
*
* so amongst other things,
* helpful to have nested seequence_xs that propagates '}'
* instead of swallowing it.
*/
ref::brw<DefineExpr> def_expr = DefineExpr::from(expr);
if (def_expr) {
/** nested_start: control returns via
* .on_expr(x)
* with x something like:
* Apply(Lambda(gensym(),
* [Variable(def_expr->lhs_name(),
* def_expr->valuetype())],
* body...))
* followed immediately by
* .on_rightbrace_token()
**/
let1_xs::start(def_expr->lhs_name(),
def_expr->rhs(),
p_psm);
} else {
this->expr_v_.push_back(expr.promote());
expect_expr_xs::start(true /*allow_defs*/,
true /*cxl_on_rightbrace*/,
p_psm);
}
}
void
sequence_xs::on_rightbrace_token(const token_type & /*tk*/,
parserstatemachine * p_psm)
{
auto self = p_psm->pop_exprstate();
/* make sequence from expressions seen at this level,
* and report it to parent
*/
auto expr = Sequence::make(this->expr_v_);
p_psm->top_exprstate().on_expr(expr, p_psm);
}
} /*namespace scm*/
} /*namespace xo*/
/* end sequence_xs.cpp */