1//! enums and structures that store the syntax tree outputed by the parser.
2
3use std::fmt;
4
5#[cfg(feature = "bigint")]
6use num_bigint::BigUint;
7
8#[cfg(feature = "wtf8")]
9use wtf8;
10
11#[cfg(feature = "bigint")]
12pub type IntegerType = BigUint;
13#[cfg(not(feature = "bigint"))]
14pub type IntegerType = u64;
15
16#[cfg(feature = "wtf8")]
17pub type PyStringContent = wtf8::Wtf8Buf;
18#[cfg(feature = "wtf8")]
19pub type PyStringCodePoint = wtf8::CodePoint;
20
21#[cfg(not(feature = "wtf8"))]
22pub type PyStringContent = String;
23#[cfg(not(feature = "wtf8"))]
24pub type PyStringCodePoint = char;
25
26pub type Name = String;
27
28/// Represents whether a function signature has `*`, `*args`, or none of these.
29#[derive(Clone, Debug, PartialEq, Eq, Hash)]
30pub enum StarParams<T> {
31 /// No single star
32 No,
33 /// `*` alone, with no name
34 Anonymous,
35 /// *args` or `*args:type`
36 Named(T),
37}
38
39impl<T> Default for StarParams<T> {
40 fn default() -> StarParams<T> {
41 StarParams::No
42 }
43}
44
45/// The list of parameters of a function definition.
46#[derive(Clone, Debug, PartialEq, Default)]
47pub struct TypedArgsList {
48 pub posonly_args: Vec<(Name, Option<Expression>, Option<Expression>)>,
49 pub args: Vec<(Name, Option<Expression>, Option<Expression>)>,
50 pub star_args: StarParams<(Name, Option<Expression>)>,
51 pub keyword_args: Vec<(Name, Option<Expression>, Option<Expression>)>,
52 pub star_kwargs: Option<(Name, Option<Expression>)>,
53}
54
55/// The list of parameters of a lambda definition.
56#[derive(Clone, Debug, PartialEq, Default)]
57pub struct UntypedArgsList {
58 pub posonly_args: Vec<(Name, Option<Expression>)>,
59 pub args: Vec<(Name, Option<Expression>)>,
60 pub star_args: StarParams<Name>,
61 pub keyword_args: Vec<(Name, Option<Expression>)>,
62 pub star_kwargs: Option<Name>,
63}
64
65/// A function or class decorator.
66#[derive(Clone, Debug, PartialEq)]
67pub struct Decorator {
68 pub name: Vec<Name>,
69 pub args: Option<Vec<Argument>>,
70}
71
72/// An argument to a function call
73#[derive(Clone, Debug, PartialEq)]
74pub enum Argument {
75 Positional(Expression),
76 Starargs(Expression),
77 Keyword(Name, Expression),
78 Kwargs(Expression),
79}
80
81/// The `foo[bar]` syntax.
82#[derive(Clone, Debug, PartialEq)]
83pub enum Subscript {
84 /// `foo[i]`
85 Simple(Expression),
86 /// `foo[start:end]`, `foo[start:]`, etc.
87 Double(Option<Expression>, Option<Expression>),
88 /// `foo[start:end:step]`, `foo[start::]`, etc.
89 Triple(Option<Expression>, Option<Expression>, Option<Expression>),
90}
91
92/// Unary operators.
93#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
94pub enum Uop {
95 Plus,
96 Minus,
97 /// `~`
98 Invert,
99 Not,
100}
101
102impl fmt::Display for Uop {
103 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
104 write!(
105 f,
106 "{}",
107 match *self {
108 Uop::Plus => "+",
109 Uop::Minus => "-",
110 Uop::Invert => "~",
111 Uop::Not => "not ",
112 }
113 )
114 }
115}
116
117/// Binary operators.
118#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
119pub enum Bop {
120 Add,
121 Sub,
122 Mult,
123 Matmult,
124 Mod,
125 Floordiv,
126 Div,
127 Power,
128 Lshift,
129 Rshift,
130 BitAnd,
131 BitXor,
132 BitOr,
133 /// lower than
134 Lt,
135 /// greater than
136 Gt,
137 Eq,
138 /// lower or equal
139 Leq,
140 /// greater or equal
141 Geq,
142 Neq,
143 In,
144 NotIn,
145 Is,
146 IsNot,
147 And,
148 Or,
149}
150
151impl fmt::Display for Bop {
152 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
153 write!(
154 f,
155 "{}",
156 match *self {
157 Bop::Add => "+",
158 Bop::Sub => "-",
159 Bop::Mult => "*",
160 Bop::Matmult => "@",
161 Bop::Mod => "%",
162 Bop::Floordiv => "//",
163 Bop::Div => "/",
164 Bop::Power => "**",
165 Bop::Lshift => "<<",
166 Bop::Rshift => ">>",
167 Bop::BitAnd => "&",
168 Bop::BitXor => "^",
169 Bop::BitOr => "|",
170 Bop::Lt => "<",
171 Bop::Gt => ">",
172 Bop::Eq => "==",
173 Bop::Leq => "<=",
174 Bop::Geq => ">=",
175 Bop::Neq => "!=",
176 Bop::In => " in ",
177 Bop::NotIn => " not in ",
178 Bop::Is => " is ",
179 Bop::IsNot => " is not ",
180 Bop::And => " and ",
181 Bop::Or => " or ",
182 }
183 )
184 }
185}
186
187/// One of the `if` or `for` clause(s) of a comprehension list/dict/set or
188/// generator expression.
189#[derive(Clone, Debug, PartialEq)]
190pub enum ComprehensionChunk {
191 If {
192 cond: Expression,
193 },
194 For {
195 async: bool,
196 item: Vec<Expression>,
197 iterator: Expression,
198 },
199}
200
201/// `**foo` or `foo:bar`, as in a dict comprehension.
202#[derive(Clone, Debug, PartialEq)]
203pub enum DictItem {
204 Star(Expression),
205 Unique(Expression, Expression),
206}
207
208/// `*foo` or `foo`, as in a list/set comprehension or a generator expression.
209#[derive(Clone, Debug, PartialEq)]
210pub enum SetItem {
211 Star(Expression),
212 Unique(Expression),
213}
214
215/// A Python string. See the doc of the crate for the boring speech about
216/// encoding stuff.
217#[derive(Clone, Debug, PartialEq, Eq)]
218pub struct PyString {
219 pub prefix: String,
220 pub content: PyStringContent,
221}
222
223/// The big thing: a Python expression.
224#[derive(Clone, Debug, PartialEq)]
225pub enum Expression {
226 Ellipsis,
227 None,
228 True,
229 False,
230 Name(Name),
231 Int(IntegerType),
232 ImaginaryInt(IntegerType),
233 Float(f64),
234 ImaginaryFloat(f64),
235 String(Vec<PyString>),
236 Bytes(Vec<u8>),
237 DictLiteral(Vec<DictItem>),
238 SetLiteral(Vec<SetItem>),
239 ListLiteral(Vec<SetItem>),
240 TupleLiteral(Vec<SetItem>),
241 DictComp(Box<DictItem>, Vec<ComprehensionChunk>),
242 SetComp(Box<SetItem>, Vec<ComprehensionChunk>),
243 ListComp(Box<SetItem>, Vec<ComprehensionChunk>),
244 Generator(Box<SetItem>, Vec<ComprehensionChunk>),
245 Await(Box<Expression>),
246
247 Call(Box<Expression>, Vec<Argument>),
248 Subscript(Box<Expression>, Vec<Subscript>),
249 /// `foo.bar`
250 Attribute(Box<Expression>, Name),
251 /// Unary operator
252 Uop(Uop, Box<Expression>),
253 /// Binary operator. A simplified version of `MultiBop`, when the
254 /// expressivity of MultiBop is not needed.
255 Bop(Bop, Box<Expression>, Box<Expression>),
256 /// Binary operator... but may be applied on more than one expr
257 /// (eg. `a <= b < c`)
258 MultiBop(Box<Expression>, Vec<(Bop, Expression)>),
259 /// 1 if 2 else 3
260 Ternary(Box<Expression>, Box<Expression>, Box<Expression>),
261 Yield(Vec<Expression>),
262 YieldFrom(Box<Expression>),
263 Star(Box<Expression>),
264 Lambdef(UntypedArgsList, Box<Expression>),
265 /// Walrus operator: 1 := 2
266 Named(Box<Expression>, Box<Expression>),
267}
268
269/// An import statement.
270#[derive(Clone, Debug, PartialEq, Eq, Hash)]
271pub enum Import {
272 /// `from x import y`
273 ImportFrom {
274 /// For `from .....x import y`, this is 5
275 leading_dots: usize,
276 /// For `from .....x import y`, this `x`
277 path: Vec<Name>,
278 /// For `from x import y, z`, this `vec![(y, None), (vec![z], None)]`.
279 /// For `from x import y as z`, this `vec![(y, Some(z))]`.
280 names: Vec<(Name, Option<Name>)>,
281 },
282 /// For `from x import *`, this is `vec![]`.
283 ImportStarFrom {
284 leading_dots: usize,
285 path: Vec<Name>,
286 },
287 /// `import x.y as z, foo.bar` is
288 /// `Import::Import(vec![(vec![x, y], Some(z)), (vec![foo, bar], None)])`.
289 Import {
290 names: Vec<(Vec<Name>, Option<Name>)>,
291 },
292}
293
294/// `+=` and its friends.
295#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
296pub enum AugAssignOp {
297 Add,
298 Sub,
299 Mult,
300 MatMult,
301 Div,
302 Mod,
303 BitAnd,
304 BitOr,
305 BitXor,
306 Lshift,
307 Rshift,
308 Power,
309 Floordiv,
310}
311
312impl fmt::Display for AugAssignOp {
313 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
314 write!(
315 f,
316 "{}",
317 match *self {
318 AugAssignOp::Add => "+=",
319 AugAssignOp::Sub => "-=",
320 AugAssignOp::Mult => "*=",
321 AugAssignOp::MatMult => "@=",
322 AugAssignOp::Div => "/=",
323 AugAssignOp::Mod => "%=",
324 AugAssignOp::BitAnd => "&=",
325 AugAssignOp::BitOr => "|=",
326 AugAssignOp::BitXor => "^=",
327 AugAssignOp::Lshift => "<<=",
328 AugAssignOp::Rshift => ">>=",
329 AugAssignOp::Power => "**=",
330 AugAssignOp::Floordiv => "//=",
331 }
332 )
333 }
334}
335
336/// A Python statement.
337#[derive(Clone, Debug, PartialEq)]
338pub enum Statement {
339 Pass,
340 Del(Vec<Expression>),
341 Break,
342 Continue,
343 Return(Vec<Expression>),
344 RaiseExcFrom(Expression, Expression),
345 RaiseExc(Expression),
346 Raise,
347 Global(Vec<Name>),
348 Nonlocal(Vec<Name>),
349 Assert(Expression, Option<Expression>),
350 Import(Import),
351 Expressions(Vec<Expression>),
352 // `lhs = rhs1 = rhs2` -> `lhs, vec![rhs1, rhs2]`
353 Assignment(Vec<Expression>, Vec<Vec<Expression>>),
354 // `lhs: type` -> `lhs, type`
355 TypeAnnotation(Vec<Expression>, Expression),
356 // `lhs: type = rhs` -> `lhs, type, rhs`
357 TypedAssignment(Vec<Expression>, Expression, Vec<Expression>),
358 // `lhs += rhs` -> `lhs, AugAssignOp::Add, rhs`
359 AugmentedAssignment(Vec<Expression>, AugAssignOp, Vec<Expression>),
360
361 Compound(Box<CompoundStatement>),
362}
363
364/// A function definition, including its decorators.
365#[derive(Clone, Debug, PartialEq)]
366pub struct Funcdef {
367 pub async: bool,
368 pub decorators: Vec<Decorator>,
369 pub name: String,
370 pub parameters: TypedArgsList,
371 pub return_type: Option<Expression>,
372 pub code: Vec<Statement>,
373}
374
375/// A class definition, including its decorators.
376#[derive(Clone, Debug, PartialEq)]
377pub struct Classdef {
378 pub decorators: Vec<Decorator>,
379 pub name: String,
380 pub arguments: Vec<Argument>,
381 pub code: Vec<Statement>,
382}
383
384/// A try block.
385#[derive(Clone, Debug, PartialEq)]
386pub struct Try {
387 pub try_block: Vec<Statement>,
388 /// except `1 [as 2]: 3`
389 pub except_clauses: Vec<(Expression, Option<Name>, Vec<Statement>)>,
390 /// Empty iff no `except:` clause.
391 pub last_except: Vec<Statement>,
392 /// Empty iff no `else:` clause.
393 pub else_block: Vec<Statement>,
394 /// Empty iff no `finally:` clause.
395 pub finally_block: Vec<Statement>,
396}
397
398/// Statements with blocks.
399#[derive(Clone, Debug, PartialEq)]
400pub enum CompoundStatement {
401 If(Vec<(Expression, Vec<Statement>)>, Option<Vec<Statement>>),
402 For {
403 async: bool,
404 item: Vec<Expression>,
405 iterator: Vec<Expression>,
406 for_block: Vec<Statement>,
407 else_block: Option<Vec<Statement>>,
408 },
409 While(Expression, Vec<Statement>, Option<Vec<Statement>>),
410 With(Vec<(Expression, Option<Expression>)>, Vec<Statement>),
411 Funcdef(Funcdef),
412 Classdef(Classdef),
413 Try(Try),
414}