Start working on expressions
This commit is contained in:
parent
627baa8449
commit
5e500e9ec3
11
src/basic.rs
11
src/basic.rs
@ -1,9 +1,12 @@
|
||||
use std::{collections::HashMap};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use nom::{bytes::complete::tag, multi::separated_list0, IResult};
|
||||
|
||||
use crate::{parsers, commands::{Primitive, PrintOutput, Command}, node::Node};
|
||||
|
||||
use crate::{
|
||||
commands::{Command, Primitive, PrintOutput},
|
||||
node::Node,
|
||||
parsers,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub struct Program {
|
||||
@ -95,8 +98,8 @@ mod tests {
|
||||
use super::{Command, Node, Primitive, Program};
|
||||
|
||||
use crate::{
|
||||
commands::Line,
|
||||
parsers::{commands::parse_line, generic::read_string},
|
||||
commands::Line
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
@ -34,4 +34,4 @@ impl Node {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
pub mod commands;
|
||||
pub mod expressions;
|
||||
pub mod generic;
|
||||
pub mod variables;
|
||||
|
119
src/parsers/expressions.rs
Normal file
119
src/parsers/expressions.rs
Normal file
@ -0,0 +1,119 @@
|
||||
use nom::{
|
||||
character::{complete::i64 as cci64, streaming::one_of},
|
||||
combinator::{map, value},
|
||||
sequence::tuple,
|
||||
IResult, branch::alt, multi::many0,
|
||||
};
|
||||
|
||||
use crate::commands::Primitive;
|
||||
|
||||
use super::variables::parse_int;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum Operator {
|
||||
Add,
|
||||
Subtract,
|
||||
Divide,
|
||||
Multiply,
|
||||
}
|
||||
|
||||
impl From<char> for Operator {
|
||||
fn from(value: char) -> Self {
|
||||
match value {
|
||||
'+' => Operator::Add,
|
||||
'-' => Operator::Subtract,
|
||||
'/' => Operator::Divide,
|
||||
'*' => Operator::Multiply,
|
||||
_ => panic!("Unrecognised character"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type Expression = (ExpressionTarget, Operator, ExpressionTarget);
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum ExpressionTarget {
|
||||
Val(Primitive),
|
||||
Expression(Box<Expression>),
|
||||
}
|
||||
|
||||
impl From<i64> for ExpressionTarget {
|
||||
fn from(value: i64) -> Self {
|
||||
ExpressionTarget::Val(Primitive::Int(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Expression> for ExpressionTarget {
|
||||
fn from(value: Expression) -> Self {
|
||||
Self::Expression(Box::new(value))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_expression_target(i: &str) -> IResult<&str, ExpressionTarget> {
|
||||
alt((
|
||||
map(parse_expression, ExpressionTarget::from),
|
||||
map(cci64, ExpressionTarget::from)
|
||||
))(i)
|
||||
}
|
||||
|
||||
pub fn parse_expression(i: &str) -> IResult<&str, Expression> {
|
||||
tuple((map(cci64, ExpressionTarget::from),
|
||||
map(one_of("*/+-"), Operator::from),
|
||||
map(cci64, ExpressionTarget::from)))(i)
|
||||
}
|
||||
|
||||
pub fn parse_full_expression(i: &str) -> IResult<&str, Expression> {
|
||||
tuple((
|
||||
parse_expression_target,
|
||||
map(one_of("*/+-"), Operator::from),
|
||||
parse_expression_target,
|
||||
))(i)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::commands::Primitive;
|
||||
|
||||
use super::{parse_full_expression, Expression, ExpressionTarget, Operator};
|
||||
|
||||
#[test]
|
||||
fn it_parses_a_simple_expression() {
|
||||
let input = "1+1";
|
||||
let expected: Expression = (
|
||||
ExpressionTarget::Val(Primitive::Int(1)),
|
||||
Operator::Add,
|
||||
ExpressionTarget::Val(Primitive::Int(1)),
|
||||
);
|
||||
let (_, result) = parse_full_expression(input).unwrap();
|
||||
assert_eq!(expected, result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_parses_a_subtraction_expression() {
|
||||
let input = "1-1";
|
||||
let expected: Expression = (
|
||||
ExpressionTarget::Val(Primitive::Int(1)),
|
||||
Operator::Subtract,
|
||||
ExpressionTarget::Val(Primitive::Int(1)),
|
||||
);
|
||||
let (_, result) = parse_full_expression(input).unwrap();
|
||||
assert_eq!(expected, result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_parses_a_left_hand_subexpression() {
|
||||
let input = "1+1+2";
|
||||
let expected: Expression = (
|
||||
ExpressionTarget::Expression(Box::new((
|
||||
ExpressionTarget::Val(Primitive::Int(1)),
|
||||
Operator::Add,
|
||||
ExpressionTarget::Val(Primitive::Int(1))
|
||||
))),
|
||||
Operator::Add,
|
||||
ExpressionTarget::Val(Primitive::Int(2))
|
||||
);
|
||||
|
||||
let (_, result) = parse_full_expression(input).unwrap();
|
||||
assert_eq!(expected, result);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user