Various other expr stuff

This commit is contained in:
Greg Shuflin 2021-11-18 04:01:40 -08:00
parent a666ac985b
commit 7a9e43bf8e
2 changed files with 77 additions and 26 deletions

View File

@ -2,7 +2,8 @@ use std::{cell::RefCell, rc::Rc};
use nom::{
branch::alt,
bytes::complete::{tag, escaped_transform, take_till},
bytes::complete::{tag, escaped_transform, take_while, take_till},
character::is_alphanumeric,
character::complete::{
alpha1, alphanumeric0, char, line_ending, none_of, not_line_ending, one_of, space0,
space1,
@ -132,14 +133,17 @@ fn type_singleton_name(input: Span) -> ParseResult<TypeSingletonName> {
}
pub fn expression_kind(input: Span) -> ParseResult<ExpressionKind> {
context("expression-kind", prefix_expr)(input)
context("expression-kind", precedence_expr)(input)
}
fn precedence_expr(input: Span) -> ParseResult<ExpressionKind> {
let handle = input.extra.clone();
map(
pair(prefix_expr, many0(precedence_continuation)),
|(first, rest): (ExpressionKind, Vec<(BinOp, ExpressionKind)>)| unimplemented!(),
)(input)
move |(first, rest): (ExpressionKind, Vec<(BinOp, ExpressionKind)>)| {
let mut handle_ref = handle.borrow_mut();
BinopSequence { first, rest }.do_precedence(&mut handle_ref)
})(input)
}
fn precedence_continuation(input: Span) -> ParseResult<(BinOp, ExpressionKind)> {
@ -178,12 +182,25 @@ fn extended_expr(input: Span) -> ParseResult<ExpressionKind> {
fn primary_expr(input: Span) -> ParseResult<ExpressionKind> {
context("primary-expr", alt((
list_expr,
list_expr, paren_expr,
string_literal, float_literal, number_literal, bool_literal, identifier_expr
))
)(input)
}
fn paren_expr(input: Span) -> ParseResult<ExpressionKind> {
delimited(
tok(char('(')),
map(separated_list0(tok(char(',')), expression),
|mut exprs| match exprs.len() {
1 => exprs.pop().unwrap().kind,
_ => ExpressionKind::TupleLiteral(exprs),
}),
tok(char(')'))
)(input)
}
fn list_expr(input: Span) -> ParseResult<ExpressionKind> {
map(
delimited(
@ -230,7 +247,7 @@ fn qualified_identifier(input: Span) -> ParseResult<QualifiedName> {
}
fn identifier(input: Span) -> ParseResult<Span> {
recognize(tuple((alt((tag("_"), alpha1)), alphanumeric0)))(input)
recognize(pair(alt((tag("_"), alpha1)), take_while(|ch: char| { is_alphanumeric(ch as u8) || ch == '_'})))(input)
}
fn bool_literal(input: Span) -> ParseResult<ExpressionKind> {
@ -335,6 +352,40 @@ fn parse_hex(digits: &str) -> Result<u64, &'static str> {
Ok(result)
}
#[derive(Debug)]
struct BinopSequence {
first: ExpressionKind,
rest: Vec<(BinOp, ExpressionKind)>,
}
impl BinopSequence {
fn do_precedence(self, store: &mut IdStore<ASTItem>) -> ExpressionKind {
fn helper(
precedence: i32,
lhs: ExpressionKind,
rest: &mut Vec<(BinOp, ExpressionKind)>,
store: &mut IdStore<ASTItem>,
) -> Expression {
let mut lhs = Expression::new(store.fresh(), lhs);
while let Some((next_op, next_rhs)) = rest.pop() {
let new_precedence = next_op.get_precedence();
if precedence >= new_precedence {
rest.push((next_op, next_rhs));
break;
}
let rhs = helper(new_precedence, next_rhs, rest, store);
lhs = Expression::new(
store.fresh(),
ExpressionKind::BinExp(next_op, Box::new(lhs), Box::new(rhs)),
);
}
lhs
}
let mut as_stack = self.rest.into_iter().rev().collect();
helper(BinOp::min_precedence(), self.first, &mut as_stack, store).kind
}
}
#[cfg(test)]
mod test {
use pretty_assertions::assert_eq;

View File

@ -179,7 +179,7 @@ fn binexps() {
use ExpressionKind::*;
use StatementKind::Expression;
assert_expr!("0xf_f_+1", binop("+", expr(NatLiteral(255)), expr(NatLiteral(1))));
assert_expr_comb!("0xf_f+1", binop("+", expr(NatLiteral(255)), expr(NatLiteral(1))));
assert_ast!(
"3; 4; 4.3",
vec![
@ -189,16 +189,16 @@ fn binexps() {
]
);
assert_expr!(
assert_expr_comb!(
"1 + 2 * 3",
binop("+", expr(NatLiteral(1)), binop("*", expr(NatLiteral(2)), expr(NatLiteral(3))))
);
assert_expr!(
assert_expr_comb!(
"1 * 2 + 3",
binop("+", binop("*", expr(NatLiteral(1)), expr(NatLiteral(2))), expr(NatLiteral(3)))
);
assert_expr!("1 && 2", binop("&&", expr(NatLiteral(1)), expr(NatLiteral(2))));
assert_expr!(
assert_expr_comb!("1 && 2", binop("&&", expr(NatLiteral(1)), expr(NatLiteral(2))));
assert_expr_comb!(
"1 + 2 * 3 + 4",
binop(
"+",
@ -206,12 +206,12 @@ fn binexps() {
expr(NatLiteral(4))
)
);
assert_expr!(
assert_expr_comb!(
"(1 + 2) * 3",
binop("*", binop("+", expr(NatLiteral(1)), expr(NatLiteral(2))), expr(NatLiteral(3)))
);
assert_expr!(".1 + .2", binop("+", expr(FloatLiteral(0.1)), expr(FloatLiteral(0.2))));
assert_expr!("1 / 2.", binop("/", expr(NatLiteral(1)), expr(FloatLiteral(2.))));
assert_expr_comb!(".1 + .2", binop("+", expr(FloatLiteral(0.1)), expr(FloatLiteral(0.2))));
assert_expr_comb!("1 / 2.", binop("/", expr(NatLiteral(1)), expr(FloatLiteral(2.))));
}
#[test]
@ -230,9 +230,9 @@ fn prefix_exps() {
fn operators() {
use ExpressionKind::*;
assert_expr!("a <- 1", binop("<-", expr(Value(qn!(a))), expr(NatLiteral(1))));
assert_expr!("a || 1", binop("||", expr(Value(qn!(a))), expr(NatLiteral(1))));
assert_expr!("a <> 1", binop("<>", expr(Value(qn!(a))), expr(NatLiteral(1))));
assert_expr_comb!("a <- 1", binop("<-", expr(Value(qn!(a))), expr(NatLiteral(1))));
assert_expr_comb!("a || 1", binop("||", expr(Value(qn!(a))), expr(NatLiteral(1))));
assert_expr_comb!("a <> 1", binop("<>", expr(Value(qn!(a))), expr(NatLiteral(1))));
}
#[test]
@ -273,12 +273,12 @@ fn accessors() {
fn tuples() {
use ExpressionKind::*;
assert_expr!("()", expr(TupleLiteral(vec![])));
assert_expr!(
assert_expr_comb!("()", expr(TupleLiteral(vec![])));
assert_expr_comb!(
r#"("hella", 34)"#,
expr(TupleLiteral(vec![expr(StringLiteral(rc("hella"))), expr(NatLiteral(34))]))
);
assert_expr!(
assert_expr_comb!(
r#"(1+2, "slough")"#,
expr(TupleLiteral(vec![
binop("+", expr(NatLiteral(1)), expr(NatLiteral(2))),
@ -291,11 +291,11 @@ fn tuples() {
fn identifiers() {
use ExpressionKind::*;
assert_expr!("a", expr(Value(qn!(a))));
assert_expr!("some_value", expr(Value(qn!(some_value))));
assert_expr!("alpha::beta::gamma", expr(Value(qn!(alpha, beta, gamma))));
assert_expr!("a + b", binop("+", expr(Value(qn!(a))), expr(Value(qn!(b)))));
assert_expr!("None", expr(Value(qn!(None))));
assert_expr_comb!("a", expr(Value(qn!(a))));
assert_expr_comb!("some_value", expr(Value(qn!(some_value))));
assert_expr_comb!("alpha::beta::gamma", expr(Value(qn!(alpha, beta, gamma))));
assert_expr_comb!("a + b", binop("+", expr(Value(qn!(a))), expr(Value(qn!(b)))));
assert_expr_comb!("None", expr(Value(qn!(None))));
assert_expr!(
"thing::item::call()",
expr(Call { f: bx(expr(Value(qn!(thing, item, call)))), arguments: vec![] })
@ -1387,7 +1387,7 @@ fn comments() {
use ExpressionKind::*;
let source = "1 + /* hella /* bro */ */ 2";
assert_expr!(source, binop("+", expr(NatLiteral(1)), expr(NatLiteral(2))));
assert_expr_comb!(source, binop("+", expr(NatLiteral(1)), expr(NatLiteral(2))));
//TODO make sure this error message makes sense
let source = "1 + /* hella /* bro */ 2";