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 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)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct Program {
|
pub struct Program {
|
||||||
@ -95,8 +98,8 @@ mod tests {
|
|||||||
use super::{Command, Node, Primitive, Program};
|
use super::{Command, Node, Primitive, Program};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
commands::Line,
|
||||||
parsers::{commands::parse_line, generic::read_string},
|
parsers::{commands::parse_line, generic::read_string},
|
||||||
commands::Line
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
pub mod commands;
|
pub mod commands;
|
||||||
|
pub mod expressions;
|
||||||
pub mod generic;
|
pub mod generic;
|
||||||
pub mod variables;
|
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