liquidscript 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +0 -1
- data/Guardfile +0 -4
- data/Rakefile +2 -2
- data/lib/liquidscript/compiler/icr/expressions.rb +2 -1
- data/lib/liquidscript/compiler/icr/literals.rb +17 -3
- data/lib/liquidscript/generator/javascript/literals.rb +18 -2
- data/lib/liquidscript/scanner.rb +3 -31
- data/lib/liquidscript/scanner/base.rb +84 -0
- data/lib/liquidscript/scanner/base/builder.rb +38 -0
- data/lib/liquidscript/scanner/base/context.rb +83 -0
- data/lib/liquidscript/scanner/base/dsl.rb +27 -0
- data/lib/liquidscript/scanner/base/lexer.rb +80 -0
- data/lib/liquidscript/scanner/liquidscript.rb +128 -0
- data/lib/liquidscript/scanner/token.rb +2 -6
- data/lib/liquidscript/template.rb +0 -1
- data/lib/liquidscript/version.rb +1 -1
- data/spec/fixtures/complex.generate.yml +1 -0
- data/spec/fixtures/main.compile.yml +1 -1
- data/spec/fixtures/string.compile.yml +15 -0
- data/spec/fixtures/string.generate.yml +3 -1
- data/spec/{lib/liquidscript → liquidscript}/buffer_spec.rb +0 -0
- data/spec/{lib/liquidscript → liquidscript}/compiler/icr_spec.rb +0 -0
- data/spec/{lib/liquidscript → liquidscript}/generator/javascript_spec.rb +7 -2
- data/spec/{lib/liquidscript → liquidscript}/icr/code_spec.rb +0 -0
- data/spec/{lib/liquidscript → liquidscript}/icr/context_spec.rb +0 -0
- data/spec/{lib/liquidscript → liquidscript}/icr/set_spec.rb +0 -0
- data/spec/{lib/liquidscript → liquidscript}/scanner/lexer_spec.rb +13 -15
- data/spec/{lib/liquidscript → liquidscript}/scanner/token_spec.rb +0 -0
- data/spec/{lib/liquidscript → liquidscript}/scanner_spec.rb +2 -2
- data/spec/spec_helper.rb +1 -0
- data/spec/support/helpers/lexer_helper.rb +1 -1
- data/spec/support/matchers/compile.rb +1 -1
- data/spec/support/matchers/generate.rb +2 -2
- metadata +28 -22
- data/lib/liquidscript/scanner/lexer.rb +0 -805
- data/lib/liquidscript/scanner/lexer.rl +0 -118
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6e5b9fbac30bdea16bbd07de8b99ca913d320b6c
|
4
|
+
data.tar.gz: 888ba150e7957d376b2d1582b8ddd7d12a1d8ecc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c8d20ebc1d0dbdcf8398304d8e2a7e4a6e67eec0468189f42ee8f08e449151b2f9d3799e73ef9b4d9be25e7b4b083c0c625e3e2379c5d69c0bb5604c8eeaaf4c
|
7
|
+
data.tar.gz: e989b3f6b374a81c8e55b282570ecb6b6969a7250611addd042c6a8ce10bbb165be7cde3dbc1e43ca9c40276245236363e07dc7ca2c976f7e36a3df92ab996e9
|
data/.travis.yml
CHANGED
data/Guardfile
CHANGED
data/Rakefile
CHANGED
@@ -9,8 +9,8 @@ namespace :ls do
|
|
9
9
|
sh "ragel -R #{t.source}"
|
10
10
|
end
|
11
11
|
|
12
|
-
desc "Builds the ragel parser."
|
13
|
-
task :ragel => ["lib/liquidscript/scanner/lexer.rb"]
|
12
|
+
#desc "Builds the ragel parser."
|
13
|
+
#task :ragel => ["lib/liquidscript/scanner/lexer.rb"]
|
14
14
|
|
15
15
|
desc "Opens up a pry session."
|
16
16
|
task :pry => [:ragel] do
|
@@ -16,10 +16,11 @@ module Liquidscript
|
|
16
16
|
# @return [ICR::Code]
|
17
17
|
def compile_vexpression
|
18
18
|
out = expect :number, :identifier,
|
19
|
-
:
|
19
|
+
:istring, :lparen,
|
20
20
|
:sstring, :operator,
|
21
21
|
:keyword, :unop,
|
22
22
|
:newline,
|
23
|
+
:istring_begin,
|
23
24
|
:lbrack => :object,
|
24
25
|
:lbrace => :array,
|
25
26
|
:arrow => :function
|
@@ -18,12 +18,26 @@ module Liquidscript
|
|
18
18
|
:_ => default
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
22
|
-
|
21
|
+
def compile_istring_begin
|
22
|
+
start = shift :istring_begin
|
23
|
+
contents = [start]
|
24
|
+
|
25
|
+
loop do
|
26
|
+
contents << compile_vexpression
|
27
|
+
contents << shift(:istring)
|
28
|
+
peek?(:istring_begin)
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
code :interop, *contents
|
33
|
+
end
|
34
|
+
|
35
|
+
def compile_istring
|
36
|
+
code :istring, shift(:istring).value
|
23
37
|
end
|
24
38
|
|
25
39
|
def compile_sstring
|
26
|
-
code :sstring,
|
40
|
+
code :sstring, shift(:sstring).value[1..-1]
|
27
41
|
end
|
28
42
|
|
29
43
|
def compile_operator
|
@@ -17,11 +17,27 @@ module Liquidscript
|
|
17
17
|
"#{code.first}"
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
21
|
-
|
20
|
+
def generate_istring(code)
|
22
21
|
"\"#{code.first.gsub("\n", "\\n")}\""
|
23
22
|
end
|
24
23
|
|
24
|
+
def generate_interop(code)
|
25
|
+
content = code[1..-1]
|
26
|
+
buf = buffer
|
27
|
+
buf.set_join! ','
|
28
|
+
|
29
|
+
content.each do |part|
|
30
|
+
case part.type
|
31
|
+
when :istring_begin, :istring
|
32
|
+
buf << "\"#{part.value}\""
|
33
|
+
else
|
34
|
+
buf << "#{replace(part)}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
"[#{buf}].join('')"
|
39
|
+
end
|
40
|
+
|
25
41
|
def generate_sstring(code)
|
26
42
|
|
27
43
|
"'#{code.first.gsub(/'/, "\\'")}'"
|
data/lib/liquidscript/scanner.rb
CHANGED
@@ -1,40 +1,12 @@
|
|
1
1
|
require "liquidscript/scanner/token"
|
2
|
-
require "liquidscript/scanner/
|
2
|
+
require "liquidscript/scanner/base"
|
3
|
+
require "liquidscript/scanner/liquidscript"
|
3
4
|
|
4
5
|
module Liquidscript
|
5
6
|
|
6
7
|
# @todo Stream scanning.
|
7
8
|
# um...
|
8
|
-
|
9
|
-
|
10
|
-
include Enumerable
|
11
|
-
|
12
|
-
def initialize(source)
|
13
|
-
@tokenizer = Lexer.new
|
14
|
-
@source = source
|
15
|
-
end
|
16
|
-
|
17
|
-
def each
|
18
|
-
e = buffer.each
|
19
|
-
|
20
|
-
if block_given?
|
21
|
-
e.each(&Proc.new)
|
22
|
-
else
|
23
|
-
e
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def inspect
|
28
|
-
"#<#{self.class.to_s}:#{'0x%08x' % self.object_id}>"
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def buffer
|
34
|
-
@_parts ||= begin
|
35
|
-
@tokenizer.perform(@source)
|
36
|
-
end
|
37
|
-
end
|
9
|
+
module Scanner
|
38
10
|
|
39
11
|
end
|
40
12
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'strscan'
|
3
|
+
require 'liquidscript/scanner/base/builder'
|
4
|
+
require 'liquidscript/scanner/base/context'
|
5
|
+
require 'liquidscript/scanner/base/dsl'
|
6
|
+
require 'liquidscript/scanner/base/lexer'
|
7
|
+
|
8
|
+
module Liquidscript
|
9
|
+
module Scanner
|
10
|
+
# TODO: documentation
|
11
|
+
class Base
|
12
|
+
|
13
|
+
EXIT = Object.new.freeze
|
14
|
+
|
15
|
+
include Lexer
|
16
|
+
include Enumerable
|
17
|
+
|
18
|
+
class << self
|
19
|
+
|
20
|
+
def contexts
|
21
|
+
@_contexts ||= Set.new
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_accessor :default
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(source)
|
29
|
+
@source = source
|
30
|
+
@scanner = StringScanner.new(@source)
|
31
|
+
@tokens = []
|
32
|
+
@_scan = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def contexts
|
36
|
+
self.class.contexts
|
37
|
+
end
|
38
|
+
|
39
|
+
def default_context
|
40
|
+
self.class.default
|
41
|
+
end
|
42
|
+
|
43
|
+
def scan
|
44
|
+
lex default_context
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def each
|
49
|
+
e = buffer.each
|
50
|
+
|
51
|
+
if block_given?
|
52
|
+
e.each(&Proc.new)
|
53
|
+
else
|
54
|
+
e
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def line
|
59
|
+
"(unknown)"
|
60
|
+
end
|
61
|
+
|
62
|
+
def column
|
63
|
+
"(unkown)"
|
64
|
+
end
|
65
|
+
|
66
|
+
def emit(token_name, body = nil)
|
67
|
+
@tokens << Token.new(token_name, body, line, column)
|
68
|
+
end
|
69
|
+
|
70
|
+
def inspect
|
71
|
+
"#<#{self.class}:#{'0x%08x' % object_id}>"
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def buffer
|
77
|
+
@_scan ||= begin
|
78
|
+
scan
|
79
|
+
@tokens
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Liquidscript
|
4
|
+
module Scanner
|
5
|
+
class Base
|
6
|
+
class Builder
|
7
|
+
|
8
|
+
EMPTY_VALUE = Object.new
|
9
|
+
|
10
|
+
attr_reader :contexts
|
11
|
+
|
12
|
+
def default_context(value = EMPTY_VALUE)
|
13
|
+
if value.equal? EMPTY_VALUE
|
14
|
+
@default_context
|
15
|
+
else
|
16
|
+
@default_context = value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def contexts
|
21
|
+
@contexts ||= Set.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def context(name)
|
25
|
+
context = Context.new(name)
|
26
|
+
context.instance_exec(&Proc.new)
|
27
|
+
contexts << context
|
28
|
+
end
|
29
|
+
|
30
|
+
def reset!
|
31
|
+
@default_context = nil
|
32
|
+
@contexts = nil
|
33
|
+
self
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Liquidscript
|
2
|
+
module Scanner
|
3
|
+
class Base
|
4
|
+
class Context
|
5
|
+
|
6
|
+
attr_reader :name
|
7
|
+
|
8
|
+
def initialize(name)
|
9
|
+
@name = name
|
10
|
+
@matches = {}
|
11
|
+
@temps = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def find_matcher(with)
|
15
|
+
best_match = [0, nil, nil]
|
16
|
+
@matches.each do |k, v|
|
17
|
+
if with.match?(k) && with.matched_size > best_match[0]
|
18
|
+
best_match = [with.matched_size, k, v]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
best_match[1..-1]
|
23
|
+
end
|
24
|
+
|
25
|
+
def exit
|
26
|
+
EXIT
|
27
|
+
end
|
28
|
+
|
29
|
+
def init
|
30
|
+
if block_given?
|
31
|
+
@init = Proc.new
|
32
|
+
else
|
33
|
+
@init || proc {}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def set(key, matcher)
|
38
|
+
@temps[key] = matcher
|
39
|
+
end
|
40
|
+
|
41
|
+
def get(key)
|
42
|
+
normalize_matcher @temps[key]
|
43
|
+
end
|
44
|
+
|
45
|
+
def on(matcher)
|
46
|
+
key = nil
|
47
|
+
value = nil
|
48
|
+
|
49
|
+
if block_given?
|
50
|
+
key = normalize_matcher matcher
|
51
|
+
value = Proc.new
|
52
|
+
else
|
53
|
+
key = normalize_matcher matcher.keys.first
|
54
|
+
value = matcher.values.first
|
55
|
+
end
|
56
|
+
|
57
|
+
@matches[key] = value
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def normalize_matcher(matcher)
|
63
|
+
case matcher
|
64
|
+
when :_
|
65
|
+
/./m
|
66
|
+
when String
|
67
|
+
Regexp.new(Regexp.escape(matcher))
|
68
|
+
when Symbol
|
69
|
+
normalize_matcher(@temps[matcher])
|
70
|
+
when Array
|
71
|
+
union = matcher.map { |m|
|
72
|
+
Regexp.escape(m.to_s)
|
73
|
+
}.join('|')
|
74
|
+
Regexp.new "(#{union})"
|
75
|
+
else
|
76
|
+
matcher
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Liquidscript
|
2
|
+
module Scanner
|
3
|
+
class Base
|
4
|
+
module DSL
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
|
8
|
+
def define
|
9
|
+
builder.instance_exec(&Proc.new)
|
10
|
+
contexts.merge builder.contexts
|
11
|
+
self.default = builder.default_context
|
12
|
+
builder.reset!
|
13
|
+
end
|
14
|
+
|
15
|
+
def builder
|
16
|
+
@_builder ||= Builder.new
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.included(base)
|
22
|
+
base.extend ClassMethods
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Liquidscript
|
2
|
+
module Scanner
|
3
|
+
class Base
|
4
|
+
module Lexer
|
5
|
+
|
6
|
+
def perform_with_context(context, scanner = @scanner)
|
7
|
+
key, value = context.find_matcher(scanner)
|
8
|
+
|
9
|
+
if value.nil? && scanner.rest?
|
10
|
+
error scanner
|
11
|
+
end
|
12
|
+
|
13
|
+
normalize_action key, value, scanner if scanner.rest?
|
14
|
+
end
|
15
|
+
|
16
|
+
def lex(argument)
|
17
|
+
context, body =
|
18
|
+
if argument.is_a?(Hash)
|
19
|
+
argument.to_a.first
|
20
|
+
else
|
21
|
+
argument
|
22
|
+
end
|
23
|
+
|
24
|
+
scanner = if body
|
25
|
+
StringScanner.new(body)
|
26
|
+
else
|
27
|
+
@scanner
|
28
|
+
end
|
29
|
+
out = []
|
30
|
+
|
31
|
+
context = find_context(context)
|
32
|
+
instance_exec &context.init
|
33
|
+
|
34
|
+
while scanner.rest? && out.last != EXIT
|
35
|
+
out << perform_with_context(context, scanner)
|
36
|
+
end
|
37
|
+
|
38
|
+
out
|
39
|
+
end
|
40
|
+
|
41
|
+
def error(scanner = @scanner)
|
42
|
+
raise SyntaxError, "Unexpected #{scanner.peek(2).inspect}" \
|
43
|
+
" (line: #{line}, column: #{column})"
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def find_context(name)
|
49
|
+
context = contexts.dup.keep_if { |c|
|
50
|
+
c.name == name
|
51
|
+
}.to_a.first
|
52
|
+
|
53
|
+
if context.nil?
|
54
|
+
raise NoContextError.new(name)
|
55
|
+
end
|
56
|
+
|
57
|
+
context
|
58
|
+
end
|
59
|
+
|
60
|
+
def exit
|
61
|
+
EXIT
|
62
|
+
end
|
63
|
+
|
64
|
+
def normalize_action(key, value, scanner)
|
65
|
+
body = scanner.scan(key)
|
66
|
+
|
67
|
+
case value
|
68
|
+
when Proc
|
69
|
+
instance_exec(*body.match(key), &value)
|
70
|
+
when Symbol
|
71
|
+
lex value
|
72
|
+
when EXIT
|
73
|
+
EXIT
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|