1use crate::ast::Program;
3
4use super::{Parser, annotate_error_with_line, tokenize};
5
6impl Parser {
7 pub fn new(source: &str) -> Self {
8 let tokens = tokenize(source);
9 Parser {
10 tokens,
11 pos: 0,
12 next_quotation_id: 0,
13 pending_allowed_lints: Vec::new(),
14 known_unions: std::collections::HashSet::new(),
15 }
16 }
17
18 pub fn register_external_unions(&mut self, union_names: &[&str]) {
21 for name in union_names {
22 self.known_unions.insert(name.to_string());
23 }
24 }
25
26 pub fn parse(&mut self) -> Result<Program, String> {
27 let mut program = Program::new();
28
29 if let Some(error_token) = self.tokens.iter().find(|t| *t == "<<<UNCLOSED_STRING>>>") {
31 return Err(format!(
32 "Unclosed string literal at line {}, column {} - missing closing quote",
33 error_token.line + 1, error_token.column + 1
35 ));
36 }
37
38 while !self.is_at_end() {
39 self.skip_comments();
40 if self.is_at_end() {
41 break;
42 }
43
44 let result = if self.check("include") {
49 self.parse_include().map(|inc| program.includes.push(inc))
50 } else if self.check("union") {
51 self.parse_union_def().map(|u| program.unions.push(u))
52 } else {
53 self.parse_word_def().map(|w| program.words.push(w))
54 };
55
56 if let Err(msg) = result {
57 let loc_token = self.current_token().or_else(|| self.tokens.last());
62 return Err(annotate_error_with_line(msg, loc_token));
63 }
64 }
65
66 Ok(program)
67 }
68}