数式をRecursive Descent Parsing
数式(四則演算記号 +, -, *, /、括弧、数値のみから成る式)の解析が知人間で少し話題になってたので自分もrustで書いてみる。数式をBNFで表現してからコードに落とし込んだ結果、以下のようになった。面倒なので、unwrap_or
をチェックしていない。
fn num(exp:&'static str,i:&mut usize)->i32{ let mut result:i32=exp.chars().nth(*i).unwrap_or('A').to_digit(10).unwrap_or(0) as i32; *i+=1; while exp.chars().nth(*i).unwrap_or('A').is_digit(10) { result=result*10+exp.chars().nth(*i).unwrap_or('A').to_digit(10).unwrap_or(0) as i32; *i+=1; } result } fn factor(exp:&'static str,i:&mut usize)->i32{ if exp.chars().nth(*i).unwrap_or('A').is_digit(10) { return num(exp,i); } *i+=1; let result:i32=analyze(exp,i); *i+=1; result } fn term(exp:&'static str,i:&mut usize)->i32{ let mut result:i32=factor(exp,i); while exp.chars().nth(*i).unwrap_or('A')=='*' || exp.chars().nth(*i).unwrap_or('A')=='/' { let op:char=exp.chars().nth(*i).unwrap_or('A'); *i+=1; let tmp:i32=factor(exp,i); if op=='*'{ result*=tmp; } else if op=='/' { result/=tmp; } } result } fn analyze(exp:&'static str,i:&mut usize)->i32{ let mut result:i32=term(exp,i); while exp.chars().nth(*i).unwrap_or('A')=='+' || exp.chars().nth(*i).unwrap_or('A')=='-' { let op:char=exp.chars().nth(*i).unwrap_or('A'); *i+=1; let tmp:i32=term(exp,i); if op=='+' { result+=tmp; } else if op=='-' { result-=tmp; } } result } fn main(){ let exp:&'static str="(3+20)*6/(2+1)-2*2"; let mut i:usize=0; println!("{}",analyze(&exp,&mut i)); }
output:
42