use crate::ast::*; use crate::lexer::*; grammar<'input>(ast: &mut ASTArena, file: FileRef); extern { type Location = usize; type Error = LexerError; enum Token<'input> { "<" => Token::LAngle, ">" => Token::RAngle, "(" => Token::LPar, ")" => Token::RPar, "{" => Token::LCurl, "}" => Token::RCurl, "[" => Token::LBrac, "]" => Token::RBrac, "|" => Token::Pipe, ":" => Token::Colon, "," => Token::Comma, ";" => Token::Semi, "." => Token::Dot, "_" => Token::Underscore, ".." => Token::DotDot, "=>" => Token::Arrow, ":=" => Token::Assn, "::=" => Token::LitAssn, "puts" => Token::Puts, "case" => Token::Case, "let" => Token::Let, "in" => Token::In, "fix" => Token::Fix, "var" => Token::Var(<&'input str>), "atom" => Token::Atom(<&'input str>), "num" => Token::Num(), "str" => Token::Str() } } pub Stmts: Vec = { ";")*> => match stmt { None => stmts, Some(stmt) => { stmts.push(stmt); stmts } }, }; pub Stmt: Stmt = { "puts" > => Stmt::Puts(<>), ":=" > => Stmt::Assn(fixed.is_some(), name, expr), "::=" >)*> => Stmt::LitAssn( fixed.is_some(), name, strs, ), "fix" => Stmt::Fix(<>), }; pub AtomLit: string_interner::DefaultSymbol = { "var" => ast.add_string(<>), "atom" => ast.add_string(<>), }; pub Name: Name = { => Located::new(ast.add_string(str), file, Span { start: start as u32, end: end as u32 }), }; pub ExprRef = Located; pub Expr: ExprId = { "|")*> => { if ts.len() == 0 { t.value.item } else { ts.push(t); ast.add_expr(Expr::Chc(ts)) } } }; pub Choice: Choice = { ":" > => Choice { weight: Some(weight), value }, > => Choice { weight: None, value } }; pub Term: ExprId = { >)*> => { match bs.len() { 0 => ast.expr_nil(), 1 => bs.pop().unwrap().item, _ => ast.add_expr(Expr::Cat(<>)), } } }; pub Branch: ExprId = { // > "." > => ast.add_expr(Expr::Ap(l, r)), > "[" ",")>*> > "]" => { rs.push(r); ast.add_expr(Expr::Ap(l, rs)) }, => <>, }; pub Subbranch: ExprId = { > ".." > => ast.add_expr(Expr::Range(l, r)), => <>, } pub Leaf: ExprId = { => ast.add_expr(Expr::Lit(<>)), => ast.add_expr(Expr::Var(<>)), "<" > ",")*> > ">" => { if es.len() == 0 && e.item.nil() { ast.add_expr(Expr::Tup(Vec::new())) } else { es.push(e); ast.add_expr(Expr::Tup(es)) } }, "let" ":=" > "in" "{" > "}" => ast.add_expr(Expr::Let(fixed.is_some(), name, e1, e2)), "{" "}" => ast.add_expr(Expr::Fun(cs)), "case" > "in" "{" "}" => ast.add_expr(Expr::Case(e, cs)), "(" ")" => e, }; pub Cases: Vec = { ";")*> => { cs.push(c); cs } }; pub Case: Case = { "=>" > => Case { pats: vec![pat], expr } }; pub FunCases: Vec = { ";")*> => { cs.push(c); cs } }; pub FunCase: Case = { "[" ",")*> "]" "=>" > => { pats.push(pat); Case { pats, expr } } }; pub Pat: Pat = { "_" => Pat::Wildcard, => Pat::Lit(<>), => Pat::Var(<>), "<" ">" => Pat::Tup(Vec::new()), "<" ",")*> ">" => { ps.push(p); Pat::Tup(ps) }, }; pub Literal: Literal = { "num" => Literal::Num(<>), "str" => Literal::Str(<>), > => Literal::Atom(atom.map(|x| ast.add_string(x))), }; #[inline] Located: Located = { => Located::new(data, file, Span { start: start as u32, end: end as u32 }), };