diff options
| -rw-r--r-- | src/interpret/walker.rs | 17 | ||||
| -rw-r--r-- | src/lex/lexer.rs | 15 | ||||
| -rw-r--r-- | src/parse/ast/expression.rs | 17 | ||||
| -rw-r--r-- | src/parse/ast/nodes.rs | 22 | ||||
| -rw-r--r-- | src/parse/parser.rs | 34 |
5 files changed, 87 insertions, 18 deletions
diff --git a/src/interpret/walker.rs b/src/interpret/walker.rs index 471da89..68dc388 100644 --- a/src/interpret/walker.rs +++ b/src/interpret/walker.rs @@ -2,7 +2,7 @@ use std::{cell::RefCell, rc::Rc}; use crate::parse::ast::{ expression::Expression, - nodes::{BinaryOperator as BinOp, BlockNode, SimpleLiteral, UnaryOperator as UnOp}, + nodes::{BinaryOperator as BinOp, BlockNode, SimpleLiteral, StrPart, UnaryOperator as UnOp}, statement::Statement, Program, }; @@ -140,13 +140,26 @@ impl Walker { let value = match token { SimpleLiteral::Int(int) => Value::Int(*int as i64), SimpleLiteral::Float(float) => Value::Float(*float as f64), - SimpleLiteral::Str(string) => Value::Str(string.clone()), SimpleLiteral::Bool(bool) => Value::Bool(*bool), }; Ok(value) } Expression::Block(block) => self.walk_block(block.as_ref()), + Expression::StrLiteral(node) => { + let mut buffer = String::new(); + + for part in &node.parts { + match part { + StrPart::Literal(literal) => buffer.push_str(literal), + StrPart::Embed(embed) => { + buffer.push_str(&self.walk_expression(embed)?.to_string()) + } + }; + } + + Ok(Value::Str(buffer)) + } Expression::FnLiteral(fn_node) => { let node = fn_node.as_ref().clone(); Ok(Value::Fn(Rc::new(RefCell::new(node)))) diff --git a/src/lex/lexer.rs b/src/lex/lexer.rs index 6467f5c..b6633d4 100644 --- a/src/lex/lexer.rs +++ b/src/lex/lexer.rs @@ -247,15 +247,19 @@ impl<'s> Lexer<'s> { let mut nest_level = 0; // Finish the last string part - self.preempted.push_back(Token { - location: location_str, - variant: TokenVariant::Str(str_buffer), - }); + if !str_buffer.is_empty() { + self.preempted.push_back(Token { + location: location_str, + variant: TokenVariant::Str(str_buffer), + }); + } str_buffer = String::new(); // Build embed let location_embed = self.location; let mut embed_buffer = String::new(); + embed_buffer.push(c); + loop { // TOOD: Same as above let c = self.advance().expect("Expected Str embed to be closed"); @@ -263,8 +267,7 @@ impl<'s> Lexer<'s> { nest_level += 1; } else if c == '}' { if nest_level <= 0 { - // Remove last '}' of embed - self.advance().unwrap(); + embed_buffer.push(c); location_str = self.location; break; } else { diff --git a/src/parse/ast/expression.rs b/src/parse/ast/expression.rs index b2b9678..d119a71 100644 --- a/src/parse/ast/expression.rs +++ b/src/parse/ast/expression.rs @@ -1,8 +1,10 @@ use std::fmt::{self, Display, Formatter}; +use crate::parse::ast::nodes::StrPart; + use super::nodes::{ ArrayAccessNode, ArrayNode, BinaryOperator, BlockNode, CallNode, FnNode, Identifier, IfNode, - LoopNode, MemberAccessNode, SimpleLiteral, UnaryOperator, + LoopNode, MemberAccessNode, SimpleLiteral, StrNode, UnaryOperator, }; #[derive(Debug, Clone)] @@ -23,6 +25,7 @@ pub enum Expression { Block(Box<BlockNode>), If(Box<IfNode>), Loop(Box<LoopNode>), + StrLiteral(Box<StrNode>), FnLiteral(Box<FnNode>), ArrayLiteral(ArrayNode), SimpleLiteral(SimpleLiteral), @@ -82,6 +85,18 @@ impl Expression { Expression::Block(block) => { Self::block_fmt(f, block, depth + 1)?; } + Expression::StrLiteral(node) => { + writeln!(f, "{}Str:", pad)?; + for (i, statement) in node.parts.iter().enumerate() { + writeln!(f, "{}- {}:", pad, i)?; + match statement { + StrPart::Literal(literal) => { + writeln!(f, "{}{}", " ".repeat(depth + 1), literal.clone()) + } + StrPart::Embed(block) => block.nested_fmt(f, depth + 1), + }?; + } + } Expression::FnLiteral(node) => { write!(f, "{}Fn (", pad)?; diff --git a/src/parse/ast/nodes.rs b/src/parse/ast/nodes.rs index 2bf3f17..c4bb1e8 100644 --- a/src/parse/ast/nodes.rs +++ b/src/parse/ast/nodes.rs @@ -64,7 +64,6 @@ impl UnaryOperator { pub enum SimpleLiteral { Int(u32), Float(f32), - Str(String), Bool(bool), } @@ -73,7 +72,6 @@ impl SimpleLiteral { match token.variant { Int(int) => Self::Int(int), Float(float) => Self::Float(float), - Str(string) => Self::Str(string), KeywordTrue => Self::Bool(true), KeywordFalse => Self::Bool(false), _ => panic!("Can't create literal from '{:?}'.", token.variant), @@ -110,14 +108,20 @@ pub struct MemberAccessNode { } #[derive(Debug, Clone)] -pub struct FnNode { - pub header: FnHeader, - pub body: BlockNode, +pub struct StrNode { + pub parts: Vec<StrPart>, } #[derive(Debug, Clone)] -pub struct ArrayNode { - pub elements: Vec<Expression>, +pub enum StrPart { + Literal(String), + Embed(Expression) +} + +#[derive(Debug, Clone)] +pub struct FnNode { + pub header: FnHeader, + pub body: BlockNode, } #[derive(Debug, Clone)] @@ -128,6 +132,10 @@ pub struct FnHeader { } #[derive(Debug, Clone)] +pub struct ArrayNode { + pub elements: Vec<Expression>, +} +#[derive(Debug, Clone)] pub struct IfNode { pub conditionals: Vec<ConditionalBlock>, pub else_block: Option<BlockNode>, diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 6b0a785..5a09a8f 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -1,11 +1,12 @@ use super::ast::expression::Expression; -use super::ast::nodes::{ArrayNode, LoopNode, UnaryOperator}; +use super::ast::nodes::{ArrayNode, LoopNode, StrNode, UnaryOperator}; use super::ast::statement::Statement; use super::ast::Program; +use crate::lex::lexer::Lexer; use crate::lex::token::TokenVariant::*; use crate::parse::ast::nodes::{ ArrayAccessNode, BinaryOperator, BlockNode, CallNode, ConditionalBlock, FnHeader, FnNode, - IfNode, MemberAccessNode, SimpleLiteral, TypedIdentifier, + IfNode, MemberAccessNode, SimpleLiteral, StrPart, TypedIdentifier, }; use crate::{check, consume, consume_if, inner, lex::token::Token}; use anyhow::{anyhow, Result}; @@ -267,6 +268,7 @@ impl<T: Iterator<Item = Token>> Parser<T> { self.tokens.next().unwrap(), Ident ))), + StrOpen => Ok(Expression::StrLiteral(Box::new(self.str()?))), GroupOpen => Ok(Expression::Group(Box::new(self.group()?))), BlockOpen => Ok(Expression::Block(Box::new(self.generic_block()?))), ArrayOpen => Ok(Expression::ArrayLiteral(self.array()?)), @@ -303,6 +305,34 @@ impl<T: Iterator<Item = Token>> Parser<T> { Ok(ArrayNode { elements }) } + fn str(&mut self) -> Result<StrNode> { + let mut parts = Vec::new(); + + consume!(self, StrOpen)?; + + loop { + let token = self.tokens.next().expect("Unclosed str."); + + let part = match token.variant { + Str(literal) => StrPart::Literal(literal), + StrEmbed(code) => { + let embed_lexer = Lexer::new(&code); + let mut embed_parser = Parser::new(embed_lexer); + + let node = embed_parser.expression()?; + + StrPart::Embed(node) + } + StrClose => break, + _ => unreachable!(), + }; + + parts.push(part); + } + + Ok(StrNode { parts }) + } + fn function(&mut self) -> Result<FnNode> { consume!(self, KeywordFn)?; let token = self.tokens.next().expect("Expected function header."); |
