Skip to content

Commit

Permalink
CSS function component values (#44470)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #44470

CSS component values, as defined in the syntax spec, are either "preserved tokens", CSS functions, or simple blocks. This is distinct from the higher-level "component value type" specified in the [values and units](https://www.w3.org/TR/css-values-3/#component-types) spec.

I was previously short-circuiting a bit, from preserved tokens, to a higher level data structure. This separates them out, adding a layer exposing the preserved token as `CSSSyntaxParser::Token`, and now a `CSSSyntaxParser::Function`, which can represent a named function and its nested component values.

This does not yet wire functions beyond CSSParser returned component values.

Changelog: [Internal]

Reviewed By: rshest

Differential Revision: D57089275

fbshipit-source-id: 97eeb1a7b3363c79d99f9419ba6e022c4c3c31d0
  • Loading branch information
NickGerleman authored and facebook-github-bot committed May 11, 2024
1 parent 3f17c8b commit a37111a
Show file tree
Hide file tree
Showing 7 changed files with 576 additions and 327 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
#include <vector>

#include <react/debug/react_native_assert.h>
#include <react/renderer/css/CSSParser.h>
#include <react/renderer/css/CSSProperties.h>
#include <react/renderer/css/CSSValueParser.h>

namespace facebook::react {

Expand Down
227 changes: 0 additions & 227 deletions packages/react-native/ReactCommon/react/renderer/css/CSSParser.h

This file was deleted.

105 changes: 105 additions & 0 deletions packages/react-native/ReactCommon/react/renderer/css/CSSSyntaxParser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#pragma once

#include <optional>
#include <variant>
#include <vector>

#include <react/renderer/css/CSSTokenizer.h>

namespace facebook::react {

/**
* CSSSyntaxParser allows parsing streams of CSS text into "component values",
* being either a preserved token, or a function.
*
* https://www.w3.org/TR/css-syntax-3/#component-value
*/
class CSSSyntaxParser {
public:
struct Function;

using PreservedToken = CSSToken;
using ComponentValue = std::variant<std::monostate, PreservedToken, Function>;

struct Function {
std::string_view name{};
std::vector<ComponentValue> args{};
};

/**
* Construct the parser over the given string_view, which must stay alive for
* the duration of the CSSSyntaxParser.
*/
explicit constexpr CSSSyntaxParser(std::string_view css)
: tokenizer_{css}, currentToken_(tokenizer_.next()) {}

/**
* Directly consume the next component value
*
* https://www.w3.org/TR/css-syntax-3/#consume-component-value
*/
inline ComponentValue consumeComponentValue() {
if (peek().type() == CSSTokenType::Function) {
auto function = consumeFunction();
return function.has_value() ? ComponentValue{std::move(*function)}
: ComponentValue{};
} else {
return consumeToken();
}
}

private:
constexpr const CSSToken& peek() const {
return currentToken_;
}

constexpr CSSToken consumeToken() {
auto prevToken = currentToken_;
currentToken_ = tokenizer_.next();
return prevToken;
}

inline std::optional<Function> consumeFunction() {
// https://www.w3.org/TR/css-syntax-3/#consume-a-function
Function function{.name = consumeToken().stringValue()};

while (true) {
auto nextValue = consumeComponentValue();
if (std::holds_alternative<std::monostate>(nextValue)) {
return {};
}

if (auto token = std::get_if<CSSToken>(&nextValue)) {
if (token->type() == CSSTokenType::CloseParen) {
return function;
}
if (token->type() == CSSTokenType::EndOfFile) {
return {};
}
function.args.emplace_back(std::move(*token));
continue;
}

if (auto func = std::get_if<Function>(&nextValue)) {
function.args.emplace_back(std::move(*func));
continue;
}

return {};
}

return function;
}

CSSTokenizer tokenizer_;
CSSToken currentToken_;
};

} // namespace facebook::react

0 comments on commit a37111a

Please sign in to comment.