From 2893112609489ae007b087474ac7a2349c0c04d9 Mon Sep 17 00:00:00 2001 From: Anand Thakker Date: Mon, 10 Jul 2017 09:03:36 -0400 Subject: Parse literal arrays and objects --- include/mbgl/style/expression/expression.hpp | 55 ++++++++++++++++++---------- include/mbgl/style/expression/parse.hpp | 11 +++++- include/mbgl/style/function/type.hpp | 4 +- src/mbgl/style/function/type.cpp | 2 +- 4 files changed, 49 insertions(+), 23 deletions(-) diff --git a/include/mbgl/style/expression/expression.hpp b/include/mbgl/style/expression/expression.hpp index a3e69e4bb3..e36db1b3c7 100644 --- a/include/mbgl/style/expression/expression.hpp +++ b/include/mbgl/style/expression/expression.hpp @@ -93,10 +93,7 @@ using namespace mbgl::style::conversion; class LiteralExpression : public Expression { public: - LiteralExpression(std::string key, float value_) : Expression(key, type::Primitive::Number), value(value_) {} - LiteralExpression(std::string key, const std::string& value_) : Expression(key, type::Primitive::String), value(value_) {} - LiteralExpression(std::string key, const mbgl::Color& value_) : Expression(key, type::Primitive::Color), value(value_) {} - LiteralExpression(std::string key, const NullValue&) : Expression(key, type::Primitive::Null), value(Null) {} + LiteralExpression(std::string key, type::Type type, Value value_) : Expression(key, type), value(value_) {} EvaluationResult evaluate(const EvaluationParameters&) const override { return value; @@ -104,31 +101,51 @@ public: template static ParseResult parse(const V& value, const ParsingContext& ctx) { - if (isUndefined(value)) - return std::make_unique(ctx.key(), Null); - + const Value& parsedValue = parseValue(value); + const type::Type& type = parsedValue.match( + [&](float) -> type::Type { return type::Primitive::Number; }, + [&](const std::string&) -> type::Type { return type::Primitive::String; }, + [&](const mbgl::Color&) -> type::Type { return type::Primitive::Color; }, + [&](const NullValue&) -> type::Type { return type::Primitive::Null; }, + [&](const std::unordered_map&) -> type::Type { return type::Primitive::Object; }, + [&](const std::vector& arr) -> type::Type { + // TODO + return type::Array(type::Primitive::Value, arr.size()); + } + ); + return std::make_unique(ctx.key(), type, parsedValue); + } + +private: + template + static Value parseValue(const V& value) { + if (isUndefined(value)) return Null; if (isObject(value)) { - return CompileError {ctx.key(), "Unimplemented: object literals"}; + std::unordered_map result; + eachMember(value, [&] (const std::string& k, const V& v) -> optional { + result.emplace(k, parseValue(v)); + return {}; + }); + return result; } - if (isArray(value)) { - return CompileError {ctx.key(), "Unimplemented: array literals"}; + std::vector result; + const auto length = arrayLength(value); + for(std::size_t i = 0; i < length; i++) { + result.emplace_back(parseValue(arrayMember(value, i))); + } + return result; } optional v = toValue(value); assert(v); return v->match( - [&] (std::string s) { return std::make_unique(ctx.key(), s); }, - [&] (bool b) { return std::make_unique(ctx.key(), b); }, - [&] (auto f) { - auto number = numericValue(f); - assert(number); - return std::make_unique(ctx.key(), *number); - } + [&] (const std::string& s) -> Value { return s; }, + [&] (bool b) -> Value { return b; }, + [&] (auto f) -> Value { return *numericValue(f); } ); } - -private: + Value value; }; diff --git a/include/mbgl/style/expression/parse.hpp b/include/mbgl/style/expression/parse.hpp index 1f5802d4fb..cba2231988 100644 --- a/include/mbgl/style/expression/parse.hpp +++ b/include/mbgl/style/expression/parse.hpp @@ -37,7 +37,8 @@ ParseResult parseExpression(const V& value, const ParsingContext& context) using namespace mbgl::style::conversion; if (isArray(value)) { - if (arrayLength(value) == 0) { + const std::size_t length = arrayLength(value); + if (length == 0) { CompileError error = { "Expected an array with at least one element. If you wanted a literal array, use [\"literal\", []].", context.key() @@ -55,6 +56,14 @@ ParseResult parseExpression(const V& value, const ParsingContext& context) return error; } + if (*op == "literal") { + if (length != 2) return CompileError { + "'literal' expression requires exactly one argument, but found " + std::to_string(length - 1) + " instead.", + context.key() + }; + return LiteralExpression::parse(arrayMember(value, 1), ParsingContext(context, {1}, {"literal"})); + } + if (*op == "+") return LambdaExpression::parse(value, context); if (*op == "-") return LambdaExpression::parse(value, context); if (*op == "*") return LambdaExpression::parse(value, context); diff --git a/include/mbgl/style/function/type.hpp b/include/mbgl/style/function/type.hpp index 94f710c005..19897ac77f 100644 --- a/include/mbgl/style/function/type.hpp +++ b/include/mbgl/style/function/type.hpp @@ -42,7 +42,7 @@ public: static Primitive Object; // It's weird for this to be on Primitive. Where should it go? - static Type Value; + static ValueType Value; private: std::string name; @@ -60,7 +60,7 @@ private: class Array { public: Array(ValueType itemType_) : itemType(itemType_) {} - Array(ValueType itemType_, int N_) : itemType(itemType_), N(N_) {} + Array(ValueType itemType_, std::size_t N_) : itemType(itemType_), N(N_) {} std::string getName() const { return "array"; } diff --git a/src/mbgl/style/function/type.cpp b/src/mbgl/style/function/type.cpp index fbfe6efbc3..5e1a95433f 100644 --- a/src/mbgl/style/function/type.cpp +++ b/src/mbgl/style/function/type.cpp @@ -12,7 +12,7 @@ Primitive Primitive::Color = {"Color"}; Primitive Primitive::Object = {"Object"}; // Need to add Array(Types::Value) to the member list somehow... -Type Primitive::Value = Variant({ + ValueType Primitive::Value = Variant({ Primitive::Null, Primitive::String, Primitive::Number, -- cgit v1.2.1