mirror of
https://github.com/kemko/liquid.git
synced 2026-01-04 01:05:40 +03:00
Replace regexpes with Ragel grammer
context parsing was handrolled and pretty ad-hoc this branch exists to explore parsing the context through a defined fsm as produced by Ragel
This commit is contained in:
5
Rakefile
5
Rakefile
@@ -7,6 +7,11 @@ require 'rubygems/package_task'
|
||||
|
||||
task :default => 'test'
|
||||
|
||||
task :ragel do
|
||||
sh "find . -name '*.rl' | xargs ragel -R"
|
||||
end
|
||||
|
||||
|
||||
Rake::TestTask.new(:test) do |t|
|
||||
t.libs << '.' << 'lib' << 'test'
|
||||
t.test_files = FileList['test/liquid/**/*_test.rb']
|
||||
|
||||
@@ -62,6 +62,7 @@ require 'liquid/standardfilters'
|
||||
require 'liquid/condition'
|
||||
require 'liquid/module_ex'
|
||||
require 'liquid/utils'
|
||||
require 'liquid/parser'
|
||||
|
||||
# Load all the tags of the standard library
|
||||
#
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
module Liquid
|
||||
|
||||
|
||||
# Context keeps the variable stack and resolves variables, as well as keywords
|
||||
#
|
||||
# context['variable'] = 'testing'
|
||||
@@ -125,13 +126,6 @@ module Liquid
|
||||
end
|
||||
|
||||
private
|
||||
LITERALS = {
|
||||
nil => nil, 'nil' => nil, 'null' => nil, '' => nil,
|
||||
'true' => true,
|
||||
'false' => false,
|
||||
'blank' => :blank?,
|
||||
'empty' => :empty?
|
||||
}
|
||||
|
||||
# Look up variable, either resolve directly after considering the name. We can directly handle
|
||||
# Strings, digits, floats and booleans (true,false).
|
||||
@@ -141,25 +135,42 @@ module Liquid
|
||||
#
|
||||
# Example:
|
||||
# products == empty #=> products.empty?
|
||||
def resolve(key)
|
||||
if LITERALS.key?(key)
|
||||
LITERALS[key]
|
||||
else
|
||||
case key
|
||||
when /^'(.*)'$/ # Single quoted strings
|
||||
$1
|
||||
when /^"(.*)"$/ # Double quoted strings
|
||||
$1
|
||||
when /^(-?\d+)$/ # Integer and floats
|
||||
$1.to_i
|
||||
when /^\((\S+)\.\.(\S+)\)$/ # Ranges
|
||||
(resolve($1).to_i..resolve($2).to_i)
|
||||
when /^(-?\d[\d\.]+)$/ # Floats
|
||||
$1.to_f
|
||||
else
|
||||
variable(key)
|
||||
def resolve(key)
|
||||
case key
|
||||
when nil, ""
|
||||
return nil
|
||||
when "blank?"
|
||||
return :blank
|
||||
when "empty?"
|
||||
return :empty
|
||||
end
|
||||
|
||||
puts "resolve(#{key})"
|
||||
|
||||
result = Parser.parse(key)
|
||||
stack = []
|
||||
|
||||
result.each do |(sym, value)|
|
||||
case sym
|
||||
when :identifier
|
||||
stack.push value
|
||||
when :lookup
|
||||
left = stack.pop
|
||||
stack.push find_variable(left)
|
||||
when :range
|
||||
right = stack.pop.to_i
|
||||
left = stack.pop.to_i
|
||||
stack.push (left..right)
|
||||
when :call
|
||||
parent = stack.pop
|
||||
key = stack.pop
|
||||
stack.push lookup_and_evaluate(parent, key)
|
||||
else
|
||||
raise "unknown #{sym}"
|
||||
end
|
||||
end
|
||||
|
||||
return stack.first
|
||||
end
|
||||
|
||||
# Fetches an object starting at the local scope and then moving up the hierachy
|
||||
@@ -254,6 +265,7 @@ module Liquid
|
||||
end
|
||||
end
|
||||
end # squash_instance_assigns_with_environments
|
||||
|
||||
end # Context
|
||||
|
||||
end # Liquid
|
||||
|
||||
628
lib/liquid/parser.rb
Normal file
628
lib/liquid/parser.rb
Normal file
@@ -0,0 +1,628 @@
|
||||
|
||||
# line 1 "./lib/liquid/parser.rl"
|
||||
=begin
|
||||
LITERALS = {
|
||||
nil => nil, 'nil' => nil, 'null' => nil, '' => nil,
|
||||
'true' => true,
|
||||
'false' => false,
|
||||
'blank' => :blank?,
|
||||
'empty' => :empty?
|
||||
}
|
||||
|
||||
def resolve(key)
|
||||
if LITERALS.key?(key)
|
||||
LITERALS[key]
|
||||
else
|
||||
case key
|
||||
when /^'(.*)'$/ # Single quoted strings
|
||||
$1
|
||||
when /^"(.*)"$/ # Double quoted strings
|
||||
$1
|
||||
when /^(-?\d+)$/ # Integer and floats
|
||||
$1.to_i
|
||||
when /^\((\S+)\.\.(\S+)\)$/ # Ranges
|
||||
(resolve($1).to_i..resolve($2).to_i)
|
||||
when /^(-?\d[\d\.]+)$/ # Floats
|
||||
$1.to_f
|
||||
else
|
||||
variable(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
=end
|
||||
|
||||
# line 91 "./lib/liquid/parser.rl"
|
||||
|
||||
# % fix syntax highlighting
|
||||
|
||||
|
||||
module Liquid
|
||||
module Parser
|
||||
|
||||
# line 43 "./lib/liquid/parser.rb"
|
||||
class << self
|
||||
attr_accessor :_fsm_actions
|
||||
private :_fsm_actions, :_fsm_actions=
|
||||
end
|
||||
self._fsm_actions = [
|
||||
0, 1, 0, 1, 1, 1, 2, 1,
|
||||
3, 1, 4, 1, 5, 1, 6, 1,
|
||||
7, 1, 8, 1, 9
|
||||
]
|
||||
|
||||
class << self
|
||||
attr_accessor :_fsm_key_offsets
|
||||
private :_fsm_key_offsets, :_fsm_key_offsets=
|
||||
end
|
||||
self._fsm_key_offsets = [
|
||||
0, 0, 15, 16, 17, 30, 31, 33,
|
||||
35, 45, 46, 48, 50, 60, 62, 65,
|
||||
68, 81, 81, 83, 87, 89, 92, 100,
|
||||
109, 118, 127, 136, 144, 154, 163, 171,
|
||||
180, 189, 198, 207, 215, 218, 219, 227,
|
||||
236, 245, 254, 263, 271, 281, 290, 298,
|
||||
307, 316, 325, 334, 342, 344, 346, 359,
|
||||
360, 362, 363, 365, 367, 371, 373, 376,
|
||||
384, 393, 402, 411, 420, 428, 438, 447,
|
||||
455, 464, 473, 482, 491, 499, 500, 501,
|
||||
501, 504, 506, 513, 514, 515, 515, 523,
|
||||
531, 539, 547, 554, 563, 571, 578, 586,
|
||||
594, 602, 610
|
||||
]
|
||||
|
||||
class << self
|
||||
attr_accessor :_fsm_trans_keys
|
||||
private :_fsm_trans_keys, :_fsm_trans_keys=
|
||||
end
|
||||
self._fsm_trans_keys = [
|
||||
34, 39, 40, 43, 45, 91, 102, 110,
|
||||
116, 48, 57, 65, 90, 97, 122, 34,
|
||||
39, 34, 39, 43, 45, 102, 110, 116,
|
||||
48, 57, 65, 90, 97, 122, 34, 34,
|
||||
46, 34, 46, 34, 39, 43, 45, 48,
|
||||
57, 65, 90, 97, 122, 39, 39, 46,
|
||||
39, 46, 34, 39, 43, 45, 48, 57,
|
||||
65, 90, 97, 122, 48, 57, 46, 48,
|
||||
57, 46, 48, 57, 34, 39, 43, 45,
|
||||
102, 110, 116, 48, 57, 65, 90, 97,
|
||||
122, 48, 57, 41, 46, 48, 57, 48,
|
||||
57, 41, 48, 57, 41, 95, 48, 57,
|
||||
65, 90, 97, 122, 41, 95, 97, 48,
|
||||
57, 65, 90, 98, 122, 41, 95, 108,
|
||||
48, 57, 65, 90, 97, 122, 41, 95,
|
||||
115, 48, 57, 65, 90, 97, 122, 41,
|
||||
95, 101, 48, 57, 65, 90, 97, 122,
|
||||
41, 95, 48, 57, 65, 90, 97, 122,
|
||||
41, 95, 105, 117, 48, 57, 65, 90,
|
||||
97, 122, 41, 95, 108, 48, 57, 65,
|
||||
90, 97, 122, 41, 95, 48, 57, 65,
|
||||
90, 97, 122, 41, 95, 108, 48, 57,
|
||||
65, 90, 97, 122, 41, 95, 114, 48,
|
||||
57, 65, 90, 97, 122, 41, 95, 117,
|
||||
48, 57, 65, 90, 97, 122, 41, 95,
|
||||
101, 48, 57, 65, 90, 97, 122, 41,
|
||||
95, 48, 57, 65, 90, 97, 122, 46,
|
||||
48, 57, 46, 46, 95, 48, 57, 65,
|
||||
90, 97, 122, 46, 95, 97, 48, 57,
|
||||
65, 90, 98, 122, 46, 95, 108, 48,
|
||||
57, 65, 90, 97, 122, 46, 95, 115,
|
||||
48, 57, 65, 90, 97, 122, 46, 95,
|
||||
101, 48, 57, 65, 90, 97, 122, 46,
|
||||
95, 48, 57, 65, 90, 97, 122, 46,
|
||||
95, 105, 117, 48, 57, 65, 90, 97,
|
||||
122, 46, 95, 108, 48, 57, 65, 90,
|
||||
97, 122, 46, 95, 48, 57, 65, 90,
|
||||
97, 122, 46, 95, 108, 48, 57, 65,
|
||||
90, 97, 122, 46, 95, 114, 48, 57,
|
||||
65, 90, 97, 122, 46, 95, 117, 48,
|
||||
57, 65, 90, 97, 122, 46, 95, 101,
|
||||
48, 57, 65, 90, 97, 122, 46, 95,
|
||||
48, 57, 65, 90, 97, 122, 48, 57,
|
||||
48, 57, 34, 39, 43, 45, 102, 110,
|
||||
116, 48, 57, 65, 90, 97, 122, 34,
|
||||
34, 93, 39, 39, 93, 48, 57, 46,
|
||||
93, 48, 57, 48, 57, 93, 48, 57,
|
||||
93, 95, 48, 57, 65, 90, 97, 122,
|
||||
93, 95, 97, 48, 57, 65, 90, 98,
|
||||
122, 93, 95, 108, 48, 57, 65, 90,
|
||||
97, 122, 93, 95, 115, 48, 57, 65,
|
||||
90, 97, 122, 93, 95, 101, 48, 57,
|
||||
65, 90, 97, 122, 93, 95, 48, 57,
|
||||
65, 90, 97, 122, 93, 95, 105, 117,
|
||||
48, 57, 65, 90, 97, 122, 93, 95,
|
||||
108, 48, 57, 65, 90, 97, 122, 93,
|
||||
95, 48, 57, 65, 90, 97, 122, 93,
|
||||
95, 108, 48, 57, 65, 90, 97, 122,
|
||||
93, 95, 114, 48, 57, 65, 90, 97,
|
||||
122, 93, 95, 117, 48, 57, 65, 90,
|
||||
97, 122, 93, 95, 101, 48, 57, 65,
|
||||
90, 97, 122, 93, 95, 48, 57, 65,
|
||||
90, 97, 122, 34, 39, 46, 48, 57,
|
||||
48, 57, 95, 48, 57, 65, 90, 97,
|
||||
122, 34, 39, 95, 97, 48, 57, 65,
|
||||
90, 98, 122, 95, 108, 48, 57, 65,
|
||||
90, 97, 122, 95, 115, 48, 57, 65,
|
||||
90, 97, 122, 95, 101, 48, 57, 65,
|
||||
90, 97, 122, 95, 48, 57, 65, 90,
|
||||
97, 122, 95, 105, 117, 48, 57, 65,
|
||||
90, 97, 122, 95, 108, 48, 57, 65,
|
||||
90, 97, 122, 95, 48, 57, 65, 90,
|
||||
97, 122, 95, 108, 48, 57, 65, 90,
|
||||
97, 122, 95, 114, 48, 57, 65, 90,
|
||||
97, 122, 95, 117, 48, 57, 65, 90,
|
||||
97, 122, 95, 101, 48, 57, 65, 90,
|
||||
97, 122, 95, 48, 57, 65, 90, 97,
|
||||
122, 0
|
||||
]
|
||||
|
||||
class << self
|
||||
attr_accessor :_fsm_single_lengths
|
||||
private :_fsm_single_lengths, :_fsm_single_lengths=
|
||||
end
|
||||
self._fsm_single_lengths = [
|
||||
0, 9, 1, 1, 7, 1, 2, 2,
|
||||
4, 1, 2, 2, 4, 0, 1, 1,
|
||||
7, 0, 0, 2, 0, 1, 2, 3,
|
||||
3, 3, 3, 2, 4, 3, 2, 3,
|
||||
3, 3, 3, 2, 1, 1, 2, 3,
|
||||
3, 3, 3, 2, 4, 3, 2, 3,
|
||||
3, 3, 3, 2, 0, 0, 7, 1,
|
||||
2, 1, 2, 0, 2, 0, 1, 2,
|
||||
3, 3, 3, 3, 2, 4, 3, 2,
|
||||
3, 3, 3, 3, 2, 1, 1, 0,
|
||||
1, 0, 1, 1, 1, 0, 2, 2,
|
||||
2, 2, 1, 3, 2, 1, 2, 2,
|
||||
2, 2, 1
|
||||
]
|
||||
|
||||
class << self
|
||||
attr_accessor :_fsm_range_lengths
|
||||
private :_fsm_range_lengths, :_fsm_range_lengths=
|
||||
end
|
||||
self._fsm_range_lengths = [
|
||||
0, 3, 0, 0, 3, 0, 0, 0,
|
||||
3, 0, 0, 0, 3, 1, 1, 1,
|
||||
3, 0, 1, 1, 1, 1, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 1, 0, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 1, 1, 3, 0,
|
||||
0, 0, 0, 1, 1, 1, 1, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 0, 0, 0,
|
||||
1, 1, 3, 0, 0, 0, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3
|
||||
]
|
||||
|
||||
class << self
|
||||
attr_accessor :_fsm_index_offsets
|
||||
private :_fsm_index_offsets, :_fsm_index_offsets=
|
||||
end
|
||||
self._fsm_index_offsets = [
|
||||
0, 0, 13, 15, 17, 28, 30, 33,
|
||||
36, 44, 46, 49, 52, 60, 62, 65,
|
||||
68, 79, 80, 82, 86, 88, 91, 97,
|
||||
104, 111, 118, 125, 131, 139, 146, 152,
|
||||
159, 166, 173, 180, 186, 189, 191, 197,
|
||||
204, 211, 218, 225, 231, 239, 246, 252,
|
||||
259, 266, 273, 280, 286, 288, 290, 301,
|
||||
303, 306, 308, 311, 313, 317, 319, 322,
|
||||
328, 335, 342, 349, 356, 362, 370, 377,
|
||||
383, 390, 397, 404, 411, 417, 419, 421,
|
||||
422, 425, 427, 432, 434, 436, 437, 443,
|
||||
449, 455, 461, 466, 473, 479, 484, 490,
|
||||
496, 502, 508
|
||||
]
|
||||
|
||||
class << self
|
||||
attr_accessor :_fsm_trans_targs
|
||||
private :_fsm_trans_targs, :_fsm_trans_targs=
|
||||
end
|
||||
self._fsm_trans_targs = [
|
||||
2, 3, 4, 52, 52, 54, 86, 91,
|
||||
95, 80, 82, 82, 0, 77, 2, 78,
|
||||
3, 5, 9, 13, 13, 39, 44, 48,
|
||||
14, 38, 38, 0, 6, 5, 6, 7,
|
||||
5, 6, 8, 5, 6, 5, 5, 5,
|
||||
5, 5, 5, 5, 10, 9, 10, 11,
|
||||
9, 10, 12, 9, 9, 10, 9, 9,
|
||||
9, 9, 9, 9, 14, 0, 15, 14,
|
||||
0, 16, 36, 0, 17, 17, 18, 18,
|
||||
23, 28, 32, 19, 22, 22, 0, 17,
|
||||
19, 0, 79, 20, 19, 0, 21, 0,
|
||||
79, 21, 0, 79, 22, 22, 22, 22,
|
||||
0, 79, 22, 24, 22, 22, 22, 0,
|
||||
79, 22, 25, 22, 22, 22, 0, 79,
|
||||
22, 26, 22, 22, 22, 0, 79, 22,
|
||||
27, 22, 22, 22, 0, 79, 22, 22,
|
||||
22, 22, 0, 79, 22, 29, 31, 22,
|
||||
22, 22, 0, 79, 22, 30, 22, 22,
|
||||
22, 0, 79, 22, 22, 22, 22, 0,
|
||||
79, 22, 29, 22, 22, 22, 0, 79,
|
||||
22, 33, 22, 22, 22, 0, 79, 22,
|
||||
34, 22, 22, 22, 0, 79, 22, 35,
|
||||
22, 22, 22, 0, 79, 22, 22, 22,
|
||||
22, 0, 37, 36, 0, 16, 0, 37,
|
||||
38, 38, 38, 38, 0, 37, 38, 40,
|
||||
38, 38, 38, 0, 37, 38, 41, 38,
|
||||
38, 38, 0, 37, 38, 42, 38, 38,
|
||||
38, 0, 37, 38, 43, 38, 38, 38,
|
||||
0, 37, 38, 38, 38, 38, 0, 37,
|
||||
38, 45, 47, 38, 38, 38, 0, 37,
|
||||
38, 46, 38, 38, 38, 0, 37, 38,
|
||||
38, 38, 38, 0, 37, 38, 45, 38,
|
||||
38, 38, 0, 37, 38, 49, 38, 38,
|
||||
38, 0, 37, 38, 50, 38, 38, 38,
|
||||
0, 37, 38, 51, 38, 38, 38, 0,
|
||||
37, 38, 38, 38, 38, 0, 80, 0,
|
||||
81, 0, 55, 57, 59, 59, 64, 69,
|
||||
73, 60, 63, 63, 0, 56, 55, 56,
|
||||
83, 55, 58, 57, 58, 84, 57, 60,
|
||||
0, 61, 85, 60, 0, 62, 0, 85,
|
||||
62, 0, 85, 63, 63, 63, 63, 0,
|
||||
85, 63, 65, 63, 63, 63, 0, 85,
|
||||
63, 66, 63, 63, 63, 0, 85, 63,
|
||||
67, 63, 63, 63, 0, 85, 63, 68,
|
||||
63, 63, 63, 0, 85, 63, 63, 63,
|
||||
63, 0, 85, 63, 70, 72, 63, 63,
|
||||
63, 0, 85, 63, 71, 63, 63, 63,
|
||||
0, 85, 63, 63, 63, 63, 0, 85,
|
||||
63, 70, 63, 63, 63, 0, 85, 63,
|
||||
74, 63, 63, 63, 0, 85, 63, 75,
|
||||
63, 63, 63, 0, 85, 63, 76, 63,
|
||||
63, 63, 0, 85, 63, 63, 63, 63,
|
||||
0, 77, 2, 78, 3, 0, 53, 80,
|
||||
0, 81, 0, 82, 82, 82, 82, 0,
|
||||
56, 55, 58, 57, 0, 82, 87, 82,
|
||||
82, 82, 0, 82, 88, 82, 82, 82,
|
||||
0, 82, 89, 82, 82, 82, 0, 82,
|
||||
90, 82, 82, 82, 0, 82, 82, 82,
|
||||
82, 0, 82, 92, 94, 82, 82, 82,
|
||||
0, 82, 93, 82, 82, 82, 0, 82,
|
||||
82, 82, 82, 0, 82, 92, 82, 82,
|
||||
82, 0, 82, 96, 82, 82, 82, 0,
|
||||
82, 97, 82, 82, 82, 0, 82, 98,
|
||||
82, 82, 82, 0, 82, 82, 82, 82,
|
||||
0, 0
|
||||
]
|
||||
|
||||
class << self
|
||||
attr_accessor :_fsm_trans_actions
|
||||
private :_fsm_trans_actions, :_fsm_trans_actions=
|
||||
end
|
||||
self._fsm_trans_actions = [
|
||||
1, 1, 0, 1, 1, 0, 1, 1,
|
||||
1, 1, 1, 1, 0, 0, 0, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 0, 0, 0, 0, 17,
|
||||
0, 0, 0, 0, 1, 1, 1, 1,
|
||||
1, 1, 1, 0, 0, 0, 0, 17,
|
||||
0, 0, 0, 0, 1, 1, 1, 1,
|
||||
1, 1, 1, 0, 0, 0, 7, 0,
|
||||
0, 0, 0, 0, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 0, 0,
|
||||
0, 0, 7, 0, 0, 0, 0, 0,
|
||||
9, 0, 0, 19, 0, 0, 0, 0,
|
||||
0, 19, 0, 0, 0, 0, 0, 0,
|
||||
19, 0, 0, 0, 0, 0, 0, 19,
|
||||
0, 0, 0, 0, 0, 0, 19, 0,
|
||||
0, 0, 0, 0, 0, 15, 0, 0,
|
||||
0, 0, 0, 19, 0, 0, 0, 0,
|
||||
0, 0, 0, 19, 0, 0, 0, 0,
|
||||
0, 0, 11, 0, 0, 0, 0, 0,
|
||||
19, 0, 0, 0, 0, 0, 0, 19,
|
||||
0, 0, 0, 0, 0, 0, 19, 0,
|
||||
0, 0, 0, 0, 0, 19, 0, 0,
|
||||
0, 0, 0, 0, 13, 0, 0, 0,
|
||||
0, 0, 9, 0, 0, 0, 0, 19,
|
||||
0, 0, 0, 0, 0, 19, 0, 0,
|
||||
0, 0, 0, 0, 19, 0, 0, 0,
|
||||
0, 0, 0, 19, 0, 0, 0, 0,
|
||||
0, 0, 19, 0, 0, 0, 0, 0,
|
||||
0, 15, 0, 0, 0, 0, 0, 19,
|
||||
0, 0, 0, 0, 0, 0, 0, 19,
|
||||
0, 0, 0, 0, 0, 0, 11, 0,
|
||||
0, 0, 0, 0, 19, 0, 0, 0,
|
||||
0, 0, 0, 19, 0, 0, 0, 0,
|
||||
0, 0, 19, 0, 0, 0, 0, 0,
|
||||
0, 19, 0, 0, 0, 0, 0, 0,
|
||||
13, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 0, 0, 0, 0,
|
||||
17, 0, 0, 0, 0, 17, 0, 0,
|
||||
0, 0, 7, 0, 0, 0, 0, 9,
|
||||
0, 0, 19, 0, 0, 0, 0, 0,
|
||||
19, 0, 0, 0, 0, 0, 0, 19,
|
||||
0, 0, 0, 0, 0, 0, 19, 0,
|
||||
0, 0, 0, 0, 0, 19, 0, 0,
|
||||
0, 0, 0, 0, 15, 0, 0, 0,
|
||||
0, 0, 19, 0, 0, 0, 0, 0,
|
||||
0, 0, 19, 0, 0, 0, 0, 0,
|
||||
0, 11, 0, 0, 0, 0, 0, 19,
|
||||
0, 0, 0, 0, 0, 0, 19, 0,
|
||||
0, 0, 0, 0, 0, 19, 0, 0,
|
||||
0, 0, 0, 0, 19, 0, 0, 0,
|
||||
0, 0, 0, 13, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0
|
||||
]
|
||||
|
||||
class << self
|
||||
attr_accessor :_fsm_eof_actions
|
||||
private :_fsm_eof_actions, :_fsm_eof_actions=
|
||||
end
|
||||
self._fsm_eof_actions = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 17, 17, 5,
|
||||
7, 9, 19, 3, 3, 3, 19, 19,
|
||||
19, 19, 15, 19, 19, 11, 19, 19,
|
||||
19, 19, 13
|
||||
]
|
||||
|
||||
class << self
|
||||
attr_accessor :fsm_start
|
||||
end
|
||||
self.fsm_start = 1;
|
||||
class << self
|
||||
attr_accessor :fsm_first_final
|
||||
end
|
||||
self.fsm_first_final = 77;
|
||||
class << self
|
||||
attr_accessor :fsm_error
|
||||
end
|
||||
self.fsm_error = 0;
|
||||
|
||||
class << self
|
||||
attr_accessor :fsm_en_main
|
||||
end
|
||||
self.fsm_en_main = 1;
|
||||
|
||||
|
||||
# line 98 "./lib/liquid/parser.rl"
|
||||
|
||||
def self.emit(sym, type, data, tokens)
|
||||
puts "emitting: #{type} #{sym} -> #{data.inspect}"
|
||||
tokens.push [sym, data]
|
||||
end
|
||||
|
||||
def self.parse(data)
|
||||
eof = data.length
|
||||
tokens = []
|
||||
|
||||
|
||||
# line 414 "./lib/liquid/parser.rb"
|
||||
begin
|
||||
p ||= 0
|
||||
pe ||= data.length
|
||||
cs = fsm_start
|
||||
end
|
||||
|
||||
# line 109 "./lib/liquid/parser.rl"
|
||||
|
||||
# line 423 "./lib/liquid/parser.rb"
|
||||
begin
|
||||
_klen, _trans, _keys, _acts, _nacts = nil
|
||||
_goto_level = 0
|
||||
_resume = 10
|
||||
_eof_trans = 15
|
||||
_again = 20
|
||||
_test_eof = 30
|
||||
_out = 40
|
||||
while true
|
||||
_trigger_goto = false
|
||||
if _goto_level <= 0
|
||||
if p == pe
|
||||
_goto_level = _test_eof
|
||||
next
|
||||
end
|
||||
if cs == 0
|
||||
_goto_level = _out
|
||||
next
|
||||
end
|
||||
end
|
||||
if _goto_level <= _resume
|
||||
_keys = _fsm_key_offsets[cs]
|
||||
_trans = _fsm_index_offsets[cs]
|
||||
_klen = _fsm_single_lengths[cs]
|
||||
_break_match = false
|
||||
|
||||
begin
|
||||
if _klen > 0
|
||||
_lower = _keys
|
||||
_upper = _keys + _klen - 1
|
||||
|
||||
loop do
|
||||
break if _upper < _lower
|
||||
_mid = _lower + ( (_upper - _lower) >> 1 )
|
||||
|
||||
if data[p].ord < _fsm_trans_keys[_mid]
|
||||
_upper = _mid - 1
|
||||
elsif data[p].ord > _fsm_trans_keys[_mid]
|
||||
_lower = _mid + 1
|
||||
else
|
||||
_trans += (_mid - _keys)
|
||||
_break_match = true
|
||||
break
|
||||
end
|
||||
end # loop
|
||||
break if _break_match
|
||||
_keys += _klen
|
||||
_trans += _klen
|
||||
end
|
||||
_klen = _fsm_range_lengths[cs]
|
||||
if _klen > 0
|
||||
_lower = _keys
|
||||
_upper = _keys + (_klen << 1) - 2
|
||||
loop do
|
||||
break if _upper < _lower
|
||||
_mid = _lower + (((_upper-_lower) >> 1) & ~1)
|
||||
if data[p].ord < _fsm_trans_keys[_mid]
|
||||
_upper = _mid - 2
|
||||
elsif data[p].ord > _fsm_trans_keys[_mid+1]
|
||||
_lower = _mid + 2
|
||||
else
|
||||
_trans += ((_mid - _keys) >> 1)
|
||||
_break_match = true
|
||||
break
|
||||
end
|
||||
end # loop
|
||||
break if _break_match
|
||||
_trans += _klen
|
||||
end
|
||||
end while false
|
||||
cs = _fsm_trans_targs[_trans]
|
||||
if _fsm_trans_actions[_trans] != 0
|
||||
_acts = _fsm_trans_actions[_trans]
|
||||
_nacts = _fsm_actions[_acts]
|
||||
_acts += 1
|
||||
while _nacts > 0
|
||||
_nacts -= 1
|
||||
_acts += 1
|
||||
case _fsm_actions[_acts - 1]
|
||||
when 0 then
|
||||
# line 34 "./lib/liquid/parser.rl"
|
||||
begin
|
||||
|
||||
mark = p
|
||||
end
|
||||
when 3 then
|
||||
# line 59 "./lib/liquid/parser.rl"
|
||||
begin
|
||||
emit(:id, :integer, Integer(data[mark..p-1]), tokens) end
|
||||
when 4 then
|
||||
# line 61 "./lib/liquid/parser.rl"
|
||||
begin
|
||||
emit(:id, :float, Float(data[mark..p-1]), tokens) end
|
||||
when 5 then
|
||||
# line 63 "./lib/liquid/parser.rl"
|
||||
begin
|
||||
emit(:id, :nil, nil, tokens) end
|
||||
when 6 then
|
||||
# line 64 "./lib/liquid/parser.rl"
|
||||
begin
|
||||
emit(:id, :bool, true, tokens) end
|
||||
when 7 then
|
||||
# line 65 "./lib/liquid/parser.rl"
|
||||
begin
|
||||
emit(:id, :bool, false, tokens) end
|
||||
when 8 then
|
||||
# line 67 "./lib/liquid/parser.rl"
|
||||
begin
|
||||
emit(:id, :string, data[mark+1..p-2], tokens) end
|
||||
when 9 then
|
||||
# line 74 "./lib/liquid/parser.rl"
|
||||
begin
|
||||
|
||||
emit(:id, :label, data[mark..p-1], tokens)
|
||||
emit(:lookup, :variable, nil, tokens)
|
||||
end
|
||||
# line 540 "./lib/liquid/parser.rb"
|
||||
end # action switch
|
||||
end
|
||||
end
|
||||
if _trigger_goto
|
||||
next
|
||||
end
|
||||
end
|
||||
if _goto_level <= _again
|
||||
if cs == 0
|
||||
_goto_level = _out
|
||||
next
|
||||
end
|
||||
p += 1
|
||||
if p != pe
|
||||
_goto_level = _resume
|
||||
next
|
||||
end
|
||||
end
|
||||
if _goto_level <= _test_eof
|
||||
if p == eof
|
||||
__acts = _fsm_eof_actions[cs]
|
||||
__nacts = _fsm_actions[__acts]
|
||||
__acts += 1
|
||||
while __nacts > 0
|
||||
__nacts -= 1
|
||||
__acts += 1
|
||||
case _fsm_actions[__acts - 1]
|
||||
when 1 then
|
||||
# line 38 "./lib/liquid/parser.rl"
|
||||
begin
|
||||
|
||||
emit(:lookup, :instruction, nil, tokens)
|
||||
end
|
||||
when 2 then
|
||||
# line 42 "./lib/liquid/parser.rl"
|
||||
begin
|
||||
|
||||
emit(:range, :instruction, nil, tokens)
|
||||
end
|
||||
when 3 then
|
||||
# line 59 "./lib/liquid/parser.rl"
|
||||
begin
|
||||
emit(:id, :integer, Integer(data[mark..p-1]), tokens) end
|
||||
when 4 then
|
||||
# line 61 "./lib/liquid/parser.rl"
|
||||
begin
|
||||
emit(:id, :float, Float(data[mark..p-1]), tokens) end
|
||||
when 5 then
|
||||
# line 63 "./lib/liquid/parser.rl"
|
||||
begin
|
||||
emit(:id, :nil, nil, tokens) end
|
||||
when 6 then
|
||||
# line 64 "./lib/liquid/parser.rl"
|
||||
begin
|
||||
emit(:id, :bool, true, tokens) end
|
||||
when 7 then
|
||||
# line 65 "./lib/liquid/parser.rl"
|
||||
begin
|
||||
emit(:id, :bool, false, tokens) end
|
||||
when 8 then
|
||||
# line 67 "./lib/liquid/parser.rl"
|
||||
begin
|
||||
emit(:id, :string, data[mark+1..p-2], tokens) end
|
||||
when 9 then
|
||||
# line 74 "./lib/liquid/parser.rl"
|
||||
begin
|
||||
|
||||
emit(:id, :label, data[mark..p-1], tokens)
|
||||
emit(:lookup, :variable, nil, tokens)
|
||||
end
|
||||
# line 611 "./lib/liquid/parser.rb"
|
||||
end # eof action switch
|
||||
end
|
||||
if _trigger_goto
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
if _goto_level <= _out
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# line 110 "./lib/liquid/parser.rl"
|
||||
return tokens
|
||||
end
|
||||
end
|
||||
end
|
||||
113
lib/liquid/parser.rl
Normal file
113
lib/liquid/parser.rl
Normal file
@@ -0,0 +1,113 @@
|
||||
=begin
|
||||
LITERALS = {
|
||||
nil => nil, 'nil' => nil, 'null' => nil, '' => nil,
|
||||
'true' => true,
|
||||
'false' => false,
|
||||
'blank' => :blank?,
|
||||
'empty' => :empty?
|
||||
}
|
||||
|
||||
def resolve(key)
|
||||
if LITERALS.key?(key)
|
||||
LITERALS[key]
|
||||
else
|
||||
case key
|
||||
when /^'(.*)'$/ # Single quoted strings
|
||||
$1
|
||||
when /^"(.*)"$/ # Double quoted strings
|
||||
$1
|
||||
when /^(-?\d+)$/ # Integer and floats
|
||||
$1.to_i
|
||||
when /^\((\S+)\.\.(\S+)\)$/ # Ranges
|
||||
(resolve($1).to_i..resolve($2).to_i)
|
||||
when /^(-?\d[\d\.]+)$/ # Floats
|
||||
$1.to_f
|
||||
else
|
||||
variable(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
=end
|
||||
%%{
|
||||
machine fsm;
|
||||
|
||||
action mark {
|
||||
mark = p
|
||||
}
|
||||
|
||||
action lookup {
|
||||
emit(:lookup, :instruction, nil, tokens)
|
||||
}
|
||||
|
||||
action range {
|
||||
emit(:range, :instruction, nil, tokens)
|
||||
}
|
||||
|
||||
var = [a-zA-Z][0-9A-Za-z_]+;
|
||||
|
||||
# strings
|
||||
string = "\"" any* "\"" | "'" any* "'";
|
||||
|
||||
# nothingness
|
||||
nil = "nil" | "null" ;
|
||||
|
||||
integer = ('+'|'-')? digit+;
|
||||
float = ('+'|'-')? digit+ '.' digit+;
|
||||
|
||||
primitive = (
|
||||
|
||||
integer >mark %{ emit(:id, :integer, Integer(data[mark..p-1]), tokens) } |
|
||||
|
||||
float >mark %{ emit(:id, :float, Float(data[mark..p-1]), tokens) } |
|
||||
|
||||
nil %{ emit(:id, :nil, nil, tokens) } |
|
||||
"true" %{ emit(:id, :bool, true, tokens) } |
|
||||
"false" %{ emit(:id, :bool, false, tokens)} |
|
||||
|
||||
string >mark %{ emit(:id, :string, data[mark+1..p-2], tokens) }
|
||||
|
||||
);
|
||||
|
||||
constants = ( "true" | "false" | "nil" | "null" );
|
||||
|
||||
entity = (
|
||||
((alpha [A-Za-z0-9_]*) - (constants)) >mark %{
|
||||
emit(:id, :label, data[mark..p-1], tokens)
|
||||
emit(:lookup, :variable, nil, tokens)
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
main := (
|
||||
entity |
|
||||
primitive |
|
||||
|
||||
|
||||
"(" (primitive | entity) ".." (primitive | entity) <: ")" %range |
|
||||
"[" (primitive | entity) "]" %lookup
|
||||
|
||||
);
|
||||
|
||||
}%%
|
||||
# % fix syntax highlighting
|
||||
|
||||
|
||||
module Liquid
|
||||
module Parser
|
||||
%% write data;
|
||||
|
||||
def self.emit(sym, type, data, tokens)
|
||||
puts "emitting: #{type} #{sym} -> #{data.inspect}"
|
||||
tokens.push [sym, data]
|
||||
end
|
||||
|
||||
def self.parse(data)
|
||||
eof = data.length
|
||||
tokens = []
|
||||
|
||||
%% write init;
|
||||
%% write exec;
|
||||
return tokens
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -9,11 +9,9 @@ puts 'Running profiler...'
|
||||
results = profiler.run_profile
|
||||
|
||||
puts 'Success'
|
||||
puts
|
||||
|
||||
[RubyProf::FlatPrinter, RubyProf::GraphPrinter, RubyProf::GraphHtmlPrinter, RubyProf::CallTreePrinter].each do |klass|
|
||||
filename = (ENV['TMP'] || '/tmp') + (klass.name.include?('Html') ? "/liquid.#{klass.name.downcase}.html" : "/callgrind.liquid.#{klass.name.downcase}.txt")
|
||||
filename.gsub!(/:+/, '_')
|
||||
File.open(filename, "w+") { |fp| klass.new(results).print(fp, :print_file => true) }
|
||||
$stderr.puts "wrote #{klass.name} output to #{filename}"
|
||||
filename = (ENV['TMP'] || '/tmp') + "/callgrind.liquid.txt"
|
||||
File.open(filename, "w+") do |fp|
|
||||
RubyProf::CallTreePrinter.new(results).print(fp, :print_file => true)
|
||||
end
|
||||
$stderr.puts "wrote RubyProf::CallTreePrinter output to #{filename}"
|
||||
|
||||
@@ -23,7 +23,7 @@ class ThemeRunner
|
||||
|
||||
theme_path = File.dirname(test) + '/theme.liquid'
|
||||
|
||||
[File.read(test), (File.file?(theme_path) ? File.read(theme_path) : nil), test]
|
||||
[Liquid::Template.parse(File.read(test)), File.file?(theme_path) ? Liquid::Template.parse(File.read(theme_path)) : nil, test]
|
||||
end.compact
|
||||
end
|
||||
|
||||
@@ -53,11 +53,17 @@ class ThemeRunner
|
||||
end
|
||||
|
||||
|
||||
<<<<<<< HEAD
|
||||
def run_profile
|
||||
RubyProf.measure_mode = RubyProf::WALL_TIME
|
||||
=======
|
||||
def run(profile = false)
|
||||
RubyProf.measure_mode = RubyProf::WALL_TIME if profile
|
||||
>>>>>>> wip
|
||||
|
||||
# Dup assigns because will make some changes to them
|
||||
assigns = Database.tables.dup
|
||||
assigns['page_title'] = 'Page title'
|
||||
|
||||
@tests.each do |liquid, layout, template_name|
|
||||
|
||||
@@ -66,16 +72,17 @@ class ThemeRunner
|
||||
page_template = File.basename(template_name, File.extname(template_name))
|
||||
|
||||
unless @started
|
||||
RubyProf.start
|
||||
RubyProf.pause
|
||||
if profile
|
||||
RubyProf.start
|
||||
RubyProf.pause
|
||||
end
|
||||
@started = true
|
||||
end
|
||||
|
||||
html = nil
|
||||
|
||||
RubyProf.resume
|
||||
html = compile_and_render(liquid, layout, assigns, page_template)
|
||||
RubyProf.pause
|
||||
assigns['template'] = page_template
|
||||
RubyProf.resume if profile
|
||||
html = render(liquid, layout, assigns)
|
||||
RubyProf.pause if profile
|
||||
|
||||
|
||||
# return the result and the MD5 of the content, this can be used to detect regressions between liquid version
|
||||
@@ -85,19 +92,15 @@ class ThemeRunner
|
||||
# File.open("/tmp/#{File.basename(template_name)}.html", "w+") { |fp| fp <<html}
|
||||
end
|
||||
|
||||
RubyProf.stop
|
||||
RubyProf.stop if profile
|
||||
end
|
||||
|
||||
def compile_and_render(template, layout, assigns, page_template)
|
||||
tmpl = Liquid::Template.new
|
||||
tmpl.assigns['page_title'] = 'Page title'
|
||||
tmpl.assigns['template'] = page_template
|
||||
|
||||
content_for_layout = tmpl.parse(template).render(assigns)
|
||||
def render(template, layout, assigns)
|
||||
content_for_layout = template.render(assigns)
|
||||
|
||||
if layout
|
||||
assigns['content_for_layout'] = content_for_layout
|
||||
tmpl.parse(layout).render(assigns)
|
||||
layout.render(assigns)
|
||||
else
|
||||
content_for_layout
|
||||
end
|
||||
|
||||
66
test/liquid/parser_test.rb
Normal file
66
test/liquid/parser_test.rb
Normal file
@@ -0,0 +1,66 @@
|
||||
require 'test_helper'
|
||||
|
||||
|
||||
class ParserTest < Test::Unit::TestCase
|
||||
include Liquid
|
||||
|
||||
|
||||
def test_strings
|
||||
assert_equal [[:id, "string"]], Parser.parse('"string"')
|
||||
assert_equal [[:id, "string"]], Parser.parse('\'string\'')
|
||||
end
|
||||
|
||||
def test_integer
|
||||
assert_equal [[:id, 1]], Parser.parse('1')
|
||||
assert_equal [[:id, 100001]], Parser.parse('100001')
|
||||
end
|
||||
|
||||
def test_float
|
||||
assert_equal [[:id, 1.1]], Parser.parse('1.1')
|
||||
assert_equal [[:id, 1.55435]], Parser.parse('1.55435')
|
||||
end
|
||||
|
||||
def test_null
|
||||
assert_equal [[:id, nil]], Parser.parse('null')
|
||||
assert_equal [[:id, nil]], Parser.parse('nil')
|
||||
end
|
||||
|
||||
def test_bool
|
||||
assert_equal [[:id, true]], Parser.parse('true')
|
||||
assert_equal [[:id, false]], Parser.parse('false')
|
||||
end
|
||||
|
||||
def test_ranges
|
||||
assert_equal [[:id, 1], [:id, 5], [:range, nil]], Parser.parse('(1..5)')
|
||||
assert_equal [[:id, 100], [:id, 500], [:range, nil]], Parser.parse('(100..500)')
|
||||
end
|
||||
|
||||
def test_ranges_with_lookups
|
||||
assert_equal [[:id, 1], [:id, "test"], [:lookup, nil], [:range, nil]], Parser.parse('(1..test)')
|
||||
end
|
||||
|
||||
def test_lookups
|
||||
assert_equal [[:id, "variable"], [:lookup, nil]], Parser.parse('variable')
|
||||
assert_equal [[:id, "underscored_variable"], [:lookup, nil]], Parser.parse('underscored_variable')
|
||||
end
|
||||
|
||||
def test_global_hash
|
||||
assert_equal [[:id, true], [:lookup, nil]], Parser.parse('[true]')
|
||||
|
||||
assert_equal [[:id, "string"], [:lookup, nil]], Parser.parse('["string"]')
|
||||
assert_equal [[:id, 5.55], [:lookup, nil]], Parser.parse('[5.55]')
|
||||
assert_equal [[:id, 0], [:lookup, nil]], Parser.parse('[0]')
|
||||
assert_equal [[:id, "variable"], [:lookup, nil], [:lookup, nil]], Parser.parse('[variable]')
|
||||
end
|
||||
|
||||
# def test_descent
|
||||
# assert_equal [[:id, "variable1"], [:lookup, nil], [:id, "variable2"], [:call, nil]], Parser.parse('variable1.varible2')
|
||||
# end
|
||||
|
||||
# def test_descent_hash
|
||||
# assert_equal [[:id, "variable1"], [:lookup, nil], [:id, "variable2"], [:call, nil]], Parser.parse('variable1["varible2"]')
|
||||
# assert_equal [[:id, "variable1"], [:lookup, nil], [:id, "variable2"], [:lookup, "variable2"], [:call, nil]], Parser.parse('variable1[varible2]')
|
||||
# end
|
||||
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user