Add assignment 4

This commit is contained in:
Seungmin Jeon
2022-09-15 21:58:55 +09:00
parent 27f0b78a2c
commit 8e5abc7048
11 changed files with 509 additions and 1 deletions

View File

@@ -0,0 +1,46 @@
//! Calculator.
use std::collections::HashMap;
use anyhow::*;
use super::syntax::{Command, Expression};
/// Calculator's context.
#[derive(Debug, Default, Clone)]
pub struct Context {
anonymous_counter: usize,
variables: HashMap<String, f64>,
}
impl Context {
/// Creates a new context.
pub fn new() -> Self {
Self::default()
}
/// Returns the current anonymous variable counter.
pub fn current_counter(&self) -> usize {
self.anonymous_counter
}
/// Calculates the given expression.
pub fn calc_expression(&self, expression: &Expression) -> Result<f64> {
todo!("fill here")
}
/// Calculates the given command.
///
/// If there is no variable lhs in the command (i.e. `command.variable = None`), its value should be stored at `$0`, `$1`, `$2`, ... respectively.
///
/// # Example
///
/// After calculating commad `3 + 5` => Context's variables = `{($0,8)}`
///
/// After calculating commad `v = 3 - 2` => Context's variables = `{($0,8),(v,1))}`
///
/// 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")
}
}

View File

@@ -0,0 +1,20 @@
//! Assignment 4: Designing a calculator.
//!
//! The primary goal of this assignment is twofold:
//! (1) understanding the `pest` third-party library from documentations; and
//! (2) using programming concepts you've learned so far to implement a simple arithmetic calculator.
//!
//! For `pest`, read the following documentations (that contain 90% of the solution):
//! - <https://pest.rs/>
//! - <https://pest.rs/book/>
//! - <https://docs.rs/pest/latest/pest>
//!
//! For calculator, just reading `syntax.rs` would suffice for you to understand what to do.
//!
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-04.sh` works fine.
//! See `assignment04_grade.rs` and `/scripts/grade-04.sh` for the test script.
//! Run `/scripts/prepare-submissions.sh` and submit `/target/assignment04.zip` to <https://gg.kaist.ac.kr>.
pub mod context;
pub mod parser;
pub mod syntax;

View File

@@ -0,0 +1,19 @@
//! Parser.
use super::syntax::*;
use anyhow::Result;
#[allow(missing_docs)]
#[allow(missing_debug_implementations)]
mod inner {
use pest_derive::*;
#[derive(Parser)]
#[grammar = "assignments/assignment04/syntax.pest"]
pub(crate) struct SyntaxParser;
}
/// Parses command.
pub fn parse_command(line: &str) -> Result<Command> {
todo!("fill here")
}

View File

@@ -0,0 +1,17 @@
num = @{ int ~ ("." ~ ASCII_DIGIT*)? ~ (^"e" ~ int)? }
int = { ("+" | "-")? ~ ASCII_DIGIT+ }
var = { ("$" | ASCII_ALPHA) ~ (ASCII_ALPHA | ASCII_DIGIT)* }
operation = _{ add | subtract | multiply | divide | power }
add = { "+" }
subtract = { "-" }
multiply = { "*" }
divide = { "/" }
power = { "^" }
expr = { term ~ (operation ~ term)* }
term = _{ num | var | "(" ~ expr ~ ")" }
command = _{ SOI ~ (var ~ "=")? ~ expr ~ EOI }
WHITESPACE = _{ " " | "\t" }

View File

@@ -0,0 +1,43 @@
//! Syntax.
/// Command of the form "<expression>" or "<var> = <expression>".
#[derive(Debug, Clone, PartialEq)]
pub struct Command {
/// Variable (lhs).
pub variable: Option<String>,
/// Expression (rhs).
pub expression: Expression,
}
/// Binary operators.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinOp {
/// Add.
Add,
/// Subtract.
Subtract,
/// Multiply.
Multiply,
/// Divide.
Divide,
/// Power.
Power,
}
/// Expression.
#[derive(Debug, Clone, PartialEq)]
pub enum Expression {
/// Number.
Num(f64),
/// Variable.
Variable(String),
/// Binary operation.
BinOp {
/// Operator.
op: BinOp,
/// Lhs.
lhs: Box<Expression>,
/// Rhs.
rhs: Box<Expression>,
},
}