From 8b4f552fa4a26b1e520e7ddddf0e079197813148 Mon Sep 17 00:00:00 2001 From: reuben olinsky Date: Wed, 19 Feb 2025 22:57:53 -0800 Subject: [PATCH] feat(arithmetic): support explicit base#literal in arithmetic --- brush-parser/src/arithmetic.rs | 28 +++++++++++++++++++++---- brush-shell/tests/cases/arithmetic.yaml | 12 +++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/brush-parser/src/arithmetic.rs b/brush-parser/src/arithmetic.rs index 7ea61daa..d38cf51e 100644 --- a/brush-parser/src/arithmetic.rs +++ b/brush-parser/src/arithmetic.rs @@ -101,9 +101,29 @@ peg::parser! { rule _() -> () = quiet!{[' ' | '\t' | '\n' | '\r']*} {} rule literal_number() -> i64 = - // TODO: handle explicit radix (e.g., #) for bases 2 through 64 - "0" ['x' | 'X'] s:$(['0'..='9' | 'a'..='f' | 'A'..='F']*) {? i64::from_str_radix(s, 16).or(Err("i64")) } / - s:$("0" ['0'..='8']*) {? i64::from_str_radix(s, 8).or(Err("i64")) } / - s:$(['1'..='9'] ['0'..='9']*) {? s.parse().or(Err("i64")) } + // Literal with explicit radix (format: #) + radix:decimal_literal() "#" s:$(['0'..='9' | 'a'..='z' | 'A'..='Z']+) {? + // TODO: Support bases larger than 36. from_str_radix can't handle that. + if radix < 2 || radix > 36 { + return Err("invalid base"); + } + + i64::from_str_radix(s, radix as u32).or(Err("i64")) + } / + // Hex literal + "0" ['x' | 'X'] s:$(['0'..='9' | 'a'..='f' | 'A'..='F']*) {? + i64::from_str_radix(s, 16).or(Err("i64")) + } / + // Octal literal + s:$("0" ['0'..='8']*) {? + i64::from_str_radix(s, 8).or(Err("i64")) + } / + // Decimal literal + decimal_literal() + + rule decimal_literal() -> i64 = + s:$(['1'..='9'] ['0'..='9']*) {? + s.parse().or(Err("i64")) + } } } diff --git a/brush-shell/tests/cases/arithmetic.yaml b/brush-shell/tests/cases/arithmetic.yaml index 263a4b3b..5e0ff56a 100644 --- a/brush-shell/tests/cases/arithmetic.yaml +++ b/brush-shell/tests/cases/arithmetic.yaml @@ -18,6 +18,18 @@ cases: echo "$((0x10))" echo "$((0x010))" + - name: "Arithmetic literals with explicit bases" + stdin: | + echo "$((2#1010))" + echo "$((8#16))" + echo "$((16#faf))" + echo "$((36#vvv))" + + - name: "Arithmetic literals with base 64 encoding" + known_failure: true # Not currently handled. + stdin: | + echo "$((64#zzz))" + - name: "Parentheses" stdin: | echo "$(((10)))"