Start working on expressions

This commit is contained in:
Lewis Dale 2023-01-27 13:51:41 +00:00
parent 627baa8449
commit 5e500e9ec3
4 changed files with 128 additions and 5 deletions

View File

@ -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]

View File

@ -34,4 +34,4 @@ impl Node {
None
}
}
}
}

View File

@ -1,3 +1,4 @@
pub mod commands;
pub mod expressions;
pub mod generic;
pub mod variables;

119
src/parsers/expressions.rs Normal file
View 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);
}
}