python_parser/lib.rs
1//! A Python parser based on nom, plus some utilities.
2//!
3//! # Panics
4//!
5//! Never (except stack overflows).
6//!
7//! # Numbers
8//!
9//! Python's integer literals may be arbitrary large. This is supported
10//! thanks to the `num_bigint` crate.
11//! Disable the `bigint` feature to fall back to `u64`.
12//!
13//! # String encoding
14//!
15//! `ast::PyString`s are WTF8-encoded if the `wtf8` feature is enabled
16//! (the default) allowing full support for Python's string literals.
17//!
18//! If that feature is disabled, they default to regular Rust strings.
19//! Note that without the `wtf8` feature, some valid string
20//! literals will be badly parsed (missing characters).
21//!
22//! # Python version support
23//!
24//! Currently supports Python 3.7's syntax (and Python 3.8 up to
25//! [2018-09-22](http://github.com/python/cpython/commit/fd97d1f1af910a6222ea12aec42c456b64f9aee4)).
26//!
27//! # Example
28//!
29//! ```
30//! use python_parser::ast::*;
31//! let code = "print(2 + 3, fd=sys.stderr)";
32//! let ast = python_parser::file_input(python_parser::make_strspan(code))
33//! .unwrap()
34//! .1;
35//! assert_eq!(ast,
36//! vec![
37//! Statement::Assignment(
38//! vec![
39//! Expression::Call(
40//! Box::new(Expression::Name("print".to_string())),
41//! vec![
42//! Argument::Positional(
43//! Expression::Bop(
44//! Bop::Add,
45//! Box::new(Expression::Int(2u32.into())),
46//! Box::new(Expression::Int(3u32.into())),
47//! )
48//! ),
49//! Argument::Keyword(
50//! "fd".to_string(),
51//! Expression::Attribute(
52//! Box::new(Expression::Name("sys".to_string())),
53//! "stderr".to_string(),
54//! )
55//! ),
56//! ]
57//! ),
58//! ],
59//! vec![],
60//! )
61//! ]
62//! );
63//! ```
64
65#![recursion_limit = "128"]
66
67#[macro_use]
68extern crate nom;
69extern crate nom_locate;
70
71#[cfg(test)]
72#[macro_use]
73extern crate pretty_assertions;
74
75extern crate unicode_xid;
76
77#[cfg(feature = "unicode-names")]
78extern crate unicode_names2;
79
80#[cfg(feature = "bigint")]
81extern crate num_bigint;
82#[cfg(feature = "bigint")]
83extern crate num_traits;
84
85#[cfg(feature = "wtf8")]
86extern crate wtf8;
87
88#[macro_use]
89mod helpers;
90#[macro_use]
91mod expressions;
92#[macro_use]
93mod statements;
94pub mod ast;
95mod bytes;
96pub mod errors;
97mod functions;
98mod numbers;
99mod strings;
100pub mod visitors;
101
102use ast::*;
103use expressions::*;
104use helpers::*;
105use statements::*;
106
107pub use helpers::make_strspan;
108
109// single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
110named_attr!(#[doc = "Parses a single interactive statement, like in the REPL."],
111pub parse_single_input <StrSpan, Vec<Statement>>,
112 alt!(
113 newline => { |_| Vec::new() }
114 | call!(statement, 0) => { |stmts| stmts }
115 )
116);
117
118// file_input: (NEWLINE | stmt)* ENDMARKER
119named_attr!(#[doc = "Parses a module or sequence of commands."],
120pub file_input <StrSpan, Vec<Statement>>,
121 fold_many0!(
122 alt!(
123 newline => { |_| None }
124 | eof!() => { |_| None }
125 | call!(statement, 0) => { |s| Some(s) }
126 ),
127 Vec::new(),
128 |acc: Vec<_>, item| { let mut acc = acc; if let Some(s) = item { acc.extend(s); } acc }
129 )
130);
131
132// eval_input: testlist NEWLINE* ENDMARKER
133named_attr!(#[doc = "Parses the input of eval()."],
134pub eval_input <StrSpan, Vec<Expression>>,
135 terminated!(ws_nonl!(call!(ExpressionParser::<NewlinesAreNotSpaces>::testlist)), many0!(newline))
136);
137
138// encoding_decl: NAME
139// TODO
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144 use helpers::{assert_parse_eq, make_strspan};
145
146 #[test]
147 fn foo() {
148 assert_parse_eq(newline(make_strspan("\n")), Ok((make_strspan(""), ())));
149 assert_parse_eq(
150 parse_single_input(make_strspan("del foo")),
151 Ok((
152 make_strspan(""),
153 vec![Statement::Del(vec![Expression::Name("foo".to_string())])],
154 )),
155 );
156 assert_parse_eq(
157 parse_single_input(make_strspan("del foo, bar")),
158 Ok((
159 make_strspan(""),
160 vec![Statement::Del(vec![
161 Expression::Name("foo".to_string()),
162 Expression::Name("bar".to_string()),
163 ])],
164 )),
165 );
166 assert_parse_eq(
167 parse_single_input(make_strspan("del foo; del bar")),
168 Ok((
169 make_strspan(""),
170 vec![
171 Statement::Del(vec![Expression::Name("foo".to_string())]),
172 Statement::Del(vec![Expression::Name("bar".to_string())]),
173 ],
174 )),
175 );
176 assert_parse_eq(
177 parse_single_input(make_strspan("del foo ;del bar")),
178 Ok((
179 make_strspan(""),
180 vec![
181 Statement::Del(vec![Expression::Name("foo".to_string())]),
182 Statement::Del(vec![Expression::Name("bar".to_string())]),
183 ],
184 )),
185 );
186 }
187}