Merge branch 'develop' into handle-bom-in-script

This commit is contained in:
Alek Mosingiewicz 2018-05-22 05:00:41 +02:00
commit be29b0a193
8 changed files with 105 additions and 38 deletions

View File

@ -370,6 +370,25 @@ if (expression) { }
if (statement; expression) { } if (statement; expression) { }
``` ```
## Switch Statements
``` chaiscript
var myvalue = 2
switch (myvalue) {
case (1) {
print("My Value is 1");
break;
}
case (2) {
print("My Value is 2");
break;
}
default {
print("My Value is something else.";
}
}
```
## Built in Types ## Built in Types
``` ```

View File

@ -23,10 +23,10 @@ namespace chaiscript
void array(const std::string &type, Module& m) void array(const std::string &type, Module& m)
{ {
typedef typename std::remove_extent<T>::type ReturnType; typedef typename std::remove_extent<T>::type ReturnType;
const auto extent = std::extent<T>::value;
m.add(user_type<T>(), type); m.add(user_type<T>(), type);
m.add(fun( m.add(fun(
[extent](T& t, size_t index)->ReturnType &{ [](T& t, size_t index)->ReturnType &{
constexpr auto extent = std::extent<T>::value;
if (extent > 0 && index >= extent) { if (extent > 0 && index >= extent) {
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent)); throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
} else { } else {
@ -37,7 +37,8 @@ namespace chaiscript
); );
m.add(fun( m.add(fun(
[extent](const T &t, size_t index)->const ReturnType &{ [](const T &t, size_t index)->const ReturnType &{
constexpr auto extent = std::extent<T>::value;
if (extent > 0 && index >= extent) { if (extent > 0 && index >= extent) {
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent)); throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
} else { } else {
@ -48,7 +49,8 @@ namespace chaiscript
); );
m.add(fun( m.add(fun(
[extent](const T &) { [](const T &) {
constexpr auto extent = std::extent<T>::value;
return extent; return extent;
}), "size"); }), "size");
} }

View File

@ -86,7 +86,7 @@ namespace chaiscript
// only compile this bit if noexcept is part of the type system // only compile this bit if noexcept is part of the type system
// //
#if __cpp_noexcept_function_type >= 201510 || (defined(_NOEXCEPT_TYPES_SUPPORTED) && _MSC_VER >= 1912) #if (defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510) || (defined(_NOEXCEPT_TYPES_SUPPORTED) && _MSC_VER >= 1912)
template<typename Ret, typename ... Param> template<typename Ret, typename ... Param>
Proxy_Function fun(Ret (*func)(Param...) noexcept) Proxy_Function fun(Ret (*func)(Param...) noexcept)
{ {

View File

@ -1042,7 +1042,7 @@ namespace chaiscript
bool saw_interpolation_marker = false; bool saw_interpolation_marker = false;
bool is_octal = false; bool is_octal = false;
bool is_hex = false; bool is_hex = false;
bool is_unicode = false; std::size_t unicode_size = 0;
const bool interpolation_allowed; const bool interpolation_allowed;
string_type octal_matches; string_type octal_matches;
@ -1066,12 +1066,12 @@ namespace chaiscript
process_hex(); process_hex();
} }
if (is_unicode) { if (unicode_size > 0) {
process_unicode(); process_unicode();
} }
} catch (const std::invalid_argument &) { } catch (const std::invalid_argument &) {
// escape sequence was invalid somehow, we'll pick this } catch (const exception::eval_error &) {
// up in the next part of parsing // Something happened with parsing, we'll catch it later?
} }
} }
@ -1101,13 +1101,43 @@ namespace chaiscript
void process_unicode() void process_unicode()
{ {
if (!hex_matches.empty()) { const auto ch = static_cast<uint32_t>(std::stoi(hex_matches, nullptr, 16));
auto val = stoll(hex_matches, nullptr, 16); const auto match_size = hex_matches.size();
hex_matches.clear(); hex_matches.clear();
match += detail::Char_Parser_Helper<string_type>::str_from_ll(val);
}
is_escaped = false; is_escaped = false;
is_unicode = false; const auto u_size = unicode_size;
unicode_size = 0;
char buf[4];
if (u_size != match_size) {
throw exception::eval_error("Incomplete unicode escape sequence");
}
if (u_size == 4 && ch >= 0xD800 && ch <= 0xDFFF) {
throw exception::eval_error("Invalid 16 bit universal character");
}
if (ch < 0x80) {
match += static_cast<char>(ch);
} else if (ch < 0x800) {
buf[0] = static_cast<char>(0xC0 | (ch >> 6));
buf[1] = static_cast<char>(0x80 | (ch & 0x3F));
match.append(buf, 2);
} else if (ch < 0x10000) {
buf[0] = static_cast<char>(0xE0 | (ch >> 12));
buf[1] = static_cast<char>(0x80 | ((ch >> 6) & 0x3F));
buf[2] = static_cast<char>(0x80 | (ch & 0x3F));
match.append(buf, 3);
} else if (ch < 0x200000) {
buf[0] = static_cast<char>(0xF0 | (ch >> 18));
buf[1] = static_cast<char>(0x80 | ((ch >> 12) & 0x3F));
buf[2] = static_cast<char>(0x80 | ((ch >> 6) & 0x3F));
buf[3] = static_cast<char>(0x80 | (ch & 0x3F));
match.append(buf, 4);
} else {
// this must be an invalid escape sequence?
throw exception::eval_error("Invalid 32 bit universal character");
}
} }
void parse(const char_type t_char, const int line, const int col, const std::string &filename) { void parse(const char_type t_char, const int line, const int col, const std::string &filename) {
@ -1143,11 +1173,11 @@ namespace chaiscript
} else { } else {
process_hex(); process_hex();
} }
} else if (is_unicode) { } else if (unicode_size > 0) {
if (is_hex_char) { if (is_hex_char) {
hex_matches.push_back(t_char); hex_matches.push_back(t_char);
if(hex_matches.size() == 4) { if(hex_matches.size() == unicode_size) {
// Format is specified to be 'slash'uABCD // Format is specified to be 'slash'uABCD
// on collecting from A to D do parsing // on collecting from A to D do parsing
process_unicode(); process_unicode();
@ -1175,7 +1205,9 @@ namespace chaiscript
} else if (t_char == 'x') { } else if (t_char == 'x') {
is_hex = true; is_hex = true;
} else if (t_char == 'u') { } else if (t_char == 'u') {
is_unicode = true; unicode_size = 4;
} else if (t_char == 'U') {
unicode_size = 8;
} else { } else {
switch (t_char) { switch (t_char) {
case ('\'') : match.push_back('\''); break; case ('\'') : match.push_back('\''); break;

View File

@ -78,7 +78,7 @@ int to_int(TestEnum t)
class TestDerivedType : public TestBaseType class TestDerivedType : public TestBaseType
{ {
public: public:
virtual ~TestDerivedType() {} ~TestDerivedType() override {}
TestDerivedType(const TestDerivedType &) = default; TestDerivedType(const TestDerivedType &) = default;
TestDerivedType() = default; TestDerivedType() = default;
virtual int func() override { return 1; } virtual int func() override { return 1; }

View File

@ -4,7 +4,7 @@
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4062 4242 4640 4702 6330 28251) #pragma warning(disable : 4062 4242 4566 4640 4702 6330 28251)
#endif #endif
@ -1276,6 +1276,16 @@ TEST_CASE("Test reference member being registered")
CHECK(d == Approx(2.3)); CHECK(d == Approx(2.3));
} }
TEST_CASE("Test unicode matches C++")
{
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
CHECK(u8"\U000000AC" == chai.eval<std::string>(R"("\U000000AC")"));
CHECK("\xF0\x9F\x8D\x8C" == chai.eval<std::string>(R"("\xF0\x9F\x8D\x8C")"));
CHECK(u8"\U0001F34C" == chai.eval<std::string>(R"("\U0001F34C")"));
CHECK(u8"\u2022" == chai.eval<std::string>(R"("\u2022")"));
}
const int add_3(const int &i) const int add_3(const int &i)
{ {

View File

@ -1,11 +1,4 @@
assert_equal('\u00aa', '\u00AA') assert_equal("\u00aa", "\u00AA")
assert_equal('\u00bb', '\uBB') assert_equal("\u00bb", "\xC2\xBB")
assert_equal('\ucc', '\u00CC')
assert_equal('\udd', '\uDD')
assert_equal('\u0ee', '\uEE')
assert_equal('\ue', '\u000E')
assert_equal("\u30\u31\u32", "012")
assert_equal("\u33Test", "3Test")
assert_equal("Test\u0040", "Test@") assert_equal("Test\u0040", "Test@")

View File

@ -1,5 +1,16 @@
assert_equal("\uc39c", "Ü") assert_equal("\uc39c", "")
assert_equal("U for \uc39cmlauts", "U for Ümlauts") assert_equal("U for \u00dcmlauts", "U for Ümlauts")
assert_equal("More \uc39cml\uc3a4\uc3bcts", "More Ümläüts")
assert_equal("Thorn \uc3be sign", "Thorn þ sign") assert_equal("Thorn \u00fe sign", "Thorn þ sign")
assert_equal("Test\u0020Me", "Test Me")
assert_equal("Test\u2022Me", "Test•Me")
assert_equal("\xF0\x9F\x8D\x8C", "🍌")
assert_equal("\U0001F34C", "🍌")
assert_throws("Invalid 16 bit universal character", fun(){ parse("\"\\uD83C\""); });
assert_throws("Incomplete unicode escape sequence", fun(){ parse("\"\\uD83 \""); });
assert_equal("\U00024B62", "𤭢")
assert_equal("Test\U0001F534Me", "Test🔴Me")