satellite_format/
parser.rs1use std::iter::Peekable;
2use std::str::Chars;
3
4#[derive(Debug, PartialEq, Clone)]
5pub enum Token {
6 Var(String), Int(i64),
8 Ident(String), Symbol(char), LParen,
11 RParen,
12 EOF,
13}
14
15pub struct Tokenizer<'a> {
16 input: Peekable<Chars<'a>>,
17}
18
19impl<'a> Tokenizer<'a> {
20 pub fn new(input: &'a str) -> Self {
21 Self {
22 input: input.chars().peekable(),
23 }
24 }
25
26 pub fn next_token(&mut self) -> Result<Token, String> {
27 self.skip_whitespace();
28
29 match self.input.peek() {
30 None => Ok(Token::EOF),
31 Some(&c) => match c {
32 '(' => { self.input.next(); Ok(Token::LParen) }
33 ')' => { self.input.next(); Ok(Token::RParen) }
34 '+' | '-' | '*' | '/' | '^' | '!' | '&' | '|' => {
35 self.input.next();
38 Ok(Token::Symbol(c))
39 }
40 '%' => self.parse_var(),
41 '0'..='9' => self.parse_int(),
42 'a'..='z' | 'A'..='Z' | '_' => self.parse_ident(),
43 _ => Err(format!("Unexpected character: {}", c)),
44 }
45 }
46 }
47
48 fn skip_whitespace(&mut self) {
49 while let Some(&c) = self.input.peek() {
50 if c.is_whitespace() {
51 self.input.next();
52 } else {
53 break;
54 }
55 }
56 }
57
58 fn parse_var(&mut self) -> Result<Token, String> {
59 let mut s = String::new();
60 s.push(self.input.next().unwrap());
62
63 if let Some(&c) = self.input.peek() {
65 if c == '^' || c == '*' {
66 s.push(self.input.next().unwrap());
67 }
68 }
69
70 while let Some(&c) = self.input.peek() {
71 if c.is_alphanumeric() || c == '_' {
72 s.push(self.input.next().unwrap());
73 } else {
74 break;
75 }
76 }
77 Ok(Token::Var(s))
78 }
79
80 fn parse_int(&mut self) -> Result<Token, String> {
81 let mut s = String::new();
82 while let Some(&c) = self.input.peek() {
83 if c.is_digit(10) {
84 s.push(self.input.next().unwrap());
85 } else {
86 break;
87 }
88 }
89 let val = s.parse::<i64>().map_err(|_| "Invalid integer".to_string())?;
90 Ok(Token::Int(val))
91 }
92
93 fn parse_ident(&mut self) -> Result<Token, String> {
94 let mut s = String::new();
95 while let Some(&c) = self.input.peek() {
96 if c.is_alphanumeric() || c == '_' {
97 s.push(self.input.next().unwrap());
98 } else {
99 break;
100 }
101 }
102 Ok(Token::Ident(s))
103 }
104}
105
106#[derive(Debug, Clone)]
108pub enum Expr {
109 Var(String),
110 Lit(i64),
111 BinaryOp { op: String, left: Box<Expr>, right: Box<Expr> },
112 UnaryOp { op: String, expr: Box<Expr> },
113 Call { name: String, args: Vec<Expr> },
114}
115
116pub struct Parser<'a> {
117 tokenizer: Tokenizer<'a>,
118 current_token: Token,
119}
120
121impl<'a> Parser<'a> {
122 pub fn new(input: &'a str) -> Self {
123 let mut tokenizer = Tokenizer::new(input);
124 let current_token = tokenizer.next_token().unwrap_or(Token::EOF);
125 Self { tokenizer, current_token }
126 }
127
128 fn advance(&mut self) {
129 self.current_token = self.tokenizer.next_token().unwrap_or(Token::EOF);
130 }
131
132 pub fn parse(&mut self) -> Result<Expr, String> {
133 self.parse_expr()
134 }
135
136 fn parse_expr(&mut self) -> Result<Expr, String> {
137 self.parse_or()
138 }
139
140 fn parse_or(&mut self) -> Result<Expr, String> {
141 let mut left = self.parse_and()?;
142
143 while let Token::Ident(ref op) = self.current_token {
144 if op == "OR" || op == "or" {
145 let op_str = op.clone();
146 self.advance();
147 let right = self.parse_and()?;
148 left = Expr::BinaryOp { op: op_str, left: Box::new(left), right: Box::new(right) };
149 } else {
150 break;
151 }
152 }
153 if let Token::Symbol('|') = self.current_token {
155 self.advance();
157 if let Token::Symbol('|') = self.current_token {
158 self.advance();
159 let right = self.parse_and()?;
160 left = Expr::BinaryOp { op: "OR".to_string(), left: Box::new(left), right: Box::new(right) };
161 }
162 }
163
164 Ok(left)
165 }
166
167 fn parse_and(&mut self) -> Result<Expr, String> {
168 let mut left = self.parse_equality()?;
169
170 while let Token::Ident(ref op) = self.current_token {
171 if op == "AND" || op == "and" {
172 let op_str = op.clone();
173 self.advance();
174 let right = self.parse_equality()?;
175 left = Expr::BinaryOp { op: op_str, left: Box::new(left), right: Box::new(right) };
176 } else {
177 break;
178 }
179 }
180 if let Token::Symbol('&') = self.current_token {
182 self.advance();
183 if let Token::Symbol('&') = self.current_token {
184 self.advance();
185 let right = self.parse_equality()?;
186 left = Expr::BinaryOp { op: "AND".to_string(), left: Box::new(left), right: Box::new(right) };
187 }
188 }
189
190 Ok(left)
191 }
192
193 fn parse_equality(&mut self) -> Result<Expr, String> {
194 let mut left = self.parse_additive()?;
195
196 loop {
197 let op = match &self.current_token {
198 Token::Ident(s) if s == "eq" || s == "neq" => Some(s.clone()),
199 Token::Symbol('=') => {
200 Some("eq".to_string())
203 },
204 _ => None
205 };
206
207 if let Some(op_str) = op {
208 self.advance();
209 if op_str == "eq" {
211 if let Token::Symbol('=') = self.current_token { self.advance(); }
212 }
213
214 let right = self.parse_additive()?;
215 left = Expr::BinaryOp { op: op_str, left: Box::new(left), right: Box::new(right) };
216 } else {
217 break;
218 }
219 }
220 Ok(left)
221 }
222
223 fn parse_additive(&mut self) -> Result<Expr, String> {
224 let mut left = self.parse_primary()?;
225
226 loop {
227 let op = match &self.current_token {
228 Token::Symbol('+') => Some("+"),
229 Token::Symbol('-') => Some("-"),
230 _ => None,
231 };
232
233 if let Some(o) = op {
234 let op_str = o.to_string();
235 self.advance();
236 let right = self.parse_primary()?;
237 left = Expr::BinaryOp { op: op_str, left: Box::new(left), right: Box::new(right) };
238 } else {
239 break;
240 }
241 }
242 Ok(left)
243 }
244
245 fn parse_primary(&mut self) -> Result<Expr, String> {
246 match self.current_token.clone() {
247 Token::Var(s) => {
248 self.advance();
249 Ok(Expr::Var(s))
250 }
251 Token::Int(i) => {
252 self.advance();
253 Ok(Expr::Lit(i))
254 }
255 Token::LParen => {
256 self.advance();
257 let expr = self.parse_expr()?;
258 if let Token::RParen = self.current_token {
259 self.advance();
260 Ok(expr)
261 } else {
262 Err("Expected ')'".to_string())
263 }
264 }
265 Token::Ident(s) => {
266 if s == "NOT" || s == "not" {
268 self.advance();
269 let expr = self.parse_primary()?;
270 Ok(Expr::UnaryOp { op: "NOT".to_string(), expr: Box::new(expr) })
271 } else {
272 self.advance();
273 if let Token::LParen = self.current_token {
275 self.advance();
276 let mut args = Vec::new();
277 if let Token::RParen = self.current_token {
278 self.advance();
279 } else {
280 loop {
281 args.push(self.parse_expr()?);
282 if let Token::Symbol(',') = self.current_token {
283 self.advance();
284 } else {
285 break;
286 }
287 }
288 if let Token::RParen = self.current_token {
289 self.advance();
290 } else {
291 return Err("Expected ')'".to_string());
292 }
293 }
294 Ok(Expr::Call { name: s, args })
295 } else {
296 if s == "True" || s == "true" { Ok(Expr::Lit(1)) }
298 else if s == "False" || s == "false" { Ok(Expr::Lit(0)) }
299 else { Err(format!("Unknown identifier: {}", s)) }
300 }
301 }
302 }
303 Token::Symbol('-') | Token::Symbol('!') => {
304 let op = if let Token::Symbol('-') = self.current_token { "-" } else { "!" };
305 self.advance();
306 let expr = self.parse_primary()?;
307 Ok(Expr::UnaryOp { op: op.to_string(), expr: Box::new(expr) })
308 }
309 _ => Err(format!("Unexpected token: {:?}", self.current_token)),
310 }
311 }
312}