Browse Source

Parse array elisions and trailing commas (#58)

* Parse array elisions and trailing commas

* cargo fmt
pull/70/head
Zach Gotsch 5 years ago committed by Jason Williams
parent
commit
b891ac3b9b
  1. 110
      src/lib/syntax/parser.rs

110
src/lib/syntax/parser.rs

@ -452,41 +452,40 @@ impl Parser {
} }
} }
TokenData::Punctuator(Punctuator::OpenBracket) => { TokenData::Punctuator(Punctuator::OpenBracket) => {
let mut array: Vec<Expr> = Vec::new(); let mut array: Vec<Expr> = vec![];
let mut expect_comma_or_end = self.get_token(self.pos)?.data let mut saw_expr_last = false;
== TokenData::Punctuator(Punctuator::CloseBracket);
loop { loop {
let token = self.get_token(self.pos)?; let token = self.get_token(self.pos)?;
if token.data == TokenData::Punctuator(Punctuator::CloseBracket) match token.data {
&& expect_comma_or_end TokenData::Punctuator(Punctuator::CloseBracket) => {
{ self.pos += 1;
self.pos += 1; break;
break; }
} else if token.data == TokenData::Punctuator(Punctuator::Comma) TokenData::Punctuator(Punctuator::Comma) => {
&& expect_comma_or_end if !saw_expr_last {
{ // An elision indicates that a space is saved in the array
expect_comma_or_end = false; array.push(mk!(self, ExprDef::ConstExpr(Const::Undefined)))
} else if token.data == TokenData::Punctuator(Punctuator::Comma) }
&& !expect_comma_or_end saw_expr_last = false;
{ self.pos += 1;
array.push(mk!(self, ExprDef::ConstExpr(Const::Null))); }
expect_comma_or_end = false; _ if saw_expr_last => {
} else if expect_comma_or_end { // Two expressions in a row is not allowed, they must be comma-separated
return Err(ParseError::Expected( return Err(ParseError::Expected(
vec![ vec![
TokenData::Punctuator(Punctuator::Comma), TokenData::Punctuator(Punctuator::Comma),
TokenData::Punctuator(Punctuator::CloseBracket), TokenData::Punctuator(Punctuator::CloseBracket),
], ],
token.clone(), token.clone(),
"array declaration", "array declaration",
)); ));
} else { }
let parsed = self.parse()?; _ => {
self.pos -= 1; let parsed = self.parse()?;
array.push(parsed); saw_expr_last = true;
expect_comma_or_end = true; array.push(parsed);
}
} }
self.pos += 1;
} }
mk!(self, ExprDef::ArrayDeclExpr(array), token) mk!(self, ExprDef::ArrayDeclExpr(array), token)
} }
@ -855,9 +854,12 @@ mod tests {
check_parser("[]", &[Expr::new(ExprDef::ArrayDeclExpr(vec![]))]); check_parser("[]", &[Expr::new(ExprDef::ArrayDeclExpr(vec![]))]);
// Check array with empty slot // Check array with empty slot
// FIXME: This does not work, it should ignore the comma: check_parser(
// <https://tc39.es/ecma262/#prod-ArrayAssignmentPattern> "[,]",
// check_parser("[,]", &[Expr::new(ExprDef::ArrayDeclExpr(vec![]))]); &[Expr::new(ExprDef::ArrayDeclExpr(vec![Expr::new(
ExprDef::ConstExpr(Const::Undefined),
)]))],
);
// Check numeric array // Check numeric array
check_parser( check_parser(
@ -870,13 +872,37 @@ mod tests {
); );
// Check numeric array with trailing comma // Check numeric array with trailing comma
// FIXME: This does not work, it should ignore the trailing comma: check_parser(
// <https://tc39.es/ecma262/#prod-ArrayAssignmentPattern> "[1, 2, 3,]",
// check_parser("[1, 2, 3,]", &[Expr::new(ExprDef::ArrayDeclExpr(vec![ &[Expr::new(ExprDef::ArrayDeclExpr(vec![
// Expr::new(ExprDef::ConstExpr(Const::Num(1.0))), Expr::new(ExprDef::ConstExpr(Const::Num(1.0))),
// Expr::new(ExprDef::ConstExpr(Const::Num(2.0))), Expr::new(ExprDef::ConstExpr(Const::Num(2.0))),
// Expr::new(ExprDef::ConstExpr(Const::Num(3.0))), Expr::new(ExprDef::ConstExpr(Const::Num(3.0))),
// ]))]); ]))],
);
// Check numeric array with an elision
check_parser(
"[1, 2, , 3]",
&[Expr::new(ExprDef::ArrayDeclExpr(vec![
Expr::new(ExprDef::ConstExpr(Const::Num(1.0))),
Expr::new(ExprDef::ConstExpr(Const::Num(2.0))),
Expr::new(ExprDef::ConstExpr(Const::Undefined)),
Expr::new(ExprDef::ConstExpr(Const::Num(3.0))),
]))],
);
// Check numeric array with repeated elision
check_parser(
"[1, 2, ,, 3]",
&[Expr::new(ExprDef::ArrayDeclExpr(vec![
Expr::new(ExprDef::ConstExpr(Const::Num(1.0))),
Expr::new(ExprDef::ConstExpr(Const::Num(2.0))),
Expr::new(ExprDef::ConstExpr(Const::Undefined)),
Expr::new(ExprDef::ConstExpr(Const::Undefined)),
Expr::new(ExprDef::ConstExpr(Const::Num(3.0))),
]))],
);
// Check combined array // Check combined array
check_parser( check_parser(

Loading…
Cancel
Save