xo-tokenizer xo-reader: + bool literals + if-expr parsing
This commit is contained in:
parent
1f532c17ed
commit
3573ec800a
23 changed files with 712 additions and 53 deletions
|
|
@ -12,6 +12,18 @@ namespace xo {
|
|||
|
||||
/** @class expect_expr_xs
|
||||
* @brief state machine to expect + capture an expression
|
||||
*
|
||||
* Examples:
|
||||
* @text
|
||||
* def x : i64 = 5 ; // with allow_defs
|
||||
* lambda (f : x64) { ... } ;
|
||||
* if (prime(x)) { ... } ;
|
||||
* 5 + x ;
|
||||
* @endtext
|
||||
*
|
||||
* top exprstate when expect_expr_xs::start() invoked
|
||||
* will receive parsed expression via
|
||||
* exprstate::on_expr() or exprstate::on_expr_with_semicolon().
|
||||
**/
|
||||
class expect_expr_xs : public exprstate {
|
||||
public:
|
||||
|
|
@ -41,6 +53,9 @@ namespace xo {
|
|||
virtual void on_symbol_token(const token_type & tk,
|
||||
parserstatemachine * p_psm) override;
|
||||
|
||||
virtual void on_bool_token(const token_type & tk,
|
||||
parserstatemachine * p_psm) override;
|
||||
|
||||
virtual void on_i64_token(const token_type & tk,
|
||||
parserstatemachine * p_psm) override;
|
||||
|
||||
|
|
@ -50,7 +65,7 @@ namespace xo {
|
|||
/** update exprstate in response to a successfully-parsed subexpression **/
|
||||
virtual void on_expr(bp<Expression> expr,
|
||||
parserstatemachine * p_psm) override;
|
||||
/** update exprstate in response to a successfully-parsed subexpression,
|
||||
/** update exprstate in response to a successfully-parsed subexpression
|
||||
* that's terminated by semicolon ';'
|
||||
**/
|
||||
virtual void on_expr_with_semicolon(bp<Expression> expr,
|
||||
|
|
|
|||
|
|
@ -17,8 +17,6 @@ namespace xo {
|
|||
* This used for top-level expressions in a translation unit.
|
||||
**/
|
||||
toplevel_batch,
|
||||
/** nested sequence, for example in function body **/
|
||||
nested,
|
||||
};
|
||||
|
||||
/** @class exprseq_xs
|
||||
|
|
@ -27,14 +25,14 @@ namespace xo {
|
|||
* expression sequences come in several types:
|
||||
* 1. top-level interactive
|
||||
* 2. top-level batch
|
||||
* 3. nested
|
||||
*
|
||||
* @text
|
||||
* 1 2 3
|
||||
* +--------
|
||||
* def | y y y
|
||||
* symbol | y n n 1: evaluate as variable
|
||||
* i64 | y n n 1: evaluate as constant
|
||||
* 1 2
|
||||
* +-----
|
||||
* def | y y
|
||||
* if | y n 1: eval as expression
|
||||
* symbol | y n 1: evaluate as variable
|
||||
* i64 | y n 1: evaluate as constant
|
||||
*
|
||||
* @endtext
|
||||
**/
|
||||
|
|
@ -45,12 +43,18 @@ namespace xo {
|
|||
static void start(exprseqtype seqtype, parserstatemachine * p_psm);
|
||||
|
||||
public:
|
||||
virtual const char * get_expect_str() const override;
|
||||
|
||||
// ----- token input methods -----
|
||||
|
||||
virtual void on_def_token(const token_type & tk,
|
||||
parserstatemachine * p_psm) override;
|
||||
virtual void on_if_token(const token_type & tk,
|
||||
parserstatemachine * p_psm) override;
|
||||
virtual void on_symbol_token(const token_type & tk,
|
||||
parserstatemachine * p_psm) override;
|
||||
virtual void on_bool_token(const token_type & tk,
|
||||
parserstatemachine * p_psm) override;
|
||||
virtual void on_i64_token(const token_type & tk,
|
||||
parserstatemachine * p_psm) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,11 @@ namespace xo {
|
|||
**/
|
||||
let1expr,
|
||||
|
||||
/** handle if-else expression
|
||||
* see @ref if_else_xs
|
||||
**/
|
||||
ifexpr,
|
||||
|
||||
expect_rhs_expression,
|
||||
expect_symbol,
|
||||
expect_type,
|
||||
|
|
@ -177,6 +182,22 @@ namespace xo {
|
|||
virtual void on_operator_token(const token_type & tk,
|
||||
parserstatemachine * p_psm);
|
||||
|
||||
/** handle incoming if-keyword token **/
|
||||
virtual void on_if_token(const token_type & tk,
|
||||
parserstatemachine * p_psm);
|
||||
|
||||
/** handle incoming then-keyword token **/
|
||||
virtual void on_then_token(const token_type & tk,
|
||||
parserstatemachine * p_psm);
|
||||
|
||||
/** handle incoming then-keyword token **/
|
||||
virtual void on_else_token(const token_type & tk,
|
||||
parserstatemachine * p_psm);
|
||||
|
||||
/** handle incoming bool-literal token **/
|
||||
virtual void on_bool_token(const token_type & tk,
|
||||
parserstatemachine * p_psm);
|
||||
|
||||
/** handle incoming integer-literal token **/
|
||||
virtual void on_i64_token(const token_type & tk,
|
||||
parserstatemachine * p_psm);
|
||||
|
|
|
|||
97
include/xo/reader/if_else_xs.hpp
Normal file
97
include/xo/reader/if_else_xs.hpp
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
/** @file if_else_xs.hpp
|
||||
*
|
||||
* author: Roland Conybeare, Jul 2025
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xo/expression/IfExpr.hpp"
|
||||
#include "exprstate.hpp"
|
||||
#include "xo/indentlog/print/ppdetail_atomic.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace scm {
|
||||
/**
|
||||
* if test-expr then then-expr else else-expr ;
|
||||
* ^ ^ ^ ^ ^ ^ ^
|
||||
* | | | | | | |
|
||||
* | if_1 if_2 if_3 if_4 if_5 if_6
|
||||
* if_0
|
||||
*
|
||||
* if_0 --on_if_token()--> if_1
|
||||
* if_1 --on_expr()--> if_2
|
||||
* if_2 --on_then_token()--> if_3
|
||||
* if_3 --on_expr()--> if_4
|
||||
* if_4 --on_else_token()--> if_5
|
||||
* --on_semicolon_token()--> (done)
|
||||
* if_5 --on_expr()-->if_6
|
||||
* if_6 --on_semicolon_token()--> (done)
|
||||
**/
|
||||
enum class ifexprstatetype {
|
||||
invalid = -1,
|
||||
|
||||
if_0,
|
||||
if_1,
|
||||
if_2,
|
||||
if_3,
|
||||
if_4,
|
||||
if_5,
|
||||
if_6,
|
||||
|
||||
n_ifexprstatetype,
|
||||
};
|
||||
|
||||
extern const char * ifexprstatetype_descr(ifexprstatetype x);
|
||||
|
||||
std::ostream &
|
||||
operator<<(std::ostream & os, ifexprstatetype x);
|
||||
|
||||
/** @class if_else_xs
|
||||
* @brief state to provide parsing of a conditional expression
|
||||
**/
|
||||
class if_else_xs : public exprstate {
|
||||
public:
|
||||
using IfExprAccess = xo::ast::IfExprAccess;
|
||||
|
||||
public:
|
||||
if_else_xs(rp<IfExprAccess> if_expr);
|
||||
virtual ~if_else_xs() = default;
|
||||
|
||||
static const if_else_xs * from(const exprstate * x) { return dynamic_cast<const if_else_xs *>(x); }
|
||||
|
||||
static void start(parserstatemachine * p_psm);
|
||||
|
||||
// ----- inherited from exprstate -----
|
||||
|
||||
virtual const char * get_expect_str() const override;
|
||||
|
||||
virtual void on_if_token(const token_type & tk,
|
||||
parserstatemachine * p_psm) override;
|
||||
virtual void on_then_token(const token_type & tk,
|
||||
parserstatemachine * p_psm) override;
|
||||
virtual void on_else_token(const token_type & tk,
|
||||
parserstatemachine * p_psm) override;
|
||||
virtual void on_semicolon_token(const token_type & tk,
|
||||
parserstatemachine * p_psm) override;
|
||||
|
||||
virtual void on_expr(bp<Expression> expr,
|
||||
parserstatemachine * p_psm) override;
|
||||
virtual void on_expr_with_semicolon(bp<Expression> expr,
|
||||
parserstatemachine * p_psm) override;
|
||||
|
||||
virtual void print(std::ostream & os) const override;
|
||||
|
||||
private:
|
||||
static std::unique_ptr<if_else_xs> make();
|
||||
|
||||
private:
|
||||
ifexprstatetype ifxs_type_;
|
||||
/** scaffold output expression here **/
|
||||
rp<IfExprAccess> if_expr_;
|
||||
|
||||
};
|
||||
} /*namespace scm*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/** end if_else_xs.hpp **/
|
||||
|
|
@ -112,6 +112,9 @@ namespace xo {
|
|||
* | symbol-literal
|
||||
* | struct-literal
|
||||
*
|
||||
*
|
||||
* boolean-literal = true | false
|
||||
*
|
||||
* variable-expr = $varname
|
||||
* apply-expr = fn-expr(arg-expr(1), .., arg-expr(n))
|
||||
* fn-expr = expression
|
||||
|
|
@ -155,8 +158,10 @@ namespace xo {
|
|||
public:
|
||||
/** create parser in initial state;
|
||||
* parser is ready to receive tokens via @ref include_token
|
||||
*
|
||||
* @p debug_flag true to enable debug logging
|
||||
**/
|
||||
parser();
|
||||
explicit parser(bool debug_flag);
|
||||
|
||||
/** true if parser is at top-level, i.e. ready for next top-level expression **/
|
||||
bool is_at_toplevel() const { return stack_size() == 0; }
|
||||
|
|
@ -243,6 +248,9 @@ namespace xo {
|
|||
|
||||
/** parser result state **/
|
||||
parser_result result_;
|
||||
|
||||
/** enable/disable debug logging **/
|
||||
bool debug_flag_;
|
||||
}; /*parser*/
|
||||
|
||||
inline std::ostream &
|
||||
|
|
|
|||
|
|
@ -28,10 +28,12 @@ namespace xo {
|
|||
public:
|
||||
parserstatemachine(exprstatestack * p_stack,
|
||||
envframestack * p_env_stack,
|
||||
parser_result * p_result)
|
||||
parser_result * p_result,
|
||||
bool debug_flag)
|
||||
: p_stack_{p_stack},
|
||||
p_env_stack_{p_env_stack},
|
||||
p_result_{p_result}
|
||||
p_result_{p_result},
|
||||
debug_flag_{debug_flag}
|
||||
{}
|
||||
|
||||
//const parser_result & result() const { return result_; }
|
||||
|
|
@ -44,6 +46,8 @@ namespace xo {
|
|||
exprstate & top_exprstate();
|
||||
void push_exprstate(std::unique_ptr<exprstate> x);
|
||||
|
||||
bool debug_flag() const { return debug_flag_; }
|
||||
|
||||
/** lookup variable name in lexical context represented by
|
||||
* this psm. nullptr if not found
|
||||
**/
|
||||
|
|
@ -54,9 +58,13 @@ namespace xo {
|
|||
**/
|
||||
void upsert_var(bp<Variable> x);
|
||||
|
||||
/** @return available variable bindings in current parsing state **/
|
||||
bp<LocalEnv> top_envframe() const;
|
||||
/** push frame @p x (with new variable bindings) onto environment stack **/
|
||||
void push_envframe(const rp<LocalEnv> & x);
|
||||
/** @return pop innermost environment frame and return it **/
|
||||
rp<LocalEnv> pop_envframe();
|
||||
/** @return number of stacked environment frames **/
|
||||
size_t env_stack_size() const { return p_env_stack_->size(); }
|
||||
|
||||
// ----- parsing outputs -----
|
||||
|
|
@ -71,6 +79,8 @@ namespace xo {
|
|||
void on_operator_token(const token_type & tk);
|
||||
void on_leftbrace_token(const token_type & tk);
|
||||
void on_rightbrace_token(const token_type & tk);
|
||||
void on_then_token(const token_type & tk);
|
||||
void on_else_token(const token_type & tk);
|
||||
|
||||
// ----- parsing error -----
|
||||
|
||||
|
|
@ -91,6 +101,8 @@ namespace xo {
|
|||
envframestack * p_env_stack_ = nullptr;
|
||||
/** parser result object **/
|
||||
parser_result * p_result_ = nullptr;
|
||||
/** enable debug logging **/
|
||||
bool debug_flag_ = false;
|
||||
};
|
||||
|
||||
inline std::ostream &
|
||||
|
|
|
|||
|
|
@ -95,6 +95,10 @@ namespace xo {
|
|||
parserstatemachine * p_psm) override;
|
||||
virtual void on_rightparen_token(const token_type & tk,
|
||||
parserstatemachine * p_psm) override;
|
||||
virtual void on_then_token(const token_type & tk,
|
||||
parserstatemachine * p_psm) override;
|
||||
virtual void on_else_token(const token_type & tk,
|
||||
parserstatemachine * p_psm) override;
|
||||
|
||||
/* entry point for an infix operator token */
|
||||
virtual void on_operator_token(const token_type & tk,
|
||||
|
|
@ -121,7 +125,7 @@ namespace xo {
|
|||
*
|
||||
* where f determined by @ref op_type_
|
||||
**/
|
||||
rp<Expression> assemble_expr();
|
||||
rp<Expression> assemble_expr(parserstatemachine * p_psm);
|
||||
|
||||
private:
|
||||
/** populate an expression here, may be followed by an operator **/
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ namespace xo {
|
|||
using span_type = tokenizer_type::span_type;
|
||||
|
||||
public:
|
||||
reader() = default;
|
||||
explicit reader(bool debug_flag);
|
||||
|
||||
/** call once before calling .read_expr()
|
||||
* for a new interactive session
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue