1#[cfg(feature = "serde")]
2use serde::Serialize;
3
4use crate::Span;
5
6use super::{
7 ArenaVec, Attribute, ClassDecl, Comment, EnumDecl, Expr, FunctionDecl, Ident, InterfaceDecl,
8 Name, TraitDecl,
9};
10
11#[cfg(feature = "serde")]
12fn is_false(b: &bool) -> bool {
13 !b
14}
15
16#[derive(Debug)]
18#[cfg_attr(feature = "serde", derive(Serialize))]
19pub struct Stmt<'arena, 'src> {
20 pub kind: StmtKind<'arena, 'src>,
22 pub span: Span,
24 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
41 pub doc_comment: Option<&'arena Comment<'src>>,
42}
43
44impl<'arena, 'src> Stmt<'arena, 'src> {
45 pub fn leading_doc_comment(&self) -> Option<&Comment<'src>> {
66 if let Some(doc) = self.doc_comment {
67 return Some(doc);
68 }
69 match &self.kind {
70 StmtKind::Function(f) => f.doc_comment.as_ref(),
71 StmtKind::Class(c) => c.doc_comment.as_ref(),
72 StmtKind::Interface(i) => i.doc_comment.as_ref(),
73 StmtKind::Trait(t) => t.doc_comment.as_ref(),
74 StmtKind::Enum(e) => e.doc_comment.as_ref(),
75 StmtKind::Const(items) => items.first().and_then(|i| i.doc_comment.as_ref()),
76 _ => None,
77 }
78 }
79}
80
81#[derive(Debug)]
87#[cfg_attr(feature = "serde", derive(Serialize))]
88#[cfg_attr(feature = "serde", serde(transparent))]
89pub struct Block<'arena, 'src> {
90 pub stmts: ArenaVec<'arena, Stmt<'arena, 'src>>,
92 #[cfg_attr(feature = "serde", serde(skip))]
95 pub span: Span,
96}
97
98#[derive(Debug)]
100#[cfg_attr(feature = "serde", derive(Serialize))]
101#[non_exhaustive]
102pub enum StmtKind<'arena, 'src> {
103 Expression(&'arena Expr<'arena, 'src>),
105
106 Echo(ArenaVec<'arena, Expr<'arena, 'src>>),
108
109 Return(Option<&'arena Expr<'arena, 'src>>),
111
112 Block(&'arena Block<'arena, 'src>),
114
115 If(&'arena IfStmt<'arena, 'src>),
117
118 While(&'arena WhileStmt<'arena, 'src>),
120
121 For(&'arena ForStmt<'arena, 'src>),
123
124 Foreach(&'arena ForeachStmt<'arena, 'src>),
126
127 DoWhile(&'arena DoWhileStmt<'arena, 'src>),
129
130 Function(&'arena FunctionDecl<'arena, 'src>),
132
133 Break(Option<&'arena Expr<'arena, 'src>>),
135
136 Continue(Option<&'arena Expr<'arena, 'src>>),
138
139 Switch(&'arena SwitchStmt<'arena, 'src>),
141
142 Goto(Ident<'src>),
144
145 Label(Ident<'src>),
147
148 Declare(&'arena DeclareStmt<'arena, 'src>),
150
151 Unset(ArenaVec<'arena, Expr<'arena, 'src>>),
153
154 Throw(&'arena Expr<'arena, 'src>),
156
157 TryCatch(&'arena TryCatchStmt<'arena, 'src>),
159
160 Global(ArenaVec<'arena, Expr<'arena, 'src>>),
162
163 Class(&'arena ClassDecl<'arena, 'src>),
165
166 Interface(&'arena InterfaceDecl<'arena, 'src>),
168
169 Trait(&'arena TraitDecl<'arena, 'src>),
171
172 Enum(&'arena EnumDecl<'arena, 'src>),
174
175 Namespace(&'arena NamespaceDecl<'arena, 'src>),
177
178 Use(&'arena UseDecl<'arena, 'src>),
180
181 Const(ArenaVec<'arena, ConstItem<'arena, 'src>>),
183
184 StaticVar(ArenaVec<'arena, StaticVar<'arena, 'src>>),
186
187 HaltCompiler(&'src str),
189
190 Nop,
192
193 InlineHtml(&'src str),
195
196 Error,
198}
199
200#[derive(Debug)]
202#[cfg_attr(feature = "serde", derive(Serialize))]
203pub struct IfStmt<'arena, 'src> {
204 pub condition: Expr<'arena, 'src>,
206 pub then_branch: &'arena Stmt<'arena, 'src>,
208 pub elseif_branches: ArenaVec<'arena, ElseIfBranch<'arena, 'src>>,
210 pub else_branch: Option<&'arena Stmt<'arena, 'src>>,
212 #[cfg_attr(feature = "serde", serde(skip))]
214 pub else_kw_span: Option<Span>,
215 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
217 pub uses_alternative: bool,
218}
219
220#[derive(Debug)]
222#[cfg_attr(feature = "serde", derive(Serialize))]
223pub struct ElseIfBranch<'arena, 'src> {
224 pub condition: Expr<'arena, 'src>,
226 pub body: Stmt<'arena, 'src>,
228 pub span: Span,
230}
231
232#[derive(Debug)]
234#[cfg_attr(feature = "serde", derive(Serialize))]
235pub struct WhileStmt<'arena, 'src> {
236 pub condition: Expr<'arena, 'src>,
238 pub body: &'arena Stmt<'arena, 'src>,
240 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
242 pub uses_alternative: bool,
243}
244
245#[derive(Debug)]
247#[cfg_attr(feature = "serde", derive(Serialize))]
248pub struct ForStmt<'arena, 'src> {
249 pub init: ArenaVec<'arena, Expr<'arena, 'src>>,
251 pub condition: ArenaVec<'arena, Expr<'arena, 'src>>,
253 pub update: ArenaVec<'arena, Expr<'arena, 'src>>,
255 pub body: &'arena Stmt<'arena, 'src>,
257 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
259 pub uses_alternative: bool,
260}
261
262#[derive(Debug)]
264#[cfg_attr(feature = "serde", derive(Serialize))]
265pub struct ForeachStmt<'arena, 'src> {
266 pub expr: Expr<'arena, 'src>,
268 pub key: Option<Expr<'arena, 'src>>,
270 pub value: Expr<'arena, 'src>,
272 pub body: &'arena Stmt<'arena, 'src>,
274 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
276 pub uses_alternative: bool,
277}
278
279#[derive(Debug)]
281#[cfg_attr(feature = "serde", derive(Serialize))]
282pub struct DoWhileStmt<'arena, 'src> {
283 pub body: &'arena Stmt<'arena, 'src>,
285 pub condition: Expr<'arena, 'src>,
287}
288
289#[derive(Debug)]
291#[cfg_attr(feature = "serde", derive(Serialize))]
292pub struct SwitchBody<'arena, 'src> {
293 pub cases: ArenaVec<'arena, SwitchCase<'arena, 'src>>,
295 #[cfg_attr(feature = "serde", serde(skip))]
297 pub span: Span,
298}
299
300#[derive(Debug)]
302#[cfg_attr(feature = "serde", derive(Serialize))]
303pub struct SwitchStmt<'arena, 'src> {
304 pub expr: Expr<'arena, 'src>,
306 #[cfg_attr(feature = "serde", serde(flatten))]
308 pub body: SwitchBody<'arena, 'src>,
309 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
311 pub uses_alternative: bool,
312}
313
314#[derive(Debug)]
316#[cfg_attr(feature = "serde", derive(Serialize))]
317pub struct SwitchCase<'arena, 'src> {
318 pub value: Option<Expr<'arena, 'src>>,
320 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
322 pub span: Span,
324}
325
326#[derive(Debug)]
328#[cfg_attr(feature = "serde", derive(Serialize))]
329pub struct TryCatchStmt<'arena, 'src> {
330 pub body: &'arena Block<'arena, 'src>,
332 pub catches: ArenaVec<'arena, CatchClause<'arena, 'src>>,
334 pub finally: Option<&'arena Block<'arena, 'src>>,
336 #[cfg_attr(feature = "serde", serde(skip))]
338 pub finally_kw_span: Option<Span>,
339}
340
341#[derive(Debug)]
343#[cfg_attr(feature = "serde", derive(Serialize))]
344pub struct CatchClause<'arena, 'src> {
345 pub types: ArenaVec<'arena, Name<'arena, 'src>>,
347 pub var: Option<&'src str>,
349 pub body: &'arena Block<'arena, 'src>,
351 pub span: Span,
353}
354
355#[derive(Debug)]
357#[cfg_attr(feature = "serde", derive(Serialize))]
358pub struct NamespaceDecl<'arena, 'src> {
359 pub name: Option<Name<'arena, 'src>>,
361 pub body: NamespaceBody<'arena, 'src>,
363}
364
365#[derive(Debug)]
367#[cfg_attr(feature = "serde", derive(Serialize))]
368#[non_exhaustive]
369pub enum NamespaceBody<'arena, 'src> {
370 Braced(&'arena Block<'arena, 'src>),
372 Simple,
374}
375
376#[derive(Debug)]
378#[cfg_attr(feature = "serde", derive(Serialize))]
379pub struct DeclareStmt<'arena, 'src> {
380 pub directives: ArenaVec<'arena, (&'src str, Expr<'arena, 'src>)>,
382 pub body: Option<&'arena Stmt<'arena, 'src>>,
384 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
386 pub uses_alternative: bool,
387}
388
389#[derive(Debug)]
391#[cfg_attr(feature = "serde", derive(Serialize))]
392pub struct UseDecl<'arena, 'src> {
393 pub kind: UseKind,
395 pub uses: ArenaVec<'arena, UseItem<'arena, 'src>>,
397}
398
399#[derive(Debug, Clone, Copy, PartialEq, Eq)]
401#[cfg_attr(feature = "serde", derive(Serialize))]
402#[non_exhaustive]
403pub enum UseKind {
404 Normal,
406 Function,
408 Const,
410}
411
412#[derive(Debug)]
414#[cfg_attr(feature = "serde", derive(Serialize))]
415pub struct UseItem<'arena, 'src> {
416 pub name: Name<'arena, 'src>,
418 pub alias: Option<&'src str>,
420 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
422 pub kind: Option<UseKind>,
423 pub span: Span,
425}
426
427#[derive(Debug)]
429#[cfg_attr(feature = "serde", derive(Serialize))]
430pub struct ConstItem<'arena, 'src> {
431 pub name: Ident<'src>,
433 pub value: Expr<'arena, 'src>,
435 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
437 pub span: Span,
439 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
441 pub doc_comment: Option<Comment<'src>>,
442}
443
444#[derive(Debug)]
446#[cfg_attr(feature = "serde", derive(Serialize))]
447pub struct StaticVar<'arena, 'src> {
448 pub name: Ident<'src>,
450 pub default: Option<Expr<'arena, 'src>>,
452 pub span: Span,
454}