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

wip (span working)

parent be369876
No related branches found
No related tags found
No related merge requests found
...@@ -149,9 +149,7 @@ fn main() { ...@@ -149,9 +149,7 @@ fn main() {
} }
// helpers // helpers
fn parse_par<'a, O, F, E>( fn parse_par<'a, O, F, E>(inner: F) -> impl Fn(&'a str) -> IResult<&'a str, O, E>
inner: F,
) -> impl Fn(&'a str) -> IResult<&'a str, O, E>
where where
F: Fn(&'a str) -> IResult<&'a str, O, E>, F: Fn(&'a str) -> IResult<&'a str, O, E>,
E: ParseError<&'a str>, E: ParseError<&'a str>,
......
...@@ -81,7 +81,6 @@ fn test_parse_i32_1() { ...@@ -81,7 +81,6 @@ fn test_parse_i32_1() {
); );
} }
fn main() { fn main() {
let (a, b) = parse_expr(Span::new("1")).unwrap(); let (a, b) = parse_expr(Span::new("1")).unwrap();
println!("{:?}", parse_expr(Span::new("1"))); println!("{:?}", parse_expr(Span::new("1")));
......
...@@ -61,7 +61,11 @@ pub fn parse_i32<'a>(i: Span<'a>) -> IResult<Span<'a>, SpanExpr> { ...@@ -61,7 +61,11 @@ pub fn parse_i32<'a>(i: Span<'a>) -> IResult<Span<'a>, SpanExpr> {
let (i, digits) = digit1(i)?; let (i, digits) = digit1(i)?;
match digits.fragment.parse() { match digits.fragment.parse() {
Ok(int) => Ok((i, (digits, Expr::Num(int)))), Ok(int) => Ok((i, (digits, Expr::Num(int)))),
Err(e) => Err(Err::Failure(Error(i, Some(digits), ErrorKind::ParseIntError(e)))), Err(e) => Err(Err::Failure(Error(
i,
Some(digits),
ErrorKind::ParseIntError(e),
))),
} }
} }
......
use crust::{ use crust::{
ast::Span, ast::Span,
parse::{parse_assign, parse_expr}, interpreter::eval_expr,
interpreter::{eval_expr} parse::{parse_assign, parse_expr, parse_prog},
}; };
fn test(s: &str, v: i32) { fn test(s: &str, v: i32) {
...@@ -19,7 +19,7 @@ fn test(s: &str, v: i32) { ...@@ -19,7 +19,7 @@ fn test(s: &str, v: i32) {
} }
} }
fn main() { fn test_expr() {
// test("- -1 + + 1", - -1 + 1); // rust does not allow + as a unary op (I do ;) // test("- -1 + + 1", - -1 + 1); // rust does not allow + as a unary op (I do ;)
// test("(-1-1)+(-1+3)", (-1 - 1) + (-1) + 3); // test("(-1-1)+(-1+3)", (-1 - 1) + (-1) + 3);
// // just to check that right associative works (you don't need to implement pow) // // just to check that right associative works (you don't need to implement pow)
...@@ -29,5 +29,15 @@ fn main() { ...@@ -29,5 +29,15 @@ fn main() {
// // just to check that we get a parse error // // 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*2+3+3*21-a12+2", 1 * 2 + 3 + 3 * 21 - 12 + 2);
test("1 + (1 - 2)", 1 + (1 - 2)); test("1 + (1 - 2)", 1 + (1 - 2));
println!("{:?}", parse_assign(Span::new("3 = a(1, 2+3)"))); }
fn main() {
// println!("{:?}", parse_assign(Span::new("3 = a(1, 2+3)")));
println!(
"{:?}",
parse_prog(Span::new(
"
fn main() { let a:i32 = 1} "
))
);
} }
...@@ -20,6 +20,8 @@ pub enum Op { ...@@ -20,6 +20,8 @@ pub enum Op {
type SpanOp<'a> = (Span<'a>, Op); type SpanOp<'a> = (Span<'a>, Op);
pub type SpanId<'a> = Span<'a>;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum Expr<'a> { pub enum Expr<'a> {
Num(i32), Num(i32),
...@@ -36,14 +38,14 @@ pub type SpanExpr<'a> = (Span<'a>, Expr<'a>); ...@@ -36,14 +38,14 @@ pub type SpanExpr<'a> = (Span<'a>, Expr<'a>);
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum Cmd<'a> { pub enum Cmd<'a> {
// let <mut> id : <& <mut>>Type = expr // let <mut> id : <& <mut>>Type = expr
Let(SpanMut<'a>, String, SpanType<'a>, SpanExpr<'a>), Let(Mutability, SpanId<'a>, Type, SpanExpr<'a>),
// id = expr // id = expr
Assign(SpanExpr<'a>, SpanExpr<'a>), Assign(SpanExpr<'a>, SpanExpr<'a>),
// if predicate do-this, and optionally do-that) // if predicate do-this, and optionally do-that)
If(SpanExpr<'a>, SpanBlock<'a>, Option<SpanBlock<'a>>), If(SpanExpr<'a>, Block<'a>, Option<Block<'a>>),
// /// while predicate do-this // while predicate do-this
// While(Expr, Block), While(SpanExpr<'a>, Block<'a>),
// Return(Expr), Return(SpanExpr<'a>),
} }
pub type SpanCmd<'a> = (Span<'a>, Cmd<'a>); pub type SpanCmd<'a> = (Span<'a>, Cmd<'a>);
...@@ -53,52 +55,32 @@ pub enum Mutability { ...@@ -53,52 +55,32 @@ pub enum Mutability {
Imm, Imm,
Mut, Mut,
} }
pub type SpanMut<'a> = (Span<'a>, Mutability); 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>>); pub type SpanBlock<'a> = (Span<'a>, Vec<SpanCmd<'a>>);
pub type Block<'a> = Vec<Cmd<'a>>; pub type Block<'a> = Vec<Cmd<'a>>;
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum Type<'a> { pub enum Type {
I32, I32,
Bool, Bool,
Unit, Unit,
Mut(Box<SpanType<'a>>), Mut(Box<Type>),
Ref(Box<SpanType<'a>>), Ref(Box<Type>),
// no structs // no structs
} }
pub type SpanType<'a> = (Span<'a>, Type<'a>); // pub type SpanType<'a> = (Span<'a>, Type<'a>);
// #[derive(Debug, PartialEq, Clone)]
// pub enum TypeDecl {
// Struct(String, Vec<(String, Type)>),
// }
// #[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
// pub struct Function { pub struct Func<'a> {
// pub sig: (String, Vec<(String, Type)>, Type), pub sig: (SpanId<'a>, Vec<(SpanId<'a>, Type)>, Type),
// pub body: Block, pub body: Block<'a>,
// } }
// #[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
// pub enum Item { pub enum Item<'a> {
// TypeDecl(TypeDecl), Func(Func<'a>),
// Function(Function), }
// }
// pub type Prog = Vec<Item>; pub type Prog<'a> = Vec<Item<'a>>;
// lib // lib
pub mod ast; pub mod ast;
pub mod parse;
pub mod interpreter; pub mod interpreter;
pub mod parse;
...@@ -6,7 +6,7 @@ use std::slice::Iter; ...@@ -6,7 +6,7 @@ use std::slice::Iter;
use nom::{ use nom::{
branch::alt, branch::alt,
bytes::complete::tag, bytes::complete::tag,
character::complete::{alpha1, char, digit1, multispace0, multispace1}, character::complete::{alpha1, alphanumeric0, char, digit1, multispace0, multispace1},
combinator::{cut, map, opt}, combinator::{cut, map, opt},
error::ParseError, error::ParseError,
multi::{many1, separated_list}, multi::{many1, separated_list},
...@@ -14,7 +14,9 @@ use nom::{ ...@@ -14,7 +14,9 @@ use nom::{
IResult, IResult,
}; };
use crate::ast::{Cmd, Expr, Op, Span, SpanCmd, SpanExpr, Block}; use crate::ast::{
Block, Cmd, Expr, Func, Item, Mutability, Op, Prog, Span, SpanCmd, SpanExpr, SpanId, Type,
};
pub fn parse_i32(i: Span) -> IResult<Span, (Span, i32)> { pub fn parse_i32(i: Span) -> IResult<Span, (Span, i32)> {
map(digit1, |digit_str: Span| { map(digit1, |digit_str: Span| {
...@@ -49,16 +51,26 @@ pub enum Token<'a> { ...@@ -49,16 +51,26 @@ pub enum Token<'a> {
type SpanToken<'a> = (Span<'a>, Token<'a>); type SpanToken<'a> = (Span<'a>, Token<'a>);
pub fn parse_id(i: Span) -> IResult<Span, Span> {
// an identifier needs to start with one or more alphas (head)
// followed by zero or more alphanumerics (tail)
map(
preceded(multispace0, tuple((alpha1, alphanumeric0))),
// we concatenate the head and tail into a single String
|(_, _)| i, // head.to_string() + &tail.to_string(),
)(i)
}
fn parse_terminal(i: Span) -> IResult<Span, SpanToken> { fn parse_terminal(i: Span) -> IResult<Span, SpanToken> {
alt(( alt((
map(parse_i32, |(s, v)| (s, Token::Num(v))), map(parse_i32, |(s, v)| (s, Token::Num(v))),
map(tag("true"), |s| (s, Token::Bool(true))), map(tag("true"), |s| (s, Token::Bool(true))),
map(tag("false"), |s| (s, Token::Bool(false))), map(tag("false"), |s| (s, Token::Bool(false))),
map( map(
tuple((alpha1, parse_par(separated_list(char(','), parse_tokens)))), tuple((parse_id, parse_par(separated_list(char(','), parse_tokens)))),
|(s, t)| (s, Token::Call(s.to_string(), t)), |(s, t)| (s, Token::Call(s.to_string(), t)),
), ),
map(alpha1, |s: Span| (s, Token::Id(s.to_string()))), map(parse_id, |s: Span| (s, Token::Id(s.to_string()))),
map(parse_par(parse_tokens), |(s, tokens)| { map(parse_par(parse_tokens), |(s, tokens)| {
(s, Token::Par(tokens)) (s, Token::Par(tokens))
}), }),
...@@ -129,78 +141,52 @@ pub fn parse_expr(i: Span) -> IResult<Span, SpanExpr> { ...@@ -129,78 +141,52 @@ pub fn parse_expr(i: Span) -> IResult<Span, SpanExpr> {
})(i) })(i)
} }
// fn parse_if(i: Span) -> IResult<Span, SpanCmd> { fn parse_if(i: Span) -> IResult<Span, Cmd> {
// map( map(
// preceded( preceded(
// // here to avoid ambiguity with other names starting with `if`, if we added // 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 // variables to our language, we say that if must be terminated by at least
// // one whitespace character // one whitespace character
// terminated(tag("if"), multispace1), terminated(tag("if"), multispace1),
// cut(tuple(( cut(tuple((
// parse_expr, parse_expr,
// parse_block, parse_block,
// opt(preceded(preceded(multispace0, tag("else")), parse_block)), opt(preceded(preceded(multispace0, tag("else")), parse_block)),
// ))), ))),
// ), ),
// |(pred, true_branch, maybe_false_branch)| { |(pred, true_branch, maybe_false_branch)| Cmd::If(pred, true_branch, maybe_false_branch),
// Cmd::If(pred, true_branch, maybe_false_branch) )(i)
// },
// )(i)
// }
// helpers
fn parse_par<'a, O, F, E>(inner: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, O, E>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O, E>,
E: ParseError<Span<'a>>,
{
// delimited allows us to split up the input
// cut allwos us to consume the input (and prevent backtracking)
delimited(char('('), preceded(multispace0, inner), cut(char(')')))
} }
fn parse_sem<'a, O, F, E>(inner: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, O, E> pub fn parse_let(i: Span) -> IResult<Span, Cmd> {
where map(
F: Fn(Span<'a>) -> IResult<Span<'a>, O, E>, preceded(
E: ParseError<Span<'a>>, // 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
// delimited allows us to split up the input // one whitespace character
// cut allwos us to consume the input (and prevent backtracking) terminated(tag("let"), multispace1),
delimited(char('{'), preceded(multispace0, inner), cut(char('}'))) 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_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>> { pub fn parse_assign<'a>(i: Span<'a>) -> IResult<Span<'a>, Cmd<'a>> {
map( map(
// here to avoid ambiguity with other names starting with `let`, if we added // here to avoid ambiguity with other names starting with `let`, if we added
...@@ -214,38 +200,32 @@ pub fn parse_assign<'a>(i: Span<'a>) -> IResult<Span<'a>, Cmd<'a>> { ...@@ -214,38 +200,32 @@ pub fn parse_assign<'a>(i: Span<'a>) -> IResult<Span<'a>, Cmd<'a>> {
)(i) )(i)
} }
// pub fn parse_return(i: &str) -> IResult<&str, Cmd, VerboseError<&str>> { pub fn parse_return(i: Span) -> IResult<Span, Cmd> {
// context( map(
// "assign", preceded(terminated(tag("return"), multispace1), parse_expr),
// map( |expr| Cmd::Return(expr),
// preceded(terminated(tag("return"), multispace1), parse_expr), )(i)
// |expr| Cmd::Return(expr), }
// ),
// )(i)
// }
// pub fn parse_while(i: &str) -> IResult<&str, Cmd, VerboseError<&str>> { pub fn parse_while(i: Span) -> IResult<Span, Cmd> {
// context( map(
// "while expression", preceded(
// map( // here to avoid ambiguity with other names starting with `let`, if we added
// preceded( // variables to our language, we say that if must be terminated by at least
// // here to avoid ambiguity with other names starting with `let`, if we added // one whitespace character
// // variables to our language, we say that if must be terminated by at least terminated(tag("while"), multispace1),
// // one whitespace character cut(tuple((parse_expr, parse_block))),
// terminated(tag("while"), multispace1), ),
// cut(tuple((parse_expr, parse_block))), |(pred, body)| Cmd::While(pred, body),
// ), )(i)
// |(pred, body)| Cmd::While(pred, body), }
// ),
// )(i)
// }
// pub fn parse_cmd<'a>(i: Span<'a>) -> IResult<Span<'a>, Cmd<'a>> { // pub fn parse_cmd<'a>(i: Span<'a>) -> IResult<Span<'a>, Cmd<'a>> {
pub fn parse_cmd(i: Span) -> IResult<Span, Cmd> { pub fn parse_cmd(i: Span) -> IResult<Span, Cmd> {
preceded( preceded(
multispace0, multispace0,
parse_assign, //parse_assign,
// alt((parse_while, parse_let, parse_if, parse_assign, parse_return)), alt((parse_while, parse_let, parse_if, parse_assign, parse_return)),
)(i) )(i)
} }
...@@ -253,106 +233,61 @@ pub fn parse_block(i: Span) -> IResult<Span, Block> { ...@@ -253,106 +233,61 @@ pub fn parse_block(i: Span) -> IResult<Span, Block> {
preceded(multispace0, parse_sem(separated_list(tag(";"), parse_cmd)))(i) preceded(multispace0, parse_sem(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>> pub fn parse_type(i: Span) -> IResult<Span, Type> {
// where preceded(
// F: Fn(&'a str) -> IResult<&'a str, O, VerboseError<&'a str>>, multispace0,
// { alt((
// // delimited allows us to split up the input map(tag("i32"), |_| Type::I32),
// // cut allows us to consume the input (and prevent backtracking) map(tag("bool"), |_| Type::Bool),
// preceded( map(preceded(tag("&"), parse_type), |t| Type::Ref(Box::new(t))),
// multispace0, map(
// delimited( preceded(terminated(tag("mut"), multispace1), parse_type),
// char('{'), |t| Type::Mut(Box::new(t)),
// preceded(multispace0, inner), ),
// context( )),
// "closing curly bracket", )(i)
// 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>> { pub fn parse_par_decls(i: Span) -> IResult<Span, Vec<(SpanId, Type)>> {
// map( parse_par(separated_list(tag(","), parse_par_decl))(i)
// 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>> { pub fn parse_par_decl(i: Span) -> IResult<Span, (SpanId, Type)> {
// preceded( map(
// preceded(multispace0, terminated(tag("struct"), multispace1)), tuple((
// map(tuple((parse_id, parse_field_decls)), |(id, fields)| { opt(preceded(multispace0, terminated(tag("mut"), multispace1))),
// TypeDecl::Struct(id, fields) parse_id,
// }), preceded(multispace0, tag(":")),
// )(i) parse_type,
// } )),
|(b, id, _, t)| (id, t),
)(i)
}
// pub fn parse_function_decl(i: &str) -> IResult<&str, Function, VerboseError<&str>> { pub fn parse_function_decl(i: Span) -> IResult<Span, Func> {
// map( map(
// preceded( preceded(
// preceded(multispace0, terminated(tag("fn"), multispace1)), preceded(multispace0, terminated(tag("fn"), multispace1)),
// tuple(( tuple((
// parse_id, parse_id,
// s_exp(separated_list(tag(","), parse_par_decl)), parse_par(separated_list(tag(","), parse_par_decl)),
// opt(preceded( opt(preceded(
// preceded(multispace0, terminated(tag("->"), multispace1)), preceded(multispace0, terminated(tag("->"), multispace1)),
// parse_type, parse_type,
// )), )),
// parse_block, parse_block,
// )), )),
// ), ),
// |(id, par, ret, body)| Function { |(id, par, ret, body)| Func {
// sig: (id, par, ret.unwrap_or(Type::Unit)), sig: (id, par, ret.unwrap_or(Type::Unit)),
// body: body, body: body,
// }, },
// )(i) )(i)
// } }
// pub fn parse_prog(i: &str) -> IResult<&str, Prog, VerboseError<&str>> { pub fn parse_prog(i: Span) -> IResult<Span, Prog> {
// separated_list( separated_list(multispace0, map(parse_function_decl, |f| Item::Func(f)))(i)
// multispace0, }
// alt((
// map(parse_function_decl, |f| Item::Function(f)),
// map(parse_type_decl, |t| Item::TypeDecl(t)),
// )),
// )(i)
// }
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
enum Ass { enum Ass {
...@@ -370,3 +305,24 @@ fn get_prec(op: &Op) -> (u8, Ass) { ...@@ -370,3 +305,24 @@ fn get_prec(op: &Op) -> (u8, Ass) {
_ => unimplemented!(), _ => unimplemented!(),
} }
} }
// helpers
fn parse_par<'a, O, F, E>(inner: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, O, E>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O, E>,
E: ParseError<Span<'a>>,
{
// delimited allows us to split up the input
// cut allwos us to consume the input (and prevent backtracking)
delimited(char('('), preceded(multispace0, inner), cut(char(')')))
}
fn parse_sem<'a, O, F, E>(inner: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, O, E>
where
F: Fn(Span<'a>) -> IResult<Span<'a>, O, E>,
E: ParseError<Span<'a>>,
{
// delimited allows us to split up the input
// cut allwos us to consume the input (and prevent backtracking)
delimited(char('{'), preceded(multispace0, inner), cut(char('}')))
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment