devalang_core/core/parser/handler/
at.rs1use devalang_types::Value;
2
3use crate::core::{
4 lexer::token::TokenKind,
5 parser::{
6 driver::parser::Parser,
7 statement::{Statement, StatementKind},
8 },
9 store::global::GlobalStore,
10};
11pub fn parse_at_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
12 parser.advance(); let Some(token) = parser.peek_clone() else {
15 return Statement::unknown();
16 };
17
18 let keyword = token.lexeme.as_str();
19
20 match keyword {
21 "use" => {
22 parser.advance(); let Some(use_token) = parser.previous_clone() else {
24 return Statement::unknown();
25 };
26
27 let Some(author_token) = parser.peek_clone() else {
29 return crate::core::parser::statement::error_from_token(
30 use_token,
31 "Expected plugin author".to_string(),
32 );
33 };
34 if author_token.kind != TokenKind::Identifier {
35 return crate::core::parser::statement::error_from_token(
36 author_token,
37 "Expected identifier for plugin author".to_string(),
38 );
39 }
40 parser.advance(); if !parser.match_token(TokenKind::Dot) {
44 return crate::core::parser::statement::error_from_token(
45 author_token,
46 "Expected '.' after plugin author".to_string(),
47 );
48 }
49
50 let Some(plugin_token) = parser.peek_clone() else {
52 return crate::core::parser::statement::error_from_token(
53 author_token,
54 "Expected plugin name".to_string(),
55 );
56 };
57
58 let name = match plugin_token.kind {
59 TokenKind::Identifier | TokenKind::Number => {
60 parser.advance();
61 format!("{}.{}", author_token.lexeme, plugin_token.lexeme)
62 }
63 _ => {
64 return crate::core::parser::statement::error_from_token(
65 plugin_token,
66 "Expected identifier or number for plugin name".to_string(),
67 );
68 }
69 };
70
71 let alias = if parser.match_token(TokenKind::As) {
73 let Some(alias_token) = parser.peek_clone() else {
74 return crate::core::parser::statement::error_from_token(
75 use_token,
76 "Expected identifier after 'as'".to_string(),
77 );
78 };
79 if alias_token.kind != TokenKind::Identifier {
80 return crate::core::parser::statement::error_from_token(
81 alias_token,
82 "Expected identifier after 'as'".to_string(),
83 );
84 }
85 parser.advance();
86 Some(alias_token.lexeme.clone())
87 } else {
88 None
89 };
90
91 Statement {
92 kind: StatementKind::Use {
93 name: name.clone(),
94 alias,
95 },
96 value: Value::Null,
97 indent: use_token.indent,
98 line: use_token.line,
99 column: use_token.column,
100 }
101 }
102
103 "import" => {
104 parser.advance(); if !parser.match_token(TokenKind::LBrace) {
107 return crate::core::parser::statement::error_from_token(
108 token,
109 "Expected '{{' after 'import'".to_string(),
110 );
111 }
112
113 let mut names = Vec::new();
114 while let Some(token) = parser.peek() {
115 match &token.kind {
116 TokenKind::Identifier => {
117 names.push(token.lexeme.clone());
118 parser.advance();
119 }
120 TokenKind::Comma => {
121 parser.advance();
122 }
123 TokenKind::RBrace => {
124 parser.advance();
125 break;
126 }
127 _ => {
128 let message =
129 format!("Unexpected token in import list: {:?}", token.kind.clone());
130 return crate::core::parser::statement::error_from_token(
131 token.clone(),
132 message,
133 );
134 }
135 }
136 }
137
138 let Some(from_token) = parser.peek_clone() else {
139 return crate::core::parser::statement::error_from_token(
140 token,
141 "Expected 'from' after import list".to_string(),
142 );
143 };
144
145 if from_token.lexeme != "from" {
146 return crate::core::parser::statement::error_from_token(
147 token,
148 "Expected keyword 'from'".to_string(),
149 );
150 }
151
152 parser.advance(); let Some(source_token) = parser.peek() else {
155 return crate::core::parser::statement::error_from_token(
156 token,
157 "Expected string after 'from'".to_string(),
158 );
159 };
160
161 if source_token.kind != TokenKind::String {
162 return crate::core::parser::statement::error_from_token(
163 token,
164 "Expected string after 'from'".to_string(),
165 );
166 }
167
168 let source = source_token.lexeme.clone();
169 parser.advance(); Statement {
172 kind: StatementKind::Import { names, source },
173 value: Value::Null,
174 indent: token.indent,
175 line: token.line,
176 column: token.column,
177 }
178 }
179
180 "export" => {
181 parser.advance(); parser.advance(); let names_tokens = parser.collect_until(|t| TokenKind::RBrace == t.kind);
186 let mut names: Vec<String> = Vec::new();
187
188 for token in names_tokens {
189 if token.kind == TokenKind::Identifier {
190 names.push(token.lexeme.clone());
191 } else if token.kind == TokenKind::Comma {
192 continue; } else if token.kind == TokenKind::RBrace {
194 break; } else {
196 return crate::core::parser::statement::error_from_token(
197 token,
198 "Unexpected token in export list".to_string(),
199 );
200 }
201 }
202
203 Statement {
204 kind: StatementKind::Export {
205 names: names.clone(),
206 source: parser.current_module.clone(),
207 },
208 value: Value::Null,
209 indent: token.indent,
210 line: token.line,
211 column: token.column,
212 }
213 }
214
215 "load" => {
216 parser.advance(); let Some(path_token) = parser.peek() else {
220 return crate::core::parser::statement::error_from_token(
221 token,
222 "Expected string after 'load'".to_string(),
223 );
224 };
225
226 if path_token.kind != TokenKind::String {
227 return crate::core::parser::statement::error_from_token(
228 token,
229 "Expected string after 'load'".to_string(),
230 );
231 }
232
233 let path = path_token.lexeme.clone();
234
235 parser.advance(); if !parser.match_token(TokenKind::As) {
238 return crate::core::parser::statement::error_from_token(
239 token,
240 "Expected 'as' after path in load statement".to_string(),
241 );
242 }
243
244 let Some(alias_token) = parser.peek_clone() else {
245 return crate::core::parser::statement::error_from_token(
246 token,
247 "Expected identifier after 'as' in load statement".to_string(),
248 );
249 };
250
251 if alias_token.kind != TokenKind::Identifier {
252 return crate::core::parser::statement::error_from_token(
253 token,
254 "Expected identifier after 'as' in load statement".to_string(),
255 );
256 }
257
258 let alias = alias_token.lexeme.clone();
259
260 parser.advance(); Statement {
263 kind: StatementKind::Load {
264 source: path,
265 alias,
266 },
267 value: Value::Null,
268 indent: token.indent,
269 line: token.line,
270 column: token.column,
271 }
272 }
273
274 _ => {
275 let message = format!("Unknown keyword after '@' : {}", keyword);
276 crate::core::parser::statement::error_from_token(token, message)
277 }
278 }
279}