//! Implement abstract syntax tree nodes for the python language. //! //! Roughly equivalent to this: https://docs.python.org/3/library/ast.html pub use super::lexer::Location; use num_bigint::BigInt; /* #[derive(Debug)] #[derive(Debug)] pub struct Node { pub location: Location, } */ #[derive(Debug, PartialEq)] pub enum Top { Program(Program), Statement(LocatedStatement), Expression(Expression), } #[derive(Debug, PartialEq)] pub struct Program { pub statements: Vec, } #[derive(Debug, PartialEq)] pub struct SingleImport { pub module: String, // (symbol name in module, name it should be assigned locally) pub symbol: Option, pub alias: Option, } #[derive(Debug, PartialEq)] pub struct Located { pub location: Location, pub node: T, } pub type LocatedStatement = Located; /// Abstract syntax tree nodes for python statements. #[derive(Debug, PartialEq)] pub enum Statement { Break, Continue, Return { value: Option>, }, Import { import_parts: Vec, }, Pass, Assert { test: Expression, msg: Option, }, Delete { targets: Vec, }, Assign { targets: Vec, value: Expression, }, AugAssign { target: Box, op: Operator, value: Box, }, Expression { expression: Expression, }, Global { names: Vec, }, Nonlocal { names: Vec, }, If { test: Expression, body: Vec, orelse: Option>, }, While { test: Expression, body: Vec, orelse: Option>, }, With { items: Vec, body: Vec, }, For { target: Expression, iter: Vec, body: Vec, orelse: Option>, }, Raise { exception: Option, cause: Option, }, Try { body: Vec, handlers: Vec, orelse: Option>, finalbody: Option>, }, ClassDef { name: String, body: Vec, bases: Vec, keywords: Vec, decorator_list: Vec, // TODO: docstring: String, }, FunctionDef { name: String, args: Parameters, // docstring: String, body: Vec, decorator_list: Vec, returns: Option, }, } #[derive(Debug, PartialEq)] pub struct WithItem { pub context_expr: Expression, pub optional_vars: Option, } #[derive(Debug, PartialEq)] pub enum Expression { BoolOp { a: Box, op: BooleanOperator, b: Box, }, Binop { a: Box, op: Operator, b: Box, }, Subscript { a: Box, b: Box, }, Unop { op: UnaryOperator, a: Box, }, Yield { value: Option>, }, YieldFrom { value: Box, }, Compare { a: Box, op: Comparison, b: Box, }, Attribute { value: Box, name: String, }, Call { function: Box, args: Vec, keywords: Vec, }, Number { value: Number, }, List { elements: Vec, }, Tuple { elements: Vec, }, Dict { elements: Vec<(Expression, Expression)>, }, Set { elements: Vec, }, Comprehension { kind: Box, generators: Vec, }, Starred { value: Box, }, Slice { elements: Vec, }, String { value: StringGroup, }, Bytes { value: Vec, }, Identifier { name: String, }, Lambda { args: Parameters, body: Box, }, IfExpression { test: Box, body: Box, orelse: Box, }, True, False, None, Ellipsis, } impl Expression { /// Returns a short name for the node suitable for use in error messages. pub fn name(&self) -> &'static str { use self::Expression::*; use self::StringGroup::*; match self { BoolOp { .. } | Binop { .. } | Unop { .. } => "operator", Subscript { .. } => "subscript", Yield { .. } | YieldFrom { .. } => "yield expression", Compare { .. } => "comparison", Attribute { .. } => "attribute", Call { .. } => "function call", Number { .. } | String { value: Constant { .. }, } | Bytes { .. } => "literal", List { .. } => "list", Tuple { .. } => "tuple", Dict { .. } => "dict display", Set { .. } => "set display", Comprehension { kind, .. } => match **kind { ComprehensionKind::List { .. } => "list comprehension", ComprehensionKind::Dict { .. } => "dict comprehension", ComprehensionKind::Set { .. } => "set comprehension", ComprehensionKind::GeneratorExpression { .. } => "generator expression", }, Starred { .. } => "starred", Slice { .. } => "slice", String { value: Joined { .. }, } | String { value: FormattedValue { .. }, } => "f-string expression", Identifier { .. } => "named expression", Lambda { .. } => "lambda", IfExpression { .. } => "conditional expression", True | False | None => "keyword", Ellipsis => "ellipsis", } } } /* * In cpython this is called arguments, but we choose parameters to * distinguish between function parameters and actual call arguments. */ #[derive(Debug, PartialEq, Default)] pub struct Parameters { pub args: Vec, pub kwonlyargs: Vec, pub vararg: Option>, // Optionally we handle optionally named '*args' or '*' pub kwarg: Option>, pub defaults: Vec, pub kw_defaults: Vec>, } #[derive(Debug, PartialEq, Default)] pub struct Parameter { pub arg: String, pub annotation: Option>, } #[derive(Debug, PartialEq)] pub enum ComprehensionKind { GeneratorExpression { element: Expression }, List { element: Expression }, Set { element: Expression }, Dict { key: Expression, value: Expression }, } #[derive(Debug, PartialEq)] pub struct Comprehension { pub target: Expression, pub iter: Expression, pub ifs: Vec, } #[derive(Debug, PartialEq)] pub struct Keyword { pub name: Option, pub value: Expression, } #[derive(Debug, PartialEq)] pub struct ExceptHandler { pub typ: Option, pub name: Option, pub body: Vec, } #[derive(Debug, PartialEq)] pub enum Operator { Add, Sub, Mult, MatMult, Div, Mod, Pow, LShift, RShift, BitOr, BitXor, BitAnd, FloorDiv, } #[derive(Debug, PartialEq)] pub enum BooleanOperator { And, Or, } #[derive(Debug, PartialEq)] pub enum UnaryOperator { Pos, Neg, Not, Inv, } #[derive(Debug, PartialEq)] pub enum Comparison { Equal, NotEqual, Less, LessOrEqual, Greater, GreaterOrEqual, In, NotIn, Is, IsNot, } #[derive(Debug, PartialEq)] pub enum Number { Integer { value: BigInt }, Float { value: f64 }, Complex { real: f64, imag: f64 }, } /// Transforms a value prior to formatting it. #[derive(Copy, Clone, Debug, PartialEq)] pub enum ConversionFlag { /// Converts by calling `str()`. Str, /// Converts by calling `ascii()`. Ascii, /// Converts by calling `repr()`. Repr, } #[derive(Debug, PartialEq)] pub enum StringGroup { Constant { value: String, }, FormattedValue { value: Box, conversion: Option, spec: String, }, Joined { values: Vec, }, }