@@ -325,6 +325,8 @@ enum Token {
325
325
Mul ,
326
326
/// A literal '/' for division
327
327
Div ,
328
+ /// A literal '//' for integer division
329
+ IntDiv ,
328
330
/// A literal '%' for mod operation
329
331
Mod ,
330
332
/// Internal-only token used for separating otherwise
@@ -426,7 +428,14 @@ fn tokenize(input: &str) -> Result<Vec<Token>> {
426
428
'+' => Token :: Add ,
427
429
'-' if !in_elref_id => Token :: Sub , // '-' is valid in an ElRef::Id
428
430
'*' => Token :: Mul ,
429
- '/' => Token :: Div ,
431
+ '/' => {
432
+ if buffer. is_empty ( ) && tokens. last ( ) == Some ( & Token :: Div ) {
433
+ tokens. pop ( ) ;
434
+ Token :: IntDiv
435
+ } else {
436
+ Token :: Div
437
+ }
438
+ }
430
439
'%' => Token :: Mod ,
431
440
',' => Token :: Comma ,
432
441
' ' | '\t' => Token :: Whitespace ,
@@ -724,6 +733,10 @@ fn factor(eval_state: &mut EvalState) -> Result<ExprValue> {
724
733
eval_state. advance ( ) ;
725
734
e /= primary ( eval_state) ?. one_number ( ) ?;
726
735
}
736
+ Some ( Token :: IntDiv ) => {
737
+ eval_state. advance ( ) ;
738
+ e = e. div_euclid ( primary ( eval_state) ?. one_number ( ) ?) ;
739
+ }
727
740
Some ( Token :: Mod ) => {
728
741
eval_state. advance ( ) ;
729
742
// note euclid remainder rather than '%' operator
@@ -1060,6 +1073,8 @@ mod tests {
1060
1073
( "6 - 9" , -3. ) ,
1061
1074
( "-4 * 5" , -20. ) ,
1062
1075
( "60 / 12" , 5. ) ,
1076
+ ( "11 // 4" , 2. ) ,
1077
+ ( "-11 // 4" , -3. ) , // ensure -a // b is rounds down
1063
1078
( "63 % 4" , 3. ) ,
1064
1079
( "-1 % 4" , 3. ) , // ensure -a % b is non-negative
1065
1080
( "-4 * 4" , -16. ) ,
@@ -1673,8 +1688,8 @@ mod tests {
1673
1688
let ctx = TestContext :: new ( ) ;
1674
1689
for ( expr, expected) in [
1675
1690
(
1676
- "{{10, 20 + 3, 2+3 , eq(123, 123), 5/2}}" ,
1677
- "10, 23, 5, 1, 2.5" ,
1691
+ "{{10, 20 + 3, 2+3 , eq(123, 123), 5/2, 3//2 }}" ,
1692
+ "10, 23, 5, 1, 2.5, 1 " ,
1678
1693
) ,
1679
1694
( "{{3, 2, swap(1, 2)}}" , "3, 2, 2, 1" ) ,
1680
1695
( "{{p2r(10, 0)}}" , "10, 0" ) ,
0 commit comments