1use crate::ast::*;
2use harn_lexer::{Span, Token, TokenKind};
3
4use super::error::ParserError;
5
6pub(crate) const MAX_NESTING_DEPTH: usize = 64;
7
8pub struct Parser {
10 pub(super) tokens: Vec<Token>,
11 pub(super) pos: usize,
12 pub(super) errors: Vec<ParserError>,
13 nesting_depth: usize,
14}
15
16impl Parser {
17 pub(super) fn at_module_scope(&self) -> bool {
18 self.nesting_depth == 0
19 }
20
21 pub fn new(tokens: Vec<Token>) -> Self {
22 Self {
23 tokens,
24 pos: 0,
25 errors: Vec::new(),
26 nesting_depth: 0,
27 }
28 }
29
30 pub(super) fn check_token_nesting_limit(&self) -> Result<(), ParserError> {
31 let mut depth = 0usize;
32 for token in &self.tokens {
33 match token.kind {
34 TokenKind::LBrace | TokenKind::LBracket | TokenKind::LParen => {
35 depth += 1;
36 if depth > MAX_NESTING_DEPTH {
37 return Err(ParserError::Unexpected {
38 got: "source nesting depth exceeded".to_string(),
39 expected: format!(
40 "parser nesting depth within {MAX_NESTING_DEPTH} levels"
41 ),
42 span: token.span,
43 });
44 }
45 }
46 TokenKind::RBrace | TokenKind::RBracket | TokenKind::RParen => {
47 depth = depth.saturating_sub(1);
48 }
49 _ => {}
50 }
51 }
52 Ok(())
53 }
54
55 pub(super) fn current_span(&self) -> Span {
56 self.tokens
57 .get(self.pos)
58 .map(|t| t.span)
59 .unwrap_or(Span::dummy())
60 }
61
62 pub(super) fn current_kind(&self) -> Option<&TokenKind> {
63 self.tokens.get(self.pos).map(|t| &t.kind)
64 }
65
66 pub(super) fn prev_span(&self) -> Span {
67 if self.pos > 0 {
68 self.tokens[self.pos - 1].span
69 } else {
70 Span::dummy()
71 }
72 }
73
74 pub(super) fn last_non_newline_span(&self) -> Span {
82 let mut i = self.pos;
83 while i > 0 {
84 i -= 1;
85 if self.tokens[i].kind != TokenKind::Newline {
86 return self.tokens[i].span;
87 }
88 }
89 Span::dummy()
90 }
91
92 pub fn parse(&mut self) -> Result<Vec<SNode>, ParserError> {
94 self.check_token_nesting_limit()?;
95
96 let mut nodes = Vec::new();
97 self.skip_newlines();
98
99 while !self.is_at_end() {
100 if self.check(&TokenKind::RBrace) {
102 self.advance();
103 self.skip_newlines();
104 continue;
105 }
106
107 let result = if self.check(&TokenKind::Import) {
108 self.parse_import()
109 } else if self.check(&TokenKind::At) {
110 self.parse_attributed_decl()
111 } else if self.check(&TokenKind::Pipeline) {
112 self.parse_pipeline()
113 } else if self.check(&TokenKind::EvalPack) {
114 self.parse_eval_pack_decl(false)
115 } else {
116 self.parse_statement()
117 };
118
119 match result {
120 Ok(node) => {
121 let end_line = node.span.end_line;
122 nodes.push(node);
123 let consumed_sep = self.consume_statement_separator();
124 if !consumed_sep && !self.is_at_end() {
125 self.require_statement_separator(end_line, "top-level item")?;
126 }
127 }
128 Err(err) => {
129 self.errors.push(err);
130 self.synchronize();
131 }
132 }
133 }
134
135 if let Some(first) = self.errors.first() {
136 return Err(first.clone());
137 }
138 Ok(nodes)
139 }
140
141 pub fn all_errors(&self) -> &[ParserError] {
143 &self.errors
144 }
145
146 pub(super) fn is_statement_start(&self) -> bool {
148 matches!(
149 self.current_kind(),
150 Some(
151 TokenKind::Let
152 | TokenKind::Const
153 | TokenKind::Var
154 | TokenKind::If
155 | TokenKind::For
156 | TokenKind::While
157 | TokenKind::Match
158 | TokenKind::Retry
159 | TokenKind::Return
160 | TokenKind::Throw
161 | TokenKind::Fn
162 | TokenKind::Pub
163 | TokenKind::Try
164 | TokenKind::Select
165 | TokenKind::Pipeline
166 | TokenKind::Import
167 | TokenKind::Parallel
168 | TokenKind::Enum
169 | TokenKind::EvalPack
170 | TokenKind::Struct
171 | TokenKind::Interface
172 | TokenKind::Emit
173 | TokenKind::Guard
174 | TokenKind::Require
175 | TokenKind::Deadline
176 | TokenKind::Yield
177 | TokenKind::Mutex
178 | TokenKind::Defer
179 | TokenKind::Break
180 | TokenKind::Continue
181 | TokenKind::Tool
182 | TokenKind::Skill
183 | TokenKind::Impl
184 )
185 )
186 }
187
188 pub(super) fn synchronize(&mut self) {
190 while !self.is_at_end() {
191 if self.check(&TokenKind::Semicolon) {
192 self.advance();
193 self.skip_newlines();
194 return;
195 }
196 if self.check(&TokenKind::Newline) {
197 self.advance();
198 if self.is_at_end() || self.is_statement_start() {
199 return;
200 }
201 continue;
202 }
203 if self.check(&TokenKind::RBrace) {
204 return;
205 }
206 self.advance();
207 }
208 }
209
210 pub(super) fn is_at_end(&self) -> bool {
211 self.pos >= self.tokens.len()
212 || matches!(self.tokens.get(self.pos), Some(t) if t.kind == TokenKind::Eof)
213 }
214
215 pub(super) fn current(&self) -> Option<&Token> {
216 self.tokens.get(self.pos)
217 }
218
219 pub(super) fn peek_kind(&self) -> Option<&TokenKind> {
220 self.tokens.get(self.pos + 1).map(|t| &t.kind)
221 }
222
223 pub(super) fn peek_kind_at(&self, offset: usize) -> Option<&TokenKind> {
224 self.tokens.get(self.pos + offset).map(|t| &t.kind)
225 }
226
227 pub(super) fn check(&self, kind: &TokenKind) -> bool {
228 self.current()
229 .map(|t| std::mem::discriminant(&t.kind) == std::mem::discriminant(kind))
230 .unwrap_or(false)
231 }
232
233 pub(super) fn check_skip_newlines(&mut self, kind: &TokenKind) -> bool {
236 let saved = self.pos;
237 self.skip_newlines();
238 if self.check(kind) {
239 true
240 } else {
241 self.pos = saved;
242 false
243 }
244 }
245
246 pub(super) fn check_identifier(&self, name: &str) -> bool {
248 matches!(self.current().map(|t| &t.kind), Some(TokenKind::Identifier(s)) if s == name)
249 }
250
251 pub(super) fn check_contextual_gen_fn(&self) -> bool {
254 if !self.check_identifier("gen") {
255 return false;
256 }
257 matches!(
258 self.tokens.get(self.pos + 1).map(|t| &t.kind),
259 Some(TokenKind::Fn)
260 )
261 }
262
263 pub(super) fn check_contextual_brace_block(&self, name: &str) -> bool {
267 if !self.check_identifier(name) {
268 return false;
269 }
270 matches!(
271 self.tokens.get(self.pos + 1).map(|t| &t.kind),
272 Some(TokenKind::LBrace)
273 )
274 }
275
276 pub(super) fn advance(&mut self) {
277 if self.pos < self.tokens.len() {
278 self.pos += 1;
279 }
280 }
281
282 pub(super) fn consume(
283 &mut self,
284 kind: &TokenKind,
285 expected: &str,
286 ) -> Result<Token, ParserError> {
287 self.skip_newlines();
288 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
289 if std::mem::discriminant(&tok.kind) != std::mem::discriminant(kind) {
290 return Err(self.make_error(expected));
291 }
292 let tok = tok.clone();
293 self.advance();
294 Ok(tok)
295 }
296
297 pub(super) fn consume_identifier(&mut self, expected: &str) -> Result<String, ParserError> {
298 self.skip_newlines();
299 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
300 if let TokenKind::Identifier(name) = &tok.kind {
301 let name = name.clone();
302 self.advance();
303 Ok(name)
304 } else {
305 let kw_name = harn_lexer::KEYWORDS
308 .iter()
309 .find(|&&kw| kw == tok.kind.to_string());
310 if let Some(kw) = kw_name {
311 Err(ParserError::Unexpected {
312 got: format!("'{kw}' (reserved keyword)"),
313 expected: expected.into(),
314 span: tok.span,
315 })
316 } else {
317 Err(self.make_error(expected))
318 }
319 }
320 }
321
322 pub(super) fn consume_contextual_keyword(
323 &mut self,
324 name: &str,
325 expected: &str,
326 ) -> Result<Token, ParserError> {
327 self.skip_newlines();
328 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
329 if matches!(&tok.kind, TokenKind::Identifier(id) if id == name) {
330 let tok = tok.clone();
331 self.advance();
332 Ok(tok)
333 } else {
334 Err(self.make_error(expected))
335 }
336 }
337
338 pub(super) fn consume_identifier_or_keyword(
342 &mut self,
343 expected: &str,
344 ) -> Result<String, ParserError> {
345 self.skip_newlines();
346 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
347 if let TokenKind::Identifier(name) = &tok.kind {
348 let name = name.clone();
349 self.advance();
350 return Ok(name);
351 }
352 let name = match &tok.kind {
353 TokenKind::Pipeline => "pipeline",
354 TokenKind::Extends => "extends",
355 TokenKind::Override => "override",
356 TokenKind::Let => "let",
357 TokenKind::Const => "const",
358 TokenKind::Var => "var",
359 TokenKind::If => "if",
360 TokenKind::Else => "else",
361 TokenKind::For => "for",
362 TokenKind::In => "in",
363 TokenKind::Match => "match",
364 TokenKind::Retry => "retry",
365 TokenKind::Parallel => "parallel",
366 TokenKind::Return => "return",
367 TokenKind::Import => "import",
368 TokenKind::True => "true",
369 TokenKind::False => "false",
370 TokenKind::Nil => "nil",
371 TokenKind::Try => "try",
372 TokenKind::Catch => "catch",
373 TokenKind::Throw => "throw",
374 TokenKind::Finally => "finally",
375 TokenKind::Fn => "fn",
376 TokenKind::Spawn => "spawn",
377 TokenKind::While => "while",
378 TokenKind::TypeKw => "type",
379 TokenKind::Enum => "enum",
380 TokenKind::EvalPack => "eval_pack",
381 TokenKind::Struct => "struct",
382 TokenKind::Interface => "interface",
383 TokenKind::Emit => "emit",
384 TokenKind::Pub => "pub",
385 TokenKind::From => "from",
386 TokenKind::To => "to",
387 TokenKind::Tool => "tool",
388 TokenKind::Exclusive => "exclusive",
389 TokenKind::Guard => "guard",
390 TokenKind::Require => "require",
391 TokenKind::Deadline => "deadline",
392 TokenKind::Defer => "defer",
393 TokenKind::Yield => "yield",
394 TokenKind::Mutex => "mutex",
395 TokenKind::Break => "break",
396 TokenKind::Continue => "continue",
397 TokenKind::Select => "select",
398 TokenKind::Impl => "impl",
399 TokenKind::Skill => "skill",
400 _ => return Err(self.make_error(expected)),
401 };
402 let name = name.to_string();
403 self.advance();
404 Ok(name)
405 }
406
407 pub(super) fn skip_newlines(&mut self) {
408 while self.pos < self.tokens.len() && self.tokens[self.pos].kind == TokenKind::Newline {
409 self.pos += 1;
410 }
411 }
412
413 pub(super) fn consume_statement_separator(&mut self) -> bool {
420 let mut consumed = false;
421 if self.check(&TokenKind::Semicolon) {
422 self.advance();
423 consumed = true;
424 }
425 let start = self.pos;
426 self.skip_newlines();
427 consumed || self.pos != start
428 }
429
430 pub(super) fn require_statement_separator(
431 &self,
432 prev_end_line: usize,
433 expected_item: &str,
434 ) -> Result<(), ParserError> {
435 let Some(tok) = self.current() else {
436 return Ok(());
437 };
438 if tok.kind == TokenKind::Eof || tok.span.line != prev_end_line {
439 return Ok(());
440 }
441 Err(ParserError::Unexpected {
442 got: tok.kind.to_string(),
443 expected: format!("{expected_item} separator (`;` or newline)"),
444 span: tok.span,
445 })
446 }
447
448 pub(super) fn make_error(&self, expected: &str) -> ParserError {
449 if let Some(tok) = self.tokens.get(self.pos) {
450 if tok.kind == TokenKind::Eof {
451 return ParserError::UnexpectedEof {
452 expected: expected.into(),
453 span: tok.span,
454 };
455 }
456 ParserError::Unexpected {
457 got: tok.kind.to_string(),
458 expected: expected.into(),
459 span: tok.span,
460 }
461 } else {
462 ParserError::UnexpectedEof {
463 expected: expected.into(),
464 span: self.prev_span(),
465 }
466 }
467 }
468
469 pub(super) fn error(&self, expected: &str) -> ParserError {
470 self.make_error(expected)
471 }
472
473 pub(super) fn with_nesting<T>(
474 &mut self,
475 context: &'static str,
476 f: impl FnOnce(&mut Self) -> Result<T, ParserError>,
477 ) -> Result<T, ParserError> {
478 if self.nesting_depth >= MAX_NESTING_DEPTH {
479 return Err(ParserError::Unexpected {
480 got: format!("{context} nesting depth exceeded"),
481 expected: format!("parser nesting depth within {MAX_NESTING_DEPTH} levels"),
482 span: self.current_span(),
483 });
484 }
485 self.nesting_depth += 1;
486 let result = f(self);
487 self.nesting_depth = self.nesting_depth.saturating_sub(1);
488 result
489 }
490}