use pomelo::pomelo; pomelo! { //%verbose; %include { use super::super::ast::*; } %token #[derive(Debug)] pub enum Token {}; %extra_argument Program; %type Ident String; %type Number i64; %type String String; %type expr Expr; %type expr_list Vec; %type stmt Stmt; %type block Vec; %type stmt_list Vec; %type arg_list Vec; %type f_decl Function; %type v_decl Variable; %left Else; %right Assign; %left Or; %left And; %nonassoc Equal NotEqual; %nonassoc Less LessEq Greater GreaterEq; %left Plus Minus; %left Mult Div; %nonassoc Not; input ::= decl_list?; decl_list ::= decl; decl_list ::= decl_list decl; decl ::= f_decl(f) { extra.add_function(f); } decl ::= v_decl(v) { extra.add_variable(v); } f_decl ::= Fn Ident(name) LParen arg_list?(args) RParen block(code) { Function::new(name, args.unwrap_or_else(Vec::new), code) } arg_list ::= Ident(n) { vec![n] } arg_list ::= arg_list(mut args) Comma Ident(n) { args.push(n); args } block ::= LBrace stmt_list?(ss) RBrace { ss.unwrap_or(Vec::new()) } v_decl ::= Var Ident(name) Assign expr(ini) Semicolon { Variable::new(name, ini) } stmt_list ::= stmt(s) { vec![s] } stmt_list ::= stmt_list(mut ss) stmt(s) { ss.push(s); ss } stmt ::= block(ss) { Stmt::Block(ss) } stmt ::= expr(e) Semicolon {Stmt::Expr(e) } stmt ::= If LParen expr(e) RParen stmt(s1) [Else] { Stmt::If(e, Box::new((s1, None))) } stmt ::= If LParen expr(e) RParen stmt(s1) Else stmt(s2) {Stmt::If(e, Box::new((s1, Some(s2)))) } stmt ::= While LParen expr(e) RParen stmt(s) { Stmt::While(e, Box::new(s)) } stmt ::= Return expr(e) Semicolon { Stmt::Return(Some(e)) } stmt ::= Return Semicolon { Stmt::Return(None) } stmt ::= Break Semicolon { Stmt::Break } stmt ::= Continue Semicolon {Stmt::Continue } expr ::= Number(n) { Expr::Number(n) } expr ::= String(s) { Expr::String(s) } expr ::= Ident(n) { Expr::Variable(n) } expr ::= Ident(n) LParen expr_list?(es) RParen { Expr::Call(n, es.unwrap_or(Vec::new())) } expr ::= LParen expr(e) RParen { e } expr ::= expr(a) Plus expr(b) { Expr::BinaryOp(BinOp::Plus, Box::new((a, b))) } expr ::= expr(a) Minus expr(b) { Expr::BinaryOp(BinOp::Minus, Box::new((a, b))) } expr ::= expr(a) Mult expr(b) { Expr::BinaryOp(BinOp::Mult, Box::new((a, b))) } expr ::= expr(a) Div expr(b) { Expr::BinaryOp(BinOp::Div, Box::new((a, b))) } expr ::= Minus expr(a) [Not] { Expr::UnaryOp(UnaOp::Neg, Box::new(a)) } expr ::= expr(a) Equal expr(b) { Expr::BinaryOp(BinOp::Equal, Box::new((a, b))) } expr ::= expr(a) NotEqual expr(b) { Expr::BinaryOp(BinOp::NotEqual, Box::new((a, b))) } expr ::= expr(a) And expr(b) { Expr::BinaryOp(BinOp::And, Box::new((a, b))) } expr ::= expr(a) Or expr(b) { Expr::BinaryOp(BinOp::Or, Box::new((a, b))) } expr ::= Not expr(a) { Expr::UnaryOp(UnaOp::Not, Box::new(a)) } expr ::= expr(a) Less expr(b) { Expr::BinaryOp(BinOp::Less, Box::new((a, b))) } expr ::= expr(a) Greater expr(b) { Expr::BinaryOp(BinOp::Greater, Box::new((a, b))) } expr ::= expr(a) LessEq expr(b) { Expr::BinaryOp(BinOp::LessEq, Box::new((a, b))) } expr ::= expr(a) GreaterEq expr(b) { Expr::BinaryOp(BinOp::GreaterEq, Box::new((a, b))) } expr ::= expr(a) Assign expr(b) { Expr::BinaryOp(BinOp::Assign, Box::new((a, b))) } expr_list ::= expr(e) { vec![e] } expr_list ::= expr_list(mut es) Comma expr(e) { es.push(e); es } } pub use parser::*;