summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/context.rs38
-rw-r--r--src/lexer.rs5
-rw-r--r--src/lib.rs18
-rw-r--r--src/parser.rs6
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};
5pub type Context = HashMap<String,Value>; 5pub type Context = HashMap<String,Value>;
6 6
7pub trait MappedStructure { 7pub trait MappedStructure {
8 fn get_value(&self, id: &Identifier) -> Option<Value>; 8 fn get_value(&self, id: &[IdentifierValue]) -> Option<Value>;
9
9} 10}
10 11
11impl MappedStructure for Context { 12impl MappedStructure for Context {
12 fn get_value(&self, id: &Identifier) -> Option<Value> { 13 fn get_value(&self, id: &[IdentifierValue]) -> Option<Value> {
13 if id.len() == 0 { 14 if id.len() == 0 {
14 return None; 15 return None;
15 } 16 }
@@ -37,6 +38,39 @@ impl MappedStructure for Context {
37 } 38 }
38} 39}
39 40
41pub struct StatefulContext<'a, T: MappedStructure> {
42 root: &'a T,
43 current: &'a T,
44}
45
46impl<'a, T: MappedStructure> StatefulContext<'a, T> {
47 pub fn root( root: &'a T ) -> Self {
48 Self {
49 root, current: root,
50 }
51 }
52
53 pub fn local(&self, current: &'a T ) -> Self {
54 Self {
55 root: self.root,
56 current
57 }
58 }
59}
60
61impl<'a, T: MappedStructure> MappedStructure for StatefulContext<'a,T> {
62 fn get_value(&self, id: &[IdentifierValue]) -> Option<Value> {
63 if id.is_empty() {
64 return None;
65 }
66 if id[0] == IdentifierValue::Root {
67 self.root.get_value( &id[1..] )
68 } else {
69 self.current.get_value( id )
70 }
71 }
72}
73
40#[derive(Debug,Clone)] 74#[derive(Debug,Clone)]
41pub enum Value { 75pub enum Value {
42 Dictionary(Context), 76 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> {
25 ElIf, 25 ElIf,
26 Else, 26 Else,
27 27
28 Sharp,
28 Equals, 29 Equals,
29 Period, 30 Period,
30 Token(&'a str), 31 Token(&'a str),
@@ -224,6 +225,10 @@ impl<'a> Lexer<'a> {
224 Some('"') => { 225 Some('"') => {
225 return self.parse_literal_str(); 226 return self.parse_literal_str();
226 } 227 }
228 Some('#') => {
229 self.next();
230 return Some(Symbol::new(SymbolType::Sharp, self.pos, self.pos));
231 }
227 Some('=') => { 232 Some('=') => {
228 self.next(); 233 self.next();
229 return Some(Symbol::new(SymbolType::Equals, self.pos, self.pos)); 234 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;
11 11
12pub use error::{CrimError,CrimResult}; 12pub use error::{CrimError,CrimResult};
13pub use position::*; 13pub use position::*;
14pub use context::{Context,Value,MappedStructure}; 14pub use context::{Context,Value,MappedStructure,StatefulContext};
15 15
16#[derive(Debug)] 16#[derive(Debug)]
17pub struct Crimtag { 17pub struct Crimtag {
@@ -41,11 +41,12 @@ struct View {
41} 41}
42 42
43impl View { 43impl View {
44 fn process(&self, input: &impl MappedStructure) -> CrimResult<Context> { 44 fn process<T: MappedStructure>(&self, input: &T) -> CrimResult<Context> {
45 let mut out_vars = Context::new(); 45 let mut out_vars = Context::new();
46 for output in &self.outputs { 46 for output in &self.outputs {
47 let mut buf = String::new(); 47 let mut buf = String::new();
48 exec( input, &output.code, &mut buf )?; 48 let sc = StatefulContext::root( input );
49 exec( &sc, &output.code, &mut buf )?;
49 out_vars.insert( output.name.clone(), Value::String(buf) ); 50 out_vars.insert( output.name.clone(), Value::String(buf) );
50 } 51 }
51 Ok(out_vars) 52 Ok(out_vars)
@@ -68,8 +69,9 @@ enum Token {
68 Text(String), 69 Text(String),
69} 70}
70 71
71#[derive(Debug,Clone)] 72#[derive(Debug,Clone,PartialEq)]
72pub enum IdentifierValue { 73pub enum IdentifierValue {
74 Root,
73 Name(String), 75 Name(String),
74 Index(usize), 76 Index(usize),
75} 77}
@@ -161,7 +163,7 @@ impl Crimtag {
161 } 163 }
162 } 164 }
163 165
164 pub fn render_partial(&self, view: &str, input: &impl MappedStructure ) -> CrimResult<Context> { 166 pub fn render_partial<T: MappedStructure>(&self, view: &str, input: &T ) -> CrimResult<Context> {
165 if let Some(view) = self.views.get(view) { 167 if let Some(view) = self.views.get(view) {
166 return view.process( input ) 168 return view.process( input )
167 } else { 169 } else {
@@ -169,7 +171,7 @@ impl Crimtag {
169 } 171 }
170 } 172 }
171 173
172 pub fn render(&self, view: &str, input: &impl MappedStructure ) -> CrimResult<String> { 174 pub fn render<T: MappedStructure>(&self, view: &str, input: &T ) -> CrimResult<String> {
173 if let Some(view) = self.views.get( view ) { 175 if let Some(view) = self.views.get( view ) {
174 //println!("::Token tree::\n{:?}", view ); 176 //println!("::Token tree::\n{:?}", view );
175 let mut output = view.process( input )?; 177 let mut output = view.process( input )?;
@@ -191,7 +193,7 @@ impl Crimtag {
191 } 193 }
192} 194}
193 195
194fn exec(input: &impl MappedStructure, tokens: &Vec<Token>, buf: &mut String) -> CrimResult<()> { 196fn exec<T: MappedStructure>(input: &StatefulContext<T>, tokens: &Vec<Token>, buf: &mut String) -> CrimResult<()> {
195 for token in tokens { 197 for token in tokens {
196 match token { 198 match token {
197 Token::Loop(ident,code) => { 199 Token::Loop(ident,code) => {
@@ -199,7 +201,7 @@ fn exec(input: &impl MappedStructure, tokens: &Vec<Token>, buf: &mut String) ->
199 let Value::List(list) = value { 201 let Value::List(list) = value {
200 for rec in &list { 202 for rec in &list {
201 if let Value::Dictionary(d) = rec { 203 if let Value::Dictionary(d) = rec {
202 exec( d, code, buf )? 204 exec( &input.local(d), code, buf )?
203 } 205 }
204 } 206 }
205 } 207 }
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 {
360 tb.add_param( ParamValue::Literal(s.to_string()) ); 360 tb.add_param( ParamValue::Literal(s.to_string()) );
361 ctx.next(); 361 ctx.next();
362 } 362 }
363 SymbolType::Token(_) => { 363 SymbolType::Token(_) | SymbolType::Sharp => {
364 if ctx.peek().is("tag data", |s| *s == SymbolType::Equals)? { 364 if ctx.peek().is("tag data", |s| *s == SymbolType::Equals)? {
365 break; 365 break;
366 } 366 }
@@ -377,6 +377,10 @@ impl Parser {
377 fn parse_identifier(&self, ctx: &mut Context ) -> CrimResult<ParamValue> { 377 fn parse_identifier(&self, ctx: &mut Context ) -> CrimResult<ParamValue> {
378 let mut id = Identifier::new(); 378 let mut id = Identifier::new();
379 379
380 if ctx.cur().is("identifier",|s| matches!( s, SymbolType::Sharp))? {
381 id.push( IdentifierValue::Root );
382 ctx.next();
383 }
380 loop { 384 loop {
381 if ctx.cur().is("identifier",|s| matches!( s, SymbolType::Token(_) ))? { 385 if ctx.cur().is("identifier",|s| matches!( s, SymbolType::Token(_) ))? {
382 if let SymbolType::Token(s) = ctx.cur().unwrap().symbol() { 386 if let SymbolType::Token(s) = ctx.cur().unwrap().symbol() {