Add comma operator and display implementations

+ Add comma token
 + Add tuple operator
 + Add tuple value type
 + Implement display for `tree::Node` and all related types
 + Add support for right-to-left chaining of operators with same precedence

The priority of chaining of operators with the same precedence remains left-to-right.
Only if two consecutive operators with the same precedence are right-to-left, they will be ordered right-to-left.

Implements #4.
This commit is contained in:
Sebastian Schmidt 2019-03-19 16:54:52 +02:00
parent 265b1214b0
commit c631171ff0
11 changed files with 454 additions and 34 deletions

View File

@ -191,3 +191,4 @@ See [LICENSE](LICENSE) for details.
## Closing Notes ## Closing Notes
If you have any ideas for features or see any problems in the code, architecture, interface, algorithmics or documentation, please open an issue on github. If you have any ideas for features or see any problems in the code, architecture, interface, algorithmics or documentation, please open an issue on github.
If there is already an issue describing what you want to say, please add a thumbs up or whatever emoji you think fits to the issue, so I know which ones I should prioritize.

View File

@ -3,7 +3,11 @@ use token::PartialToken;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum Error { pub enum Error {
WrongArgumentAmount { WrongOperatorArgumentAmount {
expected: usize,
actual: usize,
},
WrongFunctionArgumentAmount {
expected: usize, expected: usize,
actual: usize, actual: usize,
}, },
@ -50,8 +54,12 @@ pub enum Error {
} }
impl Error { impl Error {
pub fn wrong_argument_amount(actual: usize, expected: usize) -> Self { pub fn wrong_operator_argument_amount(actual: usize, expected: usize) -> Self {
Error::WrongArgumentAmount { actual, expected } Error::WrongOperatorArgumentAmount { actual, expected }
}
pub fn wrong_function_argument_amount(actual: usize, expected: usize) -> Self {
Error::WrongFunctionArgumentAmount { actual, expected }
} }
pub fn expected_number(actual: Value) -> Self { pub fn expected_number(actual: Value) -> Self {
@ -67,11 +75,19 @@ impl Error {
} }
} }
pub fn expect_argument_amount(actual: usize, expected: usize) -> Result<(), Error> { pub fn expect_operator_argument_amount(actual: usize, expected: usize) -> Result<(), Error> {
if actual == expected { if actual == expected {
Ok(()) Ok(())
} else { } else {
Err(Error::wrong_argument_amount(actual, expected)) Err(Error::wrong_operator_argument_amount(actual, expected))
}
}
pub fn expect_function_argument_amount(actual: usize, expected: usize) -> Result<(), Error> {
if actual == expected {
Ok(())
} else {
Err(Error::wrong_function_argument_amount(actual, expected))
} }
} }

View File

@ -18,7 +18,7 @@ impl Function {
} }
pub fn call(&self, arguments: &[Value]) -> Result<Value, Error> { pub fn call(&self, arguments: &[Value]) -> Result<Value, Error> {
error::expect_argument_amount(self.argument_amount, arguments.len())?; error::expect_function_argument_amount(arguments.len(), self.argument_amount)?;
(self.function)(arguments) (self.function)(arguments)
} }
} }

View File

@ -175,6 +175,8 @@
//! See [LICENSE](LICENSE) for details. //! See [LICENSE](LICENSE) for details.
//! //!
extern crate core;
mod configuration; mod configuration;
pub mod error; pub mod error;
mod function; mod function;
@ -210,7 +212,7 @@ pub fn build_operator_tree(string: &str) -> Result<Node, Error> {
mod test { mod test {
use crate::{eval, value::Value}; use crate::{eval, value::Value};
use configuration::HashMapConfiguration; use configuration::HashMapConfiguration;
use error::Error; use error::{expect_number, Error};
use eval_with_configuration; use eval_with_configuration;
use Function; use Function;
@ -377,6 +379,88 @@ mod test {
); );
} }
#[test]
fn test_n_ary_functions() {
let mut configuration = HashMapConfiguration::new();
configuration.insert_function(
"sub2",
Function::new(
1,
Box::new(|arguments| {
if let Value::Int(int) = arguments[0] {
Ok(Value::Int(int - 2))
} else if let Value::Float(float) = arguments[0] {
Ok(Value::Float(float - 2.0))
} else {
Err(Error::expected_number(arguments[0].clone()))
}
}),
),
);
configuration.insert_function(
"avg",
Function::new(
2,
Box::new(|arguments| {
expect_number(&arguments[0])?;
expect_number(&arguments[1])?;
if let (Value::Int(a), Value::Int(b)) = (&arguments[0], &arguments[1]) {
Ok(Value::Int((a + b) / 2))
} else {
Ok(Value::Float(
(arguments[0].as_float()? + arguments[1].as_float()?) / 2.0,
))
}
}),
),
);
configuration.insert_function(
"muladd",
Function::new(
3,
Box::new(|arguments| {
expect_number(&arguments[0])?;
expect_number(&arguments[1])?;
expect_number(&arguments[2])?;
if let (Value::Int(a), Value::Int(b), Value::Int(c)) =
(&arguments[0], &arguments[1], &arguments[2])
{
Ok(Value::Int(a * b + c))
} else {
Ok(Value::Float(
arguments[0].as_float()? * arguments[1].as_float()?
+ arguments[2].as_float()?,
))
}
}),
),
);
configuration.insert_variable("five".to_string(), Value::Int(5));
assert_eq!(
eval_with_configuration("avg(7, 5)", &configuration),
Ok(Value::Int(6))
);
assert_eq!(
eval_with_configuration("avg(sub2 5, 5)", &configuration),
Ok(Value::Int(4))
);
assert_eq!(
eval_with_configuration("sub2(avg(3, 6))", &configuration),
Ok(Value::Int(2))
);
assert_eq!(
eval_with_configuration("sub2 avg(3, 6)", &configuration),
Ok(Value::Int(2))
);
assert_eq!(
eval_with_configuration("muladd(3, 6, -4)", &configuration),
Ok(Value::Int(14))
);
}
#[test] #[test]
fn test_errors() { fn test_errors() {
assert_eq!( assert_eq!(
@ -387,7 +471,10 @@ mod test {
eval("1-true"), eval("1-true"),
Err(Error::expected_number(Value::Boolean(true))) Err(Error::expected_number(Value::Boolean(true)))
); );
assert_eq!(eval("true-"), Err(Error::wrong_argument_amount(1, 2))); assert_eq!(
eval("true-"),
Err(Error::wrong_operator_argument_amount(1, 2))
);
assert_eq!(eval("!(()true)"), Err(Error::AppendedToLeafNode)); assert_eq!(eval("!(()true)"), Err(Error::AppendedToLeafNode));
} }
} }

122
src/operator/display.rs Normal file
View File

@ -0,0 +1,122 @@
use operator::*;
use std::fmt::{Display, Error, Formatter};
impl Display for RootNode {
fn fmt(&self, _f: &mut Formatter) -> Result<(), Error> {
Ok(())
}
}
impl Display for Add {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "+")
}
}
impl Display for Sub {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "-")
}
}
impl Display for Neg {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "-")
}
}
impl Display for Mul {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "*")
}
}
impl Display for Div {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "/")
}
}
impl Display for Mod {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "%")
}
}
impl Display for Eq {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "==")
}
}
impl Display for Neq {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "!=")
}
}
impl Display for Gt {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, ">")
}
}
impl Display for Lt {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "<")
}
}
impl Display for Geq {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, ">=")
}
}
impl Display for Leq {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "<=")
}
}
impl Display for And {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "&&")
}
}
impl Display for Or {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "||")
}
}
impl Display for Not {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "!")
}
}
impl Display for Tuple {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, ", ")
}
}
impl Display for Const {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "{}", self.value)
}
}
impl Display for VariableIdentifier {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "{}", self.identifier)
}
}
impl Display for FunctionIdentifier {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "{}", self.identifier)
}
}

View File

@ -1,12 +1,20 @@
use crate::{configuration::Configuration, error::*, value::Value}; use crate::{configuration::Configuration, error::*, value::Value};
use std::fmt::Debug; use std::fmt::{Debug, Display};
pub trait Operator: Debug { mod display;
pub trait Operator: Debug + Display {
/// Returns the precedence of the operator. /// Returns the precedence of the operator.
/// A high precedence means that the operator has priority to be deeper in the tree. /// A high precedence means that the operator has priority to be deeper in the tree.
// Make this a const fn once #57563 is resolved // Make this a const fn once #57563 is resolved
fn precedence(&self) -> i32; fn precedence(&self) -> i32;
/// Returns true if chains of operators with the same precedence as this one should be evaluated left-to-right,
/// and false if they should be evaluated right-to-left.
/// Left-to-right chaining has priority if operators with different order but same precedence are chained.
// Make this a const fn once #57563 is resolved
fn is_left_to_right(&self) -> bool;
/// True if this operator is a leaf, meaning it accepts no arguments. /// True if this operator is a leaf, meaning it accepts no arguments.
// Make this a const fn once #57563 is resolved // Make this a const fn once #57563 is resolved
fn is_leaf(&self) -> bool { fn is_leaf(&self) -> bool {
@ -56,6 +64,9 @@ pub struct Or;
#[derive(Debug)] #[derive(Debug)]
pub struct Not; pub struct Not;
#[derive(Debug)]
pub struct Tuple;
#[derive(Debug)] #[derive(Debug)]
pub struct Const { pub struct Const {
value: Value, value: Value,
@ -94,12 +105,16 @@ impl Operator for RootNode {
200 200
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
1 1
} }
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 1)?; expect_operator_argument_amount(arguments.len(), 1)?;
Ok(arguments[0].clone()) Ok(arguments[0].clone())
} }
} }
@ -109,12 +124,16 @@ impl Operator for Add {
95 95
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
2 2
} }
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 2)?; expect_operator_argument_amount(arguments.len(), 2)?;
expect_number(&arguments[0])?; expect_number(&arguments[0])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -135,12 +154,16 @@ impl Operator for Sub {
95 95
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
2 2
} }
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 2)?; expect_operator_argument_amount(arguments.len(), 2)?;
expect_number(&arguments[0])?; expect_number(&arguments[0])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -161,12 +184,16 @@ impl Operator for Neg {
110 110
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
1 1
} }
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 1)?; expect_operator_argument_amount(arguments.len(), 1)?;
expect_number(&arguments[0])?; expect_number(&arguments[0])?;
if arguments[0].is_int() { if arguments[0].is_int() {
@ -182,12 +209,16 @@ impl Operator for Mul {
100 100
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
2 2
} }
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 2)?; expect_operator_argument_amount(arguments.len(), 2)?;
expect_number(&arguments[0])?; expect_number(&arguments[0])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -208,12 +239,16 @@ impl Operator for Div {
100 100
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
2 2
} }
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 2)?; expect_operator_argument_amount(arguments.len(), 2)?;
expect_number(&arguments[0])?; expect_number(&arguments[0])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -234,12 +269,16 @@ impl Operator for Mod {
100 100
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
2 2
} }
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 2)?; expect_operator_argument_amount(arguments.len(), 2)?;
expect_number(&arguments[0])?; expect_number(&arguments[0])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -260,12 +299,16 @@ impl Operator for Eq {
80 80
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
2 2
} }
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 2)?; expect_operator_argument_amount(arguments.len(), 2)?;
if arguments[0] == arguments[1] { if arguments[0] == arguments[1] {
Ok(Value::Boolean(true)) Ok(Value::Boolean(true))
@ -280,12 +323,16 @@ impl Operator for Neq {
80 80
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
2 2
} }
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 2)?; expect_operator_argument_amount(arguments.len(), 2)?;
if arguments[0] != arguments[1] { if arguments[0] != arguments[1] {
Ok(Value::Boolean(true)) Ok(Value::Boolean(true))
@ -300,12 +347,16 @@ impl Operator for Gt {
80 80
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
2 2
} }
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 2)?; expect_operator_argument_amount(arguments.len(), 2)?;
expect_number(&arguments[0])?; expect_number(&arguments[0])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -330,12 +381,16 @@ impl Operator for Lt {
80 80
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
2 2
} }
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 2)?; expect_operator_argument_amount(arguments.len(), 2)?;
expect_number(&arguments[0])?; expect_number(&arguments[0])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -360,12 +415,16 @@ impl Operator for Geq {
80 80
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
2 2
} }
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 2)?; expect_operator_argument_amount(arguments.len(), 2)?;
expect_number(&arguments[0])?; expect_number(&arguments[0])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -390,12 +449,16 @@ impl Operator for Leq {
80 80
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
2 2
} }
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 2)?; expect_operator_argument_amount(arguments.len(), 2)?;
expect_number(&arguments[0])?; expect_number(&arguments[0])?;
expect_number(&arguments[1])?; expect_number(&arguments[1])?;
@ -420,12 +483,16 @@ impl Operator for And {
75 75
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
2 2
} }
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 2)?; expect_operator_argument_amount(arguments.len(), 2)?;
let a = expect_boolean(&arguments[0])?; let a = expect_boolean(&arguments[0])?;
let b = expect_boolean(&arguments[1])?; let b = expect_boolean(&arguments[1])?;
@ -442,12 +509,16 @@ impl Operator for Or {
70 70
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
2 2
} }
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 2)?; expect_operator_argument_amount(arguments.len(), 2)?;
let a = expect_boolean(&arguments[0])?; let a = expect_boolean(&arguments[0])?;
let b = expect_boolean(&arguments[1])?; let b = expect_boolean(&arguments[1])?;
@ -464,12 +535,16 @@ impl Operator for Not {
110 110
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
1 1
} }
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 1)?; expect_operator_argument_amount(arguments.len(), 1)?;
let a = expect_boolean(&arguments[0])?; let a = expect_boolean(&arguments[0])?;
if !a { if !a {
@ -480,17 +555,58 @@ impl Operator for Not {
} }
} }
impl Operator for Tuple {
fn precedence(&self) -> i32 {
40
}
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize {
2
}
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
if let Value::Tuple(tuple) = &arguments[0] {
let mut tuple = tuple.clone();
if let Value::Tuple(tuple2) = &arguments[1] {
tuple.extend(tuple2.iter().cloned());
} else {
tuple.push(arguments[1].clone());
}
Ok(Value::from(tuple))
} else {
if let Value::Tuple(tuple) = &arguments[1] {
let mut tuple = tuple.clone();
tuple.insert(0, arguments[0].clone());
Ok(Value::from(tuple))
} else {
Ok(Value::from(vec![
arguments[0].clone(),
arguments[1].clone(),
]))
}
}
}
}
impl Operator for Const { impl Operator for Const {
fn precedence(&self) -> i32 { fn precedence(&self) -> i32 {
200 200
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
0 0
} }
fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], _configuration: &Configuration) -> Result<Value, Error> {
expect_argument_amount(arguments.len(), 0)?; expect_operator_argument_amount(arguments.len(), 0)?;
Ok(self.value.clone()) Ok(self.value.clone())
} }
@ -501,6 +617,10 @@ impl Operator for VariableIdentifier {
200 200
} }
fn is_left_to_right(&self) -> bool {
true
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
0 0
} }
@ -519,13 +639,24 @@ impl Operator for FunctionIdentifier {
190 190
} }
fn is_left_to_right(&self) -> bool {
false
}
fn argument_amount(&self) -> usize { fn argument_amount(&self) -> usize {
1 1
} }
fn eval(&self, arguments: &[Value], configuration: &Configuration) -> Result<Value, Error> { fn eval(&self, arguments: &[Value], configuration: &Configuration) -> Result<Value, Error> {
expect_operator_argument_amount(arguments.len(), 1)?;
let arguments = if let Value::Tuple(arguments) = &arguments[0] {
arguments
} else {
arguments
};
if let Some(function) = configuration.get_function(&self.identifier) { if let Some(function) = configuration.get_function(&self.identifier) {
// Function::call checks for correct argument amount
function.call(arguments) function.call(arguments)
} else { } else {
Err(Error::FunctionIdentifierNotFound(self.identifier.clone())) Err(Error::FunctionIdentifierNotFound(self.identifier.clone()))

View File

@ -3,7 +3,6 @@ use value::{FloatType, IntType};
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug)]
pub enum Token { pub enum Token {
// Single character tokens
// Arithmetic // Arithmetic
Plus, Plus,
Minus, Minus,
@ -26,7 +25,10 @@ pub enum Token {
LBrace, LBrace,
RBrace, RBrace,
// Complex tokens // Aggregation
Comma,
// Values, Variables and Functions
Identifier(String), Identifier(String),
Float(FloatType), Float(FloatType),
Int(IntType), Int(IntType),
@ -65,6 +67,8 @@ fn char_to_partial_token(c: char) -> PartialToken {
'(' => PartialToken::Token(Token::LBrace), '(' => PartialToken::Token(Token::LBrace),
')' => PartialToken::Token(Token::RBrace), ')' => PartialToken::Token(Token::RBrace),
',' => PartialToken::Token(Token::Comma),
c => { c => {
if c.is_whitespace() { if c.is_whitespace() {
PartialToken::Whitespace PartialToken::Whitespace
@ -98,6 +102,8 @@ impl Token {
Token::LBrace => true, Token::LBrace => true,
Token::RBrace => false, Token::RBrace => false,
Token::Comma => false,
Token::Identifier(_) => true, Token::Identifier(_) => true,
Token::Float(_) => true, Token::Float(_) => true,
Token::Int(_) => true, Token::Int(_) => true,
@ -127,6 +133,8 @@ impl Token {
Token::LBrace => false, Token::LBrace => false,
Token::RBrace => true, Token::RBrace => true,
Token::Comma => false,
Token::Identifier(_) => true, Token::Identifier(_) => true,
Token::Float(_) => true, Token::Float(_) => true,
Token::Int(_) => true, Token::Int(_) => true,

12
src/tree/display.rs Normal file
View File

@ -0,0 +1,12 @@
use std::fmt::{Display, Error, Formatter};
use Node;
impl Display for Node {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
self.operator.fmt(f)?;
for child in self.children() {
write!(f, " {}", child)?;
}
Ok(())
}
}

View File

@ -1,6 +1,8 @@
use crate::{configuration::Configuration, error::Error, operator::*, value::Value}; use crate::{configuration::Configuration, error::Error, operator::*, value::Value};
use token::Token; use token::Token;
mod display;
#[derive(Debug)] #[derive(Debug)]
pub struct Node { pub struct Node {
children: Vec<Node>, children: Vec<Node>,
@ -40,14 +42,18 @@ impl Node {
} }
fn insert_back_prioritized(&mut self, node: Node, is_root_node: bool) -> Result<(), Error> { fn insert_back_prioritized(&mut self, node: Node, is_root_node: bool) -> Result<(), Error> {
if self.operator().precedence() < node.operator().precedence() || is_root_node { if self.operator().precedence() < node.operator().precedence() || is_root_node
// Right-to-left chaining
|| (self.operator().precedence() == node.operator().precedence() && !self.operator().is_left_to_right() && !node.operator().is_left_to_right())
{
if self.operator().is_leaf() { if self.operator().is_leaf() {
Err(Error::AppendedToLeafNode) Err(Error::AppendedToLeafNode)
} else if self.has_correct_amount_of_children() { } else if self.has_correct_amount_of_children() {
if self.children.last().unwrap().operator().precedence() if self.children.last().unwrap().operator().precedence()
< node.operator().precedence() < node.operator().precedence()
// Function call // Right-to-left chaining
//|| self.children().last().unwrap() || (self.children.last().unwrap().operator().precedence()
== node.operator().precedence() && !self.children.last().unwrap().operator().is_left_to_right() && !node.operator().is_left_to_right())
{ {
self.children self.children
.last_mut() .last_mut()
@ -118,6 +124,8 @@ pub fn tokens_to_operator_tree(tokens: Vec<Token>) -> Result<Node, Error> {
} }
} }
Token::Comma => Some(Node::new(Tuple)),
Token::Identifier(identifier) => { Token::Identifier(identifier) => {
let mut result = Some(Node::new(VariableIdentifier::new(identifier.clone()))); let mut result = Some(Node::new(VariableIdentifier::new(identifier.clone())));
if let Some(next) = next { if let Some(next) = next {

26
src/value/display.rs Normal file
View File

@ -0,0 +1,26 @@
use std::fmt::{Display, Error, Formatter};
use Value;
impl Display for Value {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
match self {
Value::String(string) => write!(f, "\"{}\"", string),
Value::Float(float) => write!(f, "{}", float),
Value::Int(int) => write!(f, "{}", int),
Value::Boolean(boolean) => write!(f, "{}", boolean),
Value::Tuple(tuple) => {
write!(f, "(")?;
let mut once = false;
for value in tuple {
if once {
write!(f, ", ")?;
} else {
once = true;
}
value.fmt(f)?;
}
write!(f, ")")
}
}
}
}

View File

@ -1,5 +1,7 @@
use error::Error; use error::Error;
mod display;
pub type IntType = i64; pub type IntType = i64;
pub type FloatType = f64; pub type FloatType = f64;
@ -9,6 +11,7 @@ pub enum Value {
Float(FloatType), Float(FloatType),
Int(IntType), Int(IntType),
Boolean(bool), Boolean(bool),
Tuple(Vec<Value>),
} }
impl Value { impl Value {
@ -72,6 +75,12 @@ impl From<bool> for Value {
} }
} }
impl From<Vec<Value>> for Value {
fn from(tuple: Vec<Value>) -> Self {
Value::Tuple(tuple)
}
}
impl From<Value> for Result<Value, Error> { impl From<Value> for Result<Value, Error> {
fn from(value: Value) -> Self { fn from(value: Value) -> Self {
Ok(value) Ok(value)