rl_model/parser/
parser.rs

1use crate::model::Skillset;
2use crate::parser::error::*;
3use line_col::LineColLookup;
4use std::fs;
5
6lalrpop_mod!(grammar, "/parser/grammar.rs");
7
8pub struct Parser {
9    current: Option<String>,
10    todo: Vec<String>,
11    done: Vec<String>,
12    pub skillset: Skillset,
13}
14
15impl Default for Parser {
16    fn default() -> Self {
17        Self {
18            current: Default::default(),
19            todo: Default::default(),
20            done: Default::default(),
21            skillset: Default::default(),
22        }
23    }
24}
25
26impl Parser {
27    pub fn new<S: Into<String>>(file: S) -> Self {
28        Self {
29            current: None,
30            todo: vec![file.into()],
31            done: vec![],
32            skillset: Default::default(),
33        }
34    }
35
36    pub fn current(&self) -> &Option<String> {
37        &self.current
38    }
39
40    pub fn file(&self) -> &str {
41        self.current.as_ref().unwrap()
42    }
43
44    pub fn todo(&self) -> &Vec<String> {
45        &self.todo
46    }
47
48    pub fn done(&self) -> &Vec<String> {
49        &self.done
50    }
51
52    //------------------------- -------------------------
53
54    pub fn files(&self) -> Vec<String> {
55        let mut v = vec![];
56        if let Some(f) = &self.current {
57            v.push(f.clone());
58        }
59        v.extend(self.todo.clone().into_iter());
60        v.extend(self.done.clone().into_iter());
61        v
62    }
63
64    pub fn add<S: Into<String>>(&mut self, file: S) -> bool {
65        let file: String = file.into();
66        if self.files().contains(&file) {
67            false
68        } else {
69            self.todo.push(file);
70            true
71        }
72    }
73
74    pub fn next(&mut self) -> Option<String> {
75        if let Some(file) = &self.current {
76            self.done.push(file.clone());
77        }
78        match self.todo.pop() {
79            None => None,
80            Some(file) => {
81                self.current = Some(file.clone());
82                Some(file)
83            }
84        }
85    }
86
87    pub fn parse(&mut self) -> Result<(), RlError> {
88        loop {
89            match self.next() {
90                None => return Ok(()),
91                Some(file) => match fs::read_to_string(&file) {
92                    Ok(input) => {
93                        let lookup = LineColLookup::new(&input);
94                        match grammar::SkillsetParser::new().parse(&lookup, self, &input) {
95                            Ok(_) => {}
96                            Err(e) => return Err(RlError::new_parse(&file, &lookup, e)),
97                        }
98                    }
99                    Err(e) => {
100                        let e = RlError::File {
101                            filename: file,
102                            message: format!("{:?}", e),
103                        };
104                        return Err(e);
105                    }
106                },
107            }
108        }
109    }
110}