Skip to content

Commit d2677de

Browse files
committed
Cleanup parse_unary_expression.
No functional changes; just changed to a recursive descent approach that's a bit easier to understand, and removed a big unnecessary match statement.
1 parent 2af05b1 commit d2677de

File tree

1 file changed

+33
-52
lines changed

1 file changed

+33
-52
lines changed

compiler/parser/src/parser/expression.rs

+33-52
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,14 @@ impl<N: Network> ParserContext<'_, N> {
120120
self.parse_bin_expr(&[Token::And], Self::parse_equality_expression)
121121
}
122122

123+
fn eat_unary_op(&mut self) -> Option<UnaryOperation> {
124+
self.eat_any(&[Token::Not, Token::Sub]).then(|| match &self.prev_token.token {
125+
Token::Not => UnaryOperation::Not,
126+
Token::Sub => UnaryOperation::Negate,
127+
_ => panic!("Can't happen."),
128+
})
129+
}
130+
123131
/// Eats one of binary operators matching any in `tokens`.
124132
fn eat_bin_op(&mut self, tokens: &[Token]) -> Option<BinaryOperation> {
125133
self.eat_any(tokens).then(|| match &self.prev_token.token {
@@ -253,63 +261,36 @@ impl<N: Network> ParserContext<'_, N> {
253261
///
254262
/// Otherwise, tries to parse the next token using [`parse_postfix_expression`].
255263
pub(super) fn parse_unary_expression(&mut self) -> Result<Expression> {
256-
let mut ops = Vec::new();
257-
while self.eat_any(&[Token::Not, Token::Sub]) {
258-
let operation = match self.prev_token.token {
259-
Token::Not => UnaryOperation::Not,
260-
Token::Sub => UnaryOperation::Negate,
261-
_ => unreachable!("parse_unary_expression_ shouldn't produce this"),
262-
};
263-
ops.push((operation, self.prev_token.span));
264-
}
264+
let token_span = self.token.span;
265265

266-
let mut inner = self.parse_postfix_expression()?;
267-
268-
// If the last operation is a negation and the inner expression is a literal, then construct a negative literal.
269-
if let Some((UnaryOperation::Negate, _)) = ops.last() {
270-
match inner {
271-
Expression::Literal(Literal::Integer(integer_type, string, span, id)) if !string.starts_with('-') => {
272-
// Remove the negation from the operations.
273-
// Note that this unwrap is safe because there is at least one operation in `ops`.
274-
let (_, op_span) = ops.pop().unwrap();
275-
// Construct a negative integer literal.
276-
inner =
277-
Expression::Literal(Literal::Integer(integer_type, format!("-{string}"), op_span + span, id));
278-
}
279-
Expression::Literal(Literal::Field(string, span, id)) if !string.starts_with('-') => {
280-
// Remove the negation from the operations.
281-
// Note that
282-
let (_, op_span) = ops.pop().unwrap();
283-
// Construct a negative field literal.
284-
inner = Expression::Literal(Literal::Field(format!("-{string}"), op_span + span, id));
285-
}
286-
Expression::Literal(Literal::Group(string, span, id)) if !string.starts_with('-') => {
287-
// Remove the negation from the operations.
288-
let (_, op_span) = ops.pop().unwrap();
289-
// Construct a negative group literal.
290-
inner = Expression::Literal(Literal::Group(format!("-{string}"), op_span + span, id));
291-
}
292-
Expression::Literal(Literal::Scalar(string, span, id)) if !string.starts_with('-') => {
293-
// Remove the negation from the operations.
294-
let (_, op_span) = ops.pop().unwrap();
295-
// Construct a negative scalar literal.
296-
inner = Expression::Literal(Literal::Scalar(format!("-{string}"), op_span + span, id));
266+
let Some(op) = self.eat_unary_op() else {
267+
return self.parse_postfix_expression();
268+
};
269+
270+
let mut inner = self.parse_unary_expression()?;
271+
272+
// Try to construct a negative literal.
273+
if let UnaryOperation::Negate = op {
274+
use Literal::*;
275+
if let Expression::Literal(
276+
Integer(_, string, span, _) | Field(string, span, _) | Group(string, span, _) | Scalar(string, span, _),
277+
) = &mut inner
278+
{
279+
if !string.starts_with('-') {
280+
// The operation was a negation and the literal was not already negative, so fold it in.
281+
string.insert(0, '-');
282+
*span = token_span + *span;
283+
return Ok(inner);
297284
}
298-
_ => (), // Do nothing.
299285
}
300286
}
301287

302-
// Apply the operations in reverse order, constructing a unary expression.
303-
for (op, op_span) in ops.into_iter().rev() {
304-
inner = Expression::Unary(UnaryExpression {
305-
span: op_span + inner.span(),
306-
op,
307-
receiver: Box::new(inner),
308-
id: self.node_builder.next_id(),
309-
});
310-
}
311-
312-
Ok(inner)
288+
Ok(Expression::Unary(UnaryExpression {
289+
span: token_span + inner.span(),
290+
op,
291+
receiver: Box::new(inner),
292+
id: self.node_builder.next_id(),
293+
}))
313294
}
314295

315296
// TODO: Parse method call expressions directly and later put them into a canonical form.

0 commit comments

Comments
 (0)