Merge github.com:niXman/ChaiScript into develop

This commit is contained in:
Jason Turner 2016-12-01 14:03:56 -07:00
commit 95e119fffe
3 changed files with 151 additions and 149 deletions

View File

@ -7,6 +7,8 @@
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_ #ifndef CHAISCRIPT_ALGEBRAIC_HPP_
#define CHAISCRIPT_ALGEBRAIC_HPP_ #define CHAISCRIPT_ALGEBRAIC_HPP_
#include "../utility/fnv1a.hpp"
#include <string> #include <string>
namespace chaiscript namespace chaiscript
@ -51,76 +53,39 @@ namespace chaiscript
static Opers to_operator(const std::string &t_str, bool t_is_unary = false) static Opers to_operator(const std::string &t_str, bool t_is_unary = false)
{ {
if (t_str == "==") const auto op_hash = utility::fnv1a_32(t_str.c_str());
{ switch (op_hash) {
return Opers::equals; case utility::fnv1a_32("=="): { return Opers::equals; }
} else if (t_str == "<") { case utility::fnv1a_32("<"): { return Opers::less_than; }
return Opers::less_than; case utility::fnv1a_32(">"): { return Opers::greater_than; }
} else if (t_str == ">") { case utility::fnv1a_32("<="): { return Opers::less_than_equal; }
return Opers::greater_than; case utility::fnv1a_32(">="): { return Opers::greater_than_equal; }
} else if (t_str == "<=") { case utility::fnv1a_32("!="): { return Opers::not_equal; }
return Opers::less_than_equal; case utility::fnv1a_32("="): { return Opers::assign; }
} else if (t_str == ">=") { case utility::fnv1a_32("++"): { return Opers::pre_increment; }
return Opers::greater_than_equal; case utility::fnv1a_32("--"): { return Opers::pre_decrement; }
} else if (t_str == "!=") { case utility::fnv1a_32("*="): { return Opers::assign_product; }
return Opers::not_equal; case utility::fnv1a_32("+="): { return Opers::assign_sum; }
} else if (t_str == "=") { case utility::fnv1a_32("-="): { return Opers::assign_difference; }
return Opers::assign; case utility::fnv1a_32("&="): { return Opers::assign_bitwise_and; }
} else if (t_str == "++") { case utility::fnv1a_32("|="): { return Opers::assign_bitwise_or; }
return Opers::pre_increment; case utility::fnv1a_32("<<="): { return Opers::assign_shift_left; }
} else if (t_str == "--") { case utility::fnv1a_32(">>="): { return Opers::assign_shift_right; }
return Opers::pre_decrement; case utility::fnv1a_32("%="): { return Opers::assign_remainder; }
} else if (t_str == "*=") { case utility::fnv1a_32("^="): { return Opers::assign_bitwise_xor; }
return Opers::assign_product; case utility::fnv1a_32("<<"): { return Opers::shift_left; }
} else if (t_str == "+=") { case utility::fnv1a_32(">>"): { return Opers::shift_right; }
return Opers::assign_sum; case utility::fnv1a_32("%"): { return Opers::remainder; }
} else if (t_str == "-=") { case utility::fnv1a_32("&"): { return Opers::bitwise_and; }
return Opers::assign_difference; case utility::fnv1a_32("|"): { return Opers::bitwise_or; }
} else if (t_str == "&=") { case utility::fnv1a_32("^"): { return Opers::bitwise_xor; }
return Opers::assign_bitwise_and; case utility::fnv1a_32("~"): { return Opers::bitwise_complement; }
} else if (t_str == "|=") { case utility::fnv1a_32("+"): { return t_is_unary ? Opers::unary_plus : Opers::sum; }
return Opers::assign_bitwise_or; case utility::fnv1a_32("-"): { return t_is_unary ? Opers::unary_minus : Opers::difference; }
} else if (t_str == "<<=") { case utility::fnv1a_32("/"): { return Opers::quotient; }
return Opers::assign_shift_left; case utility::fnv1a_32("*"): { return Opers::product; }
} else if (t_str == ">>=") { default: { return Opers::invalid; }
return Opers::assign_shift_right; }
} else if (t_str == "%=") {
return Opers::assign_remainder;
} else if (t_str == "^=") {
return Opers::assign_bitwise_xor;
} else if (t_str == "<<") {
return Opers::shift_left;
} else if (t_str == ">>") {
return Opers::shift_right;
} else if (t_str == "%") {
return Opers::remainder;
} else if (t_str == "&") {
return Opers::bitwise_and;
} else if (t_str == "|") {
return Opers::bitwise_or;
} else if (t_str == "^") {
return Opers::bitwise_xor;
} else if (t_str == "~") {
return Opers::bitwise_complement;
} else if (t_str == "+") {
if (t_is_unary) {
return Opers::unary_plus;
} else {
return Opers::sum;
}
} else if (t_str == "-") {
if (t_is_unary) {
return Opers::unary_minus;
} else {
return Opers::difference;
}
} else if (t_str == "/") {
return Opers::quotient;
} else if (t_str == "*") {
return Opers::product;
} else {
return Opers::invalid;
}
} }
}; };

View File

@ -23,6 +23,7 @@
#include "chaiscript_common.hpp" #include "chaiscript_common.hpp"
#include "chaiscript_optimizer.hpp" #include "chaiscript_optimizer.hpp"
#include "chaiscript_tracer.hpp" #include "chaiscript_tracer.hpp"
#include "../utility/fnv1a.hpp"
#if defined(CHAISCRIPT_UTF16_UTF32) #if defined(CHAISCRIPT_UTF16_UTF32)
#include <locale> #include <locale>
@ -225,10 +226,18 @@ namespace chaiscript
return operators; return operators;
} }
static constexpr const char * const m_multiline_comment_begin = "/*"; static constexpr const char m_multiline_comment_begin[] = "/*";
static constexpr const char * const m_multiline_comment_end = "*/"; static constexpr const char m_multiline_comment_end[] = "*/";
static constexpr const char * const m_singleline_comment = "//"; static constexpr const char m_singleline_comment[] = "//";
static constexpr const char * const m_annotation = "#"; static constexpr const char m_annotation[] = "#";
static constexpr const char m_cr_lf[] = "\r\n";
enum {
m_multiline_comment_begin_len = sizeof(m_multiline_comment_begin)-1
,m_multiline_comment_end_len = sizeof(m_multiline_comment_end)-1
,m_singleline_comment_len = sizeof(m_singleline_comment)-1
,m_annotation_len = sizeof(m_annotation)-1
,m_cr_lf_len = sizeof(m_cr_lf)-1
};
const std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> &m_alphabet = create_alphabet(); 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<std::string>> &m_operator_matches = create_operator_matches();
@ -318,9 +327,10 @@ namespace chaiscript
return static_cast<size_t>(std::distance(m_pos, m_end)); return static_cast<size_t>(std::distance(m_pos, m_end));
} }
char operator*() const { const char& operator*() const {
if (m_pos == m_end) { if (m_pos == m_end) {
return '\0'; static const char ktmp ='\0';
return ktmp;
} else { } else {
return *m_pos; return *m_pos;
} }
@ -428,20 +438,30 @@ namespace chaiscript
} }
/// Reads a symbol group from input if it matches the parameter, without skipping initial whitespace
#define Symbol_(t_s, len) \
( \
m_position.remaining() >= len \
? std::memcmp(t_s, &(*m_position), len) == 0 \
? ((m_position += len),true) \
:false \
:false \
)
/// Skips any multi-line or single-line comment /// Skips any multi-line or single-line comment
bool SkipComment() { bool SkipComment() {
if (Symbol_(m_multiline_comment_begin)) { if (Symbol_(m_multiline_comment_begin, m_multiline_comment_begin_len)) {
while (m_position.has_more()) { while (m_position.has_more()) {
if (Symbol_(m_multiline_comment_end)) { if (Symbol_(m_multiline_comment_end, m_multiline_comment_end_len)) {
break; break;
} else if (!Eol_()) { } else if (!Eol_()) {
++m_position; ++m_position;
} }
} }
return true; return true;
} else if (Symbol_(m_singleline_comment)) { } else if (Symbol_(m_singleline_comment, m_singleline_comment_len)) {
while (m_position.has_more()) { while (m_position.has_more()) {
if (Symbol_("\r\n")) { if (Symbol_(m_cr_lf, m_cr_lf_len)) {
m_position -= 2; m_position -= 2;
break; break;
} else if (Char_('\n')) { } else if (Char_('\n')) {
@ -452,9 +472,9 @@ namespace chaiscript
} }
} }
return true; return true;
} else if (Symbol_(m_annotation)) { } else if (Symbol_(m_annotation, m_annotation_len)) {
while (m_position.has_more()) { while (m_position.has_more()) {
if (Symbol_("\r\n")) { if (Symbol_(m_cr_lf, m_cr_lf_len)) {
m_position -= 2; m_position -= 2;
break; break;
} else if (Char_('\n')) { } else if (Char_('\n')) {
@ -833,74 +853,77 @@ namespace chaiscript
const auto start = m_position; const auto start = m_position;
if (Id_()) { if (Id_()) {
const auto text = Position::str(start, m_position); auto text = Position::str(start, m_position);
const auto text_hash = utility::fnv1a_32(text.c_str());
if (validate) { if (validate) {
validate_object_name(text); validate_object_name(text);
} }
if (text == "true") { switch (text_hash) {
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col, const_var(true))); case utility::fnv1a_32("true"): {
} else if (text == "false") { 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(false))); } break;
} else if (text == "Infinity") { case utility::fnv1a_32("false"): {
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col, m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col, const_var(false)));
const_var(std::numeric_limits<double>::infinity()))); } break;
} else if (text == "NaN") { case utility::fnv1a_32("Infinity"): {
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col, m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col,
const_var(std::numeric_limits<double>::quiet_NaN()))); const_var(std::numeric_limits<double>::infinity())));
} else if (text == "__LINE__") { } break;
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col, case utility::fnv1a_32("NaN"): {
const_var(start.line))); m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col,
} else if (text == "__FILE__") { const_var(std::numeric_limits<double>::quiet_NaN())));
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col, } break;
const_var(m_filename))); case utility::fnv1a_32("__LINE__"): {
} else if (text == "__FUNC__") { m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col,
const std::string fun_name = [&]()->std::string{ const_var(start.line)));
} break;
case utility::fnv1a_32("__FILE__"): {
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col,
const_var(m_filename)));
} break;
case utility::fnv1a_32("__FUNC__"): {
std::string fun_name = "NOT_IN_FUNCTION";
for (size_t idx = m_match_stack.size() - 1; idx > 0; --idx) for (size_t idx = m_match_stack.size() - 1; idx > 0; --idx)
{ {
if (m_match_stack[idx-1]->identifier == AST_Node_Type::Id if (m_match_stack[idx-1]->identifier == AST_Node_Type::Id
&& m_match_stack[idx-0]->identifier == AST_Node_Type::Arg_List) { && m_match_stack[idx-0]->identifier == AST_Node_Type::Arg_List) {
return m_match_stack[idx-1]->text; fun_name = m_match_stack[idx-1]->text;
} }
} }
return "NOT_IN_FUNCTION";
}();
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col, m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col,
const_var(fun_name))); const_var(fun_name)));
} else if (text == "__CLASS__") { } break;
const std::string fun_name = [&]()->std::string{ case utility::fnv1a_32("__CLASS__"): {
std::string fun_name = "NOT_IN_CLASS";
for (size_t idx = m_match_stack.size() - 1; idx > 1; --idx) for (size_t idx = m_match_stack.size() - 1; idx > 1; --idx)
{ {
if (m_match_stack[idx-2]->identifier == AST_Node_Type::Id if (m_match_stack[idx-2]->identifier == AST_Node_Type::Id
&& m_match_stack[idx-1]->identifier == AST_Node_Type::Id && m_match_stack[idx-1]->identifier == AST_Node_Type::Id
&& m_match_stack[idx-0]->identifier == AST_Node_Type::Arg_List) { && m_match_stack[idx-0]->identifier == AST_Node_Type::Arg_List) {
return m_match_stack[idx-2]->text; fun_name = m_match_stack[idx-2]->text;
} }
} }
return "NOT_IN_CLASS";
}();
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col, m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col,
const_var(fun_name))); const_var(fun_name)));
} else if (text == "_") { } break;
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col, case utility::fnv1a_32("_"): {
Boxed_Value(std::make_shared<dispatch::Placeholder_Object>()))); m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col,
} else { Boxed_Value(std::make_shared<dispatch::Placeholder_Object>())));
m_match_stack.push_back(make_node<eval::Id_AST_Node<Tracer>>( } break;
[&]()->std::string{ default: {
if (*start == '`') { std::string val = std::move(text);
// 'escaped' literal, like an operator name if (*start == '`') {
return Position::str(start+1, m_position-1); // 'escaped' literal, like an operator name
} else { val = Position::str(start+1, m_position-1);
return text; }
} m_match_stack.push_back(make_node<eval::Id_AST_Node<Tracer>>(val, start.line, start.col));
}(), } break;
start.line, start.col));
} }
return true; return true;
} else { } else {
return false; return false;
@ -1330,25 +1353,6 @@ namespace chaiscript
return retval; return retval;
} }
/// Reads a symbol group from input if it matches the parameter, without skipping initial whitespace
bool Symbol_(const char *t_s) {
const auto len = strlen(t_s);
if (m_position.remaining() >= len) {
auto tmp = m_position;
for (size_t i = 0; i < len; ++i) {
if (*tmp != t_s[i]) {
return false;
}
++tmp;
}
m_position = tmp;
return true;
}
return false;
}
bool is_operator(const std::string &t_s) const { bool is_operator(const std::string &t_s) const {
return std::any_of(m_operator_matches.begin(), m_operator_matches.end(), 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<std::string> &opers) {
@ -1363,7 +1367,7 @@ namespace chaiscript
bool Symbol(const char *t_s, const bool t_disallow_prevention=false) { bool Symbol(const char *t_s, const bool t_disallow_prevention=false) {
SkipWS(); SkipWS();
const auto start = m_position; const auto start = m_position;
bool retval = Symbol_(t_s); bool retval = Symbol_(t_s, std::strlen(t_s));
// ignore substring matches // ignore substring matches
if (retval && m_position.has_more() && (t_disallow_prevention == false) && char_in_alphabet(*m_position,detail::symbol_alphabet)) { if (retval && m_position.has_more() && (t_disallow_prevention == false) && char_in_alphabet(*m_position,detail::symbol_alphabet)) {
@ -1382,7 +1386,7 @@ namespace chaiscript
bool Eol_(const bool t_eos = false) { bool Eol_(const bool t_eos = false) {
bool retval = false; bool retval = false;
if (m_position.has_more() && (Symbol_("\r\n") || Char_('\n'))) { if (m_position.has_more() && (Symbol_(m_cr_lf, m_cr_lf_len) || Char_('\n'))) {
retval = true; retval = true;
//++m_position.line; //++m_position.line;
m_position.col = 1; m_position.col = 1;
@ -2523,9 +2527,20 @@ namespace chaiscript
return m_match_stack.front(); return m_match_stack.front();
} }
}; };
template<typename Tracer, typename Optimizer>
constexpr const char ChaiScript_Parser<Tracer, Optimizer>::m_multiline_comment_begin[];
template<typename Tracer, typename Optimizer>
constexpr const char ChaiScript_Parser<Tracer, Optimizer>::m_multiline_comment_end[];
template<typename Tracer, typename Optimizer>
constexpr const char ChaiScript_Parser<Tracer, Optimizer>::m_singleline_comment[];
template<typename Tracer, typename Optimizer>
constexpr const char ChaiScript_Parser<Tracer, Optimizer>::m_annotation[];
template<typename Tracer, typename Optimizer>
constexpr const char ChaiScript_Parser<Tracer, Optimizer>::m_cr_lf[];
} }
} }
#undef Symbol_
#if defined(CHAISCRIPT_MSVC) && defined(CHAISCRIPT_PUSHED_MIN_MAX) #if defined(CHAISCRIPT_MSVC) && defined(CHAISCRIPT_PUSHED_MIN_MAX)
#undef CHAISCRIPT_PUSHED_MIN_MAX #undef CHAISCRIPT_PUSHED_MIN_MAX

View File

@ -0,0 +1,22 @@
// 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_FNV1A_HPP_
#define CHAISCRIPT_UTILITY_FNV1A_HPP_
#include <cstdint>
namespace chaiscript
{
namespace utility
{
static constexpr std::uint32_t fnv1a_32(const char *s, std::uint32_t h = 0x811c9dc5) {
return (*s == 0) ? h : fnv1a_32(s+1, ((h ^ (*s)) * 0x01000193));
}
}
}
#endif