1use super::lexer::{
2 Lexer,
3};
4use super::parser::{
5 Parser,
6 Statement,
7 StatementValue
8};
9use super::util::{check_error, get_include_path};
10use std::ops::Range;
11use std::fs;
12
13
14pub struct Preprocessor {
19 pub statements: Vec<Statement>,
20}
21
22impl Preprocessor {
23
24 pub fn preprocess(&mut self, input: Vec<Statement>, included_files: Vec<String>) -> Result<(), (String, Range<usize>)> {
26 for statement in input {
27 match statement.value {
28 StatementValue::Include(path) => {
29 if let Some(path) = get_include_path(&path) {
30 match fs::read_to_string(&path) {
31 Ok(content) => {
32 if included_files.iter().any(|n| n == &path) {
33 return Err((format!("recursive include of '{}'", path), (1..0)));
34 }
35
36 let mut lexer = Lexer::new(content.clone());
37 check_error(lexer.lex(false), &path, &content);
38 let mut parser = Parser::new(lexer.tokens, included_files.last().unwrap().clone());
39 check_error(parser.parse(), &path, &content);
40
41 let mut included_files = included_files.clone();
42 included_files.push(path);
43
44 if let Err(err) = self.preprocess(parser.statements, included_files) {
45 return Err(err);
46 }
47 },
48 Err(err) => return Err((String::from(err.to_string()), 1..0))
49 }
50 } else {
51 return Err((format!("could not find file '{}' in lib directory or current working directory", path), (1..0)));
52 }
53 },
54 _ => {
55 self.statements.push(statement);
56 }
57 }
58 }
59 Ok(())
60 }
61
62 pub fn new() -> Self {
63 Self {
64 statements: Vec::new(),
65 }
66 }
67}