more robustly parse commas in call args

This commit is contained in:
Connor Skees 2021-07-28 00:35:49 -04:00
parent f67b1c62e7
commit 63567da749
3 changed files with 67 additions and 10 deletions

View File

@ -160,6 +160,16 @@ impl<'a, 'b> Parser<'a, 'b> {
return Ok(CallArgs(args, span)); return Ok(CallArgs(args, span));
} }
if self.consume_char_if_exists(',') {
self.whitespace_or_comment();
if self.consume_char_if_exists(',') {
return Err(("expected \")\".", self.span_before).into());
}
continue;
}
if let Some(Token { kind: '$', pos }) = self.toks.peek() { if let Some(Token { kind: '$', pos }) = self.toks.peek() {
let start = self.toks.cursor(); let start = self.toks.cursor();
@ -222,6 +232,9 @@ impl<'a, 'b> Parser<'a, 'b> {
value, value,
); );
self.whitespace_or_comment(); self.whitespace_or_comment();
if self.consume_char_if_exists(',') {
return Err(("expected \")\".", self.span_before).into());
}
continue; continue;
} }
Some(Token { kind: '.', pos }) => { Some(Token { kind: '.', pos }) => {

View File

@ -79,13 +79,13 @@ impl<'a, 'b: 'a, 'c> ValueVisitor<'a, 'b, 'c> {
op, op,
Box::new(val2), Box::new(val2),
)); ));
} else {
return Ok(HigherIntermediateValue::BinaryOp(
val1_1,
val1_op,
Box::new(self.bin_op_one_level(*val1_2, op, val2, in_parens)?),
));
} }
return Ok(HigherIntermediateValue::BinaryOp(
val1_1,
val1_op,
Box::new(self.bin_op_one_level(*val1_2, op, val2, in_parens)?),
));
} }
_ => unreachable!(), _ => unreachable!(),
}; };
@ -132,13 +132,13 @@ impl<'a, 'b: 'a, 'c> ValueVisitor<'a, 'b, 'c> {
if let HigherIntermediateValue::BinaryOp(val1_1, val1_op, val1_2) = val1 { if let HigherIntermediateValue::BinaryOp(val1_1, val1_op, val1_2) = val1 {
let in_parens = op != Op::Div || val1_op != Op::Div; let in_parens = op != Op::Div || val1_op != Op::Div;
if val1_op.precedence() >= op.precedence() { return if val1_op.precedence() >= op.precedence() {
val1 = self.bin_op_one_level(*val1_1, val1_op, *val1_2, in_parens)?; val1 = self.bin_op_one_level(*val1_1, val1_op, *val1_2, in_parens)?;
return self.bin_op(val1, op, val2, in_parens); self.bin_op(val1, op, val2, in_parens)
} else { } else {
val2 = self.bin_op_one_level(*val1_2, op, val2, in_parens)?; val2 = self.bin_op_one_level(*val1_2, op, val2, in_parens)?;
return self.bin_op(*val1_1, val1_op, val2, in_parens); self.bin_op(*val1_1, val1_op, val2, in_parens)
} };
} }
Ok(match op { Ok(match op {

View File

@ -231,3 +231,47 @@ test!(
}", }",
"a {\n color: foo;\n color: bar;\n color: foo;\n}\n" "a {\n color: foo;\n color: bar;\n color: foo;\n}\n"
); );
test!(
splat_ends_with_comma,
"@function foo($arg1) {
@return $arg1;
}
a {
color: foo(a...,);
}",
"a {\n color: a;\n}\n"
);
test!(
two_splat_ends_with_comma,
"@function foo($arg1, $arg2) {
@return $arg1 $arg2;
}
a {
color: foo((value1,)..., (arg2: value2)...);
}",
"a {\n color: value1 value2;\n}\n"
);
error!(
splat_ends_with_two_commas,
"@function foo($arg1) {
@return $arg1;
}
a {
color: foo(a...,,);
}",
"Error: expected \")\"."
);
error!(
arg_ends_with_two_commas,
"@function foo($arg1) {
@return $arg1;
}
a {
color: foo(a,,);
}",
"Error: expected \")\"."
);