changeset 68:c59ad5ccd8a6

Add ast.Try
author Bastien Orivel <eijebong@bananium.fr>
date Mon, 13 Jun 2016 03:03:13 +0200
parents 8ce78e2ba48c
children a73eaf42bea1
files src/ast_convert.rs src/ast_dump.rs src/python_ast.rs tests/test_parse_files/test_try.py
diffstat 4 files changed, 83 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/ast_convert.rs
+++ b/src/ast_convert.rs
@@ -1,4 +1,4 @@
-use python_ast::{Module, stmt, expr, expr_context, cmpop, boolop, operator, unaryop, arguments, arg, alias, comprehension, keyword, withitem};
+use python_ast::{Module, stmt, expr, expr_context, cmpop, boolop, operator, unaryop, arguments, arg, alias, comprehension, keyword, withitem, excepthandler};
 
 use cpython::{Python, PyObject};
 use cpython::ObjectProtocol; //for call method
@@ -255,6 +255,18 @@ fn parse_operator(py: Python, ast: PyObj
     }
 }
 
+fn parse_excepthandler(py: Python, ast: PyObject) -> excepthandler {
+    let type_ = ast.getattr(py, "type").unwrap();
+    let name = ast.getattr(py, "name").unwrap();
+    let body = ast.getattr(py, "body").unwrap();
+
+    let type_ = parse_optional_expr(py, type_);
+    let name = if name == py.None() { None } else { Some(get_str(py, name)) };
+    let body = parse_list(py, body, parse_statement);
+
+    excepthandler{type_: type_, name: name, body: body}
+}
+
 fn parse_optional_expr(py: Python, ast: PyObject) -> Option<expr> {
     if ast == py.None() {
         None
@@ -531,6 +543,7 @@ fn parse_statement(py: Python, ast: PyOb
     let assert_type = ast_module.get(py, "Assert").unwrap();
     let with_type = ast_module.get(py, "With").unwrap();
     let raise_type = ast_module.get(py, "Raise").unwrap();
+    let try_type = ast_module.get(py, "Try").unwrap();
 
     assert!(is_instance(&ast, &ast_type));
 
@@ -695,6 +708,18 @@ fn parse_statement(py: Python, ast: PyOb
         let cause = parse_optional_expr(py, cause);
 
         stmt::Raise(exc, cause)
+    } else if is_instance(&ast, &try_type) {
+        let body = ast.getattr(py, "body").unwrap();
+        let excepthandlers = ast.getattr(py, "handlers").unwrap();
+        let orelse = ast.getattr(py, "orelse").unwrap();
+        let finalbody = ast.getattr(py, "finalbody").unwrap();
+
+        let body = parse_list(py, body, parse_statement);
+        let excepthandlers = parse_list(py, excepthandlers, parse_excepthandler);
+        let orelse = parse_list(py, orelse, parse_statement);
+        let finalbody = parse_list(py, finalbody, parse_statement);
+
+        stmt::Try(body, excepthandlers, orelse, finalbody)
     } else {
         println!("stmt {}", ast);
         panic!()
--- a/src/ast_dump.rs
+++ b/src/ast_dump.rs
@@ -1,4 +1,4 @@
-use python_ast::{Module, stmt, expr, boolop, operator, unaryop, cmpop, arguments, arg, keyword, comprehension, withitem};
+use python_ast::{Module, stmt, expr, boolop, operator, unaryop, cmpop, arguments, arg, keyword, comprehension, withitem, excepthandler};
 
 use std::iter;
 
@@ -117,6 +117,24 @@ impl to_string_able for comprehension {
     }
 }
 
+impl excepthandler {
+    fn to_string(self, indent: usize) -> String {
+        let current_indent = make_indent(indent);
+        format!("{}except {}{}:\n{}",
+            current_indent,
+            match self.type_ {
+                None => String::new(),
+                Some(ref type_) => type_.to_string()
+            },
+            match self.name {
+                None => String::new(),
+                Some(ref name) => format!(" as {}", name)
+            },
+            statements_to_string(indent, self.body)
+        )
+    }
+}
+
 impl to_string_able for expr {
     fn to_string(&self) -> String {
         match self.clone() {
@@ -346,6 +364,30 @@ impl stmt {
                         Some(ref cause) => format!(" from {}", cause.to_string())
                     }
                 )
+            },
+            stmt::Try(body, excepthandlers, orelse, finalbody) => {
+                format!("{}try:\n{}\n{}{}\n{}",
+                    current_indent,
+                    statements_to_string(indent, body),
+                    {
+                        let mut excepthandlers_ = vec!();
+                        for excepthandler in excepthandlers {
+                            let excepthandler = excepthandler.to_string(indent);
+                            excepthandlers_.push(excepthandler);
+                        }
+                        excepthandlers_.join("\n")
+                    },
+                    if !orelse.is_empty() {
+                        format!("{}else:\n{}", current_indent, statements_to_string(indent, orelse))
+                    } else {
+                        String::new()
+                    },
+                    if !finalbody.is_empty() {
+                        format!("{}finally:\n{}", current_indent, statements_to_string(indent, finalbody))
+                    } else {
+                       String::new()
+                    }
+                )
             }
         }
     }
--- a/src/python_ast.rs
+++ b/src/python_ast.rs
@@ -51,7 +51,7 @@ pub enum stmt {
     Raise(Option<expr>, Option<expr>),
 
     // Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
-    //Try(Vec<stmt>, Vec<excepthandler>, Vec<stmt>, Vec<stmt>)
+    Try(Vec<stmt>, Vec<excepthandler>, Vec<stmt>, Vec<stmt>),
 
     // Assert(expr test, expr? msg)
     Assert(expr, Option<expr>),
@@ -186,8 +186,10 @@ pub struct comprehension {
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub enum excepthandler {
-    ExceptHandler(Option<expr>, Option<String>, Vec<stmt>)
+pub struct excepthandler {
+    pub type_: Option<expr>,
+    pub name: Option<String>,
+    pub body: Vec<stmt>,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
new file mode 100644
--- /dev/null
+++ b/tests/test_parse_files/test_try.py
@@ -0,0 +1,9 @@
+def func():
+    try:
+        pass
+    except (Exception1, Exception2):
+        pass
+    except Exception3 as e:
+        pass
+    finally:
+        pass