mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-23 17:52:26 -05:00
LibWeb: Add tokenization of calc expression
Here the first step in understanding a calc() expression is taken: Finding the start of an expression and tokenizong it.
This commit is contained in:
parent
f8bf6ae911
commit
7a4c8e0b76
Notes:
sideshowbarker
2024-07-18 08:25:38 +09:00
Author: https://github.com/TobyAsE Commit: https://github.com/SerenityOS/serenity/commit/7a4c8e0b76a Pull-request: https://github.com/SerenityOS/serenity/pull/8043 Reviewed-by: https://github.com/alimpfard
1 changed files with 106 additions and 0 deletions
|
@ -1,9 +1,11 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Tobias Christiansen <tobi@tobyase.de>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/GenericLexer.h>
|
||||
#include <AK/HashMap.h>
|
||||
#include <AK/SourceLocation.h>
|
||||
#include <LibWeb/CSS/CSSImportRule.h>
|
||||
|
@ -229,6 +231,104 @@ static StringView parse_custom_property_name(const StringView& value)
|
|||
return value.substring_view(4, substring_length);
|
||||
}
|
||||
|
||||
static StringView isolate_calc_expression(const StringView& value)
|
||||
{
|
||||
if (!value.starts_with("calc(") || !value.ends_with(")"))
|
||||
return {};
|
||||
auto substring_length = value.length() - 5 - 1;
|
||||
return value.substring_view(5, substring_length);
|
||||
}
|
||||
|
||||
static Optional<NonnullOwnPtr<CSS::CalculatedStyleValue::CalcSum>> parse_calc_expression(const StringView& expression_string)
|
||||
{
|
||||
// First, tokenize
|
||||
|
||||
struct CalcToken {
|
||||
enum class Type {
|
||||
Undefined,
|
||||
Number,
|
||||
Unit,
|
||||
Whitespace,
|
||||
Plus,
|
||||
Minus,
|
||||
Asterisk,
|
||||
Slash,
|
||||
OpenBracket,
|
||||
CloseBracket,
|
||||
} type { Type::Undefined };
|
||||
String value {};
|
||||
};
|
||||
|
||||
Vector<CalcToken> tokens;
|
||||
|
||||
GenericLexer lexer(expression_string);
|
||||
while (!lexer.is_eof()) {
|
||||
// Number
|
||||
if (((lexer.next_is('+') || lexer.next_is('-')) && !isspace(lexer.peek(1)))
|
||||
|| lexer.next_is('.')
|
||||
|| lexer.next_is(isdigit)) {
|
||||
|
||||
auto number = lexer.consume_while(is_any_of("+-.0123456789"));
|
||||
tokens.append(CalcToken { CalcToken::Type ::Number, number.to_string() });
|
||||
continue;
|
||||
}
|
||||
|
||||
auto ch = lexer.consume();
|
||||
|
||||
if (isspace(ch)) {
|
||||
tokens.append(CalcToken { CalcToken::Type::Whitespace });
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == '%') {
|
||||
tokens.append(CalcToken { CalcToken::Type::Unit, "%" });
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == '+') {
|
||||
tokens.append(CalcToken { CalcToken::Type::Plus });
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == '-') {
|
||||
tokens.append(CalcToken { CalcToken::Type::Minus });
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == '*') {
|
||||
tokens.append(CalcToken { CalcToken::Type::Asterisk });
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == '/') {
|
||||
tokens.append(CalcToken { CalcToken::Type::Slash });
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == '(') {
|
||||
tokens.append(CalcToken { CalcToken::Type::OpenBracket });
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == ')') {
|
||||
tokens.append(CalcToken { CalcToken::Type::CloseBracket });
|
||||
continue;
|
||||
}
|
||||
|
||||
// Unit
|
||||
if (isalpha(ch)) {
|
||||
lexer.retreat();
|
||||
auto unit = lexer.consume_while(isalpha);
|
||||
tokens.append(CalcToken { CalcToken::Type::Unit, unit.to_string() });
|
||||
continue;
|
||||
}
|
||||
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
RefPtr<CSS::StyleValue> parse_css_value(const CSS::DeprecatedParsingContext& context, const StringView& string, CSS::PropertyID property_id)
|
||||
{
|
||||
bool is_bad_length = false;
|
||||
|
@ -257,6 +357,12 @@ RefPtr<CSS::StyleValue> parse_css_value(const CSS::DeprecatedParsingContext& con
|
|||
return CSS::LengthStyleValue::create(CSS::Length::make_auto());
|
||||
if (string.starts_with("var("))
|
||||
return CSS::CustomStyleValue::create(parse_custom_property_name(string));
|
||||
if (string.starts_with("calc(")) {
|
||||
auto calc_expression_string = isolate_calc_expression(string);
|
||||
auto calc_expression = parse_calc_expression(calc_expression_string);
|
||||
if (calc_expression.has_value())
|
||||
return CSS::CalculatedStyleValue::create(calc_expression_string, calc_expression.release_value());
|
||||
}
|
||||
|
||||
auto value_id = CSS::value_id_from_string(string);
|
||||
if (value_id != CSS::ValueID::Invalid)
|
||||
|
|
Loading…
Add table
Reference in a new issue