forked from RustPython/RustPython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser.rs
More file actions
104 lines (95 loc) · 3.12 KB
/
parser.rs
File metadata and controls
104 lines (95 loc) · 3.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use std::error::Error;
use std::path::Path;
use std::fs::File;
use std::io::Read;
use super::python;
use super::ast;
use super::lexer;
fn read_file(filename: &Path) -> Result<String, String> {
match File::open(&filename) {
Ok(mut file) => {
let mut s = String::new();
match file.read_to_string(&mut s) {
Err(why) => Err(String::from("Reading file failed: ") + why.description()),
Ok(_) => Ok(s),
}
}
Err(why) => Err(String::from("Opening file failed: ") + why.description()),
}
}
/*
* Parse python code.
* Grammar may be inspired by antlr grammar for python:
* https://github.com/antlr/grammars-v4/tree/master/python3
*/
pub fn parse(filename: &Path) -> Result<ast::Program, String> {
info!("Parsing: {}", filename.display());
match read_file(filename) {
Ok(txt) => {
debug!("Read contents of file: {}", txt);
parse_source(&txt)
}
Err(msg) => Err(msg),
}
}
pub fn parse_source(source: &String) -> Result<ast::Program, String> {
let lxr = lexer::Lexer::new(&source);
match python::ProgramParser::new().parse(lxr) {
Err(why) => Err(String::from(format!("{:?}", why))),
Ok(p) => Ok(p),
}
}
#[cfg(test)]
mod tests {
use super::parse_source;
use super::ast;
#[test]
fn test_parse_print_hello() {
let source = String::from("print('Hello world')\n");
let parse_ast = parse_source(&source).unwrap();
assert_eq!(
parse_ast,
ast::Program {
statements: vec![
ast::Statement::Expression {
expression: ast::Expression::Call {
function: Box::new(ast::Expression::Identifier {
name: String::from("print"),
}),
args: vec![
ast::Expression::String {
value: String::from("Hello world"),
},
],
},
},
],
}
);
}
#[test]
fn test_parse_print_2() {
let source = String::from("print('Hello world', 2)\n");
let parse_ast = parse_source(&source).unwrap();
assert_eq!(
parse_ast,
ast::Program {
statements: vec![
ast::Statement::Expression {
expression: ast::Expression::Call {
function: Box::new(ast::Expression::Identifier {
name: String::from("print"),
}),
args: vec![
ast::Expression::String {
value: String::from("Hello world"),
},
ast::Expression::Number { value: 2 },
],
},
},
],
}
);
}
}