satellite_format/
parser.rs

1use std::iter::Peekable;
2use std::str::Chars;
3
4#[derive(Debug, PartialEq, Clone)]
5pub enum Token {
6    Var(String), // %name or %^name or %*name
7    Int(i64),
8    Ident(String), // AND, OR, eq, etc.
9    Symbol(char), // +, -, *, /, etc.
10    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                     // Check for multi-char ops like &&, ||, == could be handled here
36                     // For now simple single char symbols
37                     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        // Consume '%'
61        s.push(self.input.next().unwrap());
62        
63        // Check for Prefix '^' or '*'
64        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// AST
107#[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        // Handle || symbol if we add it
154        if let Token::Symbol('|') = self.current_token {
155             // Expect another |
156             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        // Handle && symbol
181        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                    // Check for ==
201                    // For now just assume = is equality or consume next =
202                    Some("eq".to_string())
203                },
204                _ => None
205            };
206
207            if let Some(op_str) = op {
208                self.advance();
209                // Consume second = if present
210                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                // Could be function call or NOT
267                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                    // Check for call
274                    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                        // Just an ident, maybe a boolean constant?
297                        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}