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