use pest::iterators::{Pair, Pairs};
use pest::Parser;
use pest_derive::Parser;
use crate::ast::*;
#[derive(Parser)]
#[grammar = "grammar.pest"]
struct MiniParser;
pub type Tok<'a> = Pair<'a, Rule>;
pub type Tik<'a> = Pairs<'a, Rule>;
pub fn parse_str(input: &str) -> Result<Tok, String> {
let the_rule: Tok = MiniParser::parse(Rule::file, input)
.map_err(|err| format!("Parse failed at:{}", err))?
.next()
.unwrap()
.into_inner()
.next()
.unwrap();
let end_pos = the_rule.as_span().end_pos().pos();
if end_pos < input.len() {
let rest = &input[end_pos..];
Err(format!("Does not consume the following code:\n{}", rest))
} else {
Ok(the_rule)
}
}
pub fn parse_str_to_json(input: &str) -> Result<String, String> {
parse_str(input).map(|tok| tok.to_json())
}
#[inline]
pub fn parse_str_err_printed(code: &str) -> Result<Expression, ()> {
parse_str(code)
.map(expression_to_expression)
.map_err(|err| eprintln!("{}", err))
}
macro_rules! next_rule {
($inner:expr, $rule_name:ident, $function:ident) => {{
let token = $inner.next().unwrap();
debug_assert_eq!(token.as_rule(), Rule::$rule_name);
$function(token)
}};
}
#[inline]
fn next_expression(inner: &mut Tik) -> Expression {
next_rule!(inner, expression, expression_to_expression)
}
#[inline]
fn next_atom(inner: &mut Tik) -> Expression {
next_rule!(inner, atom, atom_to_expression)
}
#[inline]
fn next_pattern(inner: &mut Tik) -> Pattern {
next_rule!(inner, pattern, pattern_to_pattern)
}
#[inline]
fn next_constructor_name(inner: &mut Tik) -> String {
next_rule!(inner, constructor_name, identifier_to_name)
}
#[inline]
fn end_of_rule(inner: &mut Tik) {
debug_assert_eq!(inner.next(), None)
}
pub fn expression_to_expression(rules: Tok) -> Expression {
let the_rule: Tok = rules.into_inner().next().unwrap();
match the_rule.as_rule() {
Rule::declaration => declaration_to_expression(the_rule),
Rule::const_declaration => const_declaration_to_expression(the_rule),
Rule::merge_sum => merge_sum_to_expression(the_rule),
Rule::application => application_to_expression(the_rule),
Rule::function_type => function_type_to_expression(the_rule),
Rule::pair_type => pair_type_to_expression(the_rule),
Rule::first => first_to_expression(the_rule),
Rule::second => second_to_expression(the_rule),
Rule::pair => pair_to_expression(the_rule),
Rule::atom => atom_to_expression(the_rule),
_ => unreachable!(),
}
}
fn first_to_expression(the_rule: Tok) -> Expression {
let mut inner: Tik = the_rule.into_inner();
let pair = next_atom(&mut inner);
end_of_rule(&mut inner);
Expression::First(Box::new(pair))
}
fn function_type_to_expression(the_rule: Tok) -> Expression {
let (input, output) = atom_and_expression_to_tuple(the_rule);
Expression::Pi(Typed::new(Pattern::Unit, input), Box::new(output))
}
fn pair_type_to_expression(the_rule: Tok) -> Expression {
let (first, second) = atom_and_expression_to_tuple(the_rule);
Expression::Sigma(Typed::new(Pattern::Unit, first), Box::new(second))
}
fn atom_and_expression_to_tuple(the_rule: Tok) -> (Expression, Expression) {
let mut inner: Tik = the_rule.into_inner();
let input = next_atom(&mut inner);
let output = next_expression(&mut inner);
end_of_rule(&mut inner);
(input, output)
}
fn second_to_expression(the_rule: Tok) -> Expression {
let mut inner: Tik = the_rule.into_inner();
let pair = next_atom(&mut inner);
end_of_rule(&mut inner);
Expression::Second(Box::new(pair))
}
fn pair_to_expression(the_rule: Tok) -> Expression {
let mut inner: Tik = the_rule.into_inner();
let first = next_atom(&mut inner);
let second = next_expression(&mut inner);
end_of_rule(&mut inner);
Expression::Pair(Box::new(first), Box::new(second))
}
fn application_to_expression(the_rule: Tok) -> Expression {
let mut inner: Tik = the_rule.into_inner();
let function = next_atom(&mut inner);
let argument = next_expression(&mut inner);
end_of_rule(&mut inner);
Expression::Application(Box::new(function), Box::new(argument))
}
fn prefix_parameters_to_vec(the_rule: Tok) -> Vec<Typed> {
let mut map: Vec<Typed> = Default::default();
for prefix_parameter in the_rule.into_inner() {
let mut inner: Tik = prefix_parameter.into_inner();
let pattern = next_pattern(&mut inner);
let parameter_type = next_expression(&mut inner);
map.push(Typed::new(pattern, parameter_type));
}
map
}
fn declaration_to_expression(the_rule: Tok) -> Expression {
let mut inner: Tik = the_rule.into_inner();
let let_or_rec_rule = inner.next().unwrap();
let rec = match let_or_rec_rule.as_str() {
"let" => false,
"rec" => true,
_ => unreachable!(),
};
let name = next_pattern(&mut inner);
let prefix_parameters = next_rule!(inner, prefix_parameters, prefix_parameters_to_vec);
let signature = next_expression(&mut inner);
let body = next_expression(&mut inner);
let rest = inner
.next()
.map(expression_to_expression)
.unwrap_or(Expression::Void);
end_of_rule(&mut inner);
let declaration = Declaration::new(name, prefix_parameters, signature, body, rec);
Expression::Declaration(Box::new(declaration), Box::new(rest))
}
fn const_declaration_to_expression(the_rule: Tok) -> Expression {
let mut inner: Tik = the_rule.into_inner();
let name = next_pattern(&mut inner);
let body = next_expression(&mut inner);
let rest = inner
.next()
.map(expression_to_expression)
.unwrap_or(Expression::Void);
end_of_rule(&mut inner);
Expression::Constant(name, Box::new(body), Box::new(rest))
}
fn merge_sum_to_expression(the_rule: Tok) -> Expression {
let mut inner: Tik = the_rule.into_inner();
let lhs = next_atom(&mut inner);
let rhs = next_expression(&mut inner);
end_of_rule(&mut inner);
Expression::Merge(Box::new(lhs), Box::new(rhs))
}
fn atom_to_expression(rules: Tok) -> Expression {
let the_rule: Tok = rules.into_inner().next().unwrap();
match the_rule.as_rule() {
Rule::universe => universe_to_expression(the_rule),
Rule::constructor => constructor_to_expression(the_rule),
Rule::variable => variable_to_expression(the_rule),
Rule::split => Expression::Split(choices_to_tree_map(the_rule)),
Rule::sum => Expression::Sum(branches_to_tree_map(the_rule)),
Rule::one => Expression::One,
Rule::unit => Expression::Unit,
Rule::pi_type => pi_type_to_expression(the_rule),
Rule::sigma_type => sigma_type_to_expression(the_rule),
Rule::lambda_expression => lambda_expression_to_expression(the_rule),
Rule::expression => expression_to_expression(the_rule),
_ => unreachable!(),
}
}
fn branches_to_tree_map(the_rule: Tok) -> Branch {
let mut map: Branch = Default::default();
for constructor in the_rule.into_inner() {
let mut inner: Tik = constructor.into_inner();
let constructor_name = next_constructor_name(&mut inner);
let expression = inner
.next()
.map(expression_to_expression)
.unwrap_or(Expression::One);
map.insert(constructor_name, Box::new(expression));
end_of_rule(&mut inner);
}
map
}
fn choices_to_tree_map(the_rule: Tok) -> Branch {
let mut map: Branch = Default::default();
for pattern_match in the_rule.into_inner() {
let mut inner: Tik = pattern_match.into_inner();
let constructor_name = next_constructor_name(&mut inner);
let pattern = next_rule!(inner, maybe_pattern, maybe_pattern_to_pattern);
let expression = next_expression(&mut inner);
map.insert(
constructor_name,
Box::new(Expression::Lambda(pattern, None, Box::new(expression))),
);
}
map
}
fn pi_type_to_expression(the_rule: Tok) -> Expression {
let (first_name, first_type, second) = typed_abstraction_to_tuple(the_rule);
Expression::Pi(Typed::new(first_name, first_type), Box::new(second))
}
fn sigma_type_to_expression(the_rule: Tok) -> Expression {
let (input_name, input_type, output) = typed_abstraction_to_tuple(the_rule);
Expression::Sigma(Typed::new(input_name, input_type), Box::new(output))
}
fn typed_abstraction_to_tuple(the_rule: Tok) -> (Pattern, Expression, Expression) {
let mut inner: Tik = the_rule.into_inner();
let input_name = next_pattern(&mut inner);
let input_type = next_expression(&mut inner);
let output = next_expression(&mut inner);
end_of_rule(&mut inner);
(input_name, input_type, output)
}
fn atom_pattern_to_pattern(the_rule: Tok) -> Pattern {
let rule: Tok = the_rule.into_inner().next().unwrap();
match rule.as_rule() {
Rule::identifier => Pattern::Var(identifier_to_name(rule)),
Rule::meta_var => Pattern::Unit,
Rule::pattern => pattern_to_pattern(rule),
_ => unreachable!(),
}
}
fn pattern_to_pattern(the_rule: Tok) -> Pattern {
let rule: Tok = the_rule.into_inner().next().unwrap();
match rule.as_rule() {
Rule::pair_pattern => {
let mut inner: Tik = rule.into_inner();
let first = next_rule!(inner, atom_pattern, atom_pattern_to_pattern);
let second = next_pattern(&mut inner);
end_of_rule(&mut inner);
Pattern::Pair(Box::new(first), Box::new(second))
}
Rule::atom_pattern => atom_pattern_to_pattern(rule),
_ => unreachable!(),
}
}
fn lambda_expression_to_expression(the_rule: Tok) -> Expression {
let mut inner: Tik = the_rule.into_inner();
let parameter = next_pattern(&mut inner);
let body = next_expression(&mut inner);
end_of_rule(&mut inner);
Expression::Lambda(parameter, None, Box::new(body))
}
fn constructor_to_expression(the_rule: Tok) -> Expression {
let (constructor, argument) = constructor_to_tuple(the_rule);
Expression::Constructor(constructor, Box::new(argument))
}
fn universe_to_expression(the_rule: Tok) -> Expression {
let mut inner: Tik = the_rule.into_inner();
let level = inner.next().unwrap().as_str();
Expression::Type(level.parse().unwrap_or(0))
}
fn constructor_to_tuple(the_rule: Tok) -> (String, Expression) {
let mut inner: Tik = the_rule.into_inner();
let constructor = next_constructor_name(&mut inner);
let argument = inner
.next()
.map(expression_to_expression)
.unwrap_or(Expression::Unit);
end_of_rule(&mut inner);
(constructor, argument)
}
fn maybe_pattern_to_pattern(the_rule: Tok) -> Pattern {
let mut inner: Tik = the_rule.into_inner();
let pattern = inner
.next()
.map(pattern_to_pattern)
.unwrap_or(Pattern::Unit);
end_of_rule(&mut inner);
pattern
}
fn variable_to_expression(the_rule: Tok) -> Expression {
let mut inner: Tik = the_rule.into_inner();
let name = next_rule!(inner, identifier, identifier_to_name);
end_of_rule(&mut inner);
Expression::Var(name)
}
fn identifier_to_name(rule: Tok) -> String {
rule.as_span().as_str().to_string()
}
#[cfg(test)]
mod tests {
use crate::parser::parse_str_err_printed;
fn successful_test_case(code: &str) {
println!("========= source ===========");
println!("{}", code);
println!("========= result ===========");
let expr = parse_str_err_printed(code).unwrap();
print!("{}", expr);
let code = format!("{}", expr);
println!("========= double ===========");
print!("{}", parse_str_err_printed(code.as_str()).unwrap());
println!("========= finish ===========\n");
}
#[test]
fn simple_parse() {
successful_test_case("let unit_one : 1 = 0;\nlet type_one : Type0 = unit_one;");
successful_test_case("let application : k = f e;");
successful_test_case("let pair_first_second : k = ((x, y).1).2;");
successful_test_case("let sigma_type : \\Sigma x : x_type . y = x, y;");
successful_test_case("let constructor : C k = C e;");
successful_test_case("let pi_lambda : \\Pi a : b . c = \\lambda a . expr;");
successful_test_case("let pat, pat2 : \\Pi _ : b . c = \\lambda _ . expr;");
successful_test_case("let function : Sum {C e} = split {C _ => e};");
}
#[test]
fn no_reparse() {
successful_no_reparse("let function (x : a) : bla = rua;");
}
fn successful_no_reparse(code: &str) {
println!("{}", parse_str_err_printed(code).unwrap());
}
}