mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-04 10:50:00 +00:00
Parse 9slice in @image-url
This commit is contained in:
parent
dd8fefd6a2
commit
6e2280ece3
3 changed files with 145 additions and 11 deletions
|
@ -549,11 +549,24 @@ mod parser_trait {
|
|||
|
||||
/// consume everything until reaching a token of this kind
|
||||
fn until(&mut self, kind: SyntaxKind) {
|
||||
// FIXME! match {} () []
|
||||
while {
|
||||
let k = self.nth(0).kind();
|
||||
k != kind && k != SyntaxKind::Eof
|
||||
} {
|
||||
let mut parens = 0;
|
||||
let mut braces = 0;
|
||||
let mut brackets = 0;
|
||||
loop {
|
||||
match self.nth(0).kind() {
|
||||
k @ _ if k == kind && parens == 0 && braces == 0 && brackets == 0 => break,
|
||||
SyntaxKind::Eof => break,
|
||||
SyntaxKind::LParent => parens += 1,
|
||||
SyntaxKind::LBrace => braces += 1,
|
||||
SyntaxKind::LBracket => brackets += 1,
|
||||
SyntaxKind::RParent if parens == 0 => break,
|
||||
SyntaxKind::RParent => parens -= 1,
|
||||
SyntaxKind::RBrace if braces == 0 => break,
|
||||
SyntaxKind::RBrace => braces -= 1,
|
||||
SyntaxKind::RBracket if brackets == 0 => break,
|
||||
SyntaxKind::RBracket => brackets -= 1,
|
||||
_ => {}
|
||||
};
|
||||
self.consume();
|
||||
}
|
||||
self.expect(kind);
|
||||
|
|
|
@ -224,12 +224,7 @@ fn parse_at_keyword(p: &mut impl Parser) {
|
|||
debug_assert_eq!(p.peek().kind(), SyntaxKind::At);
|
||||
match p.nth(1).as_str() {
|
||||
"image-url" | "image_url" => {
|
||||
let mut p = p.start_node(SyntaxKind::AtImageUrl);
|
||||
p.consume(); // "@"
|
||||
p.consume(); // "image-url"
|
||||
p.expect(SyntaxKind::LParent);
|
||||
p.expect(SyntaxKind::StringLiteral);
|
||||
p.expect(SyntaxKind::RParent);
|
||||
parse_image_url(p);
|
||||
}
|
||||
"linear-gradient" | "linear_gradient" => {
|
||||
parse_gradient(p);
|
||||
|
@ -417,3 +412,81 @@ fn parse_tr(p: &mut impl Parser) {
|
|||
}
|
||||
p.expect(SyntaxKind::RParent);
|
||||
}
|
||||
|
||||
#[cfg_attr(test, parser_test)]
|
||||
/// ```test,AtImageUrl
|
||||
/// @image-url("foo.png")
|
||||
/// @image-url("foo.png",)
|
||||
/// @image-url("foo.png", 9slice(1 2 3 4))
|
||||
/// @image-url("foo.png", 9slice(1))
|
||||
/// ```
|
||||
fn parse_image_url(p: &mut impl Parser) {
|
||||
let mut p = p.start_node(SyntaxKind::AtImageUrl);
|
||||
p.consume(); // "@"
|
||||
p.consume(); // "image-url"
|
||||
if !(p.expect(SyntaxKind::LParent)) {
|
||||
return;
|
||||
}
|
||||
let peek = p.peek();
|
||||
if peek.kind() != SyntaxKind::StringLiteral {
|
||||
p.error("@image-url must contain a plain path as a string literal");
|
||||
p.until(SyntaxKind::RParent);
|
||||
return;
|
||||
}
|
||||
if !peek.as_str().starts_with('"') || !peek.as_str().ends_with('"') {
|
||||
p.error("@image-url must contain a plain path as a string literal, without any '\\{}' expressions");
|
||||
p.until(SyntaxKind::RParent);
|
||||
return;
|
||||
}
|
||||
p.expect(SyntaxKind::StringLiteral);
|
||||
if !p.test(SyntaxKind::Comma) {
|
||||
if !p.test(SyntaxKind::RParent) {
|
||||
p.error("Expected ')' or ','");
|
||||
p.until(SyntaxKind::RParent);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if p.test(SyntaxKind::RParent) {
|
||||
return;
|
||||
}
|
||||
if p.peek().as_str() != "9slice" {
|
||||
p.error("Expected '9slice(...)' argument");
|
||||
p.until(SyntaxKind::RParent);
|
||||
return;
|
||||
}
|
||||
p.consume();
|
||||
if !p.expect(SyntaxKind::LParent) {
|
||||
p.until(SyntaxKind::RParent);
|
||||
return;
|
||||
}
|
||||
let mut count = 0;
|
||||
loop {
|
||||
match p.peek().kind() {
|
||||
SyntaxKind::RParent => {
|
||||
if count != 1 && count != 2 && count != 4 {
|
||||
p.error("Expected 1 or 2 or 4 numbers");
|
||||
}
|
||||
p.consume();
|
||||
break;
|
||||
}
|
||||
SyntaxKind::NumberLiteral => {
|
||||
count += 1;
|
||||
p.consume();
|
||||
}
|
||||
SyntaxKind::Comma | SyntaxKind::Colon => {
|
||||
p.error("Arguments of 9slice need to be separated by spaces");
|
||||
p.until(SyntaxKind::RParent);
|
||||
break;
|
||||
}
|
||||
_ => {
|
||||
p.error("Expected number literal or ')'");
|
||||
p.until(SyntaxKind::RParent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if !p.expect(SyntaxKind::RParent) {
|
||||
p.until(SyntaxKind::RParent);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
48
internal/compiler/tests/syntax/expressions/image-url.slint
Normal file
48
internal/compiler/tests/syntax/expressions/image-url.slint
Normal file
|
@ -0,0 +1,48 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial
|
||||
|
||||
export component SuperSimple {
|
||||
property <image> i1: @image-url("hello.png");
|
||||
property <string> path;
|
||||
property <image> i2: @image-url(path);
|
||||
// ^error{@image-url must contain a plain path as a string literal}
|
||||
property <image> i3: @image-url("/home/\{path}.png");
|
||||
// ^error{@image-url must contain a plain path as a string literal, without any '\\\{}' expressions}
|
||||
property <image> i4: @image-url("/home/" + path + ".png");
|
||||
// ^error{Expected '\)' or ','}
|
||||
property <image> i5: @image-url(path + ".png");
|
||||
// ^error{@image-url must contain a plain path as a string literal}
|
||||
property <image> i6: @image-url;
|
||||
// ^error{Syntax error: expected '\('}
|
||||
property <image> i7: @image-url("foo", "bar");
|
||||
// ^error{Expected '9slice\(...\)' argument}
|
||||
property <image> i8: @image-url("foo", xyz(abc));
|
||||
// ^error{Expected '9slice\(...\)' argument}
|
||||
property <image> i9: @image-url("foo", 9slice(abc));
|
||||
// ^error{Expected number literal or '\)'}
|
||||
property <image> i10: @image-url("foo", 9slice(1 2 3));
|
||||
// ^error{Expected 1 or 2 or 4 numbers}
|
||||
property <image> i11: @image-url("foo", 9slice());
|
||||
// ^error{Expected 1 or 2 or 4 numbers}
|
||||
property <image> i12: @image-url("foo", 9slice(1 2 3 4 5));
|
||||
// ^error{Expected 1 or 2 or 4 numbers}
|
||||
property <image> i13: @image-url("foo", 9slice(1 2 foobar 4 5));
|
||||
// ^error{Expected number literal or '\)'}
|
||||
property <image> i14: @image-url("foo", 9slice);
|
||||
// ^error{Syntax error: expected '\('}
|
||||
property <image> i15: @image-url("foo", 9slice,);
|
||||
// ^error{Syntax error: expected '\('}
|
||||
property <image> i16: @image-url("foo", 9slice 42 42);
|
||||
// ^error{Syntax error: expected '\('}
|
||||
property <image> i17: @image-url("foo", 9slice(1px)); // error reported later
|
||||
property <image> i18: @image-url("foo", 9slice(1%)); // error reported later
|
||||
property <image> i19: @image-url("foo", 9slice(1, 2));
|
||||
// ^error{Arguments of 9slice need to be separated by spaces}
|
||||
property <image> i20: @image-url("foo", 9slice(2 + 3 ));
|
||||
// ^error{Expected number literal or '\)'}
|
||||
property <image> i21: @image-url("foo", 9slice(2 -3 ));
|
||||
// ^error{Expected number literal or '\)'}
|
||||
property <image> i22: @image-url("foo", 9slice(-2));
|
||||
// ^error{Expected number literal or '\)'}
|
||||
property <image> i22: @image-url("foo", 9slice(123456789));
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue