From 2d0875188e3d378a825d24348de4d92a228bf420 Mon Sep 17 00:00:00 2001 From: Joakim Hulthe Date: Thu, 20 May 2021 03:41:01 +0200 Subject: [PATCH] Add string literals --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/ast.rs | 2 ++ src/lib.rs | 28 ++++++++++++++++++++++++++++ src/parser.rs | 14 +++++++++++--- 5 files changed, 43 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 75de61e..2d8295a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,7 +46,7 @@ dependencies = [ [[package]] name = "blueprint" -version = "0.1.0" +version = "0.2.0" dependencies = [ "nom", "structopt", diff --git a/Cargo.toml b/Cargo.toml index f3c5e9a..54d40a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "blueprint" -version = "0.1.0" +version = "0.2.0" authors = ["Joakim Hulthe "] description = "A simple templating library" edition = "2018" diff --git a/src/ast.rs b/src/ast.rs index 5c21540..86e2307 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -40,6 +40,7 @@ pub enum Expr<'a> { }, Variable(Cow<'a, str>), + Str(Cow<'a, str>), } use crate::env::{Env, Value}; @@ -105,6 +106,7 @@ impl Expr<'_> { pub fn eval<'a>(&self, env: &'a Env) -> Cow<'a, Value> { match self { Expr::Variable(var) => Cow::Borrowed(env.get(&**var).unwrap_or(&Value::Null)), + Expr::Str(s) => Cow::Owned(Value::Str(s.to_string())), Expr::Cmp { op, expr1, expr2 } => { let val1 = expr1.eval(env); let val2 = expr2.eval(env); diff --git a/src/lib.rs b/src/lib.rs index fbeed9c..486ab67 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,6 +55,34 @@ mod test { ); } + #[test] + fn test_parse_if_str() { + let input = "one {% if foo >= \"bar\" %} two {% end %} three"; + let ast = parse_file(&input).expect("failed to parse"); + eprintln!("{:#?}", ast); + assert_eq!( + ast, + Template { + parts: vec![ + Part::Text("one ".into()), + Part::If { + if_then: IfThen { + cond: Expr::Cmp { + op: CmpOp::GrEq, + expr1: Box::new(Expr::Variable("foo".into())), + expr2: Box::new(Expr::Str("bar".into())), + }, + parts: vec![Part::Text(" two ".into()),] + }, + elifs: vec![], + else_part: None, + }, + Part::Text(" three".into()), + ], + } + ); + } + #[test] fn test_parse_eq() { let input = "one {% if foo == bar %} two {% end %} three"; diff --git a/src/parser.rs b/src/parser.rs index 7193740..c36b3ed 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,11 +1,11 @@ use crate::ast::*; use nom::{ branch::alt, - bytes::complete::{tag, take_until}, + bytes::complete::{is_not, tag, take_until}, character::complete::{alpha1, multispace0, multispace1}, combinator::{map, opt}, multi::many0, - sequence::tuple, + sequence::{delimited, tuple}, IResult, }; use std::borrow::Cow; @@ -17,8 +17,16 @@ fn expr_var(i: &str) -> IResult<&str, Expr> { map(alpha1, |v| Expr::Variable(Cow::Borrowed(v)))(i) } +/// Try to parse an Expr::Str +fn expr_str(i: &str) -> IResult<&str, Expr> { + const QUOTE: &str = "\""; + map(delimited(tag(QUOTE), is_not(QUOTE), tag(QUOTE)), |s| { + Expr::Str(Cow::Borrowed(s)) + })(i) +} + fn expr1(i: &str) -> IResult<&str, Expr> { - expr_var(i) + alt((expr_str, expr_var))(i) } fn cmp_op(i: &str) -> IResult<&str, CmpOp> {