mirror of
https://github.com/kmc7468/cs220.git
synced 2025-12-12 21:08:45 +00:00
Assignment 4 Done
This commit is contained in:
@@ -27,7 +27,26 @@ impl Context {
|
||||
|
||||
/// Calculates the given expression. (We assume the absence of overflow.)
|
||||
pub fn calc_expression(&self, expression: &Expression) -> Result<f64> {
|
||||
todo!("fill here")
|
||||
match expression {
|
||||
Expression::Num(value) => Ok(*value),
|
||||
Expression::Variable(name) => self
|
||||
.variables
|
||||
.get(name)
|
||||
.copied()
|
||||
.ok_or(anyhow!("Unknown variable")),
|
||||
Expression::BinOp { op, lhs, rhs } => {
|
||||
let lhs = self.calc_expression(lhs)?;
|
||||
let rhs = self.calc_expression(rhs)?;
|
||||
match op {
|
||||
BinOp::Add => Ok(lhs + rhs),
|
||||
BinOp::Subtract => Ok(lhs - rhs),
|
||||
BinOp::Multiply => Ok(lhs * rhs),
|
||||
BinOp::Divide if rhs == 0.0 => Err(anyhow!("Division by zero")),
|
||||
BinOp::Divide => Ok(lhs / rhs),
|
||||
BinOp::Power => Ok(lhs.powf(rhs)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates the given command. (We assume the absence of overflow.)
|
||||
@@ -43,6 +62,14 @@ impl Context {
|
||||
///
|
||||
/// After calculating commad `3 ^ 2` => Context's variables = `{($0,8),(v,1),($1,9)}`
|
||||
pub fn calc_command(&mut self, command: &Command) -> Result<(String, f64)> {
|
||||
todo!("fill here")
|
||||
let value = self.calc_expression(&command.expression)?;
|
||||
let name = command.variable.clone().unwrap_or_else(|| {
|
||||
let name = format!("${}", self.anonymous_counter);
|
||||
self.anonymous_counter += 1;
|
||||
name
|
||||
});
|
||||
|
||||
_ = self.variables.insert(name.clone(), value);
|
||||
Ok((name, value))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,19 @@ use super::syntax::*;
|
||||
#[allow(missing_docs)]
|
||||
#[allow(missing_debug_implementations)]
|
||||
mod inner {
|
||||
use pest::pratt_parser::{Assoc::*, *};
|
||||
use pest_derive::*;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[grammar = "assignments/assignment04/syntax.pest"]
|
||||
pub(crate) struct SyntaxParser;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref PRATT_PARSER: PrattParser<Rule> = PrattParser::new()
|
||||
.op(Op::infix(Rule::add, Left) | Op::infix(Rule::subtract, Left))
|
||||
.op(Op::infix(Rule::multiply, Left) | Op::infix(Rule::divide, Left))
|
||||
.op(Op::infix(Rule::power, Right));
|
||||
}
|
||||
}
|
||||
|
||||
use inner::*;
|
||||
@@ -32,5 +40,51 @@ use inner::*;
|
||||
/// e.g. `1+2+3` should be parsed into `(1+2)+3`, not `1+(2+3)` because the associativity of
|
||||
/// plus("add" in our hw) operator is `Left`.
|
||||
pub fn parse_command(line: &str) -> Result<Command> {
|
||||
todo!("fill here")
|
||||
let mut variable: Option<&str> = None;
|
||||
let mut expression: Option<Expression> = None;
|
||||
|
||||
for pair in SyntaxParser::parse(Rule::command, line)? {
|
||||
match pair.as_rule() {
|
||||
Rule::var => variable = Some(pair.as_str()),
|
||||
Rule::expr => expression = Some(parse_expression(pair.into_inner())?),
|
||||
Rule::EOI => {}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Command {
|
||||
variable: variable.map(|s| s.to_string()),
|
||||
expression: expression.unwrap(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Parses expression.
|
||||
pub fn parse_expression(pairs: Pairs<'_, Rule>) -> Result<Expression> {
|
||||
let mut first_term: Option<Expression> = None;
|
||||
let mut operation: Option<BinOp> = None;
|
||||
let mut second_term: Option<Expression> = None;
|
||||
|
||||
PRATT_PARSER
|
||||
.map_primary(|primary| match primary.as_rule() {
|
||||
Rule::num => Ok(Expression::Num(primary.as_str().parse()?)),
|
||||
Rule::var => Ok(Expression::Variable(primary.as_str().to_string())),
|
||||
Rule::expr => Ok(parse_expression(primary.into_inner())?),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.map_infix(|lhs, op, rhs| {
|
||||
let op = match op.as_rule() {
|
||||
Rule::add => BinOp::Add,
|
||||
Rule::subtract => BinOp::Subtract,
|
||||
Rule::multiply => BinOp::Multiply,
|
||||
Rule::divide => BinOp::Divide,
|
||||
Rule::power => BinOp::Power,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
Ok(Expression::BinOp {
|
||||
op,
|
||||
lhs: Box::new(lhs?),
|
||||
rhs: Box::new(rhs?),
|
||||
})
|
||||
})
|
||||
.parse(pairs)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user