tickly 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -1,3 +1,5 @@
1
1
  rvm:
2
2
  - 1.8.7
3
- - 1.9.3
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - ruby-head
data/Gemfile CHANGED
@@ -3,7 +3,7 @@ source "http://rubygems.org"
3
3
  # Example:
4
4
  # gem "activesupport", ">= 2.3.5"
5
5
 
6
- gem "bychar", "~> 1.0.1"
6
+ gem "bychar", "~> 1.1"
7
7
 
8
8
  # Add dependencies to develop your gem here.
9
9
  # Include everything needed to run rake, tests, features, etc.
data/lib/tickly/parser.rb CHANGED
@@ -4,22 +4,6 @@ require 'bychar'
4
4
  module Tickly
5
5
 
6
6
 
7
- # Since you parse char by char, you will likely call
8
- # eof? on each iteration. Instead. allow it to raise and do not check.
9
- # This takes the profile time down from 36 seconds to 30 seconds
10
- # for a large file.
11
- class EOFError < RuntimeError #:nodoc: all
12
- end
13
-
14
- class W < Bychar::Reader #:nodoc: all
15
- def read_one_byte
16
- cache if @buf.eos?
17
- raise EOFError if @buf.eos?
18
-
19
- @buf.getch
20
- end
21
- end
22
-
23
7
  # Simplistic, incomplete and most likely incorrect TCL parser
24
8
  class Parser
25
9
 
@@ -30,7 +14,7 @@ module Tickly
30
14
  def parse(io_or_str)
31
15
  bare_io = io_or_str.respond_to?(:read) ? io_or_str : StringIO.new(io_or_str)
32
16
  # Wrap the IO in a Bychar buffer to read faster
33
- reader = W.new(bare_io)
17
+ reader = Bychar::Reader.new(bare_io)
34
18
  sub_parse(reader)
35
19
  end
36
20
 
@@ -45,112 +29,87 @@ module Tickly
45
29
  TERMINATORS = ["\n", ";"]
46
30
  ESC = 92.chr # Backslash (\)
47
31
 
32
+ # Package the expressions, stack and buffer.
33
+ # We use a special flag to tell us whether we need multuple expressions
34
+ # or not, if not we just discard them
35
+ def wrap_up(expressions, stack, buf, stack_depth, multiple_expressions)
36
+ stack << buf if (buf.length > 0)
37
+ return stack unless multiple_expressions
38
+
39
+ expressions << stack if stack.any?
40
+ expressions.each { |expr| expand_subexpr!(expr, stack_depth + 1) }
41
+
42
+ return expressions
43
+ end
44
+
48
45
  # Parse from a passed IO object either until an unescaped stop_char is reached
49
46
  # or until the IO is exhausted. The last argument is the class used to
50
47
  # compose the subexpression being parsed. The subparser is reentrant and not
51
48
  # destructive for the object containing it.
52
49
  def sub_parse(io, stop_char = nil, stack_depth = 0)
53
50
  # A standard stack is an expression that does not evaluate to a string
51
+ expressions = []
54
52
  stack = []
55
53
  buf = ''
56
54
  last_char_was_linebreak = false
55
+ multiple_expressions = false
57
56
 
58
57
  no_eof do
59
- char = io.read_one_byte
60
-
61
- if buf[LAST_CHAR] != ESC
62
- if char == stop_char # Bail out of a subexpr
63
- stack << buf if (buf.length > 0)
64
- # Chip away the tailing linebreak if it's there
65
- chomp!(stack)
66
- return stack
67
- elsif char == " " || char == "\n" # Space
68
- if buf.length > 0
69
- stack << buf
70
- buf = ''
71
- end
72
- if TERMINATORS.include?(char) # Introduce a stack separator! This is a new line
73
- if stack.any? && !last_char_was_linebreak
74
- last_char_was_linebreak = true
75
- stack = handle_expr_terminator(stack, stack_depth)
76
- end
77
- end
78
- elsif char == '[' # Opens a new string expression
79
- stack << buf if (buf.length > 0)
80
- last_char_was_linebreak = false
81
- stack << [:b] + sub_parse(io, ']', stack_depth + 1)
82
- elsif char == '{' # Opens a new literal expression
83
- stack << buf if (buf.length > 0)
84
- last_char_was_linebreak = false
85
- stack << [:c] + sub_parse(io, '}', stack_depth + 1)
86
- elsif char == '"'
87
- stack << buf if (buf.length > 0)
88
- last_char_was_linebreak = false
89
- stack << parse_str(io, '"')
90
- elsif char == "'"
91
- stack << buf if (buf.length > 0)
92
- last_char_was_linebreak = false
93
- stack << parse_str(io, "'")
58
+ char = io.read_one_byte!
59
+
60
+ if char == stop_char # Bail out of a subexpr
61
+ # Handle any remaining subexpressions
62
+ return wrap_up(expressions, stack, buf, stack_depth, multiple_expressions)
63
+ elsif char == " " || char == "\n" # Space
64
+ if buf.length > 0
65
+ stack << buf
66
+ buf = ''
67
+ end
68
+ if TERMINATORS.include?(char) && stack.any? && !last_char_was_linebreak # Introduce a stack separator! This is a new line
69
+ stack << buf if buf.length > 0
70
+ expressions << stack
71
+ stack = []
72
+ last_char_was_linebreak = true
73
+ multiple_expressions = true
74
+ #puts "Next expression! #{expressions.inspect} #{stack.inspect} #{buf.inspect}"
94
75
  else
95
76
  last_char_was_linebreak = false
96
- buf << char
97
77
  end
78
+ elsif char == '[' # Opens a new string expression
79
+ stack << buf if (buf.length > 0)
80
+ stack << [:b] + sub_parse(io, ']', stack_depth + 1)
81
+ elsif char == '{' # Opens a new literal expression
82
+ stack << buf if (buf.length > 0)
83
+ stack << [:c] + sub_parse(io, '}', stack_depth + 1)
84
+ elsif char == '"'
85
+ stack << buf if (buf.length > 0)
86
+ stack << parse_str(io, '"')
87
+ elsif char == "'"
88
+ stack << buf if (buf.length > 0)
89
+ stack << parse_str(io, "'")
98
90
  else
99
- last_char_was_linebreak = false
100
91
  buf << char
101
92
  end
102
93
  end
103
-
104
- # Ramass any remaining buffer contents
105
- stack << buf if (buf.length > 0)
106
-
107
- # Handle any remaining subexpressions
108
- if stack.include?(nil)
109
- stack = handle_expr_terminator(stack, stack_depth)
110
- end
111
- # Chip awiy the trailing null
112
- chomp!(stack)
113
94
 
114
- return stack
95
+ return wrap_up(expressions, stack, buf, stack_depth, multiple_expressions)
115
96
  end
116
97
 
117
98
  def chomp!(stack)
118
99
  stack.delete_at(-1) if stack.any? && stack[-1].nil?
119
100
  end
120
101
 
121
- def handle_expr_terminator(stack, stack_depth)
122
- # Figure out whether there was a previous expr terminator
123
- previous_i = stack.index(nil)
124
- # If there were none, just get this over with. Wrap the stack contents
125
- # into a subexpression and carry on.
126
- unless previous_i
127
- subexpr = stack
128
- expand_subexpr!(subexpr, stack_depth + 1)
129
- return [subexpr] + [nil]
130
- end
131
-
132
- # Now, if there was one, we are the next subexpr in line that just terminated.
133
- # What we need to do is pick out all the elements from that terminator onwards
134
- # and wrap them.
135
- subexpr = stack[previous_i+1..-1]
136
-
137
- # Use expand_subexpr! to trim away any fat that we don't need
138
- expand_subexpr!(subexpr, stack_depth + 1)
139
-
140
- return stack[0...previous_i] + [subexpr] + [nil]
141
- end
142
-
143
102
  def no_eof(&blk)
144
103
  begin
145
104
  loop(&blk)
146
- rescue EOFError
105
+ rescue Bychar::EOFError
147
106
  end
148
107
  end
149
108
 
150
109
  def parse_str(io, stop_char)
151
110
  buf = ''
152
111
  no_eof do
153
- c = io.read_one_byte
112
+ c = io.read_one_byte!
154
113
  if c == stop_char && buf[LAST_CHAR] != ESC
155
114
  return buf
156
115
  elsif buf[LAST_CHAR] == ESC # Eat out the escape char
data/lib/tickly.rb CHANGED
@@ -4,7 +4,7 @@ require File.dirname(__FILE__) + "/tickly/evaluator"
4
4
  require 'forwardable'
5
5
 
6
6
  module Tickly
7
- VERSION = '0.0.6'
7
+ VERSION = '0.0.7'
8
8
 
9
9
  # Provides the methods for quickly emitting the expression arrays,
10
10
  # is used in tests
data/tickly.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "tickly"
8
- s.version = "0.0.6"
8
+ s.version = "0.0.7"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Julik Tarkhanov"]
@@ -54,14 +54,14 @@ Gem::Specification.new do |s|
54
54
  s.specification_version = 3
55
55
 
56
56
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
57
- s.add_runtime_dependency(%q<bychar>, ["~> 1.0.1"])
57
+ s.add_runtime_dependency(%q<bychar>, ["~> 1.1"])
58
58
  s.add_development_dependency(%q<shoulda>, [">= 0"])
59
59
  s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
60
60
  s.add_development_dependency(%q<bundler>, [">= 0"])
61
61
  s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
62
62
  s.add_development_dependency(%q<ruby-prof>, [">= 0"])
63
63
  else
64
- s.add_dependency(%q<bychar>, ["~> 1.0.1"])
64
+ s.add_dependency(%q<bychar>, ["~> 1.1"])
65
65
  s.add_dependency(%q<shoulda>, [">= 0"])
66
66
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
67
67
  s.add_dependency(%q<bundler>, [">= 0"])
@@ -69,7 +69,7 @@ Gem::Specification.new do |s|
69
69
  s.add_dependency(%q<ruby-prof>, [">= 0"])
70
70
  end
71
71
  else
72
- s.add_dependency(%q<bychar>, ["~> 1.0.1"])
72
+ s.add_dependency(%q<bychar>, ["~> 1.1"])
73
73
  s.add_dependency(%q<shoulda>, [">= 0"])
74
74
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
75
75
  s.add_dependency(%q<bundler>, [">= 0"])
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tickly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 1.0.1
21
+ version: '1.1'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: 1.0.1
29
+ version: '1.1'
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: shoulda
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -156,7 +156,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
156
156
  version: '0'
157
157
  segments:
158
158
  - 0
159
- hash: -2375266437877240498
159
+ hash: 1707085798664396026
160
160
  required_rubygems_version: !ruby/object:Gem::Requirement
161
161
  none: false
162
162
  requirements: