python_parser/
ast.rs

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}