liquidscript 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|