1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
4//! Module containing the parsing functions for type names
5
6use super::document::parse_qualified_name;
7use super::prelude::*;
8
9#[cfg_attr(test, parser_test)]
10/// ```test,Type
11/// string
12/// [ int ]
13/// {a: string, b: int}
14/// ```
15pub fn parse_type(p: &mut impl Parser) {
16 let mut p: Node<'_, impl Parser> = p.start_node(kind:SyntaxKind::Type);
17 match p.nth(0).kind() {
18 SyntaxKind::LBrace => parse_type_object(&mut *p),
19 SyntaxKind::LBracket => parse_type_array(&mut *p),
20 _ => {
21 parse_qualified_name(&mut *p);
22 }
23 }
24}
25
26#[cfg_attr(test, parser_test)]
27/// ```test,ObjectType
28/// {a: string, b: int}
29/// {}
30/// {a: string}
31/// {a: string,}
32/// {a: { foo: string, bar: int, }, q: {} }
33/// ```
34pub fn parse_type_object(p: &mut impl Parser) {
35 let mut p: Node<'_, impl Parser> = p.start_node(kind:SyntaxKind::ObjectType);
36 if !p.expect(kind:SyntaxKind::LBrace) {
37 return;
38 }
39 while p.nth(0).kind() != SyntaxKind::RBrace {
40 let mut p: Node<'_, impl Parser> = p.start_node(kind:SyntaxKind::ObjectTypeMember);
41 p.expect(kind:SyntaxKind::Identifier);
42 p.expect(kind:SyntaxKind::Colon);
43 parse_type(&mut *p);
44 if p.peek().kind() == SyntaxKind::Semicolon {
45 p.error("Expected ','. Use ',' instead of ';' to separate fields in a struct");
46 p.consume();
47 continue;
48 }
49 if !p.test(kind:SyntaxKind::Comma) {
50 break;
51 }
52 }
53 p.expect(kind:SyntaxKind::RBrace);
54}
55
56#[cfg_attr(test, parser_test)]
57/// ```test,ArrayType
58/// [int]
59/// [[int]]
60/// [{a: string, b: [string]}]
61/// ```
62pub fn parse_type_array(p: &mut impl Parser) {
63 let mut p: Node<'_, impl Parser> = p.start_node(kind:SyntaxKind::ArrayType);
64 p.expect(kind:SyntaxKind::LBracket);
65 parse_type(&mut *p);
66 p.expect(kind:SyntaxKind::RBracket);
67}
68
69#[cfg_attr(test, parser_test)]
70/// ```test,StructDeclaration
71/// struct Foo := { foo: bar, xxx: { aaa: bbb, } }
72/// struct Bar := {}
73/// struct Foo { foo: bar, xxx: { aaa: bbb, } }
74/// struct Bar {}
75/// ```
76pub fn parse_struct_declaration<P: Parser>(p: &mut P, checkpoint: Option<P::Checkpoint>) -> bool {
77 debug_assert_eq!(p.peek().as_str(), "struct");
78 let mut p: Node<'_, P> = p.start_node_at(checkpoint, kind:SyntaxKind::StructDeclaration);
79 p.consume(); // "struct"
80 {
81 let mut p: Node<'_, P> = p.start_node(kind:SyntaxKind::DeclaredIdentifier);
82 p.expect(kind:SyntaxKind::Identifier);
83 }
84
85 if p.peek().kind() == SyntaxKind::ColonEqual {
86 p.warning("':=' to declare a struct is deprecated. Remove the ':='");
87 p.consume();
88 }
89
90 parse_type_object(&mut *p);
91 true
92}
93
94#[cfg_attr(test, parser_test)]
95/// ```test,EnumDeclaration
96/// enum Foo {}
97/// enum Foo { el1 }
98/// enum Foo { el1, xxx, yyy }
99/// ```
100pub fn parse_enum_declaration<P: Parser>(p: &mut P, checkpoint: Option<P::Checkpoint>) -> bool {
101 debug_assert_eq!(p.peek().as_str(), "enum");
102 let mut p: Node<'_, P> = p.start_node_at(checkpoint, kind:SyntaxKind::EnumDeclaration);
103 p.consume(); // "enum"
104 {
105 let mut p: Node<'_, P> = p.start_node(kind:SyntaxKind::DeclaredIdentifier);
106 p.expect(kind:SyntaxKind::Identifier);
107 }
108
109 if !p.expect(kind:SyntaxKind::LBrace) {
110 return false;
111 }
112 while p.nth(0).kind() != SyntaxKind::RBrace {
113 {
114 let mut p: Node<'_, P> = p.start_node(kind:SyntaxKind::EnumValue);
115 p.expect(kind:SyntaxKind::Identifier);
116 }
117 if !p.test(kind:SyntaxKind::Comma) {
118 break;
119 }
120 }
121 p.expect(kind:SyntaxKind::RBrace);
122 true
123}
124
125/// ```test,AtRustAttr
126/// @rustattr(derive([()]), just some token({()}) ()..)
127/// @rustattr()
128/// ```
129pub fn parse_rustattr(p: &mut impl Parser) -> bool {
130 debug_assert_eq!(p.peek().as_str(), "@");
131 p.consume(); // "@"
132 if p.peek().as_str() != "rust-attr" {
133 p.expect(SyntaxKind::AtRustAttr);
134 }
135 p.consume(); // "rust-attr"
136 p.expect(SyntaxKind::LParent);
137 {
138 let mut p = p.start_node(SyntaxKind::AtRustAttr);
139 let mut level = 1;
140 loop {
141 match p.peek().kind() {
142 SyntaxKind::LParent => level += 1,
143 SyntaxKind::RParent => {
144 level -= 1;
145 if level == 0 {
146 break;
147 }
148 }
149 SyntaxKind::Eof => {
150 p.error("unmatched parentheses in @rust-attr");
151 return false;
152 }
153 _ => {}
154 }
155 p.consume()
156 }
157 }
158 p.expect(SyntaxKind::RParent)
159}
160