Added Rust program
This commit is contained in:
parent
7f3d00c9a1
commit
ed43edbf66
spring-2025/sen-109/00020/eval
src
target
.rustc_info.json
debug
.fingerprint
expression-eval-8b71bc81cfe4b22a
expression-eval-8f5c5b8f4c54c5d3
expression-eval-cb1cb603155897af
deps
expression-evalincremental
expression_eval-16koc7cbt8j5g
s-h3vetfhp14-0cun7bq-a4hzx5p4bc0jrj2zogp0qiogt
s-h43izi3beg-03307x0-0adozqk4du5bq6ryvq6kccm7s
s-h43izi3beg-03307x0.lockexpression_eval-2fso3c9c9bihx
s-h3vfkaw83u-1jyxmd8-b5n56l5jq1lokywnzz4ujtt4v
1rl7fpfc6luhqfa3ufvptegn8.o382ijxh3grgv552ob5uelq2uk.o3vvo5xsje6j43txjolfdcgazh.o3yifum6ghmsrip53y8sl7g9dq.o4lwzkf4p1aeoa6da00a8g776w.o4ub9lbi7lclgj0gab1zlkzo7g.o4y2iau04tt7rv0f1txia43lj1.o6bssn7oc6s41acdboahrzbl32.o6kpu3mxs32hsm2b1x7l4oy55n.o6sl8btd0ubwg2cbfe50kujpch.o74ih1cukp1rpexwazw6dw045z.oa9qn17ut5qbbtjr2oqn6dtepp.oayrhtfusc8zafykqmfys4rv1o.ob2x1eijj6u2cb0gvlrfor5g54.ob5dmgoxoe4zvu54md4kg45dgz.odep-graph.bineiqh8j51i448ndgx3uqfxiauk.o
s-h43izluwgw-1ugb4h6-84qbqgj8gbqajfzdqju042592
08pgswn8j4hu9ybi8abvh57au.o0c6g7sldd3exu9s48jfttki90.o15j6qy9frgp1xbfti1k48c5c9.o1mwtyr2k2shuhp7xgk08r2z5p.o1rl7fpfc6luhqfa3ufvptegn8.o2keq9sxt0n8agc81eil11shsg.o2rlmtj2vjupuqqjrwbu8l3xlo.o382ijxh3grgv552ob5uelq2uk.o39puzlb9mce25p0as0x5evyn6.o3c8bq39ob6qxnbckq35me0niy.o3vvo5xsje6j43txjolfdcgazh.o3yifum6ghmsrip53y8sl7g9dq.o4jh67iglpxok1pb34g2hjk4jt.o4lwzkf4p1aeoa6da00a8g776w.o4ub9lbi7lclgj0gab1zlkzo7g.o4y2iau04tt7rv0f1txia43lj1.o52g621zcqmutyccnn3bu3vsrd.o5ftc06egl57lsi6ipwiq4dbhp.o5lvm4niyga2myy4r98ywix5u8.o5n8vy1hqiubqa2uvz0cafp6en.o6bssn7oc6s41acdboahrzbl32.o6f0v2hk171x7pnsuaxfmc9crf.o6kpu3mxs32hsm2b1x7l4oy55n.o6sl8btd0ubwg2cbfe50kujpch.o6xo2a2lbn7xyf7r074bg4zoar.o7471g5x9fgui593s248l5svdu.o74ih1cukp1rpexwazw6dw045z.o7i8ydzfzgrxxy0j2qi6wgw7jp.o7pd0mgtbszp4g1z2dm0mc4rem.o7ycdppjae19p61ax3ijt07wud.o8ccaqstbw9sbjj2lpwochti46.o92t9rw30capr4frxwtik5kuqf.o9bfh9r13qeswv79ah47kft4c5.o9cmsk184bps9osgs631x3zm1h.oa9qn17ut5qbbtjr2oqn6dtepp.oado2c9kjvypdg4vi2nhoqfl37.oag631e06inf0mfv54l2j4mwkw.oayrhtfusc8zafykqmfys4rv1o.oazcavq8gmxd2grtiend9zvptb.ob2x1eijj6u2cb0gvlrfor5g54.ob2xlx7cof0i2h5gnuk5i7konz.ob5dmgoxoe4zvu54md4kg45dgz.obfkdckbcymf1emzkooqlr9qwg.obhzazune8595y3atqcy845hy7.obi4fajxcfkoeiyst9m1v6ueku.objdlqr48h2bzf65zve9lw0poi.oc3z8th0zdcoxl1z74xweovpok.od3xbpz47aseah5s9bkxx4eeab.od3z60t2cfv6mo0i2hehz3e7l1.odep-graph.bine0k98ls8grkgt02cfvs0l8ye7.oe2mgnikbrsf9nsf0u74bt071z.oeeoq6ejjltrq0xy3l0iafuvty.oeiqh8j51i448ndgx3uqfxiauk.oezdroniuut6davkyco2o4xlii.oquery-cache.binwork-products.bin
s-h43izluwgw-1ugb4h6.lockexpression_eval-3k9pz3px1jven
s-h3vetfhoyf-1vlh7di-bwam55ycf8v52qx2e8cvakuaw
s-h43izi389v-123bwy9-5u2q1lpai4u4iv8hirp9x34qr
s-h43izi389v-123bwy9.lock
|
@ -23,8 +23,8 @@ fn evaluate(expr: String) -> Result<f64, ParseError> {
|
|||
fn main() {
|
||||
println!("Hello! Welcome to Arithmetic expression evaluator.");
|
||||
println!("You can calculate value for expression such as 2*3+(4-5)+2^3/4. ");
|
||||
println!("Allowed numbers: positive, negative and decimals.");
|
||||
println!("Supported operations: Add, Subtract, Multiply, Divide, PowerOf(^). ");
|
||||
println!("Allowed numbers: positive, negative, and decimals.");
|
||||
println!("Supported operations: Add, Subtract, Multiply, Divide, PowerOf(^), Bitwise Operations: &, |. ");
|
||||
println!("Enter your arithmetic expression below:");
|
||||
loop {
|
||||
let mut input = String::new();
|
||||
|
|
|
@ -18,6 +18,7 @@ pub enum Node {
|
|||
Divide(Box<Node>, Box<Node>),
|
||||
Caret(Box<Node>, Box<Node>),
|
||||
Negative(Box<Node>),
|
||||
|
||||
Number(f64),
|
||||
}
|
||||
|
||||
|
@ -26,10 +27,16 @@ pub fn eval(expr: Node) -> Result<f64, Box<dyn error::Error>> {
|
|||
use self::Node::*;
|
||||
match expr {
|
||||
Number(i) => Ok(i),
|
||||
Add(expr1, expr2) => Ok(eval(*expr1)? + eval(*expr2)?),
|
||||
|
||||
// TODO: complete the match expression to evaluate the numeric value
|
||||
_ => panic!()
|
||||
And(expr1, expr2) => Ok((eval(*expr1)? as i32 & eval(*expr2)? as i32).into()),
|
||||
Or(expr1, expr2) => Ok((eval(*expr1)? as i32 | eval(*expr2)? as i32).into()),
|
||||
|
||||
Add(expr1, expr2) => Ok(eval(*expr1)? + eval(*expr2)?),
|
||||
Subtract(expr1, expr2) => Ok(eval(*expr1)? - eval(*expr2)?),
|
||||
Multiply(expr1, expr2) => Ok(eval(*expr1)? * eval(*expr2)?),
|
||||
Divide(expr1, expr2) => Ok(eval(*expr1)? / eval(*expr2)?),
|
||||
Negative(expr1) => Ok(-(eval(*expr1)?)),
|
||||
Caret(expr1, expr2) => Ok(eval(*expr1)?.powf(eval(*expr2)?)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@ impl<'a> Parser<'a> {
|
|||
pub fn parse(&mut self) -> Result<Node, ParseError> {
|
||||
let ast = self.generate_ast(OperPrec::DefaultZero);
|
||||
match ast {
|
||||
// TODO: Replace this with proper handling of return value from generate_ast result
|
||||
_ => panic!()
|
||||
Ok(ast) => Ok(ast),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,9 +87,15 @@ impl<'a> Parser<'a> {
|
|||
Token::LeftParen => {
|
||||
self.get_next_token()?;
|
||||
|
||||
// TODO: Replace the following code to check for matching parenthesis;
|
||||
// also convert (x)(y) to x times y
|
||||
let expr = self.generate_ast(OperPrec::DefaultZero)?;
|
||||
let _ = self.check_paren(Token::RightParen);
|
||||
|
||||
if self.current_token == Token::LeftParen
|
||||
{
|
||||
let right = self.generate_ast(OperPrec::MulDiv)?;
|
||||
return Ok(Node::Multiply(Box::new(expr), Box::new(right)));
|
||||
}
|
||||
|
||||
Ok(expr)
|
||||
}
|
||||
_ => Err(ParseError::UnableToParse("Unable to parse".to_string())),
|
||||
|
@ -110,15 +116,57 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
// Construct Operator AST nodes
|
||||
fn convert_token_to_node(&mut self, left_expr: Node) -> Result<Node, ParseError> {
|
||||
match self.current_token {
|
||||
Token::Add => {
|
||||
fn convert_token_to_node(&mut self, left_expr: Node) -> Result<Node, ParseError>
|
||||
{
|
||||
match self.current_token
|
||||
{
|
||||
Token::And =>
|
||||
{
|
||||
self.get_next_token()?;
|
||||
let right_expr = self.generate_ast(OperPrec::AndOr)?;
|
||||
Ok(Node::And(Box::new(left_expr), Box::new(right_expr)))
|
||||
},
|
||||
Token::Or =>
|
||||
{
|
||||
self.get_next_token()?;
|
||||
let right_expr = self.generate_ast(OperPrec::AndOr)?;
|
||||
Ok(Node::Or(Box::new(left_expr), Box::new(right_expr)))
|
||||
},
|
||||
Token::Add =>
|
||||
{
|
||||
self.get_next_token()?;
|
||||
//Get right-side expression
|
||||
let right_expr = self.generate_ast(OperPrec::AddSub)?;
|
||||
Ok(Node::Add(Box::new(left_expr), Box::new(right_expr)))
|
||||
}
|
||||
// TODO: Complete the node construction for other tokens
|
||||
|
||||
Token::Subtract =>
|
||||
{
|
||||
self.get_next_token()?;
|
||||
let right_expr = self.generate_ast(OperPrec::AddSub)?;
|
||||
Ok(Node::Subtract(Box::new(left_expr), Box::new(right_expr)))
|
||||
}
|
||||
|
||||
Token::Multiply =>
|
||||
{
|
||||
self.get_next_token()?;
|
||||
let right_expr = self.generate_ast(OperPrec::MulDiv)?;
|
||||
Ok(Node::Multiply(Box::new(left_expr), Box::new(right_expr)))
|
||||
}
|
||||
|
||||
Token::Divide =>
|
||||
{
|
||||
self.get_next_token()?;
|
||||
let right_expr = self.generate_ast(OperPrec::MulDiv)?;
|
||||
Ok(Node::Divide(Box::new(left_expr), Box::new(right_expr)))
|
||||
}
|
||||
|
||||
Token::Caret =>
|
||||
{
|
||||
self.get_next_token()?;
|
||||
let right_expr = self.generate_ast(OperPrec::Power)?;
|
||||
Ok(Node::Caret(Box::new(left_expr), Box::new(right_expr)))
|
||||
}
|
||||
|
||||
_ => Err(ParseError::InvalidOperator(format!(
|
||||
"Please enter valid operator {:?}",
|
||||
|
|
|
@ -41,7 +41,6 @@ impl Token {
|
|||
Add | Subtract => AddSub,
|
||||
Multiply | Divide => MulDiv,
|
||||
Caret => Power,
|
||||
|
||||
_ => DefaultZero,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
/// This module reads characters in arithmetic expression and converts them to tokens.
|
||||
/// The allowed tokens are defined in ast module.
|
||||
// Standard lib
|
||||
use std::iter::Peekable;
|
||||
use std::str::Chars;
|
||||
|
||||
//Other internal modules
|
||||
use super::token::Token;
|
||||
|
||||
// Other structs
|
||||
|
||||
// Tokenizer struct contains a Peekable iterator on the arithmetic expression
|
||||
pub struct Tokenizer<'a> {
|
||||
pub struct Tokenizer<'a>
|
||||
{
|
||||
expr: Peekable<Chars<'a>>,
|
||||
}
|
||||
|
||||
// Constructs a new instance of Tokenizer
|
||||
impl<'a> Tokenizer<'a> {
|
||||
pub fn new(new_expr: &'a str) -> Self {
|
||||
Tokenizer {
|
||||
impl<'a> Tokenizer<'a>
|
||||
{
|
||||
pub fn new(new_expr: &'a str) -> Self
|
||||
{
|
||||
Tokenizer
|
||||
{
|
||||
expr: new_expr.chars().peekable(),
|
||||
}
|
||||
}
|
||||
|
@ -26,21 +26,45 @@ impl<'a> Tokenizer<'a> {
|
|||
// Implement Iterator trait for Tokenizer struct.
|
||||
// With this, we can use next() method on tokenizer to retrieve the next token from arithmetic expression
|
||||
|
||||
impl<'a> Iterator for Tokenizer<'a> {
|
||||
impl<'a> Iterator for Tokenizer<'a>
|
||||
{
|
||||
type Item = Token;
|
||||
|
||||
fn next(&mut self) -> Option<Token> {
|
||||
fn next(&mut self) -> Option<Token>
|
||||
{
|
||||
let next_char = self.expr.next();
|
||||
|
||||
match next_char {
|
||||
match next_char
|
||||
{
|
||||
Some('0'..='9') => {
|
||||
// TODO: Iterate & peeking through the next characters to create Num token
|
||||
// Make sure to return None if the value is not parsable
|
||||
None
|
||||
let mut number = next_char?.to_string();
|
||||
while let Some(next_char) = self.expr.peek()
|
||||
{
|
||||
if next_char.is_numeric() || next_char == &'.'
|
||||
{
|
||||
number.push(self.expr.next()?);
|
||||
}
|
||||
else if next_char == &'('
|
||||
{
|
||||
return None;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
Some(Token::Num(number.parse::<f64>().unwrap()))
|
||||
},
|
||||
|
||||
// TODO: return the appropriate tokens for available symbols
|
||||
|
||||
Some('&') => Some(Token::And),
|
||||
Some('|') => Some(Token::Or),
|
||||
Some('+') => Some(Token::Add),
|
||||
Some('-') => Some(Token::Subtract),
|
||||
Some('*') => Some(Token::Multiply),
|
||||
Some('/') => Some(Token::Divide),
|
||||
Some('^') => Some(Token::Caret),
|
||||
Some('(') => Some(Token::LeftParen),
|
||||
Some(')') => Some(Token::RightParen),
|
||||
None => Some(Token::EOF),
|
||||
Some(_) => None,
|
||||
}
|
||||
|
@ -49,21 +73,25 @@ impl<'a> Iterator for Tokenizer<'a> {
|
|||
|
||||
// Unit tests
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
mod tests
|
||||
{
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_positive_integer() {
|
||||
fn test_positive_integer()
|
||||
{
|
||||
let mut tokenizer = Tokenizer::new("34");
|
||||
assert_eq!(tokenizer.next().unwrap(), Token::Num(34.0))
|
||||
}
|
||||
#[test]
|
||||
fn test_decimal_number() {
|
||||
fn test_decimal_number()
|
||||
{
|
||||
let mut tokenizer = Tokenizer::new("34.5");
|
||||
assert_eq!(tokenizer.next().unwrap(), Token::Num(34.5))
|
||||
}
|
||||
#[test]
|
||||
fn test_invalid_char() {
|
||||
fn test_invalid_char()
|
||||
{
|
||||
let mut tokenizer = Tokenizer::new("#$%");
|
||||
assert_eq!(tokenizer.next(), None);
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"rustc_fingerprint":15625702514836887422,"outputs":{"15729799797837862367":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/usr/local/rustup/toolchains/1.83.0-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""},"4614504638168534921":{"success":true,"status":"","code":0,"stdout":"rustc 1.83.0 (90b35a623 2024-11-26)\nbinary: rustc\ncommit-hash: 90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf\ncommit-date: 2024-11-26\nhost: x86_64-unknown-linux-gnu\nrelease: 1.83.0\nLLVM version: 19.1.1\n","stderr":""}},"successes":{}}
|
||||
{"rustc_fingerprint":14404728096486143510,"outputs":{"4614504638168534921":{"success":true,"status":"","code":0,"stdout":"rustc 1.83.0 (90b35a623 2024-11-26)\nbinary: rustc\ncommit-hash: 90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf\ncommit-date: 2024-11-26\nhost: x86_64-unknown-linux-gnu\nrelease: 1.83.0\nLLVM version: 19.1.1\n","stderr":""},"15729799797837862367":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/usr/local/rustup/toolchains/1.83.0-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""}},"successes":{}}
|
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue