go_parser/
errors.rs

1// Copyright 2022 The Goscript Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4//
5//
6// This code is adapted from the offical Go code written in Go
7// with license as follows:
8// Copyright 2013 The Go Authors. All rights reserved.
9// Use of this source code is governed by a BSD-style
10// license that can be found in the LICENSE file.
11
12use 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, // reported by parser (not type checker)
23    order: usize,        // display order
24}
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}