diff --git a/lib/liquid/lexer.rb b/lib/liquid/lexer.rb index 0d011b18..d8d8b566 100644 --- a/lib/liquid/lexer.rb +++ b/lib/liquid/lexer.rb @@ -29,11 +29,12 @@ module Liquid '[' => :open_square, ']' => :close_square } - IDENTIFIER = /[\w\-]+/ + IDENTIFIER = /[\w\-?]+/ SINGLE_STRING_LITERAL = /'[^\']*'/ DOUBLE_STRING_LITERAL = /"[^\"]*"/ INTEGER_LITERAL = /-?\d+/ FLOAT_LITERAL = /-?\d+(?:\.\d+)?/ + COMPARISON_OPERATOR = /==|!=|<>|<=?|>=?|contains/ def initialize(input) @ss = StringScanner.new(input) @@ -57,21 +58,26 @@ module Liquid return if @ss.eos? case + when t = @ss.scan(COMPARISON_OPERATOR) then Token[:comparison, t] when t = @ss.scan(IDENTIFIER) then Token[:id, t] when t = @ss.scan(SINGLE_STRING_LITERAL) then Token[:string, t] when t = @ss.scan(DOUBLE_STRING_LITERAL) then Token[:string, t] when t = @ss.scan(INTEGER_LITERAL) then Token[:integer, t] when t = @ss.scan(FLOAT_LITERAL) then Token[:float, t] else - c = @ss.getch - if s = SPECIALS[c] - return Token[s,c] - end - - raise SyntaxError, "Unexpected character #{c}." + lex_specials end end + def lex_specials + c = @ss.getch + if s = SPECIALS[c] + return Token[s,c] + end + + raise SyntaxError, "Unexpected character #{c}." + end + def consume_whitespace @ss.skip(/\s*/) end diff --git a/lib/liquid/tags/if.rb b/lib/liquid/tags/if.rb index e495a6bb..c5f455a4 100644 --- a/lib/liquid/tags/if.rb +++ b/lib/liquid/tags/if.rb @@ -45,7 +45,7 @@ module Liquid block = if tag == 'else' ElseCondition.new else - old_parse(markup) + parse_condition(markup) end @blocks.push(block) @@ -81,12 +81,19 @@ module Liquid new_cond.send(op.to_sym, condition) condition = new_cond end + p.consume(:end_of_string) condition end def parse_comparison(p) - + a = p.expression + if op = p.consume?(:comparison) + b = p.expression + Condition.new(a, op, b) + else + Condition.new(a) + end end end diff --git a/test/liquid/error_handling_test.rb b/test/liquid/error_handling_test.rb index 22603bbb..6eb722a3 100644 --- a/test/liquid/error_handling_test.rb +++ b/test/liquid/error_handling_test.rb @@ -63,11 +63,8 @@ class ErrorHandlingTest < Test::Unit::TestCase end def test_unrecognized_operator - assert_nothing_raised do - template = Liquid::Template.parse(' {% if 1 =! 2 %}ok{% endif %} ') - assert_equal ' Liquid error: Unknown operator =! ', template.render - assert_equal 1, template.errors.size - assert_equal Liquid::ArgumentError, template.errors.first.class + assert_raise(SyntaxError) do + Liquid::Template.parse(' {% if 1 =! 2 %}ok{% endif %} ') end end diff --git a/test/liquid/parsing_quirks_test.rb b/test/liquid/parsing_quirks_test.rb index 9f393217..2ff95ec2 100644 --- a/test/liquid/parsing_quirks_test.rb +++ b/test/liquid/parsing_quirks_test.rb @@ -40,15 +40,20 @@ class ParsingQuirksTest < Test::Unit::TestCase end def test_meaningless_parens - assigns = {'b' => 'bar', 'c' => 'baz'} - markup = "a == 'foo' or (b == 'bar' and c == 'baz') or false" - assert_template_result(' YES ',"{% if #{markup} %} YES {% endif %}", assigns) + assert_raise(SyntaxError) do + markup = "a == 'foo' or (b == 'bar' and c == 'baz') or false" + Template.parse("{% if #{markup} %} YES {% endif %}") + end end def test_unexpected_characters_silently_eat_logic - markup = "true && false" - assert_template_result(' YES ',"{% if #{markup} %} YES {% endif %}") - markup = "false || true" - assert_template_result('',"{% if #{markup} %} YES {% endif %}") + assert_raise(SyntaxError) do + markup = "true && false" + Template.parse("{% if #{markup} %} YES {% endif %}") + end + assert_raise(SyntaxError) do + markup = "false || true" + Template.parse("{% if #{markup} %} YES {% endif %}") + end end end # ParsingQuirksTest