litex/parse/
token_block.rs1use 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 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}