diff --git a/lib/liquid/lexer.rb b/lib/liquid/lexer.rb index 7b94fd4..536be02 100644 --- a/lib/liquid/lexer.rb +++ b/lib/liquid/lexer.rb @@ -7,7 +7,9 @@ module Liquid ':' => :colon, ',' => :comma, '[' => :open_square, - ']' => :close_square + ']' => :close_square, + '(' => :open_round, + ')' => :close_round } IDENTIFIER = /[\w\-?!]+/ SINGLE_STRING_LITERAL = /'[^\']*'/ diff --git a/lib/liquid/parser.rb b/lib/liquid/parser.rb index 40ba22f..f975d98 100644 --- a/lib/liquid/parser.rb +++ b/lib/liquid/parser.rb @@ -50,21 +50,22 @@ module Liquid def expression token = @tokens[@p] - str = if token[0] == :id + if token[0] == :id variable_signature elsif [:string, :number].include? token[0] consume token[1] + elsif token.first == :open_round + consume + first = expression + consume(:dot) + consume(:dot) + last = expression + consume(:close_round) + "(#{first}..#{last})" else raise SyntaxError, "#{token} is not a valid expression." end - - if look(:dot) && look(:dot, 1) - @p += 2 - str + expression - else - str - end end def argument diff --git a/lib/liquid/tags/for.rb b/lib/liquid/tags/for.rb index b752b21..f3cf03e 100644 --- a/lib/liquid/tags/for.rb +++ b/lib/liquid/tags/for.rb @@ -47,19 +47,7 @@ module Liquid Syntax = /\A(#{VariableSegment}+)\s+in\s+(#{QuotedFragment}+)\s*(reversed)?/o def initialize(tag_name, markup, tokens) - if markup =~ Syntax - @variable_name = $1 - @collection_name = $2 - @name = "#{$1}-#{$2}" - @reversed = $3 - @attributes = {} - markup.scan(TagAttributes) do |key, value| - @attributes[key] = value - end - else - raise SyntaxError.new("Syntax Error in 'for loop' - Valid syntax: for [item] in [collection]") - end - + switch_parse(markup) @nodelist = @for_block = [] super end @@ -127,6 +115,43 @@ module Liquid result end + protected + + def lax_parse(markup) + if markup =~ Syntax + @variable_name = $1 + @collection_name = $2 + @name = "#{$1}-#{$2}" + @reversed = $3 + @attributes = {} + markup.scan(TagAttributes) do |key, value| + @attributes[key] = value + end + else + raise SyntaxError.new("Syntax Error in 'for loop' - Valid syntax: for [item] in [collection]") + end + end + + def strict_parse(markup) + p = Parser.new(markup) + @variable_name = p.consume(:id) + raise SyntaxError, "For loops require an 'in' clause" unless p.id?('in') + @collection_name = p.expression + @name = "#{@variable_name}-#{@collection_name}" + @reversed = p.id?('reversed') + + @attributes = {} + while p.look(:id) && p.look(:colon, 1) + unless attribute = p.id?('limit') || p.id?('offset') + raise SyntaxError, "Invalid attribute in for loop. Valid attributes are limit and offset" + end + p.consume + val = p.expression + @attributes[attribute] = val + end + p.consume(:end_of_string) + end + private def render_else(context)