1use super::position::{File, FilePos, Pos};
13use std::cell::{Ref, RefCell};
14use std::fmt;
15use std::rc::Rc;
16
17#[derive(Clone, Debug)]
18pub struct Error {
19 pub pos: FilePos,
20 pub msg: String,
21 pub soft: bool,
22 pub by_parser: bool, order: usize, }
25
26impl fmt::Display for Error {
27 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28 let p = if self.by_parser { "[Parser]" } else { "[TC]" };
29 write!(f, "{} {} {}\n", p, self.pos, self.msg)?;
30 Ok(())
31 }
32}
33
34impl std::error::Error for Error {}
35
36#[derive(Clone, Debug)]
37pub struct ErrorList {
38 errors: Rc<RefCell<Vec<Error>>>,
39}
40
41impl fmt::Display for ErrorList {
42 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
43 write!(f, "Result: {} errors\n", self.errors.borrow().len())?;
44 for e in self.errors.borrow().iter() {
45 e.fmt(f)?;
46 }
47 Ok(())
48 }
49}
50
51impl std::error::Error for ErrorList {}
52
53impl ErrorList {
54 pub fn new() -> ErrorList {
55 ErrorList {
56 errors: Rc::new(RefCell::new(vec![])),
57 }
58 }
59
60 pub fn add(&self, p: Option<FilePos>, msg: String, soft: bool, by_parser: bool) {
61 let fp = p.unwrap_or(FilePos::null());
62 let order = if msg.starts_with('\t') {
63 self.errors
64 .borrow()
65 .iter()
66 .rev()
67 .find(|x| !x.msg.starts_with('\t'))
68 .unwrap()
69 .pos
70 .offset
71 } else {
72 fp.offset
73 };
74 self.errors.borrow_mut().push(Error {
75 pos: fp,
76 msg: msg,
77 soft: soft,
78 by_parser: by_parser,
79 order: order,
80 });
81 }
82
83 pub fn len(&self) -> usize {
84 self.errors.borrow().len()
85 }
86
87 pub fn sort(&self) {
88 self.errors.borrow_mut().sort_by_key(|e| e.order);
89 }
90
91 pub fn borrow(&self) -> Ref<Vec<Error>> {
92 self.errors.borrow()
93 }
94}
95
96#[derive(Clone, Debug)]
97pub struct FilePosErrors<'a> {
98 file: &'a File,
99 elist: &'a ErrorList,
100}
101
102impl<'a> FilePosErrors<'a> {
103 pub fn new(file: &'a File, elist: &'a ErrorList) -> FilePosErrors<'a> {
104 FilePosErrors {
105 file: file,
106 elist: elist,
107 }
108 }
109
110 pub fn add(&self, pos: Pos, msg: String, soft: bool) {
111 let p = self.file.position(pos);
112 self.elist.add(Some(p), msg, soft, false);
113 }
114
115 pub fn add_str(&self, pos: Pos, s: &str, soft: bool) {
116 self.add(pos, s.to_string(), soft);
117 }
118
119 pub fn parser_add(&self, pos: Pos, msg: String) {
120 let p = self.file.position(pos);
121 self.elist.add(Some(p), msg, false, true);
122 }
123
124 pub fn parser_add_str(&self, pos: Pos, s: &str) {
125 self.parser_add(pos, s.to_string());
126 }
127}