Skip to main content

nargo_parser/
base.rs

1pub use nargo_types::{Cursor, Error, ErrorKind, Position, Span};
2use std::collections::HashMap;
3
4pub struct ParseState<'a> {
5    pub cursor: Cursor<'a>,
6}
7
8impl<'a> ParseState<'a> {
9    pub fn new(source: &'a str) -> Self {
10        Self { cursor: Cursor::new(source) }
11    }
12
13    pub fn new_with_pos(source: &'a str, pos: Position) -> Self {
14        Self { cursor: Cursor::with_position(source, pos) }
15    }
16
17    pub fn with_cursor(cursor: Cursor<'a>) -> Self {
18        Self { cursor }
19    }
20
21    /// 获取当前位置的上下文信息
22    pub fn get_context(&self, radius: usize) -> String {
23        let start = if self.cursor.pos > radius { self.cursor.pos - radius } else { 0 };
24        let end = if self.cursor.pos + radius < self.cursor.source.len() { self.cursor.pos + radius } else { self.cursor.source.len() };
25        self.cursor.source[start..end].to_string()
26    }
27
28    /// 生成带有上下文的错误消息
29    pub fn format_error_message(&self, message: &str) -> String {
30        let line = self.cursor.line;
31        let column = self.cursor.column;
32        let context = self.get_context(20);
33        let pointer = " ".repeat(20 - (self.cursor.pos % 20)) + "^";
34
35        format!("Error at line {}, column {}:\n{}\n{}\n{}", line, column, message, context, pointer)
36    }
37
38    pub fn unexpected_char(&self) -> Error {
39        let message = format!("Unexpected character '{}'", self.cursor.peek());
40        let formatted_message = self.format_error_message(&message);
41        Error::new(ErrorKind::UnexpectedChar { character: self.cursor.peek(), span: self.cursor.span_at_current() })
42    }
43
44    pub fn expected_char(&self, expected: char) -> Error {
45        let message = format!("Expected '{}', found '{}'", expected, self.cursor.peek());
46        let formatted_message = self.format_error_message(&message);
47        Error::new(ErrorKind::ExpectedChar { expected, found: self.cursor.peek(), span: self.cursor.span_at_current() })
48    }
49
50    pub fn expected_string(&self, expected: &str) -> Error {
51        let message = format!("Expected '{}', found '{}'", expected, self.cursor.peek());
52        let formatted_message = self.format_error_message(&message);
53        Error::new(ErrorKind::ExpectedString { expected: expected.to_string(), found: self.cursor.peek().to_string(), span: self.cursor.span_at_current() })
54    }
55
56    pub fn error(&self, message: impl Into<String>) -> Error {
57        let message = message.into();
58        let formatted_message = self.format_error_message(&message);
59        Error::new(ErrorKind::Parse { message: formatted_message, span: self.cursor.span_at_current() })
60    }
61
62    /// 期望特定的标记
63    pub fn expected_token(&self, expected: &str) -> Error {
64        let message = format!("Expected '{}' token", expected);
65        let formatted_message = self.format_error_message(&message);
66        Error::new(ErrorKind::Parse { message: formatted_message, span: self.cursor.span_at_current() })
67    }
68
69    /// 语法错误
70    pub fn syntax_error(&self, message: impl Into<String>) -> Error {
71        let message = format!("Syntax error: {}", message.into());
72        let formatted_message = self.format_error_message(&message);
73        Error::new(ErrorKind::Parse { message: formatted_message, span: self.cursor.span_at_current() })
74    }
75
76    /// 类型错误
77    pub fn type_error(&self, message: impl Into<String>) -> Error {
78        let message = format!("Type error: {}", message.into());
79        let formatted_message = self.format_error_message(&message);
80        Error::new(ErrorKind::Parse { message: formatted_message, span: self.cursor.span_at_current() })
81    }
82
83    pub fn parse_tag_attributes(&mut self) -> HashMap<String, String> {
84        let mut attrs = HashMap::new();
85        self.cursor.skip_whitespace();
86        while !self.cursor.is_eof() && self.cursor.peek() != '>' {
87            let start = self.cursor.pos;
88            while !self.cursor.is_eof() && !self.cursor.peek().is_whitespace() && self.cursor.peek() != '=' && self.cursor.peek() != '>' {
89                self.cursor.consume();
90            }
91            let key = self.cursor.current_str(start).to_string();
92            self.cursor.skip_whitespace();
93            if self.cursor.peek() == '=' {
94                self.cursor.consume();
95                self.cursor.skip_whitespace();
96                let quote = self.cursor.peek();
97                if quote == '"' || quote == '\'' {
98                    self.cursor.consume();
99                    let val_start = self.cursor.pos;
100                    while !self.cursor.is_eof() && self.cursor.peek() != quote {
101                        self.cursor.consume();
102                    }
103                    let val = self.cursor.current_str(val_start).to_string();
104                    let _ = self.cursor.consume(); // consume quote
105                    attrs.insert(key, val);
106                }
107                else {
108                    let val_start = self.cursor.pos;
109                    while !self.cursor.is_eof() && !self.cursor.peek().is_whitespace() && self.cursor.peek() != '>' {
110                        self.cursor.consume();
111                    }
112                    let val = self.cursor.current_str(val_start).to_string();
113                    attrs.insert(key, val);
114                }
115            }
116            else {
117                attrs.insert(key, "true".to_string());
118            }
119            self.cursor.skip_whitespace();
120        }
121        attrs
122    }
123}