Various other expr stuff
This commit is contained in:
parent
a666ac985b
commit
7a9e43bf8e
@ -2,7 +2,8 @@ use std::{cell::RefCell, rc::Rc};
|
|||||||
|
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
bytes::complete::{tag, escaped_transform, take_till},
|
bytes::complete::{tag, escaped_transform, take_while, take_till},
|
||||||
|
character::is_alphanumeric,
|
||||||
character::complete::{
|
character::complete::{
|
||||||
alpha1, alphanumeric0, char, line_ending, none_of, not_line_ending, one_of, space0,
|
alpha1, alphanumeric0, char, line_ending, none_of, not_line_ending, one_of, space0,
|
||||||
space1,
|
space1,
|
||||||
@ -132,14 +133,17 @@ fn type_singleton_name(input: Span) -> ParseResult<TypeSingletonName> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn expression_kind(input: Span) -> ParseResult<ExpressionKind> {
|
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> {
|
fn precedence_expr(input: Span) -> ParseResult<ExpressionKind> {
|
||||||
|
let handle = input.extra.clone();
|
||||||
map(
|
map(
|
||||||
pair(prefix_expr, many0(precedence_continuation)),
|
pair(prefix_expr, many0(precedence_continuation)),
|
||||||
|(first, rest): (ExpressionKind, Vec<(BinOp, ExpressionKind)>)| unimplemented!(),
|
move |(first, rest): (ExpressionKind, Vec<(BinOp, ExpressionKind)>)| {
|
||||||
)(input)
|
let mut handle_ref = handle.borrow_mut();
|
||||||
|
BinopSequence { first, rest }.do_precedence(&mut handle_ref)
|
||||||
|
})(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn precedence_continuation(input: Span) -> ParseResult<(BinOp, ExpressionKind)> {
|
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> {
|
fn primary_expr(input: Span) -> ParseResult<ExpressionKind> {
|
||||||
context("primary-expr", alt((
|
context("primary-expr", alt((
|
||||||
list_expr,
|
list_expr, paren_expr,
|
||||||
string_literal, float_literal, number_literal, bool_literal, identifier_expr
|
string_literal, float_literal, number_literal, bool_literal, identifier_expr
|
||||||
))
|
))
|
||||||
)(input)
|
)(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> {
|
fn list_expr(input: Span) -> ParseResult<ExpressionKind> {
|
||||||
map(
|
map(
|
||||||
delimited(
|
delimited(
|
||||||
@ -230,7 +247,7 @@ fn qualified_identifier(input: Span) -> ParseResult<QualifiedName> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn identifier(input: Span) -> ParseResult<Span> {
|
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> {
|
fn bool_literal(input: Span) -> ParseResult<ExpressionKind> {
|
||||||
@ -335,6 +352,40 @@ fn parse_hex(digits: &str) -> Result<u64, &'static str> {
|
|||||||
Ok(result)
|
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)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
@ -179,7 +179,7 @@ fn binexps() {
|
|||||||
use ExpressionKind::*;
|
use ExpressionKind::*;
|
||||||
use StatementKind::Expression;
|
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!(
|
assert_ast!(
|
||||||
"3; 4; 4.3",
|
"3; 4; 4.3",
|
||||||
vec![
|
vec![
|
||||||
@ -189,16 +189,16 @@ fn binexps() {
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_expr!(
|
assert_expr_comb!(
|
||||||
"1 + 2 * 3",
|
"1 + 2 * 3",
|
||||||
binop("+", expr(NatLiteral(1)), binop("*", expr(NatLiteral(2)), expr(NatLiteral(3))))
|
binop("+", expr(NatLiteral(1)), binop("*", expr(NatLiteral(2)), expr(NatLiteral(3))))
|
||||||
);
|
);
|
||||||
assert_expr!(
|
assert_expr_comb!(
|
||||||
"1 * 2 + 3",
|
"1 * 2 + 3",
|
||||||
binop("+", binop("*", expr(NatLiteral(1)), expr(NatLiteral(2))), expr(NatLiteral(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_comb!("1 && 2", binop("&&", expr(NatLiteral(1)), expr(NatLiteral(2))));
|
||||||
assert_expr!(
|
assert_expr_comb!(
|
||||||
"1 + 2 * 3 + 4",
|
"1 + 2 * 3 + 4",
|
||||||
binop(
|
binop(
|
||||||
"+",
|
"+",
|
||||||
@ -206,12 +206,12 @@ fn binexps() {
|
|||||||
expr(NatLiteral(4))
|
expr(NatLiteral(4))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
assert_expr!(
|
assert_expr_comb!(
|
||||||
"(1 + 2) * 3",
|
"(1 + 2) * 3",
|
||||||
binop("*", binop("+", expr(NatLiteral(1)), expr(NatLiteral(2))), expr(NatLiteral(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_comb!(".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(NatLiteral(1)), expr(FloatLiteral(2.))));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -230,9 +230,9 @@ fn prefix_exps() {
|
|||||||
fn operators() {
|
fn operators() {
|
||||||
use ExpressionKind::*;
|
use ExpressionKind::*;
|
||||||
|
|
||||||
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!("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!("a <> 1", binop("<>", expr(Value(qn!(a))), expr(NatLiteral(1))));
|
assert_expr_comb!("a <> 1", binop("<>", expr(Value(qn!(a))), expr(NatLiteral(1))));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -273,12 +273,12 @@ fn accessors() {
|
|||||||
fn tuples() {
|
fn tuples() {
|
||||||
use ExpressionKind::*;
|
use ExpressionKind::*;
|
||||||
|
|
||||||
assert_expr!("()", expr(TupleLiteral(vec![])));
|
assert_expr_comb!("()", expr(TupleLiteral(vec![])));
|
||||||
assert_expr!(
|
assert_expr_comb!(
|
||||||
r#"("hella", 34)"#,
|
r#"("hella", 34)"#,
|
||||||
expr(TupleLiteral(vec![expr(StringLiteral(rc("hella"))), expr(NatLiteral(34))]))
|
expr(TupleLiteral(vec![expr(StringLiteral(rc("hella"))), expr(NatLiteral(34))]))
|
||||||
);
|
);
|
||||||
assert_expr!(
|
assert_expr_comb!(
|
||||||
r#"(1+2, "slough")"#,
|
r#"(1+2, "slough")"#,
|
||||||
expr(TupleLiteral(vec![
|
expr(TupleLiteral(vec![
|
||||||
binop("+", expr(NatLiteral(1)), expr(NatLiteral(2))),
|
binop("+", expr(NatLiteral(1)), expr(NatLiteral(2))),
|
||||||
@ -291,11 +291,11 @@ fn tuples() {
|
|||||||
fn identifiers() {
|
fn identifiers() {
|
||||||
use ExpressionKind::*;
|
use ExpressionKind::*;
|
||||||
|
|
||||||
assert_expr!("a", expr(Value(qn!(a))));
|
assert_expr_comb!("a", expr(Value(qn!(a))));
|
||||||
assert_expr!("some_value", expr(Value(qn!(some_value))));
|
assert_expr_comb!("some_value", expr(Value(qn!(some_value))));
|
||||||
assert_expr!("alpha::beta::gamma", expr(Value(qn!(alpha, beta, gamma))));
|
assert_expr_comb!("alpha::beta::gamma", expr(Value(qn!(alpha, beta, gamma))));
|
||||||
assert_expr!("a + b", binop("+", expr(Value(qn!(a))), expr(Value(qn!(b)))));
|
assert_expr_comb!("a + b", binop("+", expr(Value(qn!(a))), expr(Value(qn!(b)))));
|
||||||
assert_expr!("None", expr(Value(qn!(None))));
|
assert_expr_comb!("None", expr(Value(qn!(None))));
|
||||||
assert_expr!(
|
assert_expr!(
|
||||||
"thing::item::call()",
|
"thing::item::call()",
|
||||||
expr(Call { f: bx(expr(Value(qn!(thing, item, call)))), arguments: vec![] })
|
expr(Call { f: bx(expr(Value(qn!(thing, item, call)))), arguments: vec![] })
|
||||||
@ -1387,7 +1387,7 @@ fn comments() {
|
|||||||
use ExpressionKind::*;
|
use ExpressionKind::*;
|
||||||
|
|
||||||
let source = "1 + /* hella /* bro */ */ 2";
|
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
|
//TODO make sure this error message makes sense
|
||||||
let source = "1 + /* hella /* bro */ 2";
|
let source = "1 + /* hella /* bro */ 2";
|
||||||
|
Loading…
Reference in New Issue
Block a user