1use crate::expr::Expr;
2use crate::tokens::{Token, TokenType};
3use crate::visitor::StmtVisitor;
4
5#[derive(Clone)]
6pub(crate) struct Stmt {
7 content: StmtContent,
8 pub(crate) line: usize,
9}
10
11#[derive(Clone)]
12enum StmtContent {
13 Expression(ExpressionStmt),
14 Print(PrintStmt),
15 Input(InputStmt),
16 Assign(AssignStmt),
17 If(IfStmt),
18 While(WhileStmt),
19 For(ForStmt),
20 Return(ReturnStmt),
21 BinaryAssign(BinaryAssignStmt),
22}
23
24impl Stmt {
25 pub fn new_print(values: Vec<Expr>, line: usize) -> Self {
26 Self {
27 line,
28 content: StmtContent::Print(PrintStmt { values }),
29 }
30 }
31
32 pub fn new_input(variable: Token) -> Self {
33 Self {
34 line: variable.line,
35 content: StmtContent::Input(InputStmt { variable }),
36 }
37 }
38
39 pub fn new_expression(value: Expr, line: usize) -> Self {
40 Self {
41 line,
42 content: StmtContent::Expression(ExpressionStmt { value }),
43 }
44 }
45
46 pub fn new_assign(name: Token, value: Expr, line: usize) -> Self {
47 Self {
48 line,
49 content: StmtContent::Assign(AssignStmt { name, value }),
50 }
51 }
52
53 pub fn new_if(
54 condition: Expr,
55 then_stmts: Vec<Stmt>,
56 else_stmts: Vec<Stmt>,
57 line: usize,
58 ) -> Self {
59 Self {
60 line,
61 content: StmtContent::If(IfStmt {
62 condition,
63 then_stmts,
64 else_stmts,
65 }),
66 }
67 }
68
69 pub fn new_for(
70 variable: Token,
71 min_value: Expr,
72 max_value: Expr,
73 body: Vec<Stmt>,
74 line: usize,
75 ) -> Self {
76 Self {
77 line,
78 content: StmtContent::For(ForStmt {
79 variable,
80 min_value,
81 max_value,
82 body,
83 }),
84 }
85 }
86
87 pub fn new_while(condition: Expr, body: Vec<Stmt>, line: usize) -> Self {
88 Self {
89 line,
90 content: StmtContent::While(WhileStmt { condition, body }),
91 }
92 }
93
94 pub fn new_return(return_value: Expr, line: usize) -> Self {
95 Self {
96 line,
97 content: StmtContent::Return(ReturnStmt { return_value }),
98 }
99 }
100
101 pub fn new_binary_assign(name: Token, operator: TokenType, value: Expr, line: usize) -> Self {
102 Self {
103 line,
104 content: StmtContent::BinaryAssign(BinaryAssignStmt {
105 name,
106 operator,
107 value,
108 }),
109 }
110 }
111
112 pub(crate) fn accept<U, V>(&self, visitor: &mut V) -> U
113 where
114 V: StmtVisitor<U>,
115 {
116 let line = self.line;
117 match &self.content {
118 StmtContent::Assign(stmt) => visitor.visit_assign_stmt(stmt, line),
119 StmtContent::Expression(stmt) => visitor.visit_expression_stmt(stmt, line),
120 StmtContent::Print(stmt) => visitor.visit_print_stmt(stmt, line),
121 StmtContent::Input(stmt) => visitor.visit_input_stmt(stmt, line),
122 StmtContent::If(stmt) => visitor.visit_if_stmt(stmt, line),
123 StmtContent::While(stmt) => visitor.visit_while_stmt(stmt, line),
124 StmtContent::For(stmt) => visitor.visit_for_stmt(stmt, line),
125 StmtContent::Return(stmt) => visitor.visit_return_stmt(stmt, line),
126 StmtContent::BinaryAssign(stmt) => visitor.visit_binary_assign_stmt(stmt, line),
127 }
128 }
129}
130
131#[derive(Clone)]
132pub(crate) struct PrintStmt {
133 pub values: Vec<Expr>,
134}
135
136#[derive(Clone)]
137pub(crate) struct InputStmt {
138 pub variable: Token,
139}
140
141#[derive(Clone)]
142pub(crate) struct ExpressionStmt {
143 pub value: Expr,
144}
145
146#[derive(Clone)]
147pub(crate) struct AssignStmt {
148 pub name: Token,
149 pub value: Expr,
150}
151
152#[derive(Clone)]
153pub(crate) struct IfStmt {
154 pub condition: Expr,
155 pub then_stmts: Vec<Stmt>,
156 pub else_stmts: Vec<Stmt>,
157}
158
159#[derive(Clone)]
160pub(crate) struct WhileStmt {
161 pub condition: Expr,
162 pub body: Vec<Stmt>,
163}
164
165#[derive(Clone)]
166pub(crate) struct ForStmt {
167 pub variable: Token,
168 pub min_value: Expr,
169 pub max_value: Expr,
170 pub body: Vec<Stmt>,
171}
172
173#[derive(Clone)]
174pub(crate) struct ReturnStmt {
175 pub return_value: Expr,
176}
177
178#[derive(Clone)]
179pub(crate) struct BinaryAssignStmt {
180 pub name: Token,
181 pub operator: TokenType,
182 pub value: Expr,
183}