1mod cursor;
2mod expressions;
3mod format;
4mod lexer;
5mod lint;
6mod statements;
7mod symbols;
8
9use std::collections::{HashMap, HashSet};
10
11use rt_format::{NoNamedArguments, ParsedFormat};
12
13use crate::ValueType;
14use crate::builtins::{
15 BuiltinFunction, builtin_namespace_hint, default_host_callable, is_builtin_namespace,
16 resolve_builtin_namespace_call,
17};
18use crate::compiler::source_map::{SourceId, Span};
19
20use self::lexer::{Lexer, ParserFormatArg, Token, TokenKind, is_ident_continue, is_ident_start};
21use self::symbols::is_virtual_host_namespace_spec;
22use super::{
23 ParseError, ReplLocalBinding, STDLIB_PRINT_ARITY, STDLIB_PRINT_NAME,
24 ir::{
25 AssignmentKind, ClosureExpr, Expr, FunctionDecl, FunctionImpl, FunctionParam, LocalSlot,
26 MatchPattern, MatchTypePattern, Stmt, StructDecl, TypeSchema,
27 },
28};
29
30pub trait ParserDialect {
31 fn is_import_keyword(&self, _ident: &str) -> bool {
32 false
33 }
34
35 fn is_from_keyword(&self, _ident: &str) -> bool {
36 false
37 }
38
39 fn is_fn_alias_keyword(&self, _ident: &str) -> bool {
40 false
41 }
42
43 fn is_let_alias_keyword(&self, _ident: &str) -> bool {
44 false
45 }
46
47 fn allow_import_stmt(&self) -> bool {
48 false
49 }
50
51 fn allow_return_stmt(&self) -> bool {
52 false
53 }
54
55 fn allow_require_declaration(&self) -> bool {
56 false
57 }
58
59 fn allow_typeof_operator(&self) -> bool {
60 false
61 }
62
63 fn allow_arrow_closure(&self) -> bool {
64 false
65 }
66
67 fn allow_dotted_call(&self) -> bool {
68 false
69 }
70
71 fn allow_namespace_path_separator(&self) -> bool {
72 true
73 }
74
75 fn allow_let_mut_binding(&self) -> bool {
76 false
77 }
78
79 fn allow_macro_calls(&self) -> bool {
80 false
81 }
82
83 fn allow_plus_equal_operator(&self) -> bool {
84 false
85 }
86
87 fn allow_increment_operator(&self) -> bool {
88 false
89 }
90
91 fn allow_parenthesized_for_loop(&self) -> bool {
92 false
93 }
94
95 fn allow_for_in_loop(&self) -> bool {
96 false
97 }
98}
99
100pub(super) fn lint_trailing_function_return_semicolons(
101 source: &str,
102 source_id: SourceId,
103 dialect: &'static dyn ParserDialect,
104) -> Result<Vec<ParseError>, ParseError> {
105 lint::lint_trailing_function_return_semicolons(source, source_id, dialect)
106}
107
108pub(super) fn format_source(
109 source: &str,
110 dialect: &'static dyn ParserDialect,
111) -> Result<String, ParseError> {
112 format::format_source(source, dialect)
113}
114
115pub(super) struct Parser {
116 tokens: Vec<Token>,
117 pos: usize,
118 locals: HashMap<String, LocalSlot>,
119 named_local_bindings: Vec<(String, LocalSlot)>,
120 next_local: LocalSlot,
121 functions: HashMap<String, FunctionDecl>,
122 function_list: Vec<FunctionDecl>,
123 function_impls: HashMap<u16, FunctionImpl>,
124 next_function: u16,
125 closure_scopes: Vec<HashMap<String, LocalSlot>>,
126 closure_capture_contexts: Vec<ClosureCaptureContext>,
127 struct_schemas: HashMap<String, StructDecl>,
128 schema_reference_sites: Vec<(String, usize, usize, Span)>,
129 active_type_params: Vec<HashSet<String>>,
130 unknown_type_spans: Vec<Span>,
131 allow_implicit_externs: bool,
132 allow_implicit_semicolons: bool,
133 enforce_mutable_bindings: bool,
134 dialect: &'static dyn ParserDialect,
135 loop_depth: usize,
136 function_body_depth: usize,
137 host_namespace_aliases: HashMap<String, String>,
138 direct_host_call_aliases: HashMap<String, String>,
139 direct_host_wildcard_imports: HashSet<String>,
140 mutable_locals: Vec<bool>,
141}
142
143struct ClosureCaptureContext {
144 by_name: HashMap<String, LocalSlot>,
145 capture_copies: Vec<(LocalSlot, LocalSlot)>,
146}
147
148impl Parser {
149 pub(super) fn new(
150 source: &str,
151 source_id: SourceId,
152 allow_implicit_externs: bool,
153 allow_implicit_semicolons: bool,
154 enforce_mutable_bindings: bool,
155 dialect: &'static dyn ParserDialect,
156 ) -> Result<Self, ParseError> {
157 let mut lexer = Lexer::new(source, source_id, dialect);
158 let mut tokens = Vec::new();
159 loop {
160 let token = lexer.next_token()?;
161 let is_eof = matches!(token.kind, TokenKind::Eof);
162 tokens.push(token);
163 if is_eof {
164 break;
165 }
166 }
167 Ok(Self {
168 tokens,
169 pos: 0,
170 locals: HashMap::new(),
171 named_local_bindings: Vec::new(),
172 next_local: 0,
173 functions: HashMap::new(),
174 function_list: Vec::new(),
175 function_impls: HashMap::new(),
176 next_function: 0,
177 closure_scopes: Vec::new(),
178 closure_capture_contexts: Vec::new(),
179 struct_schemas: HashMap::new(),
180 schema_reference_sites: Vec::new(),
181 active_type_params: Vec::new(),
182 unknown_type_spans: Vec::new(),
183 allow_implicit_externs,
184 allow_implicit_semicolons,
185 enforce_mutable_bindings,
186 dialect,
187 loop_depth: 0,
188 function_body_depth: 0,
189 host_namespace_aliases: HashMap::new(),
190 direct_host_call_aliases: HashMap::new(),
191 direct_host_wildcard_imports: HashSet::new(),
192 mutable_locals: Vec::new(),
193 })
194 }
195
196 pub(super) fn new_with_predeclared_locals(
197 source: &str,
198 source_id: SourceId,
199 allow_implicit_externs: bool,
200 allow_implicit_semicolons: bool,
201 enforce_mutable_bindings: bool,
202 dialect: &'static dyn ParserDialect,
203 predeclared_locals: &[ReplLocalBinding],
204 ) -> Result<Self, ParseError> {
205 let mut parser = Self::new(
206 source,
207 source_id,
208 allow_implicit_externs,
209 allow_implicit_semicolons,
210 enforce_mutable_bindings,
211 dialect,
212 )?;
213 for binding in predeclared_locals {
214 parser.predeclare_local(binding)?;
215 }
216 Ok(parser)
217 }
218
219 pub(super) fn parse_program(&mut self) -> Result<Vec<Stmt>, ParseError> {
220 let mut stmts = Vec::new();
221 while !self.check(&TokenKind::Eof) {
222 stmts.push(self.parse_stmt()?);
223 }
224 self.validate_schema_reference_sites()?;
225 Ok(stmts)
226 }
227
228 pub(super) fn local_count(&self) -> usize {
229 self.next_local as usize
230 }
231
232 pub(super) fn function_decls(&self) -> Vec<FunctionDecl> {
233 self.function_list.clone()
234 }
235
236 pub(super) fn function_impls(&self) -> HashMap<u16, FunctionImpl> {
237 self.function_impls.clone()
238 }
239
240 pub(super) fn local_bindings(&self) -> Vec<(String, LocalSlot)> {
241 let mut locals = self.named_local_bindings.clone();
242 locals.sort_by_key(|(_, index)| *index);
243 locals
244 }
245
246 pub(super) fn local_bindings_with_mutability(&self) -> Vec<ReplLocalBinding> {
247 let mut locals = self
248 .locals
249 .iter()
250 .map(|(name, index)| ReplLocalBinding {
251 name: name.clone(),
252 mutable: self.is_local_slot_mutable(*index),
253 schema: None,
254 optional: false,
255 })
256 .collect::<Vec<_>>();
257 locals.sort_by_key(|binding| self.locals.get(&binding.name).copied().unwrap_or(0));
258 locals
259 }
260
261 pub(super) fn struct_schemas(&self) -> HashMap<String, StructDecl> {
262 self.struct_schemas.clone()
263 }
264
265 pub(super) fn unknown_type_spans(&self) -> Vec<Span> {
266 self.unknown_type_spans.clone()
267 }
268
269 fn validate_schema_reference_sites(&self) -> Result<(), ParseError> {
270 for (name, arg_count, line, span) in &self.schema_reference_sites {
271 let Some(decl) = self.struct_schemas.get(name) else {
272 return Err(ParseError {
273 span: Some(*span),
274 code: None,
275 line: *line,
276 message: format!("unknown struct schema '{name}'"),
277 });
278 };
279 if decl.type_params.len() != *arg_count {
280 return Err(ParseError {
281 span: Some(*span),
282 code: None,
283 line: *line,
284 message: format!(
285 "struct schema '{name}' expects {} type arguments, got {}",
286 decl.type_params.len(),
287 arg_count
288 ),
289 });
290 }
291 if self.struct_schemas.contains_key(name) {
292 continue;
293 }
294 }
295 Ok(())
296 }
297
298 fn push_active_type_params(&mut self, params: &[String]) {
299 self.active_type_params
300 .push(params.iter().cloned().collect::<HashSet<_>>());
301 }
302
303 fn pop_active_type_params(&mut self) {
304 self.active_type_params.pop();
305 }
306
307 fn is_active_type_param(&self, name: &str) -> bool {
308 self.active_type_params
309 .iter()
310 .rev()
311 .any(|params| params.contains(name))
312 }
313
314 fn parse_type_params(
315 &mut self,
316 owner: &str,
317 owner_name: &str,
318 ) -> Result<Vec<String>, ParseError> {
319 if !self.check(&TokenKind::Less) {
320 return Ok(Vec::new());
321 }
322
323 self.expect(&TokenKind::Less, "expected '<' before type parameters")?;
324 let mut params = Vec::new();
325 let mut seen = HashSet::new();
326 loop {
327 let param = self.expect_ident("expected type parameter name")?;
328 if !seen.insert(param.clone()) {
329 return Err(ParseError {
330 span: Some(self.current_span()),
331 code: None,
332 line: self.current_line(),
333 message: format!(
334 "duplicate type parameter '{param}' in {owner} '{owner_name}'"
335 ),
336 });
337 }
338 params.push(param);
339 if self.match_kind(&TokenKind::Comma) {
340 continue;
341 }
342 break;
343 }
344 self.expect(&TokenKind::Greater, "expected '>' after type parameters")?;
345 Ok(params)
346 }
347
348 fn parse_turbofish_type_args(&mut self) -> Result<Vec<TypeSchema>, ParseError> {
349 if !self.check_path_separator() || !self.check_kind_at(self.pos + 2, &TokenKind::Less) {
350 return Ok(Vec::new());
351 }
352
353 self.match_path_separator();
354 self.expect(&TokenKind::Less, "expected '<' after '::' in turbofish")?;
355 let mut type_args = Vec::new();
356 loop {
357 type_args.push(self.parse_declared_type_schema()?);
358 if self.match_kind(&TokenKind::Comma) {
359 continue;
360 }
361 break;
362 }
363 self.expect(&TokenKind::Greater, "expected '>' after type arguments")?;
364 Ok(type_args)
365 }
366
367 fn function_param_names(params: &[FunctionParam]) -> Vec<String> {
368 params.iter().map(|param| param.name.clone()).collect()
369 }
370}