lxl 0.2.0 → 0.2.2

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 (4) hide show
  1. data/CHANGES +7 -0
  2. data/VERSION +1 -1
  3. data/lib/lxl.rb +41 -44
  4. metadata +1 -1
data/CHANGES CHANGED
@@ -1,3 +1,10 @@
1
+ 0.2.2
2
+
3
+ - Seperated tokenize's text=>formula into tokenize_text
4
+ - LittleLexer returns types as [Symbol*] vs String (tokenize updated accordingly)
5
+ - F and C types removed (no need)
6
+ - General refactoring (code/doc cleanup)
7
+
1
8
  0.2.0
2
9
 
3
10
  - Double quotes only used to define strings.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.2.2
data/lib/lxl.rb CHANGED
@@ -54,8 +54,6 @@
54
54
  # t Token
55
55
  # ( Open (
56
56
  # ) Close )
57
- # C Constant
58
- # F Function
59
57
  #
60
58
  module LXL
61
59
 
@@ -111,29 +109,25 @@ class LXL::Parser
111
109
  ops = EXCEL_OPERATORS.collect { |v| Regexp.quote(v) }.join('|')
112
110
  #
113
111
  @lexer = LXL::LittleLexer.new([
114
- [/\A[\s,]+/,?w], # Whitespace (includes Commas)
115
- [/\A(#{ops})/,?o], # Operator
116
- [/\A[0-9]+\.[0-9]+/,?f], # Float
117
- [/\A[0-9]+/,?i], # Integer
118
- [/\A("([^"]|"")*")/m,?s], # String
119
- [/\A\w+/,?t], # Token
120
- [/\A\(/,?(], # Open (
121
- [/\A\)/,?)], # Close )
112
+ [/\A[\s,]+/, ?w], # Whitespace (includes Commas)
113
+ [/\A(#{ops})/, ?o], # Operator
114
+ [/\A("([^"]|"")*")/m, ?s], # String
115
+ [/\A[0-9]+\.[0-9]+/, ?f], # Float
116
+ [/\A[0-9]+/, ?i], # Integer
117
+ [/\A\w+/, ?t], # Token
118
+ [/\A\(/, ?(], # Open (
119
+ [/\A\)/, ?)], # Close )
122
120
  ], false)
123
-
124
- # Other
125
- @tokens = Array.new
126
- @types = Array.new
127
121
  end
128
122
 
129
123
  # Evaluate formula
130
124
  #
131
125
  def eval(formula)
132
126
  formulas = formula.to_s.split(';').collect { |f| f.strip }.find_all { |f| ! f.empty? }
133
- formulas.collect! { |f| Kernel.eval(tokenize(f).join, binding) }
127
+ formulas.collect! { |f| Kernel.eval(tokenize_text(f).join, binding) }
134
128
  formulas.size == 1 ? formulas.first : formulas
135
129
  end
136
-
130
+
137
131
  # Register a function
138
132
  #
139
133
  # * Converts name to symbol
@@ -181,44 +175,45 @@ class LXL::Parser
181
175
  }
182
176
  end
183
177
 
178
+ # Translates text to a formula before tokenizing
179
+ #
180
+ def tokenize_text(text)
181
+ formula = (text =~ /^=/) ? text : '="'+text.gsub('"','""')+'"'
182
+ tokenize(formula)
183
+ end
184
+
184
185
  # Tokenize formula (String => Array)
185
186
  #
186
187
  def tokenize(formula)
187
188
  ops = Hash[*EXCEL_OPERATORS.zip(RUBY_OPERATORS).flatten]
188
189
 
189
190
  # Parse formula
190
- formula = '="'+formula.gsub('"','""')+'"' unless formula =~ /^=/ # text to formula (text to ="quoted-text")
191
191
  types, tokens = @lexer.scan(formula.gsub(/^=/,''))
192
- types = types.split(//)
193
192
  raise SyntaxError, 'unbalanced parentheses' unless balanced?(tokens)
194
193
 
195
194
  # Parse tokens
196
195
  tokens.each_index do |i|
197
196
  type, token = types[i], tokens[i]
198
- token = case type
199
- when 'i': token.to_i
200
- when 'f': token.to_f
201
- when 's': token.gsub(/([^\\])""/,'\1\"') # "" to \"
202
- else token
203
- end
204
- if type == 't'
205
- token = name(token)
206
- if @functions.key?(token)
207
- if tokens[i+1] != '('
208
- raise ArgumentError, "wrong number of arguments for #{token}"
197
+ tokens[i] = case type
198
+ when :i then token.to_i
199
+ when :f then token.to_f
200
+ when :s then token.gsub(/([^\\])""/,'\1\"') # "" to \"
201
+ when :t then
202
+ name = name(token)
203
+ if @functions.key?(name)
204
+ if tokens[i+1] != '('
205
+ raise ArgumentError, "wrong number of arguments for #{token}"
206
+ else
207
+ "@functions[:#{name}].call"
208
+ end
209
+ elsif @constants.key?(name)
210
+ "@constants[:#{name}]"
209
211
  else
210
- types[i] = 'F'
211
- token = '@functions['+token.inspect+'].call'
212
+ raise NameError, "unknown constant #{token}"
212
213
  end
213
- elsif @constants.key?(token)
214
- types[i] = 'C'
215
- token = '@constants['+token.inspect+']'
216
214
  else
217
- raise NameError, "unknown constant #{token}"
218
- end
215
+ EXCEL_OPERATORS.include?(token) ? ops[token] : token
219
216
  end
220
- token = ops[token] if EXCEL_OPERATORS.include?(token)
221
- tokens[i] = token
222
217
  end
223
218
 
224
219
  tokens
@@ -242,33 +237,34 @@ end
242
237
  #
243
238
  # http://www.rubyforge.org/projects/littlelexer
244
239
  #
240
+ # CHANGE: types are returned as [Symbol*] vs String
241
+ #
245
242
  class LXL::LittleLexer #:nodoc: all
246
243
 
247
244
  class LexerJammed < Exception; end
248
245
 
249
- def initialize(regex_to_char,skip_white_space = true)
246
+ def initialize(regex_to_char,skip_white_space=true)
250
247
  @skip_white_space = skip_white_space
251
248
  @regex_to_char = regex_to_char
252
249
  end
253
250
 
254
251
  def scan(string,string_token_list=nil)
255
- result_string = ''
252
+ result_list = []
256
253
  token_list = []
257
-
258
254
  if string_token_list
259
255
  next_token(string) do |t,token, tail|
260
- result_string << t
256
+ result_list << t.chr.to_sym
261
257
  token_list << [string_token_list[0...tail], string[0...tail]]
262
258
  string = string[tail..-1]
263
259
  string_token_list = string_token_list[tail..-1]
264
260
  end
265
261
  else
266
262
  next_token(string) do |t,token, tail|
267
- result_string << t
263
+ result_list << t.chr.to_sym
268
264
  token_list << token
269
265
  end
270
266
  end
271
- return result_string, token_list
267
+ return result_list, token_list
272
268
  end
273
269
 
274
270
  private
@@ -317,4 +313,5 @@ if $0 == __FILE__
317
313
 
318
314
  # multiple formulas separated by semi-colon
319
315
  puts LXL.eval(formulas).inspect # => ["This is some text", "This is some \"quoted\" text", 6, true, true, [1, "two", 3.0], true, false, true, "yes"]
316
+
320
317
  end
metadata CHANGED
@@ -3,7 +3,7 @@ rubygems_version: 0.8.3
3
3
  specification_version: 1
4
4
  name: lxl
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.2.0
6
+ version: 0.2.2
7
7
  date: 2005-02-08
8
8
  summary: LXL (Like Excel) is a mini-language that mimics Microsoft Excel formulas. Easily extended with new constants and functions.
9
9
  require_paths: