rusty_basic/
ast.rs

1use std::fmt;
2
3#[derive(Debug, PartialEq, Clone)]
4pub struct Variable {
5    identifier: u8,
6}
7
8impl Variable {
9    pub fn new(identifier: u8) -> Self {
10        debug_assert!(identifier.is_ascii_uppercase());
11        Self { identifier }
12    }
13
14    pub fn identifier(&self) -> u8 {
15        self.identifier
16    }
17}
18
19impl fmt::Display for Variable {
20    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21        write!(f, "{}", self.identifier as char)
22    }
23}
24
25#[derive(Debug, PartialEq, Clone)]
26pub struct NumberLiteral {
27    value: i16,
28}
29
30impl NumberLiteral {
31    pub fn new(value: i16) -> Self {
32        Self { value }
33    }
34
35    pub fn value(&self) -> i16 {
36        self.value
37    }
38}
39
40impl fmt::Display for NumberLiteral {
41    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42        write!(f, "{}", self.value)
43    }
44}
45
46#[derive(Debug, PartialEq, Clone)]
47pub struct StringLiteral {
48    value: Vec<u8>,
49}
50
51impl StringLiteral {
52    pub fn new(value: Vec<u8>) -> Self {
53        Self { value }
54    }
55
56    pub fn value(&self) -> &Vec<u8> {
57        &self.value
58    }
59}
60
61impl fmt::Display for StringLiteral {
62    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63        write!(f, "{}", String::from_utf8_lossy(&self.value))
64    }
65}
66
67#[derive(Debug, PartialEq, Clone)]
68pub enum Factor {
69    Variable(Variable),
70    NumberLiteral(NumberLiteral),
71    Expression(Box<Expression>),
72}
73
74impl fmt::Display for Factor {
75    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76        match self {
77            Factor::Variable(variable) => write!(f, "{}", variable),
78            Factor::NumberLiteral(number_literal) => write!(f, "{}", number_literal),
79            Factor::Expression(expression) => write!(f, "({})", expression),
80        }
81    }
82}
83
84#[derive(Debug, PartialEq, Clone)]
85pub struct Term {
86    factor: Factor,
87    operations: Vec<(MultiplicativeOperator, Factor)>,
88}
89
90impl Term {
91    pub fn new(factor: Factor, next: Vec<(MultiplicativeOperator, Factor)>) -> Self {
92        Self {
93            factor,
94            operations: next,
95        }
96    }
97
98    pub fn factor(&self) -> &Factor {
99        &self.factor
100    }
101
102    pub fn operations(&self) -> &[(MultiplicativeOperator, Factor)] {
103        &self.operations
104    }
105}
106
107impl fmt::Display for Term {
108    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109        write!(f, "{}", self.factor)?;
110
111        for operation in &self.operations {
112            write!(f, " {} {}", operation.0, operation.1)?;
113        }
114
115        Ok(())
116    }
117}
118
119#[derive(Debug, PartialEq, Clone)]
120pub enum MultiplicativeOperator {
121    Multiplication,
122    Division,
123}
124
125impl fmt::Display for MultiplicativeOperator {
126    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
127        match self {
128            MultiplicativeOperator::Multiplication => write!(f, "*"),
129            MultiplicativeOperator::Division => write!(f, "/"),
130        }
131    }
132}
133
134#[derive(Debug, PartialEq, Clone)]
135pub struct Expression {
136    unary_operator: Option<AdditiveOperator>,
137    term: Term,
138    others: Vec<(AdditiveOperator, Term)>,
139}
140
141impl Expression {
142    pub fn new(
143        unary_operator: Option<AdditiveOperator>,
144        term: Term,
145        others: Vec<(AdditiveOperator, Term)>,
146    ) -> Self {
147        Self {
148            unary_operator,
149            term,
150            others,
151        }
152    }
153
154    pub fn unary_operator(&self) -> &Option<AdditiveOperator> {
155        &self.unary_operator
156    }
157
158    pub fn term(&self) -> &Term {
159        &self.term
160    }
161
162    pub fn others(&self) -> &[(AdditiveOperator, Term)] {
163        &self.others
164    }
165}
166
167impl fmt::Display for Expression {
168    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
169        if let Some(operator) = &self.unary_operator {
170            write!(f, "{}", operator)?;
171        }
172
173        write!(f, "{}", self.term)?;
174
175        for (operator, term) in &self.others {
176            write!(f, " {} {}", operator, term)?;
177        }
178
179        Ok(())
180    }
181}
182
183#[derive(Debug, PartialEq, Clone)]
184pub enum AdditiveOperator {
185    Addition,
186    Subtraction,
187}
188
189impl fmt::Display for AdditiveOperator {
190    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
191        match self {
192            AdditiveOperator::Addition => write!(f, "+"),
193            AdditiveOperator::Subtraction => write!(f, "-"),
194        }
195    }
196}
197
198#[derive(Debug, PartialEq, Clone)]
199pub enum ExpressionListElement {
200    StringLiteral(StringLiteral),
201    Expression(Expression),
202}
203
204impl fmt::Display for ExpressionListElement {
205    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
206        match self {
207            ExpressionListElement::StringLiteral(string_literal) => write!(f, "{}", string_literal),
208            ExpressionListElement::Expression(expression) => write!(f, "{}", expression),
209        }
210    }
211}
212
213#[derive(Debug, PartialEq, Clone)]
214pub enum Statement {
215    Print {
216        expression_list: Vec<ExpressionListElement>,
217    },
218    If {
219        left: Expression,
220        operator: RelationalOperator,
221        right: Expression,
222        then: Box<Statement>,
223    },
224    Goto {
225        expression: Expression,
226    },
227    Input {
228        variable_list: Vec<Variable>,
229    },
230    Let {
231        variable: Variable,
232        expression: Expression,
233    },
234    GoSub {
235        expression: Expression,
236    },
237    Return,
238    Clear,
239    List,
240    Run,
241    End,
242}
243
244impl fmt::Display for Statement {
245    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
246        match self {
247            Statement::Print { expression_list } => {
248                write!(f, "PRINT ")?;
249
250                for (i, element) in expression_list.iter().enumerate() {
251                    if i > 0 {
252                        write!(f, ", ")?;
253                    }
254
255                    write!(f, "{}", element)?;
256                }
257
258                Ok(())
259            }
260            Statement::If {
261                left,
262                operator,
263                right,
264                then,
265            } => write!(f, "IF {} {} {} THEN {}", left, operator, right, then),
266            Statement::Goto { expression } => write!(f, "GOTO {}", expression),
267            Statement::Input { variable_list } => {
268                write!(f, "INPUT ")?;
269
270                for (i, variable) in variable_list.iter().enumerate() {
271                    if i > 0 {
272                        write!(f, ", ")?;
273                    }
274
275                    write!(f, "{}", variable)?;
276                }
277
278                Ok(())
279            }
280            Statement::Let {
281                variable,
282                expression,
283            } => write!(f, "LET {} = {}", variable, expression),
284            Statement::GoSub { expression } => write!(f, "GOSUB {}", expression),
285            Statement::Return => write!(f, "RETURN"),
286            Statement::Clear => write!(f, "CLEAR"),
287            Statement::List => write!(f, "LIST"),
288            Statement::Run => write!(f, "RUN"),
289            Statement::End => write!(f, "END"),
290        }
291    }
292}
293
294#[derive(Debug, PartialEq, Clone)]
295pub enum RelationalOperator {
296    Equal,
297    NotEqual,
298    LessThan,
299    LessThanOrEqual,
300    GreaterThan,
301    GreaterThanOrEqual,
302}
303
304impl fmt::Display for RelationalOperator {
305    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
306        match self {
307            RelationalOperator::Equal => write!(f, "="),
308            RelationalOperator::NotEqual => write!(f, "<>"),
309            RelationalOperator::LessThan => write!(f, "<"),
310            RelationalOperator::LessThanOrEqual => write!(f, "<="),
311            RelationalOperator::GreaterThan => write!(f, ">"),
312            RelationalOperator::GreaterThanOrEqual => write!(f, ">="),
313        }
314    }
315}
316
317#[derive(Debug, PartialEq, Clone)]
318pub struct Line {
319    number: Option<u8>,
320    statement: Statement,
321}
322
323impl Line {
324    pub fn new(number: Option<u8>, statement: Statement) -> Self {
325        Self { number, statement }
326    }
327
328    pub fn number(&self) -> Option<u8> {
329        self.number
330    }
331
332    pub fn statement(&self) -> &Statement {
333        &self.statement
334    }
335}
336
337impl fmt::Display for Line {
338    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
339        if let Some(number) = self.number {
340            write!(f, "{} ", number)?;
341        }
342
343        write!(f, "{}", self.statement)
344    }
345}