use std::str::FromStr; use crate::ast; use crate::types; grammar(id_generator: ast::IdGenerator); pub TypeUsage: ast::TypeUsage = { "fn" "(" > ")" => ast::TypeUsage::Function(ast::FunctionTypeUsage{arguments: args, return_type: ast::new_unit()}), "fn" "(" > ")" ":" => ast::TypeUsage::Function(ast::FunctionTypeUsage{arguments: args, return_type: return_type), => ast::TypeUsage::Named(ast::NamedTypeUsage{name: name}) }; pub LiteralInt: i64 = { => i64::from_str(literal).unwrap() }; pub SpannedLiteralInt: ast::LiteralInt { > => ast::LiteralInt{value: literal_int, type: ast::new_named("i64")}, }; pub LiteralFloat: f64 = { => f64::from_str(literal).unwrap() }; pub SpannedLiteralInt: ast::LiteralFloat { > => ast::LiteralFloat{value: literal_float, type: ast::new_named("f64")}, }; pub Identifier: ast::Identifier = { => ast::Identifier{name: i.to_string()} }; pub FunctionCall: ast::FunctionCall = { > "(" >> ")" => ast::FunctionCall{name:i, arguments: args} } pub Expression: Box = { > "+" > => Box::new(ast::Expression::Op(ast::Operation{left: l, op: ast::Operator::Plus, right: r})), > "-" > => Box::new(ast::Expression::Op(ast::Operation{left: l, op: ast::Operator::Minus, right: r})), Factor, } pub Factor: Box = { > "*" > => Box::new(ast::Expression::Op(ast::Operation{left: l, op: ast::Operator::Mul, right: r})), > "/" > => Box::new(ast::Expression::Op(ast::Operation{left: l, op: ast::Operator::Div, right: r})), Term, } pub Term: Box = { Spanned => Box::new(ast::Expression::LiteralInt(<>)), Spanned => Box::new(ast::Expression::Identifier(<>)), Spanned => Box::new(ast::Expression::FunctionCall(<>)), "(" ")" => e } pub LetStatement: ast::Assignment = { //TODO: support destructuring with tuples, when they exist. //TODO: add mut, weak "let" > "=" > => ast::Assignment{name: n, type_usage: None, expression: e}, "let" > ":" > "=" > => ast::Assignment{name: n, type_usage: Some(t), expression: e}, } pub Statement: ast::Statement = { > => ast::Statement::Assignment(l), > => ast::Statement::Expression(e), } pub Block: ast::Block = { "{" >> "}" => ast::Block{statements: s} } pub TypeUsage: ast::TypeUsage = { > => ast::TypeUsage{name: n, ty: types::SpecifiedType::Unknown} } pub VariableDeclaration: ast::VariableDeclaration = { > ":" > => ast::VariableDeclaration{name: i, type_usage: t}, } pub Function: ast::Function = { "fn" > "(" > ")" > => ast::Function{name: n, arguments: args, block: b, return_type: rt} } pub Module: ast::Module = { => ast::Module{functions: fs} } // From https://lalrpop.github.io/lalrpop/tutorial/006_macros.html // Comma seperated list of T with optional trailing comma Comma: Vec = { ",")*> => match e { None => v, Some(e) => { let mut v = v; v.push(e); v } } }; LineDelimiter: Vec = { r"\n|;")*> => { let mut v = v; v.push(e); v } }; Spanned: ast::Spanned = { => ast::Spanned{span: ast::Span{left: l, right: r}, value: rule} };