mul/src/parse/parser.lalrpop

81 lines
2.0 KiB
Plaintext

use crate::syntax::{
Binding,
Block,
Expression,
Item,
InteractiveEntry,
Name,
Parameter,
Program,
Type,
};
grammar;
pub Program: Program = Item*;
pub InteractiveEntry: InteractiveEntry = {
Item => InteractiveEntry::Item(<>),
<Binding> ";"? => InteractiveEntry::Binding(<>),
<Expression> ";"? => InteractiveEntry::Expression(<>),
}
Type: Type = {
Name => Type::Constructor(<>),
"fn" "(" <parameters:Comma<Type>> ")" "->" <result:Boxed<Type>> => Type::Function { <> },
"(" <Type> ")",
}
Item: Item = {
"fn" <name:Name> "(" <parameters:Comma<Parameter>> ")" <return_type:("->" <Type>)?> <body:Block> ";"? => Item::Fn { <> },
}
Parameter: Parameter =
<name:Name> <annotation:(":" <Type>)?> => Parameter { <> };
Binding: Binding =
"let" <name:Name> <annotation:(":" <Type>)?> "=" <expression:Expression> => Binding { <> };
Expression: Expression = {
"|" <parameters:Comma<Parameter>> "|" <return_type:("->" <Type>)?> <result:Boxed<Expression>> => Expression::Lambda { <> },
Boxed<Block> => Expression::Block(<>),
<expression:Boxed<Atom>> ":" <annotation:Type> => Expression::Annotation { <> },
Atom,
};
Atom: Expression = {
Name => Expression::Variable(<>),
<callee:Boxed<Atom>> "(" <arguments:Comma<Expression>> ")" => Expression::Call { <> },
Integer => Expression::Integer(<>),
Boolean => Expression::Boolean(<>),
"(" ")" => Expression::Unit,
"(" <Expression> ")",
};
BlockBinding = <Binding> ";";
Block: Block =
"{" <bindings:BlockBinding*> <result:Expression> "}" => Block { <> };
// TODO: decide on identifier syntax
Name: Name = r"[a-zA-Z_]+" => <>.to_string();
Integer: i64 = r"[0-9]+" => <>.parse::<i64>().unwrap();
Boolean: bool = {
"true" => true,
"false" => false,
}
Boxed<T>: Box<T> = T => Box::new(<>);
Comma<T>: Vec<T> = {
<mut v:(<T> ",")*> <e:T?> => match e {
None => v,
Some(e) => {
v.push(e);
v
}
}
};