rl_model/parser/
parser.rs1use 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 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}