From bb151d1cee6ab3f59859fb41c33e0c9140a343cc Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 17 Jul 2018 16:20:06 -0700 Subject: [core] Support two-argument shorthand for "match" expression --- mapbox-gl-js | 2 +- src/mbgl/style/expression/match.cpp | 107 +++++++++++++++++++++--------------- 2 files changed, 64 insertions(+), 45 deletions(-) diff --git a/mapbox-gl-js b/mapbox-gl-js index bb5806e2b5..8094cbe71b 160000 --- a/mapbox-gl-js +++ b/mapbox-gl-js @@ -1 +1 @@ -Subproject commit bb5806e2b5996dcebf006e9b0334255c5acb4db9 +Subproject commit 8094cbe71b400a07197b6409069e7d809a477991 diff --git a/src/mbgl/style/expression/match.cpp b/src/mbgl/style/expression/match.cpp index 0f05001a97..1f644b5844 100644 --- a/src/mbgl/style/expression/match.cpp +++ b/src/mbgl/style/expression/match.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -223,10 +224,39 @@ static ParseResult create(type::Type outputType, )); } +optional> parseLabel(const Convertible& label, ParsingContext& ctx, std::size_t index, optional& inputType) { + std::vector labels; + // Match pair inputs are provided as either a literal value or a + // raw JSON array of string / number / boolean values. + if (isArray(label)) { + auto groupLength = arrayLength(label); + if (groupLength == 0) { + ctx.error("Expected at least one branch label.", index); + return {}; + } + + labels.reserve(groupLength); + for (size_t j = 0; j < groupLength; j++) { + const optional inputValue = parseInputValue(arrayMember(label, j), ctx, index, inputType); + if (!inputValue) { + return {}; + } + labels.push_back(*inputValue); + } + } else { + const optional inputValue = parseInputValue(label, ctx, index, inputType); + if (!inputValue) { + return {}; + } + labels.push_back(*inputValue); + } + return labels; +} + ParseResult parseMatch(const Convertible& value, ParsingContext& ctx) { assert(isArray(value)); auto length = arrayLength(value); - if (length < 5) { + if (length < 5 && length != 3) { ctx.error( "Expected at least 4 arguments, but found only " + util::toString(length - 1) + "." ); @@ -234,6 +264,7 @@ ParseResult parseMatch(const Convertible& value, ParsingContext& ctx) { } // Expect odd-length array: ["match", input, 2 * (n pairs)..., otherwise] + // or: ["match", input, label] if (length % 2 != 1) { ctx.error("Expected an even number of arguments."); return ParseResult(); @@ -245,59 +276,47 @@ ParseResult parseMatch(const Convertible& value, ParsingContext& ctx) { outputType = ctx.getExpected(); } + auto input = ctx.parse(arrayMember(value, 1), 1, {type::Value}); + if (!input) { + return ParseResult(); + } + std::vector, std::unique_ptr>> branches; + ParseResult otherwise; - branches.reserve((length - 3) / 2); - for (size_t i = 2; i + 1 < length; i += 2) { - const auto& label = arrayMember(value, i); - - std::vector labels; - // Match pair inputs are provided as either a literal value or a - // raw JSON array of string / number / boolean values. - if (isArray(label)) { - auto groupLength = arrayLength(label); - if (groupLength == 0) { - ctx.error("Expected at least one branch label.", i); + if (length == 3) { + auto labels = parseLabel(arrayMember(value, 2), ctx, 2, inputType); + if (!labels) { + return ParseResult(); + } + branches.push_back(std::make_pair(std::move(*labels), std::make_unique(true))); + otherwise = { std::make_unique(false) }; + outputType = type::Type(type::Boolean); + } else { + branches.reserve((length - 3) / 2); + for (size_t i = 2; i + 1 < length; i += 2) { + auto labels = parseLabel(arrayMember(value, i), ctx, i, inputType); + if (!labels) { return ParseResult(); } - - labels.reserve(groupLength); - for (size_t j = 0; j < groupLength; j++) { - const optional inputValue = parseInputValue(arrayMember(label, j), ctx, i, inputType); - if (!inputValue) { - return ParseResult(); - } - labels.push_back(*inputValue); - } - } else { - const optional inputValue = parseInputValue(label, ctx, i, inputType); - if (!inputValue) { + + ParseResult output = ctx.parse(arrayMember(value, i + 1), i + 1, outputType); + if (!output) { return ParseResult(); } - labels.push_back(*inputValue); + + if (!outputType) { + outputType = (*output)->getType(); + } + + branches.push_back(std::make_pair(std::move(*labels), std::move(*output))); } - - ParseResult output = ctx.parse(arrayMember(value, i + 1), i + 1, outputType); - if (!output) { + + otherwise = ctx.parse(arrayMember(value, length - 1), length - 1, outputType); + if (!otherwise) { return ParseResult(); } - - if (!outputType) { - outputType = (*output)->getType(); - } - - branches.push_back(std::make_pair(std::move(labels), std::move(*output))); - } - - auto input = ctx.parse(arrayMember(value, 1), 1, {type::Value}); - if (!input) { - return ParseResult(); - } - - auto otherwise = ctx.parse(arrayMember(value, length - 1), length - 1, outputType); - if (!otherwise) { - return ParseResult(); } assert(inputType && outputType); -- cgit v1.2.1