Move the parser to string_view

This commit is contained in:
Jason Turner 2017-08-25 11:17:47 -06:00
parent ff70341af2
commit e49df4c54d
6 changed files with 114 additions and 44 deletions

View File

@ -210,6 +210,16 @@ namespace chaiscript {
return final_value(t, base, exponent, neg_exponent); return final_value(t, base, exponent, neg_exponent);
} }
struct str_less {
bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept {
return t_lhs < t_rhs;
}
template<typename LHS, typename RHS>
bool operator()(const LHS &t_lhs, const RHS &t_rhs) const noexcept {
return std::lexicographical_compare(t_lhs.begin(), t_lhs.end(), t_rhs.begin(), t_rhs.end());
}
struct is_transparent{};
};
enum class Options enum class Options
{ {

View File

@ -437,16 +437,6 @@ namespace chaiscript
/// of the object stack, functions and registered types. /// of the object stack, functions and registered types.
class Dispatch_Engine class Dispatch_Engine
{ {
struct str_less {
bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept {
return t_lhs < t_rhs;
}
template<typename LHS, typename RHS>
bool operator()(const LHS &t_lhs, const RHS &t_rhs) const noexcept {
return std::lexicographical_compare(t_lhs.begin(), t_lhs.end(), t_rhs.begin(), t_rhs.end());
}
struct is_transparent{};
};
public: public:
typedef std::map<std::string, chaiscript::Type_Info, str_less> Type_Name_Map; typedef std::map<std::string, chaiscript::Type_Info, str_less> Type_Name_Map;

View File

@ -45,6 +45,19 @@ namespace chaiscript
return words.count(name) == 1; return words.count(name) == 1;
} }
static bool is_reserved_word(const std::string_view &name) noexcept
{
static const std::unordered_set<std::string_view> words {
"def", "fun", "while", "for", "if", "else",
"&&", "||", ",", "auto", "return", "break",
"true", "false", "class", "attr", "var", "global",
"GLOBAL", "_",
"__LINE__", "__FILE__", "__FUNC__", "__CLASS__"
};
return words.count(name) == 1;
}
static bool valid_object_name(const std::string &name) noexcept static bool valid_object_name(const std::string &name) noexcept
{ {
return name.find("::") == std::string::npos && !is_reserved_word(name); return name.find("::") == std::string::npos && !is_reserved_word(name);
@ -60,6 +73,22 @@ namespace chaiscript
throw exception::illegal_name_error(name); throw exception::illegal_name_error(name);
} }
} }
static bool valid_object_name(const std::string_view &name) noexcept
{
return name.find("::") == std::string::npos && !is_reserved_word(name);
}
static void validate_object_name(const std::string_view &name)
{
if (is_reserved_word(name)) {
throw exception::reserved_word_error(std::string(name));
}
if (name.find("::") != std::string::npos) {
throw exception::illegal_name_error(std::string(name));
}
}
}; };
/// Signature of module entry point that all binary loadable modules must implement. /// Signature of module entry point that all binary loadable modules must implement.

View File

@ -210,7 +210,7 @@ namespace chaiscript
std::array<utility::Static_String, 3> m_10 {{SS("*"), SS("/"), SS("%")}}; std::array<utility::Static_String, 3> m_10 {{SS("*"), SS("/"), SS("%")}};
std::array<utility::Static_String, 6> m_11 {{SS("++"), SS("--"), SS("-"), SS("+"), SS("!"), SS("~")}}; std::array<utility::Static_String, 6> m_11 {{SS("++"), SS("--"), SS("-"), SS("+"), SS("!"), SS("~")}};
bool is_match(const std::string &t_str) const noexcept { bool is_match(const std::string_view &t_str) const noexcept {
constexpr std::array<std::size_t, 12> groups{{0,1,2,3,4,5,6,7,8,9,10,11}}; constexpr std::array<std::size_t, 12> groups{{0,1,2,3,4,5,6,7,8,9,10,11}};
return std::any_of(groups.begin(), groups.end(), [&t_str, this](const std::size_t group){ return is_match(group, t_str); }); return std::any_of(groups.begin(), groups.end(), [&t_str, this](const std::size_t group){ return is_match(group, t_str); });
} }
@ -239,9 +239,9 @@ namespace chaiscript
} }
} }
bool is_match(const std::size_t t_group, const std::string &t_str) const noexcept { constexpr bool is_match(const std::size_t t_group, const std::string_view &t_str) const noexcept {
auto match = [&t_str](const auto &array) { auto match = [&t_str](const auto &array) {
return std::any_of(array.begin(), array.end(), [&t_str](const auto &v){ return v.c_str() == t_str; }); return std::any_of(array.begin(), array.end(), [&t_str](const auto &v){ return v == t_str; });
}; };
switch (t_group) { switch (t_group) {
@ -325,9 +325,9 @@ namespace chaiscript
{ {
} }
static std::string str(const Position &t_begin, const Position &t_end) noexcept { static std::string_view str(const Position &t_begin, const Position &t_end) noexcept {
if (t_begin.m_pos != nullptr && t_end.m_pos != nullptr) { if (t_begin.m_pos != nullptr && t_end.m_pos != nullptr) {
return std::string(t_begin.m_pos, t_end.m_pos); return std::string_view(t_begin.m_pos, std::distance(t_begin.m_pos, t_end.m_pos));
} else { } else {
return {}; return {};
} }
@ -423,10 +423,10 @@ namespace chaiscript
Tracer m_tracer; Tracer m_tracer;
Optimizer m_optimizer; Optimizer m_optimizer;
void validate_object_name(const std::string &name) const void validate_object_name(const std::string_view &name) const
{ {
if (!Name_Validator::valid_object_name(name)) { if (!Name_Validator::valid_object_name(name)) {
throw exception::eval_error("Invalid Object Name: " + name, File_Position(m_position.line, m_position.col), *m_filename); throw exception::eval_error("Invalid Object Name: " + std::string(name), File_Position(m_position.line, m_position.col), *m_filename);
} }
} }
@ -720,7 +720,7 @@ namespace chaiscript
} }
/// Parses a floating point value and returns a Boxed_Value representation of it /// Parses a floating point value and returns a Boxed_Value representation of it
static Boxed_Value buildFloat(const std::string &t_val) static Boxed_Value buildFloat(const std::string_view &t_val)
{ {
bool float_ = false; bool float_ = false;
bool long_ = false; bool long_ = false;
@ -753,7 +753,7 @@ namespace chaiscript
static Boxed_Value buildInt(const int base, const std::string &t_val, const bool prefixed) static Boxed_Value buildInt(const int base, std::string_view t_val, const bool prefixed)
{ {
bool unsigned_ = false; bool unsigned_ = false;
bool long_ = false; bool long_ = false;
@ -780,7 +780,7 @@ namespace chaiscript
} }
} }
const auto val = prefixed?std::string(t_val.begin()+2,t_val.end()):t_val; if (prefixed) { t_val.remove_prefix(2); };
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC diagnostic push #pragma GCC diagnostic push
@ -793,7 +793,8 @@ namespace chaiscript
#endif #endif
try { try {
auto u = std::stoll(val,nullptr,base); /// TODO fix this to use from_chars
auto u = std::stoll(std::string(t_val),nullptr,base);
if (!unsigned_ && !long_ && u >= std::numeric_limits<int>::min() && u <= std::numeric_limits<int>::max()) { if (!unsigned_ && !long_ && u >= std::numeric_limits<int>::min() && u <= std::numeric_limits<int>::max()) {
@ -813,7 +814,8 @@ namespace chaiscript
} catch (const std::out_of_range &) { } catch (const std::out_of_range &) {
// too big to be signed // too big to be signed
try { try {
auto u = std::stoull(val,nullptr,base); /// TODO fix this to use from_chars
auto u = std::stoull(std::string(t_val),nullptr,base);
if (!longlong_ && u >= std::numeric_limits<unsigned long>::min() && u <= std::numeric_limits<unsigned long>::max()) { if (!longlong_ && u >= std::numeric_limits<unsigned long>::min() && u <= std::numeric_limits<unsigned long>::max()) {
return const_var(static_cast<unsigned long>(u)); return const_var(static_cast<unsigned long>(u));
@ -833,9 +835,9 @@ namespace chaiscript
} }
template<typename T, typename ... Param> template<typename T, typename ... Param>
std::unique_ptr<eval::AST_Node_Impl<Tracer>> make_node(std::string t_match, const int t_prev_line, const int t_prev_col, Param && ...param) std::unique_ptr<eval::AST_Node_Impl<Tracer>> make_node(std::string_view t_match, const int t_prev_line, const int t_prev_col, Param && ...param)
{ {
return chaiscript::make_unique<eval::AST_Node_Impl<Tracer>, T>(std::move(t_match), Parse_Location(m_filename, t_prev_line, t_prev_col, m_position.line, m_position.col), std::forward<Param>(param)...); return chaiscript::make_unique<eval::AST_Node_Impl<Tracer>, T>(std::string(t_match), Parse_Location(m_filename, t_prev_line, t_prev_col, m_position.line, m_position.col), std::forward<Param>(param)...);
} }
/// Reads a number from the input, detecting if it's an integer or floating point /// Reads a number from the input, detecting if it's an integer or floating point
@ -848,20 +850,20 @@ namespace chaiscript
if (Hex_()) { if (Hex_()) {
auto match = Position::str(start, m_position); auto match = Position::str(start, m_position);
auto bv = buildInt(16, match, true); auto bv = buildInt(16, match, true);
m_match_stack.emplace_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(match), start.line, start.col, std::move(bv))); m_match_stack.emplace_back(make_node<eval::Constant_AST_Node<Tracer>>(match, start.line, start.col, std::move(bv)));
return true; return true;
} }
if (Binary_()) { if (Binary_()) {
auto match = Position::str(start, m_position); auto match = Position::str(start, m_position);
auto bv = buildInt(2, match, true); auto bv = buildInt(2, match, true);
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(match), start.line, start.col, std::move(bv))); m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(match, start.line, start.col, std::move(bv)));
return true; return true;
} }
if (Float_()) { if (Float_()) {
auto match = Position::str(start, m_position); auto match = Position::str(start, m_position);
auto bv = buildFloat(match); auto bv = buildFloat(match);
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(match), start.line, start.col, std::move(bv))); m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(match, start.line, start.col, std::move(bv)));
return true; return true;
} }
else { else {
@ -869,11 +871,11 @@ namespace chaiscript
auto match = Position::str(start, m_position); auto match = Position::str(start, m_position);
if (!match.empty() && (match[0] == '0')) { if (!match.empty() && (match[0] == '0')) {
auto bv = buildInt(8, match, false); auto bv = buildInt(8, match, false);
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(match), start.line, start.col, std::move(bv))); m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(match, start.line, start.col, std::move(bv)));
} }
else if (!match.empty()) { else if (!match.empty()) {
auto bv = buildInt(10, match, false); auto bv = buildInt(10, match, false);
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(match), start.line, start.col, std::move(bv))); m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(match, start.line, start.col, std::move(bv)));
} else { } else {
return false; return false;
} }
@ -932,7 +934,7 @@ namespace chaiscript
if (Id_()) { if (Id_()) {
auto text = Position::str(start, m_position); auto text = Position::str(start, m_position);
const auto text_hash = utility::fnv1a_32(text.c_str()); const auto text_hash = utility::fnv1a_32(text);
if (validate) { if (validate) {
validate_object_name(text); validate_object_name(text);
@ -945,25 +947,25 @@ namespace chaiscript
switch (text_hash) { switch (text_hash) {
case utility::fnv1a_32("true"): { case utility::fnv1a_32("true"): {
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col, const_var(true))); m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col, const_var(true)));
} break; } break;
case utility::fnv1a_32("false"): { case utility::fnv1a_32("false"): {
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col, const_var(false))); m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col, const_var(false)));
} break; } break;
case utility::fnv1a_32("Infinity"): { case utility::fnv1a_32("Infinity"): {
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col, m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col,
const_var(std::numeric_limits<double>::infinity()))); const_var(std::numeric_limits<double>::infinity())));
} break; } break;
case utility::fnv1a_32("NaN"): { case utility::fnv1a_32("NaN"): {
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col, m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col,
const_var(std::numeric_limits<double>::quiet_NaN()))); const_var(std::numeric_limits<double>::quiet_NaN())));
} break; } break;
case utility::fnv1a_32("__LINE__"): { case utility::fnv1a_32("__LINE__"): {
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col, m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col,
const_var(start.line))); const_var(start.line)));
} break; } break;
case utility::fnv1a_32("__FILE__"): { case utility::fnv1a_32("__FILE__"): {
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col, m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col,
const_var(m_filename))); const_var(m_filename)));
} break; } break;
case utility::fnv1a_32("__FUNC__"): { case utility::fnv1a_32("__FUNC__"): {
@ -976,7 +978,7 @@ namespace chaiscript
} }
} }
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col, m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col,
const_var(fun_name))); const_var(fun_name)));
} break; } break;
case utility::fnv1a_32("__CLASS__"): { case utility::fnv1a_32("__CLASS__"): {
@ -998,10 +1000,11 @@ namespace chaiscript
Boxed_Value(std::make_shared<dispatch::Placeholder_Object>()))); Boxed_Value(std::make_shared<dispatch::Placeholder_Object>())));
} break; } break;
default: { default: {
std::string val = std::move(text); auto val = text;
if (*start == '`') { if (*start == '`') {
// 'escaped' literal, like an operator name // 'escaped' literal, like an operator name
val = Position::str(start+1, m_position-1); val = Position::str(start+1, m_position-1);
// val.remove_prefix(1); val.remove_suffix(1);
} }
m_match_stack.push_back(make_node<eval::Id_AST_Node<Tracer>>(val, start.line, start.col)); m_match_stack.push_back(make_node<eval::Id_AST_Node<Tracer>>(val, start.line, start.col));
} break; } break;
@ -1444,7 +1447,7 @@ namespace chaiscript
return retval; return retval;
} }
bool is_operator(const std::string &t_s) const noexcept { bool is_operator(const std::string_view &t_s) const noexcept {
constexpr Operator_Matches operator_matches; constexpr Operator_Matches operator_matches;
return operator_matches.is_match(t_s); return operator_matches.is_match(t_s);
} }

View File

@ -18,9 +18,8 @@ namespace chaiscript
namespace utility namespace utility
{ {
template<typename Itr>
static constexpr std::uint32_t fnv1a_32(Itr begin, Itr end) noexcept {
static constexpr std::uint32_t fnv1a_32(const char *s, std::uint32_t h = 0x811c9dc5) noexcept {
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion" #pragma GCC diagnostic ignored "-Wsign-conversion"
@ -30,7 +29,14 @@ namespace chaiscript
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4307) #pragma warning(disable : 4307)
#endif #endif
return (*s == 0) ? h : fnv1a_32(s+1, ((h ^ (*s)) * 0x01000193)); std::uint32_t h = 0x811c9dc5;
while (begin != end) {
h = (h ^ (*begin)) * 0x01000193;
++begin;
}
return h;
#ifdef CHAISCRIPT_MSVC #ifdef CHAISCRIPT_MSVC
#pragma warning(pop) #pragma warning(pop)
#endif #endif
@ -42,8 +48,16 @@ namespace chaiscript
} }
template<size_t N>
static constexpr std::uint32_t fnv1a_32(const char (&str)[N]) noexcept {
return fnv1a_32(std::begin(str), std::end(str)-1);
} }
static constexpr std::uint32_t fnv1a_32(const std::string_view &sv) noexcept {
return fnv1a_32(sv.begin(), sv.end());
}
}
} }

View File

@ -28,6 +28,30 @@ namespace chaiscript
return data; return data;
} }
constexpr auto begin() const noexcept {
return data;
}
constexpr auto end() const noexcept {
return data + m_size;
}
constexpr bool operator==(const std::string_view &other) const noexcept {
//return std::string_view(data, m_size) == other;
auto b1 = begin();
const auto e1 = end();
auto b2 = other.begin();
const auto e2 = other.end();
if (e1 - b1 != e2 - b2) { return false; }
while (b1 != e1) {
if (*b1 != *b2) { return false; }
++b1; ++b2;
}
return true;
}
const size_t m_size; const size_t m_size;
const char *data = nullptr; const char *data = nullptr;
}; };