@@ -120,6 +120,14 @@ impl<N: Network> ParserContext<'_, N> {
120
120
self . parse_bin_expr ( & [ Token :: And ] , Self :: parse_equality_expression)
121
121
}
122
122
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
+
123
131
/// Eats one of binary operators matching any in `tokens`.
124
132
fn eat_bin_op ( & mut self , tokens : & [ Token ] ) -> Option < BinaryOperation > {
125
133
self . eat_any ( tokens) . then ( || match & self . prev_token . token {
@@ -253,63 +261,36 @@ impl<N: Network> ParserContext<'_, N> {
253
261
///
254
262
/// Otherwise, tries to parse the next token using [`parse_postfix_expression`].
255
263
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 ;
265
265
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) ;
297
284
}
298
- _ => ( ) , // Do nothing.
299
285
}
300
286
}
301
287
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
+ } ) )
313
294
}
314
295
315
296
// TODO: Parse method call expressions directly and later put them into a canonical form.
0 commit comments