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() {
}
// helpers
fn parse_par<'a, O, F, E>(
inner: F,
) -> impl Fn(&'a str) -> IResult<&'a str, O, E>
fn parse_par<'a, O, F, E>(inner: F) -> impl Fn(&'a str) -> IResult<&'a str, O, E>
where
F: Fn(&'a str) -> IResult<&'a str, O, E>,
E: ParseError<&'a str>,
......
......@@ -81,7 +81,6 @@ fn test_parse_i32_1() {
);
}
fn main() {
let (a, b) = parse_expr(Span::new("1")).unwrap();
println!("{:?}", parse_expr(Span::new("1")));
......
......@@ -61,7 +61,11 @@ pub fn parse_i32<'a>(i: Span<'a>) -> IResult<Span<'a>, SpanExpr> {
let (i, digits) = digit1(i)?;
match digits.fragment.parse() {
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::{
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) {
......@@ -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+3)", (-1 - 1) + (-1) + 3);
// // just to check that right associative works (you don't need to implement pow)
......@@ -29,5 +29,15 @@ fn main() {
// // 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 - 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 {
type SpanOp<'a> = (Span<'a>, Op);
pub type SpanId<'a> = Span<'a>;
#[derive(Debug, Clone, PartialEq)]
pub enum Expr<'a> {
Num(i32),
......@@ -36,14 +38,14 @@ 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>),
Let(Mutability, SpanId<'a>, Type, SpanExpr<'a>),
// id = expr
Assign(SpanExpr<'a>, SpanExpr<'a>),
// if predicate do-this, and optionally do-that)
If(SpanExpr<'a>, SpanBlock<'a>, Option<SpanBlock<'a>>),
// /// while predicate do-this
// While(Expr, Block),
// Return(Expr),
If(SpanExpr<'a>, Block<'a>, Option<Block<'a>>),
// while predicate do-this
While(SpanExpr<'a>, Block<'a>),
Return(SpanExpr<'a>),
}
pub type SpanCmd<'a> = (Span<'a>, Cmd<'a>);
......@@ -53,52 +55,32 @@ 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>>);
pub type Block<'a> = Vec<Cmd<'a>>;
#[derive(Debug, PartialEq, Clone)]
pub enum Type<'a> {
pub enum Type {
I32,
Bool,
Unit,
Mut(Box<SpanType<'a>>),
Ref(Box<SpanType<'a>>),
Mut(Box<Type>),
Ref(Box<Type>),
// no structs
}
pub type SpanType<'a> = (Span<'a>, Type<'a>);
// #[derive(Debug, PartialEq, Clone)]
// pub enum TypeDecl {
// Struct(String, Vec<(String, Type)>),
// }
// pub type SpanType<'a> = (Span<'a>, Type<'a>);
// #[derive(Debug, PartialEq, Clone)]
// pub struct Function {
// pub sig: (String, Vec<(String, Type)>, Type),
// pub body: Block,
// }
#[derive(Debug, PartialEq, Clone)]
pub struct Func<'a> {
pub sig: (SpanId<'a>, Vec<(SpanId<'a>, Type)>, Type),
pub body: Block<'a>,
}
// #[derive(Debug, PartialEq, Clone)]
// pub enum Item {
// TypeDecl(TypeDecl),
// Function(Function),
// }
#[derive(Debug, PartialEq, Clone)]
pub enum Item<'a> {
Func(Func<'a>),
}
// pub type Prog = Vec<Item>;
pub type Prog<'a> = Vec<Item<'a>>;
// lib
pub mod ast;
pub mod parse;
pub mod interpreter;
pub mod parse;
......@@ -6,7 +6,7 @@ use std::slice::Iter;
use nom::{
branch::alt,
bytes::complete::tag,
character::complete::{alpha1, char, digit1, multispace0, multispace1},
character::complete::{alpha1, alphanumeric0, char, digit1, multispace0, multispace1},
combinator::{cut, map, opt},
error::ParseError,
multi::{many1, separated_list},
......@@ -14,7 +14,9 @@ use nom::{
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)> {
map(digit1, |digit_str: Span| {
......@@ -49,16 +51,26 @@ pub enum 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> {
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)))),
tuple((parse_id, parse_par(separated_list(char(','), parse_tokens)))),
|(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)| {
(s, Token::Par(tokens))
}),
......@@ -129,78 +141,52 @@ pub fn parse_expr(i: Span) -> IResult<Span, SpanExpr> {
})(i)
}
// fn parse_if(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)
// }
// 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_if(i: Span) -> IResult<Span, Cmd> {
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)
}
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('}')))
pub fn parse_let(i: Span) -> IResult<Span, Cmd> {
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_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
......@@ -214,38 +200,32 @@ pub fn parse_assign<'a>(i: Span<'a>) -> IResult<Span<'a>, Cmd<'a>> {
)(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_return(i: Span) -> IResult<Span, Cmd> {
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_while(i: Span) -> IResult<Span, Cmd> {
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<'a>(i: Span<'a>) -> IResult<Span<'a>, Cmd<'a>> {
pub fn parse_cmd(i: Span) -> IResult<Span, Cmd> {
preceded(
multispace0,
parse_assign,
// alt((parse_while, parse_let, parse_if, parse_assign, parse_return)),
//parse_assign,
alt((parse_while, parse_let, parse_if, parse_assign, parse_return)),
)(i)
}
......@@ -253,106 +233,61 @@ pub fn parse_block(i: Span) -> IResult<Span, Block> {
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>>
// 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_type(i: Span) -> IResult<Span, Type> {
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_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_par_decls(i: Span) -> IResult<Span, Vec<(SpanId, Type)>> {
parse_par(separated_list(tag(","), parse_par_decl))(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_par_decl(i: Span) -> IResult<Span, (SpanId, Type)> {
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_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_function_decl(i: Span) -> IResult<Span, Func> {
map(
preceded(
preceded(multispace0, terminated(tag("fn"), multispace1)),
tuple((
parse_id,
parse_par(separated_list(tag(","), parse_par_decl)),
opt(preceded(
preceded(multispace0, terminated(tag("->"), multispace1)),
parse_type,
)),
parse_block,
)),
),
|(id, par, ret, body)| Func {
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)
// }
pub fn parse_prog(i: Span) -> IResult<Span, Prog> {
separated_list(multispace0, map(parse_function_decl, |f| Item::Func(f)))(i)
}
#[derive(Debug, Copy, Clone, PartialEq)]
enum Ass {
......@@ -370,3 +305,24 @@ fn get_prec(op: &Op) -> (u8, Ass) {
_ => 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