Add 'xo-reader/' from commit 'c46c0f1cc4'
git-subtree-dir: xo-reader git-subtree-mainline:dacdeb2cd7git-subtree-split:c46c0f1cc4
This commit is contained in:
commit
0ae98c211d
48 changed files with 5184 additions and 0 deletions
29
xo-reader/src/reader/CMakeLists.txt
Normal file
29
xo-reader/src/reader/CMakeLists.txt
Normal 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
|
||||
276
xo-reader/src/reader/define_xs.cpp
Normal file
276
xo-reader/src/reader/define_xs.cpp
Normal 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 */
|
||||
34
xo-reader/src/reader/envframe.cpp
Normal file
34
xo-reader/src/reader/envframe.cpp
Normal 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 */
|
||||
86
xo-reader/src/reader/envframestack.cpp
Normal file
86
xo-reader/src/reader/envframestack.cpp
Normal 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 */
|
||||
227
xo-reader/src/reader/expect_expr_xs.cpp
Normal file
227
xo-reader/src/reader/expect_expr_xs.cpp
Normal 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 */
|
||||
113
xo-reader/src/reader/expect_formal_arglist_xs.cpp
Normal file
113
xo-reader/src/reader/expect_formal_arglist_xs.cpp
Normal 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 */
|
||||
109
xo-reader/src/reader/expect_formal_xs.cpp
Normal file
109
xo-reader/src/reader/expect_formal_xs.cpp
Normal 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 */
|
||||
47
xo-reader/src/reader/expect_symbol_xs.cpp
Normal file
47
xo-reader/src/reader/expect_symbol_xs.cpp
Normal 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 */
|
||||
66
xo-reader/src/reader/expect_type_xs.cpp
Normal file
66
xo-reader/src/reader/expect_type_xs.cpp
Normal 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 */
|
||||
81
xo-reader/src/reader/exprseq_xs.cpp
Normal file
81
xo-reader/src/reader/exprseq_xs.cpp
Normal 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 */
|
||||
448
xo-reader/src/reader/exprstate.cpp
Normal file
448
xo-reader/src/reader/exprstate.cpp
Normal 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 */
|
||||
71
xo-reader/src/reader/exprstatestack.cpp
Normal file
71
xo-reader/src/reader/exprstatestack.cpp
Normal 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 */
|
||||
128
xo-reader/src/reader/lambda_xs.cpp
Normal file
128
xo-reader/src/reader/lambda_xs.cpp
Normal 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 */
|
||||
119
xo-reader/src/reader/let1_xs.cpp
Normal file
119
xo-reader/src/reader/let1_xs.cpp
Normal 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 */
|
||||
252
xo-reader/src/reader/paren_xs.cpp
Normal file
252
xo-reader/src/reader/paren_xs.cpp
Normal 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 */
|
||||
81
xo-reader/src/reader/parser.cpp
Normal file
81
xo-reader/src/reader/parser.cpp
Normal 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 */
|
||||
154
xo-reader/src/reader/parserstatemachine.cpp
Normal file
154
xo-reader/src/reader/parserstatemachine.cpp
Normal 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 */
|
||||
439
xo-reader/src/reader/progress_xs.cpp
Normal file
439
xo-reader/src/reader/progress_xs.cpp
Normal 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 */
|
||||
98
xo-reader/src/reader/reader.cpp
Normal file
98
xo-reader/src/reader/reader.cpp
Normal 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 */
|
||||
113
xo-reader/src/reader/sequence_xs.cpp
Normal file
113
xo-reader/src/reader/sequence_xs.cpp
Normal 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 */
|
||||
Loading…
Add table
Add a link
Reference in a new issue