Skip to content

Commit

Permalink
regex search command & ast command (#50)
Browse files Browse the repository at this point in the history
  • Loading branch information
nbittich authored Mar 16, 2023
1 parent 23e4b61 commit 588b17c
Show file tree
Hide file tree
Showing 11 changed files with 202 additions and 72 deletions.
42 changes: 31 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "adana"
version = "0.13.21"
version = "0.13.22"
edition = "2021"
authors = ["Nordine Bittich"]
license = "MIT"
Expand All @@ -15,14 +15,15 @@ bincode = "1.3.3"
dirs = "4.0.0"
log = "0.4.17"
nom = { version = "7.1.3"}
nu-ansi-term = "0.46.0"
nu-ansi-term = "0.47.0"
rustyline = "11.0.0"
rustyline-derive = "0.8.0"
serde = {version = "1.0.155", features= ['serde_derive', 'rc']}
serde_json = "1.0.94"
slab_tree = "0.3.2"
strum = { version = "0.24.1", features = ["derive"] }
ctrlc = "3.2.5"
regex = "1.7.1"

[dependencies.env_logger]
default-features = false
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ There is no possible interaction with the scripting language yet.
| print_script_ctx | script_ctx | Print script context |
| store_script_ctx | | Store script context (optional name) e.g `store_script_ctx 12022023` or `store_script_ctx` |
| load_script_ctx | | Load script context (optional name) e.g `load_script_ctx 12022023` or `load_script_ctx` |
| ast | | print ast for script code e.g `ast 9*9` |
| help | | Display help. |

### Shortcuts
Expand Down
68 changes: 45 additions & 23 deletions src/adana_script/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fn filter_op(
}
}

pub(super) fn to_ast(
pub fn to_ast(
ctx: &mut BTreeMap<String, RefPrimitive>,
value: Value,
tree: &mut Tree<TreeNodeValue>,
Expand Down Expand Up @@ -120,22 +120,25 @@ pub(super) fn to_ast(
}
}

let op_pos = None
.or_else(filter_op(Operator::Or, &operations))
.or_else(filter_op(Operator::And, &operations))
.or_else(filter_op(Operator::GreaterOrEqual, &operations))
.or_else(filter_op(Operator::LessOrEqual, &operations))
.or_else(filter_op(Operator::Greater, &operations))
.or_else(filter_op(Operator::Less, &operations))
.or_else(filter_op(Operator::Equal, &operations))
.or_else(filter_op(Operator::NotEqual, &operations))
.or_else(filter_op(Operator::Add, &operations))
.or_else(filter_op(Operator::Subtr, &operations))
.or_else(filter_op(Operator::Mult, &operations))
.or_else(filter_op(Operator::Mod, &operations))
.or_else(filter_op(Operator::Div, &operations))
.or_else(filter_op(Operator::Pow, &operations))
.or_else(filter_op(Operator::Not, &operations));
let get_next_op_pos = |operations: &Vec<Value>| {
None.or_else(filter_op(Operator::Or, operations))
.or_else(filter_op(Operator::And, operations))
.or_else(filter_op(Operator::GreaterOrEqual, operations))
.or_else(filter_op(Operator::LessOrEqual, operations))
.or_else(filter_op(Operator::Greater, operations))
.or_else(filter_op(Operator::Less, operations))
.or_else(filter_op(Operator::Equal, operations))
.or_else(filter_op(Operator::NotEqual, operations))
.or_else(filter_op(Operator::Add, operations))
.or_else(filter_op(Operator::Subtr, operations))
.or_else(filter_op(Operator::Mult, operations))
.or_else(filter_op(Operator::Mod, operations))
.or_else(filter_op(Operator::Div, operations))
.or_else(filter_op(Operator::Pow, operations))
.or_else(filter_op(Operator::Not, operations))
};

let op_pos = get_next_op_pos(&operations);

if let Some(op_pos) = op_pos {
let mut left: Vec<Value> =
Expand All @@ -145,7 +148,18 @@ pub(super) fn to_ast(

// handle negation
if operation == Value::Operation(Operator::Subtr)
&& matches!(left.last(), Some(Value::Operation(_)))
&& matches!(
left.last(),
Some(
Value::Operation(Operator::Subtr)
| Value::Operation(Operator::Mult)
| Value::Operation(Operator::Pow)
| Value::Operation(Operator::Add) // FIXME too tired to think about
// it. Is it needed?
| Value::Operation(Operator::Mod)
| Value::Operation(Operator::Div)
)
)
{
let right_first = match operations.first() {
Some(Value::Decimal(d)) => Some(Value::Decimal(-d)),
Expand All @@ -156,7 +170,8 @@ pub(super) fn to_ast(
_ => None,
};
if let Some(first) = right_first {
operations[0] = first;
operations[0] = first; // override one of the negate operator by the
// negated value
left.append(&mut operations);
return to_ast(
ctx,
Expand All @@ -169,8 +184,8 @@ pub(super) fn to_ast(

if cfg!(test) {
println!("Left => {left:?}");
println!("Right => {operation:?}");
println!("Op => {operation:?}");
println!("Right => {operations:?}");
println!();
}

Expand All @@ -179,14 +194,21 @@ pub(super) fn to_ast(
to_ast(ctx, Value::BlockParen(left), tree, &curr_node_id)?;
to_ast(
ctx,
Value::BlockParen(operations),
if operations.len() == 1 {
operations.remove(0)
} else {
Value::BlockParen(operations)
},
tree,
&curr_node_id,
)?;

Ok(curr_node_id)
} else {
Err(anyhow::Error::msg("AST ERROR: invalid expression!"))
Err(anyhow::Error::msg(format!(
"{} invalid expression!",
nu_ansi_term::Color::Red.paint("AST ERROR:")
)))
}
}

Expand Down Expand Up @@ -320,7 +342,7 @@ pub(super) fn to_ast(
Value::VariableExpr { name, expr } => {
anyhow::ensure!(
tree.root().is_none(),
"invalid variable assignment "
"invalid variable assignment, tree root is not none"
);
let variable_assign_node = if let Value::Variable(n) = *name {
Ok(TreeNodeValue::VariableAssign(Some(n)))
Expand Down
30 changes: 18 additions & 12 deletions src/adana_script/compute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,6 @@ fn compute_recur(
let right = compute_recur(node.last_child(), ctx)?;
Ok(left.div(&right))
}
TreeNodeValue::Ops(Operator::Equal) => {
if node.children().count() == 1 {
return Err(Error::msg(
"only one value, no '==' comparison possible",
));
}
let left = compute_recur(node.first_child(), ctx)?;
let right = compute_recur(node.last_child(), ctx)?;
Ok(left.is_equal(&right))
}
TreeNodeValue::Ops(Operator::And) => {
if node.children().count() == 1 {
return Err(Error::msg(
Expand Down Expand Up @@ -151,6 +141,16 @@ fn compute_recur(
let right = compute_recur(node.last_child(), ctx)?;
Ok(left.or(&right))
}
TreeNodeValue::Ops(Operator::Equal) => {
if node.children().count() == 1 {
return Err(Error::msg(
"only one value, no '==' comparison possible",
));
}
let left = compute_recur(node.first_child(), ctx)?;
let right = compute_recur(node.last_child(), ctx)?;
Ok(left.is_equal(&right))
}
TreeNodeValue::Ops(Operator::NotEqual) => {
if node.children().count() == 1 {
return Err(Error::msg(
Expand Down Expand Up @@ -796,7 +796,10 @@ pub fn compute(
ctx: &mut BTreeMap<String, RefPrimitive>,
) -> anyhow::Result<Primitive> {
let (rest, instructions) = parse_instructions(s).map_err(|e| {
anyhow::Error::msg(format!("could not parse instructions. {e}"))
anyhow::Error::msg(format!(
"{} could not parse instructions. {e}",
Red.paint("PARSER ERROR:")
))
})?;

if cfg!(test) {
Expand All @@ -806,7 +809,10 @@ pub fn compute(

anyhow::ensure!(
rest.trim().is_empty(),
format!("{}: {instructions:?} => {rest}", Red.paint("Parsing Error!"))
format!(
"{} rest is not empty! {instructions:?} => {rest}",
Red.paint("PARSING ERROR:")
)
);

compute_instructions(instructions, ctx)
Expand Down
40 changes: 39 additions & 1 deletion src/adana_script/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@ mod primitive;
use std::collections::BTreeMap;

pub use compute::compute;
use nu_ansi_term::Color;
pub use primitive::Primitive;
pub use primitive::RefPrimitive;

use serde::{Deserialize, Serialize};
use slab_tree::Tree;
use strum::EnumCount;

use crate::adana_script::ast::to_ast;
use crate::adana_script::parser::parse_instructions;

use self::constants::TO_STRING;
use self::constants::{
ABS, COS, EVAL, INCLUDE, LENGTH, LN, LOG, PRINT, PRINT_LN, READ_LINES, SIN,
Expand Down Expand Up @@ -209,7 +214,7 @@ pub enum Operator {
}

#[derive(Debug)]
pub(super) enum TreeNodeValue {
pub enum TreeNodeValue {
Break,
EarlyReturn(Option<Value>),
Drop(Vec<Value>),
Expand Down Expand Up @@ -281,5 +286,38 @@ impl Operator {
}
}

pub fn print_ast(script: &str) -> anyhow::Result<()> {
let (rest, instructions) = parse_instructions(script).map_err(|e| {
anyhow::Error::msg(format!(
"{} could not parse instructions. {e}",
Color::Red.paint("PRINT AST ERROR:")
))
})?;

anyhow::ensure!(
rest.trim().is_empty(),
format!(
"{} rest is not empty! {instructions:?} => {rest}",
Color::Red.paint("PRINT AST ERROR:")
)
);

let mut dummy_ctx = BTreeMap::new();
for instruction in instructions {
let mut tree: Tree<TreeNodeValue> = Tree::new();

println!("==================INSTRUCTION================");
println!("{instruction:?}");
to_ast(&mut dummy_ctx, instruction, &mut tree, &None)?;

let mut tree_fmt = String::new();
tree.write_formatted(&mut tree_fmt)?;
println!("===================AST TREE==================");
print!("{tree_fmt}");
}
Ok(())
}

// keep this
#[cfg(test)]
mod tests;
11 changes: 3 additions & 8 deletions src/adana_script/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::{
prelude::{
all_consuming, alt, delimited, double, many0, many1, map, map_parser,
multispace0, one_of, opt, pair, peek, preceded, recognize_float, rest,
separated_list0, separated_list1, separated_pair, tag, tag_no_case,
take_until, take_while1, terminated, tuple, verify, Res, I128,
separated_list0, separated_list1, separated_pair, tag, take_until,
take_while1, terminated, tuple, verify, Res, I128,
},
reserved_keywords::check_reserved_keyword,
};
Expand All @@ -26,11 +26,6 @@ fn tag_no_space<'a>(t: &'a str) -> impl Fn(&'a str) -> Res<&'a str> {
move |s: &str| delimited(multispace0, tag(t), multispace0)(s)
}

#[allow(dead_code)]
fn tag_no_space_no_case<'a>(t: &'a str) -> impl Fn(&'a str) -> Res<&'a str> {
move |s: &str| delimited(multispace0, tag_no_case(t), multispace0)(s)
}

fn parse_number(s: &str) -> Res<Value> {
map_parser(
recognize_float,
Expand Down Expand Up @@ -685,7 +680,7 @@ fn parse_early_return(s: &str) -> Res<Value> {
})(s)
}

pub(super) fn parse_instructions(instructions: &str) -> Res<Vec<Value>> {
pub fn parse_instructions(instructions: &str) -> Res<Vec<Value>> {
let (instructions, _) = opt(comments)(instructions)?;
let instructions = instructions.trim();
if instructions.is_empty() {
Expand Down
Loading

0 comments on commit 588b17c

Please sign in to comment.