Skip to content

Commit

Permalink
fix(parse): Error on empty expressions
Browse files Browse the repository at this point in the history
Initially, I planned for `{{}}` to evaluate to `""`.  I asked myself:
when would people ever do `{{}}` intentionally?  How often might it be
unintentional?  So I decided to make it
an error for now.

Fixes #139
  • Loading branch information
epage committed Dec 26, 2017
1 parent bd45c14 commit 5cffe44
Showing 1 changed file with 22 additions and 10 deletions.
32 changes: 22 additions & 10 deletions src/compiler/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,29 +42,32 @@ pub fn parse(elements: &[Element], options: &LiquidOptions) -> Result<Vec<Box<Re
let mut iter = elements.iter();
let mut token = iter.next();
while token.is_some() {
match *token.unwrap() {
Element::Expression(ref tokens, _) => ret.push(try!(parse_expression(tokens, options))),
Element::Tag(ref tokens, _) => ret.push(try!(parse_tag(&mut iter, tokens, options))),
Element::Raw(ref x) => ret.push(Box::new(Text::new(x))),
}
let render = match *token.unwrap() {
Element::Expression(ref tokens, _) => parse_expression(tokens, options)?,
Element::Tag(ref tokens, _) => parse_tag(&mut iter, tokens, options)?,
Element::Raw(ref x) => Box::new(Text::new(x)),
};
ret.push(render);
token = iter.next();
}
Ok(ret)
}

// creates an expression, which wraps everything that gets rendered
fn parse_expression(tokens: &[Token], options: &LiquidOptions) -> Result<Box<Renderable>> {
match tokens[0] {
Token::Identifier(ref x) if tokens.len() > 1 &&
(tokens[1] == Token::Dot || tokens[1] == Token::OpenSquare) => {
match tokens.get(0) {
Some(&Token::Identifier(ref x)) if tokens.len() > 1 &&
(tokens[1] == Token::Dot ||
tokens[1] == Token::OpenSquare) => {
let indexes = parse_indexes(&tokens[1..])?;
let mut result = Variable::new(x.clone());
result.extend(indexes);
Ok(Box::new(result))
}
Token::Identifier(ref x) if options.tags.contains_key(x) => {
Some(&Token::Identifier(ref x)) if options.tags.contains_key(x) => {
options.tags[x].parse(x, &tokens[1..], options)
}
None => Error::parser("expression", None),
_ => {
let output = parse_output(tokens)?;
Ok(Box::new(output))
Expand Down Expand Up @@ -381,6 +384,7 @@ mod test_split_block {
use super::super::FnParseBlock;
use interpreter::Renderable;
use interpreter::Context;
use interpreter;

#[derive(Debug)]
struct NullBlock;
Expand Down Expand Up @@ -409,6 +413,15 @@ mod test_split_block {
options
}

#[test]
fn parse_empty_expression() {
let text = "{{}}";

let tokens = tokenize(&text).unwrap();
let template = parse(&tokens, &options()).map(interpreter::Template::new);
assert!(template.is_err());
}

#[test]
fn handles_nonmatching_stream() {
// A stream of tokens with lots of `else`s in it, but only one at the
Expand All @@ -425,7 +438,6 @@ mod test_split_block {
assert!(trailing.is_none());
}


#[test]
fn honours_nesting() {
// A stream of tokens with lots of `else`s in it, but only one at the
Expand Down

0 comments on commit 5cffe44

Please sign in to comment.