Skip to content
Snippets Groups Projects
Commit fee50aa2 authored by Per's avatar Per
Browse files

work in progress

parent 0259a429
Branches
No related tags found
No related merge requests found
extern crate nom;
use crust::parse::test;
use crust::{
ast::Span,
parse::{parse_assign, test},
};
fn main() {
test("- -1 + + 1", - -1 + 1); // rust does not allow + as a unary op (I do ;)
test("(-1-1)+(-1+3)", (-1 - 1) + (-1) + 3);
// just to check that right associative works (you don't need to implement pow)
test("2+3**2**3*5+1", 2 + 3i32.pow(2u32.pow(3)) * 5 + 1);
test("(12*2)/3-4", (12 * 2) / 3 - 4);
test("1*2+3", 1 * 2 + 3);
// just to check that we get a parse error
test("1*2+3+3*21-a12+2", 1 * 2 + 3 + 3 * 21 - 12 + 2);
// test("- -1 + + 1", - -1 + 1); // rust does not allow + as a unary op (I do ;)
// test("(-1-1)+(-1+3)", (-1 - 1) + (-1) + 3);
// // just to check that right associative works (you don't need to implement pow)
// test("2+3**2**3*5+1", 2 + 3i32.pow(2u32.pow(3)) * 5 + 1);
// test("(12*2)/3-4", (12 * 2) / 3 - 4);
// test("1*2+3", 1 * 2 + 3);
// // just to check that we get a parse error
// test("1*2+3+3*21-a12+2", 1 * 2 + 3 + 3 * 21 - 12 + 2);
test("1 + a(1, 2)", 1 + 2);
println!("{:?}", parse_assign(Span::new("3 = 4")));
}
......@@ -23,11 +23,81 @@ type SpanOp<'a> = (Span<'a>, Op);
#[derive(Debug, Clone, PartialEq)]
pub enum Expr<'a> {
Num(i32),
Bool(bool),
Par(Box<SpanExpr<'a>>),
// Identifier
// Function application
Id(String),
Fn(String, Vec<SpanExpr<'a>>),
BinOp(Op, Box<SpanExpr<'a>>, Box<SpanExpr<'a>>),
UnaryOp(Op, Box<SpanExpr<'a>>),
}
pub type SpanExpr<'a> = (Span<'a>, Expr<'a>);
#[derive(Debug, PartialEq, Clone)]
pub enum Cmd<'a> {
// let <mut> id : <& <mut>>Type = expr
Let(SpanMut<'a>, String, SpanType<'a>, SpanExpr<'a>),
// id = expr
Assign(SpanExpr<'a>, SpanExpr<'a>),
// /// if predicate do-this, and optionally do-that)
// If(Expr, Block, Option<Block>),
// /// while predicate do-this
// While(Expr, Block),
// Return(Expr),
}
pub type SpanCmd<'a> = (Span<'a>, Cmd<'a>);
#[derive(Debug, PartialEq, Clone)]
pub enum Mutability {
Imm,
Mut,
}
pub type SpanMut<'a> = (Span<'a>, Mutability);
// #[derive(Debug, PartialEq, Clone)]
// pub enum Cmd {
// /// let <mut> id : <& <mut>>Type = expr
// Let(Mutability, String, Type, Expr),
// /// id = expr
// Assign(Expr, Expr),
// /// if predicate do-this, and optionally do-that)
// If(Expr, Block, Option<Block>),
// /// while predicate do-this
// While(Expr, Block),
// Return(Expr),
// }
pub type SpanBlock<'a> = (Span<'a>, Vec<SpanCmd<'a>>);
#[derive(Debug, PartialEq, Clone)]
pub enum Type<'a> {
I32,
Bool,
Unit,
Mut(Box<SpanType<'a>>),
Ref(Box<SpanType<'a>>),
// no structs
}
pub type SpanType<'a> = (Span<'a>, Type<'a>);
// #[derive(Debug, PartialEq, Clone)]
// pub enum TypeDecl {
// Struct(String, Vec<(String, Type)>),
// }
// #[derive(Debug, PartialEq, Clone)]
// pub struct Function {
// pub sig: (String, Vec<(String, Type)>, Type),
// pub body: Block,
// }
// #[derive(Debug, PartialEq, Clone)]
// pub enum Item {
// TypeDecl(TypeDecl),
// Function(Function),
// }
// pub type Prog = Vec<Item>;
......@@ -6,16 +6,15 @@ use std::slice::Iter;
use nom::{
branch::alt,
bytes::complete::tag,
character::complete::char,
character::complete::{digit1, multispace0},
character::complete::{alpha1, char, digit1, multispace0},
combinator::{cut, map},
error::ParseError,
multi::many1,
sequence::{delimited, preceded},
multi::{many1, separated_list},
sequence::{delimited, preceded, tuple},
IResult,
};
use crate::ast::{Expr, Op, Span, SpanExpr};
use crate::ast::{Cmd, Expr, Op, Span, SpanCmd, SpanExpr};
pub fn parse_i32(i: Span) -> IResult<Span, (Span, i32)> {
map(digit1, |digit_str: Span| {
......@@ -41,6 +40,9 @@ fn parse_op(i: Span) -> IResult<Span, (Span, Op)> {
#[derive(Debug, Clone, PartialEq)]
pub enum Token<'a> {
Num(i32),
Bool(bool),
Id(String),
Fn(String, Vec<(Span<'a>, Vec<SpanToken<'a>>)>),
Par(Vec<SpanToken<'a>>),
Op(Op),
}
......@@ -50,6 +52,12 @@ type SpanToken<'a> = (Span<'a>, Token<'a>);
fn parse_terminal(i: Span) -> IResult<Span, SpanToken> {
alt((
map(parse_i32, |(s, v)| (s, Token::Num(v))),
map(tag("true"), |s| (s, Token::Bool(true))),
map(tag("false"), |s| (s, Token::Bool(false))),
map(tuple((alpha1, parse_par(separated_list(char(','), parse_tokens)))), |(s, t)| {
(s, Token::Fn(s.to_string(), t))
}),
map(alpha1, |s: Span| (s, Token::Id(s.to_string()))),
map(parse_par(parse_tokens), |(s, tokens)| {
(s, Token::Par(tokens))
}),
......@@ -71,8 +79,12 @@ fn parse_tokens(i: Span) -> IResult<Span, (Span, Vec<SpanToken>)> {
fn compute_atom<'a>(t: &mut Peekable<Iter<SpanToken<'a>>>) -> SpanExpr<'a> {
match t.next() {
Some((s, Token::Num(i))) => (*s, Expr::Num(*i)),
Some((s, Token::Bool(b))) => (*s, Expr::Bool(*b)),
Some((s, Token::Id(id))) => (*s, Expr::Id(id.to_string())),
Some((_, Token::Par(v))) => climb(&mut v.iter().peekable(), 0),
Some((s, Token::Op(op))) => (*s, Expr::UnaryOp(*op, Box::new(climb(t, 4)))), // assume highest precedence
Some((s, Token::Op(op))) => {
(*s, Expr::UnaryOp(*op, Box::new(climb(t, 4))))
} // assume highest precedence
_ => panic!("error in compute atom"),
}
}
......@@ -107,12 +119,15 @@ fn climb<'a>(
result
}
pub fn parse_expr(i: Span) -> IResult<Span, SpanExpr> {
map(parse_tokens, |(_, tokens)| {
climb(&mut tokens.iter().peekable(), 0)
})(i)
}
pub fn test(s: &str, v: i32) {
match parse_tokens(Span::new(s)) {
Ok((Span { fragment: "", .. }, (_, t))) => {
let mut t = t.iter().peekable();
println!("{:?}", &t);
let e = climb(&mut t, 0);
match parse_expr(Span::new(s)) {
Ok((Span { fragment: "", .. }, e)) => {
println!("{:?}", &e);
println!("eval {} {}", math_eval(&e), v);
assert_eq!(math_eval(&e), v);
......@@ -138,6 +153,209 @@ where
delimited(char('('), preceded(multispace0, inner), cut(char(')')))
}
// fn parse_if<'a>(i: Span) -> IResult<Span, SpanCmd> {
// map(
// preceded(
// // here to avoid ambiguity with other names starting with `if`, if we added
// // variables to our language, we say that if must be terminated by at least
// // one whitespace character
// terminated(tag("if"), multispace1),
// cut(tuple((
// parse_expr,
// parse_block,
// opt(preceded(preceded(multispace0, tag("else")), parse_block)),
// ))),
// ),
// |(pred, true_branch, maybe_false_branch)| {
// Cmd::If(pred, true_branch, maybe_false_branch)
// },
// )(i)
// }
// pub fn parse_let(i: &str) -> IResult<&str, Cmd, VerboseError<&str>> {
// context(
// "let expression",
// map(
// preceded(
// // here to avoid ambiguity with other names starting with `let`, if we added
// // variables to our language, we say that if must be terminated by at least
// // one whitespace character
// terminated(tag("let"), multispace1),
// cut(tuple((
// opt(preceded(multispace0, terminated(tag("mut"), multispace1))),
// parse_id,
// preceded(preceded(multispace0, tag(":")), parse_type),
// preceded(preceded(multispace0, tag("=")), parse_expr),
// ))),
// ),
// |(m, id, t, expr)| {
// Cmd::Let(
// if m.is_some() {
// Mutability::Mut
// } else {
// Mutability::Imm
// },
// id,
// t,
// expr,
// )
// },
// ),
// )(i)
// }
pub fn parse_assign<'a>(i: Span<'a>) -> IResult<Span<'a>, Cmd<'a>> {
map(
// here to avoid ambiguity with other names starting with `let`, if we added
// variables to our language, we say that if must be terminated by at least
// one whitespace character
tuple((
parse_expr,
preceded(preceded(multispace0, tag("=")), parse_expr),
)),
|(id_expr, expr)| Cmd::Assign(id_expr, expr),
)(i)
}
// pub fn parse_return(i: &str) -> IResult<&str, Cmd, VerboseError<&str>> {
// context(
// "assign",
// map(
// preceded(terminated(tag("return"), multispace1), parse_expr),
// |expr| Cmd::Return(expr),
// ),
// )(i)
// }
// pub fn parse_while(i: &str) -> IResult<&str, Cmd, VerboseError<&str>> {
// context(
// "while expression",
// map(
// preceded(
// // here to avoid ambiguity with other names starting with `let`, if we added
// // variables to our language, we say that if must be terminated by at least
// // one whitespace character
// terminated(tag("while"), multispace1),
// cut(tuple((parse_expr, parse_block))),
// ),
// |(pred, body)| Cmd::While(pred, body),
// ),
// )(i)
// }
// pub fn parse_cmd(i: &str) -> IResult<&str, Cmd, VerboseError<&str>> {
// preceded(
// multispace0,
// alt((parse_while, parse_let, parse_if, parse_assign, parse_return)),
// )(i)
// }
// pub fn parse_block(i: &str) -> IResult<&str, Block, VerboseError<&str>> {
// preceded(multispace0, s_cmd(separated_list(tag(";"), parse_cmd)))(i)
// }
// fn s_cmd<'a, O, F>(inner: F) -> impl Fn(&'a str) -> IResult<&'a str, O, VerboseError<&'a str>>
// where
// F: Fn(&'a str) -> IResult<&'a str, O, VerboseError<&'a str>>,
// {
// // delimited allows us to split up the input
// // cut allows us to consume the input (and prevent backtracking)
// preceded(
// multispace0,
// delimited(
// char('{'),
// preceded(multispace0, inner),
// context(
// "closing curly bracket",
// cut(preceded(multispace0, char('}'))),
// ),
// ),
// )
// }
// pub fn parse_type(i: &str) -> IResult<&str, Type, VerboseError<&str>> {
// preceded(
// multispace0,
// alt((
// map(tag("i32"), |_| Type::I32),
// map(tag("bool"), |_| Type::Bool),
// map(preceded(tag("&"), parse_type), |t| Type::Ref(Box::new(t))),
// map(
// preceded(terminated(tag("mut"), multispace1), parse_type),
// |t| Type::Mut(Box::new(t)),
// ),
// )),
// )(i)
// }
// pub fn parse_field_decl(i: &str) -> IResult<&str, (String, Type), VerboseError<&str>> {
// map(
// tuple((parse_id, preceded(multispace0, tag(":")), parse_type)),
// |(l, _, r)| (l, r),
// )(i)
// }
// pub fn parse_field_decls(i: &str) -> IResult<&str, Vec<(String, Type)>, VerboseError<&str>> {
// s_cmd(separated_list(tag(","), parse_field_decl))(i)
// }
// // pub fn parse_par_decls(i: &str) -> IResult<&str, Vec<(String, Type)>, VerboseError<&str>> {
// // s_cmd(separated_list(tag(","), parse_par_decl))(i)
// // }
// pub fn parse_par_decl(i: &str) -> IResult<&str, (String, Type), VerboseError<&str>> {
// map(
// tuple((
// opt(preceded(multispace0, terminated(tag("mut"), multispace1))),
// parse_id,
// preceded(multispace0, tag(":")),
// parse_type,
// )),
// |(b, id, _, t)| (id, t),
// )(i)
// }
// pub fn parse_type_decl(i: &str) -> IResult<&str, TypeDecl, VerboseError<&str>> {
// preceded(
// preceded(multispace0, terminated(tag("struct"), multispace1)),
// map(tuple((parse_id, parse_field_decls)), |(id, fields)| {
// TypeDecl::Struct(id, fields)
// }),
// )(i)
// }
// pub fn parse_function_decl(i: &str) -> IResult<&str, Function, VerboseError<&str>> {
// map(
// preceded(
// preceded(multispace0, terminated(tag("fn"), multispace1)),
// tuple((
// parse_id,
// s_exp(separated_list(tag(","), parse_par_decl)),
// opt(preceded(
// preceded(multispace0, terminated(tag("->"), multispace1)),
// parse_type,
// )),
// parse_block,
// )),
// ),
// |(id, par, ret, body)| Function {
// sig: (id, par, ret.unwrap_or(Type::Unit)),
// body: body,
// },
// )(i)
// }
// pub fn parse_prog(i: &str) -> IResult<&str, Prog, VerboseError<&str>> {
// separated_list(
// multispace0,
// alt((
// map(parse_function_decl, |f| Item::Function(f)),
// map(parse_type_decl, |t| Item::TypeDecl(t)),
// )),
// )(i)
// }
// tests
fn math_eval(e: &SpanExpr) -> i32 {
match e.clone().1 {
Expr::Num(i) => i,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment