1use crate::complex_pu;
2
3use super::*;
4
5use py_lex::syntax::Symbol;
6
7#[derive(Debug, Clone)]
8pub struct VarAssign {
9 pub val: Expr,
10}
11
12impl ParseUnit<Token> for VarAssign {
13 type Target = VarAssign;
14
15 fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
16 p.r#match(Symbol::Assign)?;
17 let val = p.parse::<Expr>()?;
18 Ok(Self { val })
19 }
20}
21
22#[derive(Debug, Clone)]
23pub struct VarDefine {
24 pub ty: PU<types::TypeDefine>,
25 pub name: Ident,
26 pub init: Option<VarAssign>,
27}
28
29impl ParseUnit<Token> for VarDefine {
30 type Target = VarDefine;
31
32 fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
33 let ty = p.parse::<PU<types::TypeDefine>>()?;
34 let name = p.parse::<Ident>()?;
35 let init = p.parse::<VarAssign>().apply(mapper::Try)?;
36 Ok(Self { ty, name, init })
37 }
38}
39
40#[derive(Debug, Clone)]
41pub struct VarStore {
42 pub name: Ident,
43 pub assign: PU<VarAssign>,
44}
45
46impl ParseUnit<Token> for VarStore {
47 type Target = VarStore;
48
49 fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
50 let name = p.parse::<Ident>()?;
51 let assign = p.parse::<PU<VarAssign>>()?;
52 Ok(VarStore { name, assign })
53 }
54}
55
56#[derive(Debug, Clone)]
57pub struct Parameter {
58 inner: VarDefine,
60}
61
62impl std::ops::Deref for Parameter {
63 type Target = VarDefine;
64
65 fn deref(&self) -> &Self::Target {
66 &self.inner
67 }
68}
69
70impl ParseUnit<Token> for Parameter {
71 type Target = Parameter;
72
73 fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
74 let ty = p.parse::<PU<types::TypeDefine>>()?;
75 let name = p.parse::<Ident>()?;
76 let inner = VarDefine {
77 ty,
78 name,
79 init: None,
80 };
81 Ok(Parameter { inner })
82 }
83}
84
85#[derive(Debug, Clone)]
86pub struct Parameters {
87 pub params: Vec<PU<Parameter>>,
88}
89
90impl std::ops::Deref for Parameters {
91 type Target = Vec<PU<Parameter>>;
92
93 fn deref(&self) -> &Self::Target {
94 &self.params
95 }
96}
97
98impl ParseUnit<Token> for Parameters {
99 type Target = Parameters;
100
101 fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
102 p.r#match(Symbol::Parameter)?;
103 let Some(arg) = p.parse::<PU<Parameter>>().apply(mapper::Try)? else {
104 p.r#match(Symbol::EndOfBlock).apply(mapper::MustMatch)?;
105
106 return Ok(Parameters { params: vec![] });
107 };
108
109 let mut params = vec![arg];
110
111 while p.r#match(Symbol::Semicolon).is_ok() {
112 params.push(p.parse::<PU<Parameter>>()?);
113 }
114
115 p.r#match(Symbol::EndOfBlock).apply(mapper::MustMatch)?;
116 Ok(Parameters { params })
117 }
118}
119
120macro_rules! statement_wrapper {
122 (
123 $(
124 $(#[$metas:meta])*
125 $from:ident => $into:ident,
126 )*
127 ) => {
128 $(
129 #[derive(Debug, Clone)]
130 $(#[$metas])*
131 pub struct $into(py_lex::PU<$from>);
132
133 impl terl::ParseUnit<py_lex::Token> for $into {
134 type Target = $into;
135
136 fn parse(p: &mut terl::Parser<py_lex::Token>) -> terl::ParseResult<Self, py_lex::Token> {
137
138 let inner = p.parse::<py_lex::PU<$from>>()?;
139 p.r#match(py_lex::syntax::Symbol::Semicolon).apply(terl::mapper::MustMatch)?;
140 Ok($into(inner))
141 }
142 }
143
144 impl std::ops::Deref for $into {
145 type Target = py_lex::PU<$from>;
146
147 fn deref(&self) -> &Self::Target {
148 &self.0
149 }
150 }
151
152 impl std::ops::DerefMut for $into {
153 fn deref_mut(&mut self) -> &mut Self::Target {
154 &mut self.0
155 }
156 }
157
158 )*
159 };
160}
161
162statement_wrapper! {
163 VarDefine => VarDefineStmt,
164 FnCall => FnCallStmt,
165 VarStore => VarStoreStmt,
166}
167
168macro_rules! statements {
170 (
171 $(#[$metas:meta])*
172 stmt $enum_name:ident {
173 $(
174 $(#[$v_metas:meta])*
175 $variant:ident
176 ),*
177 }) => {
178 #[derive(Debug, Clone)]
179 $(#[$metas])*
180 pub enum $enum_name {
181 $(
182 $(#[$v_metas])*
183 $variant(Box<$variant>),
184 )*
185 }
186
187 $(
188 impl From<$variant> for $enum_name {
189 fn from(v: $variant) -> $enum_name {
190 <$enum_name>::$variant(Box::new(v))
191 }
192 }
193 )*
194
195 impl terl::ParseUnit<py_lex::Token> for $enum_name {
196 type Target = $enum_name;
197
198 fn parse(p: &mut terl::Parser<py_lex::Token>) -> terl::ParseResult<Self, py_lex::Token>
199 {
200 terl::Try::<$enum_name ,_>::new(p)
201 $(
202 .or_try::<Self, _>(|p| {
203 p.once_no_try::<$variant ,_>($variant::parse)
204 .map(Box::new).map(<$enum_name>::$variant)
205 })
206 )*
207 .finish()
208 }
209 }
210 };
211}
212
213statements! {
214 stmt Statement {
215
216 FnCallStmt,
218 VarStoreStmt,
220
221 VarDefineStmt,
223 If,
224 While,
225 Return,
226 Comment,
227 CodeBlock
228 }
229}
230
231complex_pu! {
232 cpu Item {
233 FnDefine,
235 Comment
236 }
237}
238
239#[cfg(test)]
240mod tests {
241 use crate::parse_test;
242
243 use super::*;
244
245 #[test]
246 fn variable_define() {
247 parse_test("kuan1 32 zheng3 a", |p| {
248 p.parse::<VarDefine>()?;
249 Ok(())
250 })
251 }
252
253 #[test]
254 fn variable_define_init() {
255 let src = "kuan1 32 zheng3 a wei2 114514 fen1";
256 parse_test(src, |p| {
257 p.parse::<VarDefine>()?;
258 Ok(())
259 });
260 parse_test(src, |p| {
261 p.parse::<Statement>()?;
262 Ok(())
263 });
264 }
265
266 #[test]
267 fn variable_reassign() {
268 parse_test("a wei2 114514 fen1", |p| {
269 p.parse::<Statement>()?;
270 Ok(())
271 });
272 parse_test("a wei2 114514 fen1", |p| {
273 p.parse::<VarStore>()?;
274 Ok(())
275 });
276 }
277}