// See also: file:///usr/share/doc/python/html/reference/grammar.html?highlight=grammar use super::ast; use super::lexer; use std::iter::FromIterator; grammar; pub Program: ast::Program = { => ast::Program { statements: Vec::from_iter(lines.into_iter().filter_map(|e| e)) }, }; // A file line either has a declaration, or an empty newline: FileLine: Option = { => Some(s), "\n" => None, }; Suite: Vec = { => vec![s], "\n" indent dedent => s, }; pub Statement: ast::Statement = { SimpleStatement, CompoundStatement, }; SimpleStatement: ast::Statement = { "\n" => s, }; SmallStatement: ast::Statement = { // => ast::Statement::Expression { expression: e }, ExpressionStatement, "pass" => ast::Statement::Pass, FlowStatement, ImportStatement, AssertStatement, }; ExpressionStatement: ast::Statement = { => { //match e2 { // None => ast::Statement::Expression { expression: e }, // Some(e3) => ast::Statement::Expression { expression: e }, //} if e2.len() > 0 { // Dealing with assignment here // TODO: for rhs in e2 { let rhs = e2.into_iter().next().unwrap(); // ast::Expression::Tuple { elements: e2.into_iter().next().unwrap() let v = rhs.into_iter().next().unwrap(); let lhs = ast::Statement::Assign { targets: e, value: v }; lhs } else { if e.len() > 1 { panic!("Not good?"); // ast::Statement::Expression { expression: e[0] } } else { ast::Statement::Expression { expression: e.into_iter().next().unwrap() } } } }, }; AssignSuffix: Vec = { "=" => e, }; FlowStatement: ast::Statement = { "break" => ast::Statement::Break, "continue" => ast::Statement::Continue, "return" => ast::Statement::Return { value: t}, // raise // yield }; ImportStatement: ast::Statement = { "import" => ast::Statement::Import { name: n }, }; DottedName: String = { => n, }; AssertStatement: ast::Statement = { "assert" => ast::Statement::Assert { test: t, msg: match m { Some(e) => Some(e.1), None => None, } }, }; CompoundStatement: ast::Statement = { IfStatement, WhileStatement, ForStatement, WithStatement, FuncDef, ClassDef, }; IfStatement: ast::Statement = { "if" ":" => ast::Statement::If { test: e, body: s }, }; WhileStatement: ast::Statement = { "while" ":" => ast::Statement::While { test: e, body: s }, }; ForStatement: ast::Statement = { "for" "in" ":" => ast::Statement::For { target: e, iter: t, body: s, or_else: None }, }; WithStatement: ast::Statement = { "with" "as" ":" => ast::Statement::With { items: t, body: s }, }; FuncDef: ast::Statement = { "def" "(" ")" ":" => ast::Statement::FunctionDef { name: i, body: s }, }; ClassDef: ast::Statement = { "class" ":" => ast::Statement::ClassDef { name: n }, }; Test: ast::Expression = { => e, }; OrTest: ast::Expression = { => e, }; AndTest: ast::Expression = { => e, }; NotTest: ast::Expression = { => e, }; Comparison: ast::Expression = { => ast::Expression::Compare { a: Box::new(e1), op: op, b: Box::new(e2) }, => e, }; CompOp: ast::Comparison = { "==" => ast::Comparison::Equal, "!=" => ast::Comparison::NotEqual, "<" => ast::Comparison::Less, "<=" => ast::Comparison::LessOrEqual, ">" => ast::Comparison::Greater, ">=" => ast::Comparison::GreaterOrEqual, "in" => ast::Comparison::In, "not" "in" => ast::Comparison::NotIn, "is" => ast::Comparison::Is, "is" "not" => ast::Comparison::IsNot, }; pub Expression: ast::Expression = { "|" => ast::Expression::Binop { a: Box::new(e1), op: ast::Operator::BitOr, b: Box::new(e2) }, => e, }; XorExpression: ast::Expression = { "^" => ast::Expression::Binop { a: Box::new(e1), op: ast::Operator::BitXor, b: Box::new(e2) }, => e, }; AndExpression: ast::Expression = { "&" => ast::Expression::Binop { a: Box::new(e1), op: ast::Operator::BitAnd, b: Box::new(e2) }, => e, }; ArithmaticExpression: ast::Expression = { => ast::Expression::Binop { a: Box::new(a), op: op, b: Box::new(b) }, Term, }; AddOp: ast::Operator = { "+" => ast::Operator::Add, "-" => ast::Operator::Sub, }; Term: ast::Expression = { => ast::Expression::Binop { a: Box::new(a), op: op, b: Box::new(b) }, Factor, }; MulOp: ast::Operator = { "*" => ast::Operator::Mult, "/" => ast::Operator::Div, "//" => ast::Operator::FloorDiv, "%" => ast::Operator::Mod, "@" => ast::Operator::MatMult, }; Factor: ast::Expression = { "+" => e, "-" => ast::Expression::Unop { a: Box::new(e), op: ast::UnaryOperator::Neg }, => e, }; Power: ast::Expression = { => e, }; AtomExpr: ast::Expression = { => e, "(" ")" => ast::Expression::Call { function: Box::new(f), args: a }, "[" "]" => ast::Expression::Binop { a: Box::new(e), op: ast::Operator::Subscript, b: Box::new(s) }, "." => ast::Expression::Attribute { value: Box::new(e), name: n }, }; Subscript: ast::Expression = { => e, ":" => { let s1 = match e1 { None => ast::Expression::None, Some(e) => e, }; let s2 = match e2 { None => ast::Expression::None, Some(e) => e, }; ast::Expression::Slice { elements: vec![s1, s2] } } }; Atom: ast::Expression = { => ast::Expression::String { value: s }, => ast::Expression::Number { value: n }, => ast::Expression::Identifier { name: i }, "[" "]" => ast::Expression::List { elements: e }, "(" ")" => e, "True" => ast::Expression::True, "False" => ast::Expression::False, "None" => ast::Expression::None, }; ExpressionList: Vec = { > => e, }; TestList: Vec = { => { let mut l = vec![e1]; l.extend(e2.into_iter().map(|x| x.1)); l } }; FunctionArguments: Vec = { > => e, }; Comma: Vec = { ",")*> => { let mut items = items; items.extend(last); items } }; Number: i32 = => s; String: String = { => s, }; Identifier: String = => s; // Hook external lexer: extern { type Location = usize; type Error = lexer::LexicalError; enum lexer::Tok { indent => lexer::Tok::Indent, dedent => lexer::Tok::Dedent, "+" => lexer::Tok::Plus, "-" => lexer::Tok::Minus, ":" => lexer::Tok::Colon, "." => lexer::Tok::Dot, "," => lexer::Tok::Comma, "*" => lexer::Tok::Star, "&" => lexer::Tok::Amper, "@" => lexer::Tok::At, "%" => lexer::Tok::Percent, "//" => lexer::Tok::DoubleSlash, "^" => lexer::Tok::CircumFlex, "|" => lexer::Tok::Vbar, "/" => lexer::Tok::Slash, "(" => lexer::Tok::Lpar, ")" => lexer::Tok::Rpar, "[" => lexer::Tok::Lsqb, "]" => lexer::Tok::Rsqb, "=" => lexer::Tok::Equal, "+=" => lexer::Tok::PlusEqual, "-=" => lexer::Tok::MinusEqual, "==" => lexer::Tok::EqEqual, "!=" => lexer::Tok::NotEqual, "<" => lexer::Tok::Less, "<=" => lexer::Tok::LessEqual, ">" => lexer::Tok::Greater, ">=" => lexer::Tok::GreaterEqual, "as" => lexer::Tok::As, "assert" => lexer::Tok::Assert, "break" => lexer::Tok::Break, "class" => lexer::Tok::Class, "continue" => lexer::Tok::Break, "def" => lexer::Tok::Def, "for" => lexer::Tok::For, "if" => lexer::Tok::If, "in" => lexer::Tok::In, "is" => lexer::Tok::Is, "import" => lexer::Tok::Import, "not" => lexer::Tok::Not, "pass" => lexer::Tok::Pass, "return" => lexer::Tok::Return, "while" => lexer::Tok::While, "with" => lexer::Tok::With, "True" => lexer::Tok::True, "False" => lexer::Tok::False, "None" => lexer::Tok::None, number => lexer::Tok::Number { value: }, string => lexer::Tok::String { value: }, name => lexer::Tok::Name { name: }, "\n" => lexer::Tok::Newline, } }