xo-tokenizer xo-reader: + bool literals + if-expr parsing

This commit is contained in:
Roland Conybeare 2025-07-22 07:20:56 -05:00
commit ce760bd5cf
30 changed files with 848 additions and 74 deletions

View file

@ -60,6 +60,12 @@ namespace xo {
/** create invalid token (same as null ctor, but explicit) **/
static token invalid() { return token(); }
/** Create token representing a boolean literal from text @p txt
* @p txt must be @c true or @c false
**/
static token bool_token(const std::string & txt) {
return token(tokentype::tk_bool, txt);
}
/** Create token representing 64-bit signed integer literal parsed from decimal @p txt.
* The string @p txt must be a decimal integer literal, since @ref i64_value re-parses @p txt.
**/
@ -132,6 +138,8 @@ namespace xo {
static token lambda() { return token(tokentype::tk_lambda); }
/** token representing keyword @c if **/
static token if_token() { return token(tokentype::tk_if); }
/** token representing keyword @c else **/
static token else_token() { return token(tokentype::tk_else); }
/** token representing keyword @c let **/
static token let() { return token(tokentype::tk_let); }
/** token representing keyword @c in **/
@ -165,10 +173,13 @@ namespace xo {
|| tk_type_ == tokentype::tk_string
|| tk_type_ == tokentype::tk_symbol); }
/** expect input matching @c "[+|-][0-9][0-9]*" **/
/** expect input matching @c true or @c false **/
bool bool_value() const;
/** expect input matching @c [+|-][0-9][0-9]* **/
std::int64_t i64_value() const;
/** expect input matching @c "[+|-][0-9]*[.][0-9]*[e|E][+|-][0-9]*" **/
/** expect input matching @c [+|-][0-9]*[.][0-9]*[e|E][+|-][0-9]* **/
double f64_value() const;
/** print human-readable token representation on stream @p os **/
@ -196,6 +207,29 @@ namespace xo {
///@}
};
template <typename CharT>
bool
token<CharT>::bool_value() const {
if (tk_type_ != tokentype::tk_bool) {
throw (std::runtime_error
(tostr("token::bool_value",
": token with type tk found where tk_bool expected",
xtag("tk", tk_type_))));
}
if (text_ == "true")
return true;
if (text_ == "false")
return false;
throw (std::runtime_error
(tostr("token::bool_value",
": unexpected input string tk_bool token",
xtag("text", text_))));
return false;
}
template <typename CharT>
std::int64_t
token<CharT>::i64_value() const {

View file

@ -479,9 +479,6 @@ namespace xo {
(error_type(__FUNCTION__ /*src_function*/,
"expecting key following escape character \\",
input_state_,
//current_line_,
//current_pos_,
//initial_whitespace,
(ix - tk_start)));
}
@ -511,9 +508,6 @@ namespace xo {
(error_type(__FUNCTION__ /*src_function*/,
"expecting one of n|r|\"|\\ following escape \\",
input_state_,
//current_line_,
//current_pos_,
//initial_whitespace,
(ix - tk_start)));
}
break;
@ -531,9 +525,6 @@ namespace xo {
(error_type(__FUNCTION__ /*src_function*/,
"missing terminating '\"' to complete literal string",
input_state_,
//current_line_,
//current_pos_,
//initial_whitespace,
(ix - tk_start)));
}
@ -683,7 +674,10 @@ namespace xo {
bool keep_text = false;
if (tk_text == "type") {
if ((tk_text == "true") || (tk_text == "false")) {
tk_type = tokentype::tk_bool;
keep_text = true;
} else if (tk_text == "type") {
tk_type = tokentype::tk_type;
} else if (tk_text == "def") {
tk_type = tokentype::tk_def;
@ -691,6 +685,10 @@ namespace xo {
tk_type = tokentype::tk_lambda;
} else if (tk_text == "if") {
tk_type = tokentype::tk_if;
} else if (tk_text == "then") {
tk_type = tokentype::tk_then;
} else if (tk_text == "else") {
tk_type = tokentype::tk_else;
} else if (tk_text == "let") {
tk_type = tokentype::tk_let;
} else if (tk_text == "in") {
@ -842,9 +840,6 @@ namespace xo {
(error_type(__FUNCTION__ /*src_function*/,
"must use \\n or \\r to encode newline/cr in string literal",
input_state_,
//current_line_,
//current_pos_,
//whitespace.size(),
(ix - tk_start)));
}

View file

@ -49,6 +49,9 @@ namespace xo {
/** sentinel value **/
tk_invalid = -1,
/** a boolean constant **/
tk_bool,
/** an integer constant (signed 64-bit integer) **/
tk_i64,
@ -135,6 +138,12 @@ namespace xo {
/** keyword @c 'if' **/
tk_if,
/** keyworkd @c 'then' **/
tk_then,
/** keyword @c 'else' **/
tk_else,
/** keyword @c 'let' **/
tk_let,

View file

@ -13,6 +13,7 @@ namespace xo {
#define CASE(x) case tokentype::x: return STRINGIFY(x)
switch(tk_type) {
CASE(tk_bool);
CASE(tk_i64);
CASE(tk_f64);
CASE(tk_string);
@ -46,6 +47,8 @@ namespace xo {
CASE(tk_def);
CASE(tk_lambda);
CASE(tk_if);
CASE(tk_then);
CASE(tk_else);
CASE(tk_let);
CASE(tk_in);