Last active
November 24, 2022 10:27
-
-
Save sozysozbot/27383570b9d01d91736f7de294df75a8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[test] | |
fn test_eat_primary() { | |
assert_eq!(eat_primary("3+5"), (3, "+5")); | |
assert_eq!(eat_primary("8-5*4+3"), (8, "-5*4+3")); | |
} | |
// 先頭から数字を一個食って、「食った数字と食い残した文字列」を返す | |
fn eat_primary(s: &str) -> (i32, &str) { | |
if s.starts_with('0') { return (0, &s[1..]); } | |
if s.starts_with('1') { return (1, &s[1..]); } | |
if s.starts_with('2') { return (2, &s[1..]); } | |
if s.starts_with('3') { return (3, &s[1..]); } | |
if s.starts_with('4') { return (4, &s[1..]); } | |
if s.starts_with('5') { return (5, &s[1..]); } | |
if s.starts_with('6') { return (6, &s[1..]); } | |
if s.starts_with('7') { return (7, &s[1..]); } | |
if s.starts_with('8') { return (8, &s[1..]); } | |
if s.starts_with('9') { return (9, &s[1..]); } | |
if s.starts_with('(') { | |
let (result, remaining) = eat_expression(&s[1..]); | |
if remaining.starts_with(')') { | |
(result, &remaining[1..]) | |
} else { | |
panic!("`{}` を読もうとしましたが、左カッコに対応する右カッコが見当たりません", s); | |
} | |
} else { | |
panic!("`{}` の先頭の文字を処理できませんでした", s); | |
} | |
} | |
#[test] | |
fn test_eat_multiplicative() { | |
assert_eq!(eat_multiplicative("3+7"), (3, "+7")); | |
assert_eq!(eat_multiplicative("3*5+7"), (15, "+7")); | |
assert_eq!(eat_multiplicative("3*5*7+7"), (105, "+7")); | |
} | |
fn eat_multiplicative(s: &str) -> (i32, &str) { | |
// まず primary を食う | |
let (mut result, mut remaining) = eat_primary(s); | |
// "*" の後に primary が来る構造が0回以上繰り返される | |
loop { | |
// "*" が来ないなら、食うのをやめる | |
if !remaining.starts_with('*') { break; } | |
// 先頭の * を削って、もう一個 primary を食べる | |
let (result2, remaining2) = eat_primary(&remaining[1..]); | |
// 計算結果がほしいので、どんどん掛け算していく | |
result *= result2; | |
remaining = remaining2; | |
} | |
(result, remaining) | |
} | |
#[test] | |
fn test_eat_expression() { | |
assert_eq!(eat_expression("3-5+7"), (5, "")); | |
assert_eq!(eat_expression("3*5+7"), (22, "")); | |
assert_eq!(eat_expression("3*5+7*4"), (43, "")); | |
assert_eq!(eat_expression("3*5+7*4-2*3*5"), (13, "")); | |
assert_eq!(eat_expression("3*(5+7-3)*(6-(3-(2+(4))+5))"), (3*(5+7-3)*(6-(3-(2+(4))+5)), "")); | |
} | |
fn eat_expression(s: &str) -> (i32, &str) { | |
let (mut result, mut remaining) = eat_multiplicative(s); | |
// "+" か "-" の後に multiplicative が来る構造が0回以上繰り返される | |
loop { | |
// "+" も "-" も来ないなら、食うのをやめる | |
if !remaining.starts_with('+') && !remaining.starts_with('-') { break; } | |
let is_plus = remaining.starts_with('+'); | |
// 先頭の + または - を削って、もう一個 multiplicative を食べる | |
let (result2, remaining2) = eat_multiplicative(&remaining[1..]); | |
// 計算結果がほしいので、どんどん足し引きしていく | |
if is_plus { | |
result += result2; | |
} else { | |
result -= result2; | |
} | |
remaining = remaining2; | |
} | |
(result, remaining) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment