From 6188fa4c32160846908e4ff7654c4ff7bc177797 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Sat, 13 Jun 2026 00:21:12 -0700 Subject: Adding root access in identifiers. There's an issue, it doesn't compile yet. --- src/context.rs | 38 ++++++++++++++++++++++++++++++++++++-- src/lexer.rs | 5 +++++ src/lib.rs | 18 ++++++++++-------- src/parser.rs | 6 +++++- 4 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/context.rs b/src/context.rs index e4cd5c2..7484a1f 100644 --- a/src/context.rs +++ b/src/context.rs @@ -5,11 +5,12 @@ use crate::{Identifier,IdentifierValue}; pub type Context = HashMap; pub trait MappedStructure { - fn get_value(&self, id: &Identifier) -> Option; + fn get_value(&self, id: &[IdentifierValue]) -> Option; + } impl MappedStructure for Context { - fn get_value(&self, id: &Identifier) -> Option { + fn get_value(&self, id: &[IdentifierValue]) -> Option { if id.len() == 0 { return None; } @@ -37,6 +38,39 @@ impl MappedStructure for Context { } } +pub struct StatefulContext<'a, T: MappedStructure> { + root: &'a T, + current: &'a T, +} + +impl<'a, T: MappedStructure> StatefulContext<'a, T> { + pub fn root( root: &'a T ) -> Self { + Self { + root, current: root, + } + } + + pub fn local(&self, current: &'a T ) -> Self { + Self { + root: self.root, + current + } + } +} + +impl<'a, T: MappedStructure> MappedStructure for StatefulContext<'a,T> { + fn get_value(&self, id: &[IdentifierValue]) -> Option { + if id.is_empty() { + return None; + } + if id[0] == IdentifierValue::Root { + self.root.get_value( &id[1..] ) + } else { + self.current.get_value( id ) + } + } +} + #[derive(Debug,Clone)] pub enum Value { Dictionary(Context), diff --git a/src/lexer.rs b/src/lexer.rs index afff5a8..4e95854 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -25,6 +25,7 @@ pub enum SymbolType<'a> { ElIf, Else, + Sharp, Equals, Period, Token(&'a str), @@ -224,6 +225,10 @@ impl<'a> Lexer<'a> { Some('"') => { return self.parse_literal_str(); } + Some('#') => { + self.next(); + return Some(Symbol::new(SymbolType::Sharp, self.pos, self.pos)); + } Some('=') => { self.next(); return Some(Symbol::new(SymbolType::Equals, self.pos, self.pos)); diff --git a/src/lib.rs b/src/lib.rs index 84a5a43..b413d2a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,7 @@ mod context; pub use error::{CrimError,CrimResult}; pub use position::*; -pub use context::{Context,Value,MappedStructure}; +pub use context::{Context,Value,MappedStructure,StatefulContext}; #[derive(Debug)] pub struct Crimtag { @@ -41,11 +41,12 @@ struct View { } impl View { - fn process(&self, input: &impl MappedStructure) -> CrimResult { + fn process(&self, input: &T) -> CrimResult { let mut out_vars = Context::new(); for output in &self.outputs { let mut buf = String::new(); - exec( input, &output.code, &mut buf )?; + let sc = StatefulContext::root( input ); + exec( &sc, &output.code, &mut buf )?; out_vars.insert( output.name.clone(), Value::String(buf) ); } Ok(out_vars) @@ -68,8 +69,9 @@ enum Token { Text(String), } -#[derive(Debug,Clone)] +#[derive(Debug,Clone,PartialEq)] pub enum IdentifierValue { + Root, Name(String), Index(usize), } @@ -161,7 +163,7 @@ impl Crimtag { } } - pub fn render_partial(&self, view: &str, input: &impl MappedStructure ) -> CrimResult { + pub fn render_partial(&self, view: &str, input: &T ) -> CrimResult { if let Some(view) = self.views.get(view) { return view.process( input ) } else { @@ -169,7 +171,7 @@ impl Crimtag { } } - pub fn render(&self, view: &str, input: &impl MappedStructure ) -> CrimResult { + pub fn render(&self, view: &str, input: &T ) -> CrimResult { if let Some(view) = self.views.get( view ) { //println!("::Token tree::\n{:?}", view ); let mut output = view.process( input )?; @@ -191,7 +193,7 @@ impl Crimtag { } } -fn exec(input: &impl MappedStructure, tokens: &Vec, buf: &mut String) -> CrimResult<()> { +fn exec(input: &StatefulContext, tokens: &Vec, buf: &mut String) -> CrimResult<()> { for token in tokens { match token { Token::Loop(ident,code) => { @@ -199,7 +201,7 @@ fn exec(input: &impl MappedStructure, tokens: &Vec, buf: &mut String) -> let Value::List(list) = value { for rec in &list { if let Value::Dictionary(d) = rec { - exec( d, code, buf )? + exec( &input.local(d), code, buf )? } } } diff --git a/src/parser.rs b/src/parser.rs index fff00b1..d1fe4d7 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -360,7 +360,7 @@ impl Parser { tb.add_param( ParamValue::Literal(s.to_string()) ); ctx.next(); } - SymbolType::Token(_) => { + SymbolType::Token(_) | SymbolType::Sharp => { if ctx.peek().is("tag data", |s| *s == SymbolType::Equals)? { break; } @@ -377,6 +377,10 @@ impl Parser { fn parse_identifier(&self, ctx: &mut Context ) -> CrimResult { let mut id = Identifier::new(); + if ctx.cur().is("identifier",|s| matches!( s, SymbolType::Sharp))? { + id.push( IdentifierValue::Root ); + ctx.next(); + } loop { if ctx.cur().is("identifier",|s| matches!( s, SymbolType::Token(_) ))? { if let SymbolType::Token(s) = ctx.cur().unwrap().symbol() { -- cgit v1.2.3