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