Finish removing runtime string comparisons
* Now virtually all parser string work is done at compile time * Continuing the work started by @niXman
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
#include "chaiscript_optimizer.hpp"
|
||||
#include "chaiscript_tracer.hpp"
|
||||
#include "../utility/fnv1a.hpp"
|
||||
#include "../utility/static_string.hpp"
|
||||
|
||||
#if defined(CHAISCRIPT_UTF16_UTF32)
|
||||
#include <locale>
|
||||
@@ -187,8 +188,8 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
static const std::vector<std::vector<std::string>> &create_operator_matches() {
|
||||
static const std::vector<std::vector<std::string>> operator_matches {
|
||||
static const std::vector<std::vector<utility::Static_String>> &create_operator_matches() {
|
||||
static const std::vector<std::vector<utility::Static_String>> operator_matches {
|
||||
{"?"},
|
||||
{"||"},
|
||||
{"&&"},
|
||||
@@ -226,48 +227,38 @@ namespace chaiscript
|
||||
return operators;
|
||||
}
|
||||
|
||||
static const std::pair<const char *, size_t> &multiline_comment_end()
|
||||
static const utility::Static_String &multiline_comment_end()
|
||||
{
|
||||
static const char str[] = "*/";
|
||||
static const size_t len = sizeof(str) - 1;
|
||||
static const std::pair<const char *, size_t> p(str, len);
|
||||
return p;
|
||||
static const utility::Static_String s("*/");
|
||||
return s;
|
||||
}
|
||||
|
||||
static const std::pair<const char *, size_t> &multiline_comment_begin()
|
||||
static const utility::Static_String &multiline_comment_begin()
|
||||
{
|
||||
static const char str[] = "/*";
|
||||
static const size_t len = sizeof(str) - 1;
|
||||
static const std::pair<const char *, size_t> p(str, len);
|
||||
return p;
|
||||
static const utility::Static_String s("/*");
|
||||
return s;
|
||||
}
|
||||
|
||||
static const std::pair<const char *, size_t> &singleline_comment()
|
||||
static const utility::Static_String &singleline_comment()
|
||||
{
|
||||
static const char str[] = "//";
|
||||
static const size_t len = sizeof(str) - 1;
|
||||
static const std::pair<const char *, size_t> p(str, len);
|
||||
return p;
|
||||
static const utility::Static_String s("//");
|
||||
return s;
|
||||
}
|
||||
|
||||
static const std::pair<const char *, size_t> &annotation()
|
||||
static const utility::Static_String &annotation()
|
||||
{
|
||||
static const char str[] = "#";
|
||||
static const size_t len = sizeof(str) - 1;
|
||||
static const std::pair<const char *, size_t> p(str, len);
|
||||
return p;
|
||||
static const utility::Static_String s("#");
|
||||
return s;
|
||||
}
|
||||
|
||||
static const std::pair<const char *, size_t> &cr_lf()
|
||||
static const utility::Static_String &cr_lf()
|
||||
{
|
||||
static const char str[] = "\r\n";
|
||||
static const size_t len = sizeof(str) - 1;
|
||||
static const std::pair<const char *, size_t> p(str, len);
|
||||
return p;
|
||||
static const utility::Static_String s("\r\n");
|
||||
return s;
|
||||
}
|
||||
|
||||
const std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> &m_alphabet = create_alphabet();
|
||||
const std::vector<std::vector<std::string>> &m_operator_matches = create_operator_matches();
|
||||
const std::vector<std::vector<utility::Static_String>> &m_operator_matches = create_operator_matches();
|
||||
const std::array<Operator_Precidence, 12> &m_operators = create_operators();
|
||||
|
||||
std::shared_ptr<std::string> m_filename;
|
||||
@@ -466,13 +457,14 @@ namespace chaiscript
|
||||
|
||||
|
||||
/// Reads a symbol group from input if it matches the parameter, without skipping initial whitespace
|
||||
inline bool Symbol_(const char *t_s, const size_t len)
|
||||
inline auto Symbol_(const utility::Static_String &sym)
|
||||
{
|
||||
const auto len = sym.size();
|
||||
if (m_position.remaining() >= len) {
|
||||
const char *file_pos = &(*m_position);
|
||||
for (size_t pos = 0; pos < len; ++pos)
|
||||
{
|
||||
if (t_s[pos] != file_pos[pos]) { return false; }
|
||||
if (sym.c_str()[pos] != file_pos[pos]) { return false; }
|
||||
}
|
||||
m_position += len;
|
||||
return true;
|
||||
@@ -480,11 +472,6 @@ namespace chaiscript
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool Symbol_(const std::pair<const char *, size_t> &sym)
|
||||
{
|
||||
return Symbol_(sym.first, sym.second);
|
||||
}
|
||||
|
||||
/// Skips any multi-line or single-line comment
|
||||
bool SkipComment() {
|
||||
if (Symbol_(multiline_comment_begin())) {
|
||||
@@ -1358,13 +1345,12 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// Reads a string from input if it matches the parameter, without skipping initial whitespace
|
||||
bool Keyword_(const char *t_s) {
|
||||
const auto len = strlen(t_s);
|
||||
|
||||
bool Keyword_(const utility::Static_String &t_s) {
|
||||
const auto len = t_s.size();
|
||||
if (m_position.remaining() >= len) {
|
||||
auto tmp = m_position;
|
||||
for (size_t i = 0; tmp.has_more() && i < len; ++i) {
|
||||
if (*tmp != t_s[i]) {
|
||||
if (*tmp != t_s.c_str()[i]) {
|
||||
return false;
|
||||
}
|
||||
++tmp;
|
||||
@@ -1377,7 +1363,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// Reads (and potentially captures) a string from input if it matches the parameter
|
||||
bool Keyword(const char *t_s) {
|
||||
bool Keyword(const utility::Static_String &t_s) {
|
||||
SkipWS();
|
||||
const auto start = m_position;
|
||||
bool retval = Keyword_(t_s);
|
||||
@@ -1392,19 +1378,19 @@ namespace chaiscript
|
||||
|
||||
bool is_operator(const std::string &t_s) const {
|
||||
return std::any_of(m_operator_matches.begin(), m_operator_matches.end(),
|
||||
[t_s](const std::vector<std::string> &opers) {
|
||||
[t_s](const std::vector<utility::Static_String> &opers) {
|
||||
return std::any_of(opers.begin(), opers.end(),
|
||||
[t_s](const std::string &s) {
|
||||
return s == t_s;
|
||||
[t_s](const utility::Static_String &s) {
|
||||
return t_s == s.c_str();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Reads (and potentially captures) a symbol group from input if it matches the parameter
|
||||
bool Symbol(const char *t_s, const bool t_disallow_prevention=false) {
|
||||
bool Symbol(const utility::Static_String &t_s, const bool t_disallow_prevention=false) {
|
||||
SkipWS();
|
||||
const auto start = m_position;
|
||||
bool retval = Symbol_(t_s, std::strlen(t_s));
|
||||
bool retval = Symbol_(t_s);
|
||||
|
||||
// ignore substring matches
|
||||
if (retval && m_position.has_more() && (t_disallow_prevention == false) && char_in_alphabet(*m_position,detail::symbol_alphabet)) {
|
||||
@@ -2277,18 +2263,25 @@ namespace chaiscript
|
||||
/// Reads a unary prefixed expression from input
|
||||
bool Prefix() {
|
||||
const auto prev_stack_top = m_match_stack.size();
|
||||
constexpr const std::array<const char *, 6> prefix_opers{{"++", "--", "-", "+", "!", "~"}};
|
||||
using SS = utility::Static_String;
|
||||
constexpr const std::array<utility::Static_String, 6> prefix_opers{
|
||||
SS{"++"},
|
||||
SS{"--"},
|
||||
SS{"-"},
|
||||
SS{"+"},
|
||||
SS{"!"},
|
||||
SS{"~"}};
|
||||
|
||||
for (const auto &oper : prefix_opers)
|
||||
{
|
||||
bool is_char = strlen(oper) == 1;
|
||||
if ((is_char && Char(oper[0])) || (!is_char && Symbol(oper)))
|
||||
const bool is_char = oper.size();
|
||||
if ((is_char && Char(oper.c_str()[0])) || (!is_char && Symbol(oper)))
|
||||
{
|
||||
if (!Operator(m_operators.size()-1)) {
|
||||
throw exception::eval_error("Incomplete prefix '" + std::string(oper) + "' expression", File_Position(m_position.line, m_position.col), *m_filename);
|
||||
throw exception::eval_error("Incomplete prefix '" + std::string(oper.c_str()) + "' expression", File_Position(m_position.line, m_position.col), *m_filename);
|
||||
}
|
||||
|
||||
build_match<eval::Prefix_AST_Node<Tracer>>(prev_stack_top, oper);
|
||||
build_match<eval::Prefix_AST_Node<Tracer>>(prev_stack_top, oper.c_str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2303,8 +2296,8 @@ namespace chaiscript
|
||||
|
||||
bool Operator_Helper(const size_t t_precedence, std::string &oper) {
|
||||
for (auto & elem : m_operator_matches[t_precedence]) {
|
||||
if (Symbol(elem.c_str())) {
|
||||
oper = elem;
|
||||
if (Symbol(elem)) {
|
||||
oper = elem.c_str();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2432,8 +2425,10 @@ namespace chaiscript
|
||||
bool Equation() {
|
||||
const auto prev_stack_top = m_match_stack.size();
|
||||
|
||||
using SS = utility::Static_String;
|
||||
|
||||
if (Operator()) {
|
||||
for (const auto sym : {"=", ":=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", "&=", "^=", "|="})
|
||||
for (const auto sym : {SS{"="}, SS{":="}, SS{"+="}, SS{"-="}, SS{"*="}, SS{"/="}, SS{"%="}, SS{"<<="}, SS{">>="}, SS{"&="}, SS{"^="}, SS{"|="}})
|
||||
{
|
||||
if (Symbol(sym, true)) {
|
||||
SkipWS(true);
|
||||
@@ -2441,7 +2436,7 @@ namespace chaiscript
|
||||
throw exception::eval_error("Incomplete equation", File_Position(m_position.line, m_position.col), *m_filename);
|
||||
}
|
||||
|
||||
build_match<eval::Equation_AST_Node<Tracer>>(prev_stack_top, sym);
|
||||
build_match<eval::Equation_AST_Node<Tracer>>(prev_stack_top, sym.c_str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
37
include/chaiscript/utility/static_string.hpp
Normal file
37
include/chaiscript/utility/static_string.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_UTILITY_STATIC_STRING_HPP_
|
||||
#define CHAISCRIPT_UTILITY_STATIC_STRING_HPP_
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace utility
|
||||
{
|
||||
|
||||
struct Static_String
|
||||
{
|
||||
template<size_t N>
|
||||
constexpr Static_String(const char (&str)[N])
|
||||
: m_size(N-1), data(&str[0])
|
||||
{
|
||||
}
|
||||
|
||||
constexpr size_t size() {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
constexpr const char *c_str() {
|
||||
return data;
|
||||
}
|
||||
|
||||
const size_t m_size;
|
||||
const char *data = nullptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user