diff --git a/src/main.rs b/src/main.rs index d300322d..c0374d16 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ use crate::utils::metadata::ParserMetadata; fn main() { let code = vec![ - "'interpolate {'this {1} this'} and {'that'} :)'" + "$echo test$" ].join("\n"); let rules = rules::get_rules(); let mut cc = Compiler::new("Amber", rules); diff --git a/src/modules/expression/expr.rs b/src/modules/expression/expr.rs index 5d484052..acb90269 100644 --- a/src/modules/expression/expr.rs +++ b/src/modules/expression/expr.rs @@ -4,7 +4,8 @@ use crate::utils::metadata::ParserMetadata; use super::literal::{ bool::Bool, number::Number, - text::Text + text::Text, + command::Command }; use super::binop::{ add::Add, @@ -31,6 +32,7 @@ pub enum ExprType { Bool(Bool), Number(Number), Text(Text), + Command(Command), Parenthesis(Parenthesis), VariableGet(VariableGet), Add(Add), @@ -82,6 +84,7 @@ impl Expr { // Literals ExprType::VariableGet(VariableGet::new()), ExprType::Parenthesis(Parenthesis::new()), + ExprType::Command(Command::new()), ExprType::Bool(Bool::new()), ExprType::Number(Number::new()), ExprType::Text(Text::new()) @@ -108,6 +111,7 @@ impl Expr { ExprType::Div(ex) => self.get(meta, ex, ExprType::Div), // Literals ExprType::Parenthesis(ex) => self.get(meta, ex, ExprType::Parenthesis), + ExprType::Command(ex) => self.get(meta, ex, ExprType::Command), ExprType::Bool(ex) => self.get(meta, ex, ExprType::Bool), ExprType::Number(ex) => self.get(meta, ex, ExprType::Number), ExprType::Text(ex) => self.get(meta, ex, ExprType::Text), diff --git a/src/modules/expression/literal/command.rs b/src/modules/expression/literal/command.rs new file mode 100644 index 00000000..cb92f877 --- /dev/null +++ b/src/modules/expression/literal/command.rs @@ -0,0 +1,33 @@ +use heraclitus_compiler::prelude::*; +use crate::{utils::metadata::ParserMetadata, modules::{Type, Typed}}; +use crate::modules::expression::expr::Expr; + +use super::parse_interpolated_region; + +#[derive(Debug)] +pub struct Command { + strings: Vec, + interps: Vec +} + +impl Typed for Command { + fn get_type(&self) -> Type { + Type::Text + } +} + +impl SyntaxModule for Command { + syntax_name!("Command"); + + fn new() -> Self { + Command { + strings: vec![], + interps: vec![] + } + } + + fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult { + (self.strings, self.interps) = parse_interpolated_region(meta, '$')?; + Ok(()) + } +} \ No newline at end of file diff --git a/src/modules/expression/literal/mod.rs b/src/modules/expression/literal/mod.rs index 67311563..655df24d 100644 --- a/src/modules/expression/literal/mod.rs +++ b/src/modules/expression/literal/mod.rs @@ -1,4 +1,53 @@ +use std::vec; + +use heraclitus_compiler::prelude::*; +use crate::utils::metadata::ParserMetadata; +use crate::modules::expression::expr::Expr; + pub mod bool; pub mod number; pub mod text; -pub mod void; \ No newline at end of file +pub mod void; +pub mod command; + +pub fn parse_interpolated_region(meta: &mut ParserMetadata, letter: char) -> Result<(Vec, Vec), ErrorDetails> { + let mut strings = vec![]; + let mut interps = vec![]; + // Handle full string + if let Ok(word) = token_by(meta, |word| word.starts_with(letter) && word.ends_with(letter) && word.len() > 1) { + let stripped = word.chars().take(word.len() - 1).skip(1).collect::(); + strings.push(stripped); + Ok((strings, interps)) + } + else { + let mut is_interp = false; + // Initialize string + strings.push(token_by(meta, |word| word.starts_with(letter))?); + // Factor rest of the interpolation + while let Some(token) = meta.get_current_token() { + // Track interpolations + match token.word.as_str() { + "{" => is_interp = true, + "}" => is_interp = false, + // Manage inserting strings and intrpolations + _ => if is_interp { + let mut expr = Expr::new(); + syntax(meta, &mut expr)?; + interps.push(expr); + // TODO: [H50] In the next release of Heraclitus + // Change this line to `meta.offset_index(-1)` + meta.set_index(meta.get_index() - 1); + } + else { + strings.push(token.word.clone()); + if token.word.ends_with(letter) { + meta.increment_index(); + return Ok((strings, interps)) + } + } + } + meta.increment_index(); + } + Err(ErrorDetails::from_metadata(meta)) + } +} \ No newline at end of file diff --git a/src/modules/expression/literal/text.rs b/src/modules/expression/literal/text.rs index e15041e8..164f5d25 100644 --- a/src/modules/expression/literal/text.rs +++ b/src/modules/expression/literal/text.rs @@ -2,58 +2,14 @@ use heraclitus_compiler::prelude::*; use crate::{utils::metadata::ParserMetadata, modules::{Type, Typed}}; use crate::modules::expression::expr::Expr; +use super::parse_interpolated_region; + #[derive(Debug)] pub struct Text { strings: Vec, interps: Vec } -impl Text { - fn closure_full_string(word: &String) -> bool { - word.starts_with('\'') && word.ends_with('\'') && word.len() > 1 - } - - fn parse_text(&mut self, meta: &mut ParserMetadata) -> SyntaxResult { - // Handle full string - if let Ok(word) = token_by(meta, Text::closure_full_string) { - let stripped = word.chars().take(word.len() - 1).skip(1).collect::(); - self.strings.push(stripped); - Ok(()) - } - else { - let mut is_interp = false; - // Initialize string - self.strings.push(token_by(meta, |word| word.starts_with('\''))?); - // Factor rest of the interpolation - while let Some(token) = meta.get_current_token() { - // Track interpolations - match token.word.as_str() { - "{" => is_interp = true, - "}" => is_interp = false, - // Manage inserting strings and intrpolations - _ => if is_interp { - let mut expr = Expr::new(); - syntax(meta, &mut expr)?; - self.interps.push(expr); - // TODO: [H50] In the next release of Heraclitus - // Change this line to `meta.offset_index(-1)` - meta.set_index(meta.get_index() - 1); - } - else { - self.strings.push(token.word.clone()); - if token.word.ends_with('\'') { - meta.increment_index(); - return Ok(()) - } - } - } - meta.increment_index(); - } - Err(ErrorDetails::from_metadata(meta)) - } - } -} - impl Typed for Text { fn get_type(&self) -> Type { Type::Text @@ -71,7 +27,7 @@ impl SyntaxModule for Text { } fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult { - self.parse_text(meta)?; + (self.strings, self.interps) = parse_interpolated_region(meta, '\'')?; Ok(()) } } \ No newline at end of file