diff --git a/src/cs_bcode.cc b/src/cs_bcode.cc index c111beb..965fc7e 100644 --- a/src/cs_bcode.cc +++ b/src/cs_bcode.cc @@ -1,6 +1,5 @@ #include "cs_bcode.hh" - -#include "cs_util.hh" +#include "cs_state.hh" namespace cscript { diff --git a/src/cs_error.cc b/src/cs_error.cc index 71788de..3aec79b 100644 --- a/src/cs_error.cc +++ b/src/cs_error.cc @@ -1,6 +1,5 @@ #include -#include "cs_util.hh" #include "cs_vm.hh" namespace cscript { diff --git a/src/cs_gen.cc b/src/cs_gen.cc index 4ac0e04..0926010 100644 --- a/src/cs_gen.cc +++ b/src/cs_gen.cc @@ -1,6 +1,6 @@ #include #include "cs_vm.hh" -#include "cs_util.hh" +#include "cs_std.hh" #include @@ -114,11 +114,11 @@ static inline std::pair compileblock( ); void cs_gen_state::gen_int(std::string_view word) { - gen_int(cs_parse_int(word)); + gen_int(parse_int(word)); } void cs_gen_state::gen_float(std::string_view word) { - gen_float(cs_parse_float(word)); + gen_float(parse_float(word)); } void cs_gen_state::gen_value(int wordtype, std::string_view word, int line) { @@ -1317,7 +1317,7 @@ noid: switch (rettype) { case CS_VAL_ANY: { std::string_view end = idname.str_term(); - cs_int val = cs_parse_int(end, &end); + cs_int val = parse_int(end, &end); if (!end.empty()) { gs.gen_str(idname.str_term()); } else { diff --git a/src/cs_ident.hh b/src/cs_ident.hh index ad20db4..5f0dc43 100644 --- a/src/cs_ident.hh +++ b/src/cs_ident.hh @@ -3,8 +3,6 @@ #include -#include "cs_util.hh" - namespace cscript { enum { diff --git a/src/cs_state.cc b/src/cs_state.cc index e806631..bc94ef5 100644 --- a/src/cs_state.cc +++ b/src/cs_state.cc @@ -1,6 +1,5 @@ #include -#include "cs_util.hh" #include "cs_bcode.hh" #include "cs_state.hh" #include "cs_strman.hh" diff --git a/src/cs_std.cc b/src/cs_std.cc new file mode 100644 index 0000000..ca28d3e --- /dev/null +++ b/src/cs_std.cc @@ -0,0 +1,183 @@ +#include +#include + +#include "cs_std.hh" + +namespace cscript { + +static inline char const *p_skip_white(char const *beg, char const *end) { + while ((beg != end) && isspace(*beg)) { + ++beg; + } + return beg; +} + +static inline void p_set_end( + char const *nbeg, char const *nend, std::string_view *end +) { + if (!end) { + return; + } + *end = std::string_view{nbeg, nend}; +} +/* this function assumes the input is definitely a hex digit */ +static inline cs_int p_hexd_to_int(char c) { + if (c >= 97) { /* a-f */ + return (c - 'a') + 10; + } else if (c >= 65) { /* A-F */ + return (c - 'A') + 10; + } + /* 0-9 */ + return c - '0'; +} + +static inline bool p_check_neg(char const *&input) { + bool neg = (*input == '-'); + if (neg || (*input == '+')) { + ++input; + } + return neg; +} + +cs_int parse_int(std::string_view input, std::string_view *endstr) { + char const *beg = input.begin(); + char const *end = input.end(); + char const *orig = beg; + beg = p_skip_white(beg, end); + if (beg == end) { + p_set_end(orig, end, endstr); + return cs_int(0); + } + bool neg = p_check_neg(beg); + cs_int ret = 0; + char const *past = beg; + if ((end - beg) >= 2) { + std::string_view pfx = std::string_view{beg, 2}; + if ((pfx == "0x") || (pfx == "0X")) { + beg += 2; + past = beg; + while ((past != end) && std::isxdigit(*past)) { + ret = ret * 16 + p_hexd_to_int(*past++); + } + goto done; + } else if ((pfx == "0b") || (pfx == "0B")) { + beg += 2; + past = beg; + while ((past != end) && ((*past == '0') || (*past == '1'))) { + ret = ret * 2 + (*past++ - '0'); + } + goto done; + } + } + while ((past != end) && std::isdigit(*past)) { + ret = ret * 10 + (*past++ - '0'); + } +done: + p_set_end((past == beg) ? orig : past, end, endstr); + if (neg) { + return -ret; + } + return ret; +} + +template +static inline bool p_read_exp(char const *&beg, char const *end, cs_int &fn) { + if (beg == end) { + return true; + } + if ((*beg != e1) && (*beg != e2)) { + return true; + } + if (++beg == end) { + return false; + } + bool neg = p_check_neg(beg); + if ((beg == end) || !std::isdigit(*beg)) { + return false; + } + cs_int exp = 0; + while ((beg != end) && std::isdigit(*beg)) { + exp = exp * 10 + (*beg++ - '0'); + } + if (neg) { + exp = -exp; + } + fn += exp; + return true; +} + +template +static inline bool parse_gen_float( + char const *&beg, char const *end, std::string_view *endstr, cs_float &ret +) { + auto read_digits = [&beg, end](double r, cs_int &n) { + while ( + (beg != end) && + (Hex ? std::isxdigit(*beg) : std::isdigit(*beg)) + ) { + if (Hex) { + r = r * 16.0 + double(p_hexd_to_int(*beg)); + } else { + r = r * 10.0 + double(*beg - '0'); + } + ++n; + ++beg; + } + return r; + }; + cs_int wn = 0, fn = 0; + double r = read_digits(0.0, wn); + if ((beg != end) && (*beg == '.')) { + ++beg; + r = read_digits(r, fn); + } + if (!wn && !fn) { + return false; + } + fn = -fn; + p_set_end(beg, end, endstr); /* we have a valid number until here */ + if (p_read_exp(beg, end, fn)) { + p_set_end(beg, end, endstr); + } + if (Hex) { + ret = cs_float(ldexp(r, fn * 4)); + } else { + ret = cs_float(r * pow(10, fn)); + } + return true; +} + +cs_float parse_float(std::string_view input, std::string_view *endstr) { + char const *beg = input.begin(); + char const *end = input.end(); + char const *orig = beg; + beg = p_skip_white(beg, end); + if (beg == end) { + p_set_end(orig, end, endstr); + return cs_float(0); + } + bool neg = p_check_neg(beg); + cs_float ret = cs_float(0); + if ((end - beg) >= 2) { + std::string_view pfx = std::string_view{beg, 2}; + if ((pfx == "0x") || (pfx == "0X")) { + beg += 2; + if (!parse_gen_float(beg, end, endstr, ret)) { + p_set_end(orig, end, endstr); + return ret; + } + goto done; + } + } + if (!parse_gen_float(beg, end, endstr, ret)) { + p_set_end(orig, end, endstr); + return ret; + } +done: + if (neg) { + return -ret; + } + return ret; +} + +} /* namespace cscript */ diff --git a/src/cs_std.hh b/src/cs_std.hh index 63a78f5..d9333da 100644 --- a/src/cs_std.hh +++ b/src/cs_std.hh @@ -1,9 +1,12 @@ #ifndef LIBCUBESCRIPT_STD_HH #define LIBCUBESCRIPT_STD_HH +#include + #include #include #include +#include #include "cs_state.hh" @@ -117,6 +120,11 @@ struct cs_charbuf: cs_valbuf { } }; +/* literal parsing */ + +cs_int parse_int(std::string_view input, std::string_view *end = nullptr); +cs_float parse_float(std::string_view input, std::string_view *end = nullptr); + } /* namespace cscript */ #endif diff --git a/src/cs_util.cc b/src/cs_util.cc index 30290c7..a5363ff 100644 --- a/src/cs_util.cc +++ b/src/cs_util.cc @@ -1,5 +1,4 @@ #include -#include "cs_util.hh" #include "cs_vm.hh" #include "cs_strman.hh" @@ -10,179 +9,6 @@ namespace cscript { -static inline char const *p_skip_white(char const *beg, char const *end) { - while ((beg != end) && isspace(*beg)) { - ++beg; - } - return beg; -} - -static inline void p_set_end( - char const *nbeg, char const *nend, std::string_view *end -) { - if (!end) { - return; - } - *end = std::string_view{nbeg, std::size_t(nend - nbeg)}; -} - -/* this function assumes the input is definitely a hex digit */ -static inline cs_int p_hexd_to_int(char c) { - if (c >= 97) { /* a-f */ - return (c - 'a') + 10; - } else if (c >= 65) { /* A-F */ - return (c - 'A') + 10; - } - /* 0-9 */ - return c - '0'; -} - -static inline bool p_check_neg(char const *&input) { - bool neg = (*input == '-'); - if (neg || (*input == '+')) { - ++input; - } - return neg; -} - -cs_int cs_parse_int(std::string_view input, std::string_view *endstr) { - char const *beg = input.begin(); - char const *end = input.end(); - char const *orig = beg; - beg = p_skip_white(beg, end); - if (beg == end) { - p_set_end(orig, end, endstr); - return cs_int(0); - } - bool neg = p_check_neg(beg); - cs_int ret = 0; - char const *past = beg; - if ((end - beg) >= 2) { - std::string_view pfx = std::string_view{beg, 2}; - if ((pfx == "0x") || (pfx == "0X")) { - beg += 2; - past = beg; - while ((past != end) && isxdigit(*past)) { - ret = ret * 16 + p_hexd_to_int(*past++); - } - goto done; - } else if ((pfx == "0b") || (pfx == "0B")) { - beg += 2; - past = beg; - while ((past != end) && ((*past == '0') || (*past == '1'))) { - ret = ret * 2 + (*past++ - '0'); - } - goto done; - } - } - while ((past != end) && isdigit(*past)) { - ret = ret * 10 + (*past++ - '0'); - } -done: - p_set_end((past == beg) ? orig : past, end, endstr); - if (neg) { - return -ret; - } - return ret; -} - -template -static inline bool p_read_exp(char const *&beg, char const *end, cs_int &fn) { - if (beg == end) { - return true; - } - if ((*beg != e1) && (*beg != e2)) { - return true; - } - if (++beg == end) { - return false; - } - bool neg = p_check_neg(beg); - if ((beg == end) || !isdigit(*beg)) { - return false; - } - cs_int exp = 0; - while ((beg != end) && isdigit(*beg)) { - exp = exp * 10 + (*beg++ - '0'); - } - if (neg) { - exp = -exp; - } - fn += exp; - return true; -} - -template -static inline bool parse_gen_float( - char const *&beg, char const *end, std::string_view *endstr, cs_float &ret -) { - auto read_digits = [&beg, end](double r, cs_int &n) { - while ((beg != end) && (Hex ? isxdigit(*beg) : isdigit(*beg))) { - if (Hex) { - r = r * 16.0 + double(p_hexd_to_int(*beg)); - } else { - r = r * 10.0 + double(*beg - '0'); - } - ++n; - ++beg; - } - return r; - }; - cs_int wn = 0, fn = 0; - double r = read_digits(0.0, wn); - if ((beg != end) && (*beg == '.')) { - ++beg; - r = read_digits(r, fn); - } - if (!wn && !fn) { - return false; - } - fn = -fn; - p_set_end(beg, end, endstr); /* we have a valid number until here */ - if (p_read_exp(beg, end, fn)) { - p_set_end(beg, end, endstr); - } - if (Hex) { - ret = cs_float(ldexp(r, fn * 4)); - } else { - ret = cs_float(r * pow(10, fn)); - } - return true; -} - -cs_float cs_parse_float(std::string_view input, std::string_view *endstr) { - char const *beg = input.begin(); - char const *end = input.end(); - char const *orig = beg; - beg = p_skip_white(beg, end); - if (beg == end) { - p_set_end(orig, end, endstr); - return cs_float(0); - } - bool neg = p_check_neg(beg); - cs_float ret = cs_float(0); - if ((end - beg) >= 2) { - std::string_view pfx = std::string_view{beg, 2}; - if ((pfx == "0x") || (pfx == "0X")) { - beg += 2; - if (!parse_gen_float(beg, end, endstr, ret)) { - p_set_end(orig, end, endstr); - return ret; - } - goto done; - } - } - if (!parse_gen_float(beg, end, endstr, ret)) { - p_set_end(orig, end, endstr); - return ret; - } -done: - if (neg) { - return -ret; - } - return ret; -} - /* strref */ cs_strref::cs_strref(cs_shared_state *cs, std::string_view str): diff --git a/src/cs_util.hh b/src/cs_util.hh deleted file mode 100644 index 5d0b72f..0000000 --- a/src/cs_util.hh +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef LIBCUBESCRIPT_CS_UTIL_HH -#define LIBCUBESCRIPT_CS_UTIL_HH - -#include -#include -#include - -#include "cs_bcode.hh" -#include "cs_state.hh" - -namespace cscript { - -cs_int cs_parse_int( - std::string_view input, std::string_view *end = nullptr -); - -cs_float cs_parse_float( - std::string_view input, std::string_view *end = nullptr -); - -} /* namespace cscript */ - -#endif /* LIBCUBESCRIPT_CS_UTIL_HH */ diff --git a/src/cs_val.cc b/src/cs_val.cc index 7b85e2a..553bac0 100644 --- a/src/cs_val.cc +++ b/src/cs_val.cc @@ -1,6 +1,6 @@ #include #include "cs_vm.hh" -#include "cs_util.hh" +#include "cs_std.hh" #include @@ -190,7 +190,7 @@ cs_float cs_value::force_float() { rf = csv_get(p_stor); break; case cs_value_type::STRING: - rf = cs_parse_float( + rf = parse_float( *reinterpret_cast(&p_stor) ); break; @@ -210,7 +210,7 @@ cs_int cs_value::force_int() { ri = csv_get(p_stor); break; case cs_value_type::STRING: - ri = cs_parse_int( + ri = parse_int( *reinterpret_cast(&p_stor) ); break; @@ -250,7 +250,7 @@ cs_int cs_value::get_int() const { case cs_value_type::INT: return csv_get(p_stor); case cs_value_type::STRING: - return cs_parse_int( + return parse_int( *reinterpret_cast(&p_stor) ); default: @@ -266,7 +266,7 @@ cs_float cs_value::get_float() const { case cs_value_type::INT: return cs_float(csv_get(p_stor)); case cs_value_type::STRING: - return cs_parse_float( + return parse_float( *reinterpret_cast(&p_stor) ); default: @@ -343,12 +343,12 @@ static inline bool cs_get_bool(std::string_view s) { return false; } std::string_view end = s; - cs_int ival = cs_parse_int(end, &end); + cs_int ival = parse_int(end, &end); if (end.empty()) { return !!ival; } end = s; - cs_float fval = cs_parse_float(end, &end); + cs_float fval = parse_float(end, &end); if (end.empty()) { return !!fval; } diff --git a/src/cs_vm.cc b/src/cs_vm.cc index 6852c55..0b76545 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -1,6 +1,6 @@ #include #include "cs_vm.hh" -#include "cs_util.hh" +#include "cs_std.hh" #include #include @@ -823,7 +823,7 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { ); continue; case ID_SVAR: - arg.set_int(cs_parse_int( + arg.set_int(parse_int( static_cast(id)->get_value() )); continue; @@ -866,7 +866,7 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { ); continue; case ID_SVAR: - arg.set_float(cs_parse_float( + arg.set_float(parse_float( static_cast(id)->get_value() )); continue; @@ -1022,12 +1022,12 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { )->get_value()); continue; case CS_CODE_SVAR | CS_RET_INT: - args[numargs++].set_int(cs_parse_int(static_cast( + args[numargs++].set_int(parse_int(static_cast( cs.p_state->identmap[op >> 8] )->get_value())); continue; case CS_CODE_SVAR | CS_RET_FLOAT: - args[numargs++].set_float(cs_parse_float(static_cast( + args[numargs++].set_float(parse_float(static_cast( cs.p_state->identmap[op >> 8] )->get_value())); continue; diff --git a/src/cs_vm.hh b/src/cs_vm.hh index f8cf6b3..94e7495 100644 --- a/src/cs_vm.hh +++ b/src/cs_vm.hh @@ -9,7 +9,6 @@ #include #include "cs_std.hh" -#include "cs_util.hh" #include "cs_bcode.hh" #include "cs_ident.hh" diff --git a/src/lib_list.cc b/src/lib_list.cc index 2af6314..cb5c56a 100644 --- a/src/lib_list.cc +++ b/src/lib_list.cc @@ -2,7 +2,6 @@ #include #include -#include "cs_util.hh" #include "cs_std.hh" namespace cscript { @@ -249,14 +248,14 @@ void cs_init_lib_list(cs_state &gcs) { gcs.new_command("listfind=", "i", [](auto &cs, auto args, auto &res) { cs_list_find( cs, args, res, [](cs_list_parser const &p, cs_int val) { - return cs_parse_int(p.get_raw_item()) == val; + return parse_int(p.get_raw_item()) == val; } ); }); gcs.new_command("listfind=f", "f", [](auto &cs, auto args, auto &res) { cs_list_find( cs, args, res, [](cs_list_parser const &p, cs_float val) { - return cs_parse_float(p.get_raw_item()) == val; + return parse_float(p.get_raw_item()) == val; } ); }); @@ -271,14 +270,14 @@ void cs_init_lib_list(cs_state &gcs) { gcs.new_command("listassoc=", "i", [](auto &cs, auto args, auto &res) { cs_list_assoc( cs, args, res, [](cs_list_parser const &p, cs_int val) { - return cs_parse_int(p.get_raw_item()) == val; + return parse_int(p.get_raw_item()) == val; } ); }); gcs.new_command("listassoc=f", "f", [](auto &cs, auto args, auto &res) { cs_list_assoc( cs, args, res, [](cs_list_parser const &p, cs_float val) { - return cs_parse_float(p.get_raw_item()) == val; + return parse_float(p.get_raw_item()) == val; } ); }); diff --git a/src/lib_str.cc b/src/lib_str.cc index 2ebc5d7..77a9dc4 100644 --- a/src/lib_str.cc +++ b/src/lib_str.cc @@ -3,7 +3,6 @@ #include -#include "cs_util.hh" #include "cs_std.hh" #include "cs_strman.hh" diff --git a/src/meson.build b/src/meson.build index 6bc8cdd..d6aaefc 100644 --- a/src/meson.build +++ b/src/meson.build @@ -9,6 +9,7 @@ libcubescript_src = [ 'cs_gen.cc', 'cs_ident.cc', 'cs_state.cc', + 'cs_std.cc', 'cs_strman.cc', 'cs_util.cc', 'cs_val.cc',