Add object parsing and tests

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-05-05 17:21:12 -04:00
parent 4c2f18b7c9
commit ae99bbfc1e

View File

@@ -9,6 +9,7 @@ const BASE_EXPR_START: &[TokenKind] = &[
TokenKind::LParen, TokenKind::LParen,
TokenKind::LBracket, TokenKind::LBracket,
TokenKind::LBrace, TokenKind::LBrace,
TokenKind::ObjBrace,
]; ];
const UN_EXPR_START: &[TokenKind] = &[TokenKind::Plus, TokenKind::Minus, TokenKind::Bang]; const UN_EXPR_START: &[TokenKind] = &[TokenKind::Plus, TokenKind::Minus, TokenKind::Bang];
@@ -61,6 +62,15 @@ impl<'t> Parser<'t> {
} }
} }
////////////////////////////////////////////////////////////////////////////////
// Statement parsing
////////////////////////////////////////////////////////////////////////////////
impl<'t> Parser<'t> {
pub fn next_stmt(&mut self) -> Result<Stmt> {
todo!()
}
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Expression parsing // Expression parsing
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -165,7 +175,17 @@ impl<'t> Parser<'t> {
} }
.into() .into()
} }
TokenKind::LBrace => todo!(), TokenKind::LBrace => todo!("TODO body expressions"),
TokenKind::ObjBrace => {
let prev_skip = self.set_skip_newlines(true)?;
let object = self.next_obj_list()?;
let end_token = self.expect_token_kind(TokenKind::RBrace, "end of object (right curly brace)")?;
let span = token.span().union(end_token.span());
Expr::Base(BaseExpr {
kind: BaseExprKind::Object(object),
span,
})
}
TokenKind::LParen => { TokenKind::LParen => {
let prev_skip = self.set_skip_newlines(true)?; let prev_skip = self.set_skip_newlines(true)?;
let first = self.next_expr()?; let first = self.next_expr()?;
@@ -175,7 +195,7 @@ impl<'t> Parser<'t> {
self.set_skip_newlines(prev_skip)?; self.set_skip_newlines(prev_skip)?;
let end_token = self.expect_token_kind(TokenKind::RParen, "end of tuple")?; let end_token = self.expect_token_kind(TokenKind::RParen, "end of tuple")?;
let span = first.span().union(end_token.span()); let span = token.span().union(end_token.span());
list.insert(0, first); list.insert(0, first);
Expr::Base( Expr::Base(
BaseExpr { BaseExpr {
@@ -212,6 +232,28 @@ impl<'t> Parser<'t> {
Ok(list_items) Ok(list_items)
} }
/// Parses the tail of a `BaseExprKind::Object` expression.
///
/// This function expects that the initial object brace `%{` has already been eaten.
fn next_obj_list(&mut self) -> Result<Vec<(Expr, Expr)>> {
let mut object = Vec::new();
// Parses this pattern:
// ( key EQ value ( COMMA key = value )* COMMA? )?
while !self.is_token_kind(TokenKind::RBrace) {
let key = self.next_expr()?;
self.expect_token_kind(TokenKind::Eq, "equals sign for object item")?;
let value = self.next_expr()?;
object.push((key, value));
// match a comma, otherwise exit the loop
if self.match_token_kind(TokenKind::Comma)?.is_none() {
break;
}
}
Ok(object)
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Token matching functions // Token matching functions
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -220,13 +262,19 @@ impl<'t> Parser<'t> {
let mut next_token = self.lexer.next_token()?; let mut next_token = self.lexer.next_token()?;
if self.is_skip_newlines() { if self.is_skip_newlines() {
while next_token.map(|t| t.kind() == TokenKind::Newline).unwrap_or(false) { while next_token
.map(|t| t.kind() == TokenKind::Newline)
.unwrap_or(false)
{
next_token = self.lexer.next_token()?; next_token = self.lexer.next_token()?;
} }
if self.is_token_kind(TokenKind::Newline) { if self.is_token_kind(TokenKind::Newline) {
self.curr_token = next_token; self.curr_token = next_token;
while next_token.map(|t| t.kind() == TokenKind::Newline).unwrap_or(false) { while next_token
.map(|t| t.kind() == TokenKind::Newline)
.unwrap_or(false)
{
next_token = self.lexer.next_token()?; next_token = self.lexer.next_token()?;
} }
} }
@@ -485,9 +533,7 @@ mod test {
test_parser!( test_parser!(
Parser::try_from("(:sym,)").unwrap(), Parser::try_from("(:sym,)").unwrap(),
next_expr, next_expr,
base_expr(BaseExprKind::Tuple(vec![ base_expr(BaseExprKind::Tuple(vec![base_expr(BaseExprKind::Sym),]))
base_expr(BaseExprKind::Sym),
]))
); );
test_parser!( test_parser!(
@@ -497,6 +543,26 @@ mod test {
); );
} }
#[test]
fn test_object_expr() {
test_parser!(
Parser::try_from(
r#"%{
:sym = value,
key = "value",
"lit" = 1,
}"#
)
.unwrap(),
next_expr,
base_expr(BaseExprKind::Object(vec![
(base_expr(BaseExprKind::Sym), base_expr(BaseExprKind::Ident)),
(base_expr(BaseExprKind::Ident), base_expr(BaseExprKind::Str)),
(base_expr(BaseExprKind::Str), base_expr(BaseExprKind::Num)),
]))
);
}
#[test] #[test]
fn test_bin_expr() { fn test_bin_expr() {
test_parser!( test_parser!(
@@ -613,26 +679,30 @@ mod test {
#[test] #[test]
fn test_multiline_exprs() { fn test_multiline_exprs() {
test_parser!( test_parser!(
Parser::try_from(r"[ Parser::try_from(
r"[
1, 1,
x, x,
['value', :value], ['value', :value],
:sym :sym
]").unwrap(), ]"
)
.unwrap(),
next_expr, next_expr,
base_expr(BaseExprKind::List(vec![ base_expr(BaseExprKind::List(vec![
base_expr(BaseExprKind::Num), base_expr(BaseExprKind::Num),
base_expr(BaseExprKind::Ident), base_expr(BaseExprKind::Ident),
base_expr(BaseExprKind::List(vec![ base_expr(BaseExprKind::List(vec![
base_expr(BaseExprKind::Str), base_expr(BaseExprKind::Str),
base_expr(BaseExprKind::Sym), base_expr(BaseExprKind::Sym),
])), ])),
base_expr(BaseExprKind::Sym), base_expr(BaseExprKind::Sym),
])) ]))
); );
test_parser!( test_parser!(
Parser::try_from(r"( Parser::try_from(
r"(
1, 1,
x, x,
[ [
@@ -640,26 +710,31 @@ mod test {
'value', 'value',
], ],
:sym :sym
)").unwrap(), )"
)
.unwrap(),
next_expr, next_expr,
base_expr(BaseExprKind::Tuple(vec![ base_expr(BaseExprKind::Tuple(vec![
base_expr(BaseExprKind::Num), base_expr(BaseExprKind::Num),
base_expr(BaseExprKind::Ident), base_expr(BaseExprKind::Ident),
base_expr(BaseExprKind::List(vec![ base_expr(BaseExprKind::List(vec![
base_expr(BaseExprKind::Sym), base_expr(BaseExprKind::Sym),
base_expr(BaseExprKind::Str), base_expr(BaseExprKind::Str),
])), ])),
base_expr(BaseExprKind::Sym), base_expr(BaseExprKind::Sym),
])) ]))
); );
test_parser!( test_parser!(
Parser::try_from(r"( Parser::try_from(
r"(
+ 1 + 1
+ 2 + 2
+ 3 + 3
+ 4 + 4
)").unwrap(), )"
)
.unwrap(),
next_expr, next_expr,
bin_expr( bin_expr(
un_expr(UnOp::Plus, base_expr(BaseExprKind::Num)), un_expr(UnOp::Plus, base_expr(BaseExprKind::Num)),
@@ -677,29 +752,30 @@ mod test {
); );
test_parser!( test_parser!(
Parser::try_from(r"( Parser::try_from(
r"(
+ 1 + 1
+ 2 + 2
+ 3 + 3
+ 4 + 4
, ,
)").unwrap(), )"
)
.unwrap(),
next_expr, next_expr,
base_expr(BaseExprKind::Tuple(vec![ base_expr(BaseExprKind::Tuple(vec![bin_expr(
un_expr(UnOp::Plus, base_expr(BaseExprKind::Num)),
BinOp::Plus,
bin_expr( bin_expr(
un_expr(UnOp::Plus, base_expr(BaseExprKind::Num)), base_expr(BaseExprKind::Num),
BinOp::Plus, BinOp::Plus,
bin_expr( bin_expr(
base_expr(BaseExprKind::Num), base_expr(BaseExprKind::Num),
BinOp::Plus, BinOp::Plus,
bin_expr( base_expr(BaseExprKind::Num)
base_expr(BaseExprKind::Num),
BinOp::Plus,
base_expr(BaseExprKind::Num)
)
) )
) )
])) )]))
); );
} }
} }