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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -1
  3. data/Guardfile +0 -4
  4. data/Rakefile +2 -2
  5. data/lib/liquidscript/compiler/icr/expressions.rb +2 -1
  6. data/lib/liquidscript/compiler/icr/literals.rb +17 -3
  7. data/lib/liquidscript/generator/javascript/literals.rb +18 -2
  8. data/lib/liquidscript/scanner.rb +3 -31
  9. data/lib/liquidscript/scanner/base.rb +84 -0
  10. data/lib/liquidscript/scanner/base/builder.rb +38 -0
  11. data/lib/liquidscript/scanner/base/context.rb +83 -0
  12. data/lib/liquidscript/scanner/base/dsl.rb +27 -0
  13. data/lib/liquidscript/scanner/base/lexer.rb +80 -0
  14. data/lib/liquidscript/scanner/liquidscript.rb +128 -0
  15. data/lib/liquidscript/scanner/token.rb +2 -6
  16. data/lib/liquidscript/template.rb +0 -1
  17. data/lib/liquidscript/version.rb +1 -1
  18. data/spec/fixtures/complex.generate.yml +1 -0
  19. data/spec/fixtures/main.compile.yml +1 -1
  20. data/spec/fixtures/string.compile.yml +15 -0
  21. data/spec/fixtures/string.generate.yml +3 -1
  22. data/spec/{lib/liquidscript → liquidscript}/buffer_spec.rb +0 -0
  23. data/spec/{lib/liquidscript → liquidscript}/compiler/icr_spec.rb +0 -0
  24. data/spec/{lib/liquidscript → liquidscript}/generator/javascript_spec.rb +7 -2
  25. data/spec/{lib/liquidscript → liquidscript}/icr/code_spec.rb +0 -0
  26. data/spec/{lib/liquidscript → liquidscript}/icr/context_spec.rb +0 -0
  27. data/spec/{lib/liquidscript → liquidscript}/icr/set_spec.rb +0 -0
  28. data/spec/{lib/liquidscript → liquidscript}/scanner/lexer_spec.rb +13 -15
  29. data/spec/{lib/liquidscript → liquidscript}/scanner/token_spec.rb +0 -0
  30. data/spec/{lib/liquidscript → liquidscript}/scanner_spec.rb +2 -2
  31. data/spec/spec_helper.rb +1 -0
  32. data/spec/support/helpers/lexer_helper.rb +1 -1
  33. data/spec/support/matchers/compile.rb +1 -1
  34. data/spec/support/matchers/generate.rb +2 -2
  35. metadata +28 -22
  36. data/lib/liquidscript/scanner/lexer.rb +0 -805
  37. data/lib/liquidscript/scanner/lexer.rl +0 -118
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 93358b89fa051538828ed587aaa478796f993676
4
- data.tar.gz: bf64eeb97bbdf9cb43150bf94b3d49d79bbba043
3
+ metadata.gz: 6e5b9fbac30bdea16bbd07de8b99ca913d320b6c
4
+ data.tar.gz: 888ba150e7957d376b2d1582b8ddd7d12a1d8ecc
5
5
  SHA512:
6
- metadata.gz: e91ab8b884aa60ed0d52d12f793f0f0b0f0cb13d3fbd060ae9d0345a56ef693dd99560fb280a8d68ea28f63fdf14f4f6b0106fbd34bbf3b039dd4456d2705b92
7
- data.tar.gz: 5bf5238837a656e9926809656fd90b3d96d768c6c589fd15886085852ec2e3fbc4e8963502ead086483a15cd0dea5f29bbdd0d5328d21c5e3eac2643bb9acba4
6
+ metadata.gz: c8d20ebc1d0dbdcf8398304d8e2a7e4a6e67eec0468189f42ee8f08e449151b2f9d3799e73ef9b4d9be25e7b4b083c0c625e3e2379c5d69c0bb5604c8eeaaf4c
7
+ data.tar.gz: e989b3f6b374a81c8e55b282570ecb6b6969a7250611addd042c6a8ce10bbb165be7cde3dbc1e43ca9c40276245236363e07dc7ca2c976f7e36a3df92ab996e9
data/.travis.yml CHANGED
@@ -4,5 +4,4 @@ rvm:
4
4
  - 1.9.3
5
5
  - jruby-19mode
6
6
  - rbx
7
- before_script: bundle exec rake ls:ragel
8
7
  script: bundle exec rspec -f d spec
data/Guardfile CHANGED
@@ -1,7 +1,3 @@
1
- guard :rake, :task => "ls:ragel" do
2
- watch("lib/liquidscript/scanner/lexer.rl")
3
- end
4
-
5
1
  guard :rspec do
6
2
  watch(%r{^spec/.+_spec\.rb})
7
3
  watch(%r{^lib/(.+)\.rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
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
- :dstring, :lparen,
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 compile_dstring
22
- code :dstring, pop.value[1..-2]
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, pop.value[1..-1]
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 generate_dstring(code)
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(/'/, "\\'")}'"
@@ -1,40 +1,12 @@
1
1
  require "liquidscript/scanner/token"
2
- require "liquidscript/scanner/lexer"
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
- class Scanner
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