lxl 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +9 -0
- data/VERSION +1 -1
- data/lib/lxl.rb +37 -27
- data/test/lxl_test.rb +2 -1
- metadata +2 -1
data/CHANGES
ADDED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.1
|
data/lib/lxl.rb
CHANGED
@@ -43,17 +43,19 @@
|
|
43
43
|
#
|
44
44
|
# * The number zero is interpereted as FALSE
|
45
45
|
# * Return multiple results in an array by separating formulas with a semi-colon (;)
|
46
|
+
# * A :SYMBOL token is recognized as a ruby symbol
|
46
47
|
#
|
47
48
|
# =Lexical Types
|
48
49
|
#
|
49
50
|
# w Whitespace (includes Commas)
|
50
51
|
# ; Semi-Colon (statement separator)
|
51
52
|
# o Operator
|
52
|
-
# i Integer
|
53
53
|
# f Float
|
54
|
+
# i Integer
|
55
|
+
# ' String (single quoted)
|
56
|
+
# " String (double quoted)
|
57
|
+
# s Symbol
|
54
58
|
# t Token
|
55
|
-
# s String (single quoted)
|
56
|
-
# S String (double quoted)
|
57
59
|
# ( Open (
|
58
60
|
# ) Close )
|
59
61
|
# C Constant
|
@@ -89,26 +91,25 @@ class LXL::Parser
|
|
89
91
|
def initialize
|
90
92
|
|
91
93
|
# Constants
|
92
|
-
@constants =
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
}
|
94
|
+
@constants = Hash.new
|
95
|
+
register_constant(:TRUE, true)
|
96
|
+
register_constant(:FALSE, false)
|
97
|
+
register_constant(:NULL, nil)
|
97
98
|
|
98
99
|
# Functions
|
99
100
|
@functions = Hash.new
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
101
|
+
register_function(:AND) { |a,b| to_b(a) && to_b(b) }
|
102
|
+
register_function(:OR) { |a,b| to_b(a) || to_b(b) }
|
103
|
+
register_function(:IF) { |v,a,b| to_b(v) ? a : b }
|
104
|
+
register_function(:LIST) { |*args| args }
|
105
|
+
register_function(:IN) { |n,h| h.respond_to?(:include?) ? h.include?(n) : false }
|
106
|
+
register_function(:TODAY) { Date.today.ajd.to_f }
|
107
|
+
register_function(:NOW) { DateTime.now.ajd.to_f }
|
108
|
+
register_function(:DATE) { |y,m,d| Date.new(y,m,d).ajd.to_f }
|
109
|
+
register_function(:DATETIME) { |value| DateTime.parse(value).ajd.to_f }
|
110
|
+
register_function(:TIME) { |h,m,s|
|
109
111
|
DateTime.valid_time?(h,m,s) ? DateTime.valid_time?(h,m,s).to_f : raise(ArgumentError, 'invalid time')
|
110
112
|
}
|
111
|
-
register(:DATETIME) { |value| DateTime.parse(value).ajd.to_f }
|
112
113
|
|
113
114
|
# Lexer
|
114
115
|
ops = EXCEL_OPERATORS.collect { |v| Regexp.quote(v) }.join('|')
|
@@ -119,8 +120,9 @@ class LXL::Parser
|
|
119
120
|
[/\A(#{ops})/,?o], # Operator
|
120
121
|
[/\A[0-9]+\.[0-9]+/,?f], # Float
|
121
122
|
[/\A[0-9]+/,?i], # Integer
|
122
|
-
[/\A("[^\"]*")/m,?
|
123
|
-
[/\A('[^\']*')/m,?
|
123
|
+
[/\A("[^\"]*")/m,?'], # String (single quoted)
|
124
|
+
[/\A('[^\']*')/m,?"], # String (double quoted)
|
125
|
+
[/\A:\w+/,?s], # Symbol
|
124
126
|
[/\A\w+/,?t], # Token
|
125
127
|
[/\A\(/,?(], # Open (
|
126
128
|
[/\A\)/,?)], # Close )
|
@@ -153,12 +155,20 @@ class LXL::Parser
|
|
153
155
|
|
154
156
|
protected
|
155
157
|
|
158
|
+
# Register a constant
|
159
|
+
#
|
160
|
+
# * Converts name to symbol
|
161
|
+
#
|
162
|
+
def register_constant(name, value)
|
163
|
+
@constants[name.to_sym] = value
|
164
|
+
end
|
165
|
+
|
156
166
|
# Register a function
|
157
167
|
#
|
158
168
|
# * Converts name to symbol
|
159
169
|
# * Wraps function with a debugging procedure
|
160
170
|
#
|
161
|
-
def
|
171
|
+
def register_function(name, &block)
|
162
172
|
@functions[name.to_sym] = debug(name.to_sym, &block)
|
163
173
|
end
|
164
174
|
|
@@ -166,13 +176,13 @@ class LXL::Parser
|
|
166
176
|
#
|
167
177
|
# * Raise an error unless given the correct number of arguments
|
168
178
|
#
|
169
|
-
def debug(name, &
|
179
|
+
def debug(name, &block)
|
170
180
|
raise ArgumentError, 'block not given to debug' unless block_given?
|
171
181
|
Proc.new { |*args|
|
172
|
-
if
|
173
|
-
raise ArgumentError, "wrong number of arguments (#{args.size} for #{
|
182
|
+
if block.arity >= 0 and block.arity != args.size
|
183
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for #{block.arity}) for #{name}"
|
174
184
|
end
|
175
|
-
|
185
|
+
block.call(*args)
|
176
186
|
}
|
177
187
|
end
|
178
188
|
|
@@ -185,12 +195,13 @@ class LXL::Parser
|
|
185
195
|
types, @tokens = @lexer.scan(formula)
|
186
196
|
@types = types.split(//)
|
187
197
|
raise SyntaxError, 'unbalanced parentheses' unless balanced?
|
188
|
-
|
198
|
+
|
189
199
|
# Parse tokens
|
190
200
|
@tokens.each_index do |i|
|
191
201
|
type, token = @types[i], @tokens[i]
|
192
202
|
token = token.to_i if type == 'i'
|
193
203
|
token = token.to_f if type == 'f'
|
204
|
+
token = token.to_sym if type == 's'
|
194
205
|
if type == 't'
|
195
206
|
token = token.to_sym
|
196
207
|
if @functions.key?(token)
|
@@ -300,7 +311,6 @@ if $0 == __FILE__
|
|
300
311
|
IF(1+1=2, "yes", "no");
|
301
312
|
}
|
302
313
|
|
303
|
-
# single formula
|
304
314
|
puts LXL.eval('5+5').inspect # => 10
|
305
315
|
|
306
316
|
# multiple formulas separated by semi-colon
|
data/test/lxl_test.rb
CHANGED
@@ -10,6 +10,7 @@ class LXLTest < Test::Unit::TestCase
|
|
10
10
|
|
11
11
|
def test_multiple_formula
|
12
12
|
formulas = %{
|
13
|
+
:SYMBOL;
|
13
14
|
((1+2)*(10-6))/2;
|
14
15
|
DATETIME("2004-11-22 11:11:00")=DATE(2004,11,22)+TIME(11,11,00);
|
15
16
|
IN(" is ", "this is a string");
|
@@ -19,7 +20,7 @@ class LXLTest < Test::Unit::TestCase
|
|
19
20
|
OR(TRUE, FALSE);
|
20
21
|
IF(1+1=2, "yes", "no");
|
21
22
|
}
|
22
|
-
expected = [6, true, true, [1, "two", 3.0], true, false, true, "yes"]
|
23
|
+
expected = [:SYMBOL, 6, true, true, [1, "two", 3.0], true, false, true, "yes"]
|
23
24
|
results = LXL.eval(formulas)
|
24
25
|
expected.each_index { |i| assert_equal(expected[i], results[i]) }
|
25
26
|
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.1.
|
6
|
+
version: 0.1.1
|
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:
|
@@ -29,6 +29,7 @@ authors:
|
|
29
29
|
files:
|
30
30
|
- lib
|
31
31
|
- test
|
32
|
+
- CHANGES
|
32
33
|
- README
|
33
34
|
- VERSION
|
34
35
|
- lib/lxl.rb
|