devalang_core/core/parser/handler/
at.rs1use crate::core::{
2 lexer::token::TokenKind,
3 parser::{
4 driver::Parser,
5 statement::{Statement, StatementKind},
6 },
7 shared::value::Value,
8 store::global::GlobalStore,
9};
10pub fn parse_at_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
11 parser.advance(); let Some(token) = parser.peek_clone() else {
14 return Statement::unknown();
15 };
16
17 let keyword = token.lexeme.as_str();
18
19 match keyword {
20 "use" => {
21 parser.advance(); let Some(use_token) = parser.previous_clone() else {
23 return Statement::unknown();
24 };
25
26 let Some(author_token) = parser.peek_clone() else {
28 return Statement::error(use_token, "Expected plugin author".to_string());
29 };
30 if author_token.kind != TokenKind::Identifier {
31 return Statement::error(
32 author_token,
33 "Expected identifier for plugin author".to_string(),
34 );
35 }
36 parser.advance(); if !parser.match_token(TokenKind::Dot) {
40 return Statement::error(
41 author_token,
42 "Expected '.' after plugin author".to_string(),
43 );
44 }
45
46 let Some(plugin_token) = parser.peek_clone() else {
48 return Statement::error(author_token, "Expected plugin name".to_string());
49 };
50
51 let name = match plugin_token.kind {
52 TokenKind::Identifier | TokenKind::Number => {
53 parser.advance();
54 format!("{}.{}", author_token.lexeme, plugin_token.lexeme)
55 }
56 _ => {
57 return Statement::error(
58 plugin_token,
59 "Expected identifier or number for plugin name".to_string(),
60 );
61 }
62 };
63
64 let alias = if parser.match_token(TokenKind::As) {
66 let Some(alias_token) = parser.peek_clone() else {
67 return Statement::error(
68 use_token,
69 "Expected identifier after 'as'".to_string(),
70 );
71 };
72 if alias_token.kind != TokenKind::Identifier {
73 return Statement::error(
74 alias_token,
75 "Expected identifier after 'as'".to_string(),
76 );
77 }
78 parser.advance();
79 Some(alias_token.lexeme.clone())
80 } else {
81 None
82 };
83
84 Statement {
85 kind: StatementKind::Use {
86 name: name.clone(),
87 alias,
88 },
89 value: Value::Null,
90 indent: use_token.indent,
91 line: use_token.line,
92 column: use_token.column,
93 }
94 }
95
96 "import" => {
97 parser.advance(); if !parser.match_token(TokenKind::LBrace) {
100 return Statement::error(token, "Expected '{{' after 'import'".to_string());
101 }
102
103 let mut names = Vec::new();
104 while let Some(token) = parser.peek() {
105 match &token.kind {
106 TokenKind::Identifier => {
107 names.push(token.lexeme.clone());
108 parser.advance();
109 }
110 TokenKind::Comma => {
111 parser.advance();
112 }
113 TokenKind::RBrace => {
114 parser.advance();
115 break;
116 }
117 _ => {
118 let message =
119 format!("Unexpected token in import list: {:?}", token.kind.clone());
120 return Statement::error(token.clone(), message);
121 }
122 }
123 }
124
125 let Some(from_token) = parser.peek_clone() else {
126 return Statement::error(token, "Expected 'from' after import list".to_string());
127 };
128
129 if from_token.lexeme != "from" {
130 return Statement::error(token, "Expected keyword 'from'".to_string());
131 }
132
133 parser.advance(); let Some(source_token) = parser.peek() else {
136 return Statement::error(token, "Expected string after 'from'".to_string());
137 };
138
139 if source_token.kind != TokenKind::String {
140 return Statement::error(token, "Expected string after 'from'".to_string());
141 }
142
143 let source = source_token.lexeme.clone();
144 parser.advance(); Statement {
147 kind: StatementKind::Import { names, source },
148 value: Value::Null,
149 indent: token.indent,
150 line: token.line,
151 column: token.column,
152 }
153 }
154
155 "export" => {
156 parser.advance(); parser.advance(); let names_tokens = parser.collect_until(|t| TokenKind::RBrace == t.kind);
161 let mut names: Vec<String> = Vec::new();
162
163 for token in names_tokens {
164 if token.kind == TokenKind::Identifier {
165 names.push(token.lexeme.clone());
166 } else if token.kind == TokenKind::Comma {
167 continue; } else if token.kind == TokenKind::RBrace {
169 break; } else {
171 return Statement::error(token, "Unexpected token in export list".to_string());
172 }
173 }
174
175 Statement {
176 kind: StatementKind::Export {
177 names: names.clone(),
178 source: parser.current_module.clone(),
179 },
180 value: Value::Null,
181 indent: token.indent,
182 line: token.line,
183 column: token.column,
184 }
185 }
186
187 "load" => {
188 parser.advance(); let Some(path_token) = parser.peek() else {
192 return Statement::error(token, "Expected string after 'load'".to_string());
193 };
194
195 if path_token.kind != TokenKind::String {
196 return Statement::error(token, "Expected string after 'load'".to_string());
197 }
198
199 let path = path_token.lexeme.clone();
200
201 parser.advance(); if !parser.match_token(TokenKind::As) {
204 return Statement::error(
205 token,
206 "Expected 'as' after path in load statement".to_string(),
207 );
208 }
209
210 let Some(alias_token) = parser.peek_clone() else {
211 return Statement::error(
212 token,
213 "Expected identifier after 'as' in load statement".to_string(),
214 );
215 };
216
217 if alias_token.kind != TokenKind::Identifier {
218 return Statement::error(
219 token,
220 "Expected identifier after 'as' in load statement".to_string(),
221 );
222 }
223
224 let alias = alias_token.lexeme.clone();
225
226 parser.advance(); Statement {
229 kind: StatementKind::Load {
230 source: path,
231 alias,
232 },
233 value: Value::Null,
234 indent: token.indent,
235 line: token.line,
236 column: token.column,
237 }
238 }
239
240 _ => {
241 let message = format!("Unknown keyword after '@' : {}", keyword);
242 Statement::error(token, message)
243 }
244 }
245}