1use crate::ast::*;
2use harn_lexer::{Span, Token, TokenKind};
3
4use super::error::ParserError;
5
6pub struct Parser {
8 pub(super) tokens: Vec<Token>,
9 pub(super) pos: usize,
10 pub(super) errors: Vec<ParserError>,
11}
12
13impl Parser {
14 pub fn new(tokens: Vec<Token>) -> Self {
15 Self {
16 tokens,
17 pos: 0,
18 errors: Vec::new(),
19 }
20 }
21
22 pub(super) fn current_span(&self) -> Span {
23 self.tokens
24 .get(self.pos)
25 .map(|t| t.span)
26 .unwrap_or(Span::dummy())
27 }
28
29 pub(super) fn current_kind(&self) -> Option<&TokenKind> {
30 self.tokens.get(self.pos).map(|t| &t.kind)
31 }
32
33 pub(super) fn prev_span(&self) -> Span {
34 if self.pos > 0 {
35 self.tokens[self.pos - 1].span
36 } else {
37 Span::dummy()
38 }
39 }
40
41 pub(super) fn last_non_newline_span(&self) -> Span {
49 let mut i = self.pos;
50 while i > 0 {
51 i -= 1;
52 if self.tokens[i].kind != TokenKind::Newline {
53 return self.tokens[i].span;
54 }
55 }
56 Span::dummy()
57 }
58
59 pub fn parse(&mut self) -> Result<Vec<SNode>, ParserError> {
61 let mut nodes = Vec::new();
62 self.skip_newlines();
63
64 while !self.is_at_end() {
65 if self.check(&TokenKind::RBrace) {
67 self.advance();
68 self.skip_newlines();
69 continue;
70 }
71
72 let result = if self.check(&TokenKind::Import) {
73 self.parse_import()
74 } else if self.check(&TokenKind::At) {
75 self.parse_attributed_decl()
76 } else if self.check(&TokenKind::Pipeline) {
77 self.parse_pipeline()
78 } else if self.check(&TokenKind::EvalPack) {
79 self.parse_eval_pack_decl(false)
80 } else {
81 self.parse_statement()
82 };
83
84 match result {
85 Ok(node) => {
86 let end_line = node.span.end_line;
87 nodes.push(node);
88 let consumed_sep = self.consume_statement_separator();
89 if !consumed_sep && !self.is_at_end() {
90 self.require_statement_separator(end_line, "top-level item")?;
91 }
92 }
93 Err(err) => {
94 self.errors.push(err);
95 self.synchronize();
96 }
97 }
98 }
99
100 if let Some(first) = self.errors.first() {
101 return Err(first.clone());
102 }
103 Ok(nodes)
104 }
105
106 pub fn all_errors(&self) -> &[ParserError] {
108 &self.errors
109 }
110
111 pub(super) fn is_statement_start(&self) -> bool {
113 matches!(
114 self.current_kind(),
115 Some(
116 TokenKind::Let
117 | TokenKind::Const
118 | TokenKind::Var
119 | TokenKind::If
120 | TokenKind::For
121 | TokenKind::While
122 | TokenKind::Match
123 | TokenKind::Retry
124 | TokenKind::Return
125 | TokenKind::Throw
126 | TokenKind::Fn
127 | TokenKind::Pub
128 | TokenKind::Try
129 | TokenKind::Select
130 | TokenKind::Pipeline
131 | TokenKind::Import
132 | TokenKind::Parallel
133 | TokenKind::Enum
134 | TokenKind::EvalPack
135 | TokenKind::Struct
136 | TokenKind::Interface
137 | TokenKind::Emit
138 | TokenKind::Guard
139 | TokenKind::Require
140 | TokenKind::Deadline
141 | TokenKind::Yield
142 | TokenKind::Mutex
143 | TokenKind::Defer
144 | TokenKind::Break
145 | TokenKind::Continue
146 | TokenKind::Tool
147 | TokenKind::Skill
148 | TokenKind::Impl
149 )
150 )
151 }
152
153 pub(super) fn synchronize(&mut self) {
155 while !self.is_at_end() {
156 if self.check(&TokenKind::Semicolon) {
157 self.advance();
158 self.skip_newlines();
159 return;
160 }
161 if self.check(&TokenKind::Newline) {
162 self.advance();
163 if self.is_at_end() || self.is_statement_start() {
164 return;
165 }
166 continue;
167 }
168 if self.check(&TokenKind::RBrace) {
169 return;
170 }
171 self.advance();
172 }
173 }
174
175 pub(super) fn is_at_end(&self) -> bool {
176 self.pos >= self.tokens.len()
177 || matches!(self.tokens.get(self.pos), Some(t) if t.kind == TokenKind::Eof)
178 }
179
180 pub(super) fn current(&self) -> Option<&Token> {
181 self.tokens.get(self.pos)
182 }
183
184 pub(super) fn peek_kind(&self) -> Option<&TokenKind> {
185 self.tokens.get(self.pos + 1).map(|t| &t.kind)
186 }
187
188 pub(super) fn peek_kind_at(&self, offset: usize) -> Option<&TokenKind> {
189 self.tokens.get(self.pos + offset).map(|t| &t.kind)
190 }
191
192 pub(super) fn check(&self, kind: &TokenKind) -> bool {
193 self.current()
194 .map(|t| std::mem::discriminant(&t.kind) == std::mem::discriminant(kind))
195 .unwrap_or(false)
196 }
197
198 pub(super) fn check_skip_newlines(&mut self, kind: &TokenKind) -> bool {
201 let saved = self.pos;
202 self.skip_newlines();
203 if self.check(kind) {
204 true
205 } else {
206 self.pos = saved;
207 false
208 }
209 }
210
211 pub(super) fn check_identifier(&self, name: &str) -> bool {
213 matches!(self.current().map(|t| &t.kind), Some(TokenKind::Identifier(s)) if s == name)
214 }
215
216 pub(super) fn check_contextual_gen_fn(&self) -> bool {
219 if !self.check_identifier("gen") {
220 return false;
221 }
222 matches!(
223 self.tokens.get(self.pos + 1).map(|t| &t.kind),
224 Some(TokenKind::Fn)
225 )
226 }
227
228 pub(super) fn advance(&mut self) {
229 if self.pos < self.tokens.len() {
230 self.pos += 1;
231 }
232 }
233
234 pub(super) fn consume(
235 &mut self,
236 kind: &TokenKind,
237 expected: &str,
238 ) -> Result<Token, ParserError> {
239 self.skip_newlines();
240 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
241 if std::mem::discriminant(&tok.kind) != std::mem::discriminant(kind) {
242 return Err(self.make_error(expected));
243 }
244 let tok = tok.clone();
245 self.advance();
246 Ok(tok)
247 }
248
249 pub(super) fn consume_identifier(&mut self, expected: &str) -> Result<String, ParserError> {
250 self.skip_newlines();
251 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
252 if let TokenKind::Identifier(name) = &tok.kind {
253 let name = name.clone();
254 self.advance();
255 Ok(name)
256 } else {
257 let kw_name = harn_lexer::KEYWORDS
260 .iter()
261 .find(|&&kw| kw == tok.kind.to_string());
262 if let Some(kw) = kw_name {
263 Err(ParserError::Unexpected {
264 got: format!("'{kw}' (reserved keyword)"),
265 expected: expected.into(),
266 span: tok.span,
267 })
268 } else {
269 Err(self.make_error(expected))
270 }
271 }
272 }
273
274 pub(super) fn consume_contextual_keyword(
275 &mut self,
276 name: &str,
277 expected: &str,
278 ) -> Result<Token, ParserError> {
279 self.skip_newlines();
280 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
281 if matches!(&tok.kind, TokenKind::Identifier(id) if id == name) {
282 let tok = tok.clone();
283 self.advance();
284 Ok(tok)
285 } else {
286 Err(self.make_error(expected))
287 }
288 }
289
290 pub(super) fn consume_identifier_or_keyword(
294 &mut self,
295 expected: &str,
296 ) -> Result<String, ParserError> {
297 self.skip_newlines();
298 let tok = self.current().ok_or_else(|| self.make_error(expected))?;
299 if let TokenKind::Identifier(name) = &tok.kind {
300 let name = name.clone();
301 self.advance();
302 return Ok(name);
303 }
304 let name = match &tok.kind {
305 TokenKind::Pipeline => "pipeline",
306 TokenKind::Extends => "extends",
307 TokenKind::Override => "override",
308 TokenKind::Let => "let",
309 TokenKind::Const => "const",
310 TokenKind::Var => "var",
311 TokenKind::If => "if",
312 TokenKind::Else => "else",
313 TokenKind::For => "for",
314 TokenKind::In => "in",
315 TokenKind::Match => "match",
316 TokenKind::Retry => "retry",
317 TokenKind::Parallel => "parallel",
318 TokenKind::Return => "return",
319 TokenKind::Import => "import",
320 TokenKind::True => "true",
321 TokenKind::False => "false",
322 TokenKind::Nil => "nil",
323 TokenKind::Try => "try",
324 TokenKind::Catch => "catch",
325 TokenKind::Throw => "throw",
326 TokenKind::Finally => "finally",
327 TokenKind::Fn => "fn",
328 TokenKind::Spawn => "spawn",
329 TokenKind::While => "while",
330 TokenKind::TypeKw => "type",
331 TokenKind::Enum => "enum",
332 TokenKind::EvalPack => "eval_pack",
333 TokenKind::Struct => "struct",
334 TokenKind::Interface => "interface",
335 TokenKind::Emit => "emit",
336 TokenKind::Pub => "pub",
337 TokenKind::From => "from",
338 TokenKind::To => "to",
339 TokenKind::Tool => "tool",
340 TokenKind::Exclusive => "exclusive",
341 TokenKind::Guard => "guard",
342 TokenKind::Require => "require",
343 TokenKind::Deadline => "deadline",
344 TokenKind::Defer => "defer",
345 TokenKind::Yield => "yield",
346 TokenKind::Mutex => "mutex",
347 TokenKind::Break => "break",
348 TokenKind::Continue => "continue",
349 TokenKind::Select => "select",
350 TokenKind::Impl => "impl",
351 TokenKind::Skill => "skill",
352 TokenKind::RequestApproval => "request_approval",
353 TokenKind::DualControl => "dual_control",
354 TokenKind::AskUser => "ask_user",
355 TokenKind::EscalateTo => "escalate_to",
356 _ => return Err(self.make_error(expected)),
357 };
358 let name = name.to_string();
359 self.advance();
360 Ok(name)
361 }
362
363 pub(super) fn skip_newlines(&mut self) {
364 while self.pos < self.tokens.len() && self.tokens[self.pos].kind == TokenKind::Newline {
365 self.pos += 1;
366 }
367 }
368
369 pub(super) fn consume_statement_separator(&mut self) -> bool {
376 let mut consumed = false;
377 if self.check(&TokenKind::Semicolon) {
378 self.advance();
379 consumed = true;
380 }
381 let start = self.pos;
382 self.skip_newlines();
383 consumed || self.pos != start
384 }
385
386 pub(super) fn require_statement_separator(
387 &self,
388 prev_end_line: usize,
389 expected_item: &str,
390 ) -> Result<(), ParserError> {
391 let Some(tok) = self.current() else {
392 return Ok(());
393 };
394 if tok.kind == TokenKind::Eof || tok.span.line != prev_end_line {
395 return Ok(());
396 }
397 Err(ParserError::Unexpected {
398 got: tok.kind.to_string(),
399 expected: format!("{expected_item} separator (`;` or newline)"),
400 span: tok.span,
401 })
402 }
403
404 pub(super) fn make_error(&self, expected: &str) -> ParserError {
405 if let Some(tok) = self.tokens.get(self.pos) {
406 if tok.kind == TokenKind::Eof {
407 return ParserError::UnexpectedEof {
408 expected: expected.into(),
409 span: tok.span,
410 };
411 }
412 ParserError::Unexpected {
413 got: tok.kind.to_string(),
414 expected: expected.into(),
415 span: tok.span,
416 }
417 } else {
418 ParserError::UnexpectedEof {
419 expected: expected.into(),
420 span: self.prev_span(),
421 }
422 }
423 }
424
425 pub(super) fn error(&self, expected: &str) -> ParserError {
426 self.make_error(expected)
427 }
428}