Fix index/call parsing
This commit is contained in:
parent
46fe03b43f
commit
1c6545fb74
@ -69,15 +69,21 @@
|
||||
//! ```text
|
||||
//! expression := precedence_expr type_anno?
|
||||
//! precedence_expr := prefix_expr
|
||||
//! prefix_expr := prefix_op call_expr
|
||||
//! prefix_op := "+" | "-" | "!" | "~"
|
||||
//! call_expr := index_expr ( "(" invocation_list ")" )* | ε
|
||||
//! invocation_list := invocation_argument ("," invocation_argument)* | ε
|
||||
//! invocation_argument := expression | IDENTIFIER "=" expression | "_"
|
||||
//! index_expr := primary ( "[" (expression ("," (expression)* | ε) "]" )*
|
||||
//! prefix_expr := prefix_op extended_expr
|
||||
//!
|
||||
//! prefix_op := "+" | "-" | "!" | "~" | ε
|
||||
//!
|
||||
//! extended_expr := primary (ε | index | call | access)*
|
||||
//! index := "[" (expression ("," expression)*) "]"
|
||||
//! call := "(" invocation_list ")"
|
||||
//! access := "." identifier
|
||||
//! primary := literal | paren_expr | if_expr | for_expr | while_expr | identifier_expr | lambda_expr | anonymous_struct | list_expr
|
||||
//! expr_or_block := "{" (statement delimiter)* "}" | expr
|
||||
//!
|
||||
//! invocation_list := invocation_argument ("," invocation_argument)* | ε
|
||||
//! invocation_argument := expression | IDENTIFIER "=" expression | "_"
|
||||
//! ```
|
||||
//! //TODO fix expressions, add accessor_expr as a new thing
|
||||
//!
|
||||
//! ### Primary expressions
|
||||
//!
|
||||
@ -688,20 +694,39 @@ impl Parser {
|
||||
ExpressionKind::PrefixExp(prefix_op, Box::new(expr))
|
||||
))
|
||||
},
|
||||
_ => self.call_expr()
|
||||
_ => self.extended_expr()
|
||||
}
|
||||
}
|
||||
|
||||
#[recursive_descent_method]
|
||||
fn call_expr(&mut self) -> ParseResult<Expression> {
|
||||
let mut expr = self.index_expr()?;
|
||||
//TODO look at this
|
||||
while let LParen = self.token_handler.peek_kind() {
|
||||
let arguments = delimited!(self, LParen, invocation_argument, Comma, RParen);
|
||||
expr = Expression::new(self.id_store.fresh(), ExpressionKind::Call { f: Box::new(expr), arguments }); //TODO no type anno is incorrect
|
||||
fn extended_expr(&mut self) -> ParseResult<Expression> {
|
||||
let mut expression = self.primary()?;
|
||||
loop {
|
||||
//TODO need a next non whitespace
|
||||
let next = self.token_handler.peek_kind();
|
||||
match next {
|
||||
Period => unimplemented!(),
|
||||
LSquareBracket => {
|
||||
let indexers = delimited!(self, LSquareBracket, expression, Comma, RSquareBracket);
|
||||
if indexers.is_empty() {
|
||||
return ParseError::new_with_token("Empty index expressions are not allowed", self.token_handler.peek());
|
||||
}
|
||||
|
||||
Ok(expr)
|
||||
expression = Expression::new(self.id_store.fresh(), ExpressionKind::Index {
|
||||
indexee: Box::new(expression),
|
||||
indexers,
|
||||
});
|
||||
},
|
||||
LParen => {
|
||||
let arguments = delimited!(self, LParen, invocation_argument, Comma, RParen);
|
||||
expression = Expression::new(self.id_store.fresh(), ExpressionKind::Call {
|
||||
f: Box::new(expression),
|
||||
arguments,
|
||||
});
|
||||
},
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
Ok(expression)
|
||||
}
|
||||
|
||||
#[recursive_descent_method]
|
||||
|
@ -120,7 +120,6 @@ macro_rules! assert_fail_expr {
|
||||
assert_eq!(err.msg, $failure);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic_literals() {
|
||||
use ExpressionKind::*;
|
||||
@ -202,14 +201,14 @@ fn operators() {
|
||||
assert_expr!("a <> 1", binop("<>", expr(Value(qn!(a))), expr(NatLiteral(1))));
|
||||
}
|
||||
|
||||
//TODO have a test for dot accessors
|
||||
#[test]
|
||||
fn accessors() {
|
||||
/*
|
||||
assert_expr!("a.b.c.d", exst!(binexp!(".",
|
||||
binexp!(".",
|
||||
binexp!(".", val!("a"), val!("b")),
|
||||
val!("c")),
|
||||
val!("d"))));
|
||||
assert_expr!("a.b");
|
||||
assert_expr!("a.b.c.d()");
|
||||
assert_expr!("a.b().c.d()");
|
||||
*/
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuples() {
|
||||
@ -273,17 +272,19 @@ fn index() {
|
||||
indexers: vec![expr(Value(qn!(b))), expr(Value(qn!(c)))]
|
||||
})
|
||||
);
|
||||
//TODO this is a parser bug
|
||||
/*
|
||||
assert_expr!("perspicacity()[a]", expr(Index{
|
||||
indexee: bx(expr(Call {
|
||||
f: bx(expr(Value(qn!(perspicacity)))),
|
||||
arguments: vec![]
|
||||
})),
|
||||
assert_expr!(
|
||||
"perspicacity()[a]",
|
||||
expr(Index {
|
||||
indexee: bx(expr(Call { f: bx(expr(Value(qn!(perspicacity)))), arguments: vec![] })),
|
||||
indexers: vec![expr(Value(qn!(a)))]
|
||||
}));
|
||||
*/
|
||||
//TODO parse_test("a()[b]()[d]")
|
||||
})
|
||||
);
|
||||
|
||||
let a = expr(Call { f: bx(expr(Value(qn!(a)))), arguments: vec![] });
|
||||
let b = expr(Index { indexee: bx(a), indexers: vec![expr(Value(qn!(b)))] });
|
||||
let c = expr(Call { f: bx(b), arguments: vec![] });
|
||||
let d = expr(Index { indexee: bx(c), indexers: vec![expr(Value(qn!(d)))] });
|
||||
assert_expr!("a()[b]()[d]", d);
|
||||
|
||||
assert_fail_expr!("a[]", "Empty index expressions are not allowed");
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#![cfg(test)]
|
||||
use test_case::test_case;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use crate::{
|
||||
symbol_table::SymbolTable,
|
||||
|
Loading…
Reference in New Issue
Block a user