Skip to main content

litex/parse/
token_block.rs

1use crate::prelude::*;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub struct TokenBlock {
5    pub header: Vec<String>,
6    pub body: Vec<TokenBlock>,
7    pub line_file: LineFile,
8    pub parse_index: usize,
9}
10
11impl TokenBlock {
12    /// 返回当前 token;若已读完则返回 Error。
13    pub fn current(&self) -> Result<&str, RuntimeError> {
14        self.header
15            .get(self.parse_index)
16            .map(|s| s.as_str())
17            .ok_or_else(|| {
18                RuntimeError::from(ParseRuntimeError(
19                    RuntimeErrorStruct::new_with_msg_and_line_file(
20                        "Unexpected end of tokens".to_string(),
21                        self.line_file.clone(),
22                    ),
23                ))
24            })
25    }
26
27    pub fn skip_token(self: &mut Self, token: &str) -> Result<(), RuntimeError> {
28        if self.current()? == token {
29            self.parse_index += 1;
30            Ok(())
31        } else {
32            Err(RuntimeError::from(ParseRuntimeError(
33                RuntimeErrorStruct::new_with_msg_and_line_file(
34                    format!("Expected token: {}", token),
35                    self.line_file.clone(),
36                ),
37            )))
38        }
39    }
40
41    pub fn advance(&mut self) -> Result<String, RuntimeError> {
42        let t = self.current()?.to_string();
43        self.parse_index += 1;
44        Ok(t)
45    }
46
47    pub fn skip(&mut self) -> Result<(), RuntimeError> {
48        self.current()?;
49        self.parse_index += 1;
50        Ok(())
51    }
52
53    pub fn exceed_end_of_head(&self) -> bool {
54        return self.parse_index >= self.header.len();
55    }
56
57    pub fn skip_token_and_colon_and_exceed_end_of_head(
58        &mut self,
59        token: &str,
60    ) -> Result<(), RuntimeError> {
61        self.skip_token(token)?;
62        self.skip_token(COLON)?;
63        if !self.exceed_end_of_head() {
64            return Err(RuntimeError::from(ParseRuntimeError(
65                RuntimeErrorStruct::new_with_msg_and_line_file(
66                    "Expected token: at head".to_string(),
67                    self.line_file.clone(),
68                ),
69            )));
70        }
71        Ok(())
72    }
73
74    pub fn token_at_index(&self, index: usize) -> Result<&str, RuntimeError> {
75        self.header.get(index).map(|s| s.as_str()).ok_or_else(|| {
76            RuntimeError::from(ParseRuntimeError(
77                RuntimeErrorStruct::new_with_msg_and_line_file(
78                    format!("Expected token: at index {}", index),
79                    self.line_file.clone(),
80                ),
81            ))
82        })
83    }
84
85    pub fn current_token_empty_if_exceed_end_of_head(&self) -> &str {
86        if self.exceed_end_of_head() {
87            return "";
88        }
89        self.header
90            .get(self.parse_index)
91            .map(|s| s.as_str())
92            .unwrap_or("")
93    }
94
95    pub fn current_token_is_equal_to(&self, token: &str) -> bool {
96        self.current_token_empty_if_exceed_end_of_head() == token
97    }
98
99    pub fn token_at_end_of_head(&self) -> &str {
100        self.header
101            .get(self.header.len() - 1)
102            .map(|s| s.as_str())
103            .unwrap_or("")
104    }
105
106    pub fn token_at_add_index(&self, index: usize) -> &str {
107        self.header
108            .get(self.parse_index + index)
109            .map(|s| s.as_str())
110            .unwrap_or("")
111    }
112}
113
114impl TokenBlock {
115    pub fn new(tokens: Vec<String>, body: Vec<TokenBlock>, line_file: LineFile) -> TokenBlock {
116        TokenBlock {
117            header: tokens,
118            body,
119            line_file,
120            parse_index: 0,
121        }
122    }
123}