diff src/ast_dump.rs @ 13:38b0d63697b1

Import the full AST grammar from CPython 3.5.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Thu, 02 Jun 2016 05:33:23 +0100
parents 94ff501bf336
children 719a27f1c1c7
line wrap: on
line diff
--- a/src/ast_dump.rs
+++ b/src/ast_dump.rs
@@ -1,38 +1,116 @@
-use python_ast::{Module, Statement, Expr, BinOp, UnaryOp};
+use python_ast::{Module, stmt, expr, boolop, operator, unaryop, cmpop, arguments, arg, keyword};
 
 use std::iter;
 
-impl UnaryOp {
+impl boolop {
+    fn to_string(&self) -> &'static str {
+        match *self {
+            boolop::And => "and",
+            boolop::Or => "or"
+        }
+    }
+}
+
+impl operator {
     fn to_string(&self) -> &'static str {
         match *self {
-            UnaryOp::UAdd => "+",
-            UnaryOp::USub => "-",
-            UnaryOp::Error => "BinOp::Error"
+            operator::Add => "+",
+            operator::Sub => "-",
+            operator::Mult => "*",
+            operator::MatMult => "@",
+            operator::Div => "/",
+            operator::Mod => "%",
+            operator::Pow => "**",
+            operator::LShift => "<<",
+            operator::RShift => ">>",
+            operator::BitOr => "|",
+            operator::BitXor => "^",
+            operator::BitAnd => "&",
+            operator::FloorDiv => "//",
+        }
+    }
+}
+
+impl unaryop {
+    fn to_string(&self) -> &'static str {
+        match *self {
+            unaryop::Invert => "~",
+            unaryop::Not => "!",
+            unaryop::UAdd => "+",
+            unaryop::USub => "-"
         }
     }
 }
 
-impl BinOp {
+impl cmpop {
     fn to_string(&self) -> &'static str {
         match *self {
-            BinOp::BinAdd => "+",
-            BinOp::BinMult => "*",
-            BinOp::BinEq => "==",
-            BinOp::BinLt => "<",
-            BinOp::BinGt => ">",
-            BinOp::Sub => "-",
-            BinOp::Div => "/",
-            BinOp::Error => "BinOp::Error"
+            cmpop::Eq => "==",
+            cmpop::NotEq => "!=",
+            cmpop::Lt => "<",
+            cmpop::LtE => "<=",
+            cmpop::Gt => ">",
+            cmpop::GtE => ">=",
+            cmpop::Is => "is",
+            cmpop::IsNot => "is not",
+            cmpop::In => "in",
+            cmpop::NotIn => "not in",
         }
     }
 }
 
-impl Expr {
+fn args_to_string(args: Vec<expr>) -> String {
+    let mut arguments = vec!();
+    for arg in args {
+        arguments.push(arg.to_string());
+    }
+    arguments.join(", ")
+}
+
+fn kwargs_to_string(kwargs: Vec<keyword>) -> String {
+    let mut arguments = vec!();
+    for arg in kwargs {
+        match arg.arg {
+            Some(arg) => arguments.push(arg),
+            None => arguments.push("**kwarg".to_string())
+        }
+    }
+    arguments.join(", ")
+}
+
+fn arguments_to_string(args: arguments) -> String {
+    let mut arguments = vec!();
+    for arg in args.args {
+        arguments.push(arg.arg);
+    }
+    arguments.join(", ")
+}
+
+fn statements_to_string(indent: usize, body: Vec<stmt>) -> String {
+    let mut statements = vec!();
+    for statement in body {
+        statements.push(statement.to_string(indent + 1));
+    }
+    statements.join("\n")
+}
+
+fn if_else_statements_to_string(indent: usize, body: Vec<stmt>, orelse: Vec<stmt>) -> String {
+    let body = statements_to_string(indent, body);
+    if orelse.is_empty() {
+        body
+    } else {
+        format!("{}\n{}else:\n{}", body, make_indent(indent), statements_to_string(indent, orelse))
+    }
+}
+
+impl expr {
     fn to_string(&self) -> String {
         match self.clone() {
-            Expr::UnaryOp(op, operand) => format!("{}{}", op.to_string(), operand.to_string()),
-            Expr::BinOp(a, op, b) => format!("{} {} {}", a.to_string(), op.to_string(), b.to_string()),
-            Expr::Compare(left, ops, comparators) => format!("{} {}", left.to_string(), {
+            expr::BoolOp(op, values) => format!("{}({})", op.to_string(), args_to_string(values)),
+            expr::BinOp(a, op, b) => format!("{} {} {}", a.to_string(), op.to_string(), b.to_string()),
+            expr::UnaryOp(op, operand) => format!("{}{}", op.to_string(), operand.to_string()),
+
+            expr::Compare(left, ops, comparators) => format!("{} {}", left.to_string(), {
                 let mut arguments = vec!();
 
                 // XXX: wrong order!
@@ -52,142 +130,60 @@ impl Expr {
 
                 arguments.join(" ")
             }),
-            Expr::Call(func, args) => format!("{}({})", func.to_string(), {
-                let mut arguments = vec!();
-                for arg in args {
-                    arguments.push(arg.to_string());
-                }
-                arguments.join(", ")
-            }),
-            Expr::Alias(name, asname) => {
-                match asname {
-                    None => format!("{}", name),
-                    Some(asname) => format!("{} as {}", name, asname)
-                }
-            }
-            Expr::Attribute(lhs, rhs) => format!("{}.{}", lhs.to_string(), rhs),
-            Expr::Name(name) => format!("{}", name),
-            Expr::NameConstant(name) => format!("{}", name),
-            Expr::Str(s) => format!("\"{}\"", s),
-            Expr::Num(n) => format!("{}", n),
-            Expr::List(elts) => format!("[{}]", {
-                let mut elements = vec!();
-                for elt in elts {
-                    elements.push(elt.to_string());
-                }
-                elements.join(", ")
-            }),
-            Expr::Error => "Expr::Error".to_string()
+            expr::Call(func, args, keywords) => format!("{}({}{})", func.to_string(), args_to_string(args), kwargs_to_string(keywords)),
+            expr::Num(n) => format!("{}", n),
+            expr::Str(s) => format!("\"{}\"", s),
+            expr::NameConstant(name) => format!("{}", name),
+            expr::Attribute(value, attr, ctx) => format!("{}.{}", value.to_string(), attr),
+            expr::Name(name, ctx) => format!("{}", name),
+            expr::List(elts, ctx) => format!("[{}]", args_to_string(elts))
         }
     }
 }
 
+impl arguments {
+    fn to_string(&self) -> String {
+        let mut args = vec!();
+        for arg in self.args.clone() {
+            args.push(arg.arg);
+        }
+        args.join(", ")
+    }
+}
+
 fn make_indent(indent: usize) -> String {
-    let indent: String = iter::repeat("    ").take(indent).collect();
-    indent
+    iter::repeat("    ").take(indent).collect()
 }
 
-impl Statement {
+impl stmt {
     fn to_string(&self, indent: usize) -> String {
+        let current_indent = make_indent(indent);
         match self.clone() {
-            Statement::ClassDef(name, classes, body) => format!("{}def {}({}):\n{}", make_indent(indent), name, {
-                let mut bases = vec!();
-                for class in classes {
-                    bases.push(class.to_string());
-                }
-                bases.join(", ")
-            }, {
-                let mut statements = vec!();
-                for statement in body {
-                    statements.push(statement.to_string(indent + 1));
-                }
-                statements.join("\n")
-            }),
-            Statement::FunctionDef(name, arguments, body) => format!("{}def {}({}):\n{}", make_indent(indent), name, {
-                let mut args = vec!();
-                for arg in arguments {
-                    args.push(arg.to_string());
-                }
-                args.join(", ")
-            }, {
-                let mut statements = vec!();
-                for statement in body {
-                    statements.push(statement.to_string(indent + 1));
-                }
-                statements.join("\n")
+            stmt::ClassDef(name, bases, keywords, body, decorator_list) => format!("{}def {}({}):\n{}", current_indent, name, args_to_string(bases), statements_to_string(indent, body)),
+            stmt::FunctionDef(name, arguments, body, decorator_list, returns) => format!("{}def {}({}):\n{}", current_indent, name, arguments_to_string(arguments), statements_to_string(indent, body)),
+            stmt::Global(names) => format!("{}global {}", current_indent, names.join(", ")),
+            stmt::If(test, body, orelse) => format!("{}if {}:\n{}", current_indent, test.to_string(), if_else_statements_to_string(indent, body, orelse)),
+            stmt::While(test, body, orelse) => format!("{}while {}:\n{}", current_indent, test.to_string(), if_else_statements_to_string(indent, body, orelse)),
+            stmt::For(target, iter, body, orelse) => format!("{}for {} in {}:\n{}", current_indent, target.to_string(), iter.to_string(), if_else_statements_to_string(indent, body, orelse)),
+            stmt::Assign(targets, value) => format!("{}{} = {}", current_indent, args_to_string(targets), value.to_string()),
+            stmt::AugAssign(target, op, value) => format!("{}{} {}= {}", current_indent, target.to_string(), op.to_string(), value.to_string()),
+            stmt::Return(expr) => format!("{}return{}", current_indent, match expr {
+                Some(expr) => format!(" {}", expr.to_string()),
+                None => "".to_string()
             }),
-            Statement::Global(names) => format!("{}global {}", make_indent(indent), names.join(", ")),
-            Statement::If(test, body, orelse) => format!("{}if {}:\n{}", make_indent(indent), test.to_string(), {
-                let mut statements = vec!();
-                for arg in body {
-                    statements.push(arg.to_string(indent + 1));
-                }
-
-                let mut orelse_ = vec!();
-                for arg in orelse {
-                    orelse_.push(arg.to_string(indent + 1));
-                }
-
-                if orelse_.is_empty() {
-                    statements.join("\n")
-                } else {
-                    format!("{}\n{}else:\n{}", statements.join("\n"), make_indent(indent), orelse_.join("\n"))
-                }
-            }),
-            Statement::While(test, body, orelse) => format!("{}while {}:\n{}", make_indent(indent), test.to_string(), {
-                let mut statements = vec!();
-                for arg in body {
-                    statements.push(arg.to_string(indent + 1));
-                }
-
-                let mut orelse_ = vec!();
-                for arg in orelse {
-                    orelse_.push(arg.to_string(indent + 1));
-                }
-
-                if orelse_.is_empty() {
-                    statements.join("\n")
-                } else {
-                    format!("{}\n{}else:\n{}", statements.join("\n"), make_indent(indent), orelse_.join("\n"))
-                }
-            }),
-            Statement::For(target, iter, body, orelse) => format!("{}for {} in {}:\n{}", make_indent(indent), target.to_string(), iter.to_string(), {
-                let mut statements = vec!();
-                for arg in body {
-                    statements.push(arg.to_string(indent + 1));
-                }
-
-                let mut orelse_ = vec!();
-                for arg in orelse {
-                    orelse_.push(arg.to_string(indent + 1));
-                }
-
-                if orelse_.is_empty() {
-                    statements.join("\n")
-                } else {
-                    format!("{}\n{}else:\n{}", statements.join("\n"), make_indent(indent), orelse_.join("\n"))
-                }
-            }),
-            Statement::Assign(targets, value) => format!("{}{} = {}", make_indent(indent), {
-                let mut exprs = vec!();
-                for target in targets {
-                    exprs.push(target.to_string());
-                }
-                exprs.join(", ")
-            }, value.to_string()),
-            Statement::AugAssign(target, op, value) => format!("{}{} {}= {}", make_indent(indent), target.to_string(), op.to_string(), value.to_string()),
-            Statement::Return(expr) => format!("{}return {}", make_indent(indent), expr.to_string()),
-            Statement::ImportFrom(module, names) => format!("{}from {} import {}", make_indent(indent), module.to_string(), {
+            stmt::ImportFrom(module, names, level) => format!("{}from {} import {}", current_indent, module.to_string(), {
+                /*
                 let mut exprs = vec!();
                 for alias in names.iter() {
                     let alias = alias.to_string();
                     exprs.push(alias);
                 }
                 exprs.join(", ")
+                */
+                "".to_string()
             }),
-            Statement::Expr(expr) => format!("{}{}", make_indent(indent), expr.to_string()),
-            Statement::Break => format!("{}break", make_indent(indent)),
-            Statement::Error => format!("{}Statement::Error", make_indent(indent))
+            stmt::Expr(expr) => format!("{}{}", current_indent, expr.to_string()),
+            stmt::Break => format!("{}break", current_indent)
         }
     }
 }