fexpr 0.1

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.
data/LICENSE ADDED
@@ -0,0 +1 @@
1
+ Apache
data/README.md ADDED
@@ -0,0 +1 @@
1
+ Floting point version of expr
data/lib/fexpr.rb ADDED
@@ -0,0 +1,8 @@
1
+ $:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
2
+
3
+ # stdlib
4
+ require 'logger'
5
+
6
+ # internal requires
7
+ require 'fexpr/base'
8
+ require 'fexpr/main'
data/lib/fexpr/base.rb ADDED
@@ -0,0 +1,247 @@
1
+ module FExpr
2
+
3
+ class Evaluator
4
+
5
+ def initialize(argv)
6
+ @argv = argv
7
+ @node_stack = []
8
+ @opt_trace = false
9
+ end
10
+
11
+ # Void -> String
12
+ def eval
13
+ @toks = Array.new @argv
14
+ @tok = nil
15
+ next_token
16
+ expr
17
+ evaluate.to_s
18
+ end
19
+
20
+ private
21
+
22
+ # Classes
23
+
24
+ class Node
25
+ def to_s
26
+ to_string 0
27
+ end
28
+ def to_string(depth)
29
+ raise 'Implement to_string, stupid!'
30
+ end
31
+ def eval
32
+ raise 'Implement eval, stupid!'
33
+ end
34
+ def x(n)
35
+ Array.new(n) { |x| '.' }.join(' ') + ' '
36
+ end
37
+ end
38
+
39
+ class OpNode < Node
40
+ attr_reader :op , :a, :b
41
+ def initialize(op,a,b)
42
+ @op = op
43
+ @a = a
44
+ @b = b
45
+ end
46
+ def eval
47
+ a = @a.eval
48
+ b = @b.eval
49
+ case @op
50
+ when '|' then a and a != 0 ? a : b
51
+ when '&' then (a and a!=0 and b and b!=0) ? a : 0
52
+ when '=' then a == b
53
+ when '>' then a > b
54
+ when '>=' then a >= b
55
+ when '<' then a < b
56
+ when '<=' then a <= b
57
+ when '!=' then a != b
58
+ when '+' then a + b
59
+ when '-' then a - b
60
+ when '*' then a * b
61
+ when 'x' then a * b
62
+ when '/' then a / b
63
+ when '%' then a.to_i % b.to_i
64
+ else error 'Invalid operator \'' + @op + '\''
65
+ end
66
+ end
67
+ def to_string(n)
68
+ str = x(n) + @op + "\n"
69
+ str += a.to_string(n+1) + "\n"
70
+ str += b.to_string(n+1)
71
+ return str
72
+ end
73
+ end
74
+
75
+ class NumNode < Node
76
+ attr_reader :val
77
+ def initialize(val)
78
+ @val = val
79
+ end
80
+ def eval
81
+ @val
82
+ end
83
+ def to_string(n)
84
+ x(n) + @val.to_s
85
+ end
86
+ end
87
+
88
+ # Misc
89
+
90
+ def trace(s)
91
+ STDERR.puts s if @opt_trace
92
+ end
93
+
94
+ def shift(t)
95
+ shift_one_of [t]
96
+ end
97
+
98
+ def shift_one_of(ts)
99
+ found = false
100
+ ts.each do |t|
101
+ if @tok == t
102
+ next_token
103
+ return t
104
+ end
105
+ end
106
+ return nil
107
+ end
108
+
109
+ def next_token
110
+ if not @toks.empty?
111
+ @tok = @toks.shift.gsub /[,_\$]/,''
112
+ end
113
+ @tok
114
+ end
115
+
116
+ def error(msg)
117
+ STDERR.puts msg
118
+ STDERR.flush
119
+ exit 1
120
+ end
121
+
122
+ def push(n)
123
+ @node_stack << NumNode.new(n)
124
+ end
125
+
126
+ def push_binop(op)
127
+ b = pop
128
+ a = pop
129
+ @node_stack << OpNode.new(op,a,b)
130
+ end
131
+
132
+ def pop
133
+ @node_stack.pop
134
+ end
135
+
136
+ # Void -> String
137
+ def evaluate
138
+ trace @node_stack
139
+ pop.eval
140
+ end
141
+
142
+ # Parsing
143
+
144
+ # -------------------------------------------------------------------------------------------
145
+ # Grammar:
146
+ #
147
+ # expr ::= or_expr
148
+ # or_expr ::= or_expr '|' and_expr
149
+ # and_expr ::= and_expr '&' rel_expr
150
+ # rel_expr ::= rel_expr ( '=' | '>' | '>=' | '<' | '<=' | '!=' )add_expr
151
+ # add_expr ::= add_expr ( '+' | '_' ) mul_expr
152
+ # mul_expr ::= mul_expr ( 'x' | '*' | '/' | '%' ) sim_expr
153
+ # sim_expr ::= <number>
154
+ #
155
+ # The Re-factored Grammar:
156
+ # -----------
157
+ #
158
+ # expr ::= or_expr
159
+ # or_expr ::= and_expr or_expr_tail
160
+ # or_expr_tail ::= '|' and_expr or_expr_tail
161
+ # and_expr ::= rel_expr and_expr_tail
162
+ # and_expr_tail ::= '&' rel_expr and_expr_tail
163
+ # rel_expr ::= add_expr rel_expr_tail
164
+ # rel_expr_tail ::= ( '=' | '>' | '>=' | '<' | '<=' | '!=' ) add_expr rel_expr_tail
165
+ # add_expr ::= mul_expr and_expr_tail
166
+ # add_expr_tail ::= ( '+' | '-' ) mul_expr add_expr_tail
167
+ # mul_expr ::= sim_expr mul_expr_tail
168
+ # mul_expr_tail ::= ( 'x' | '*' | '/' | '%' ) sim_expr mul_expr_tail
169
+ # sim_expr ::= <number>
170
+ # -------------------------------------------------------------------------------------------
171
+
172
+ def expr
173
+ or_expr
174
+ end
175
+
176
+ def or_expr
177
+ and_expr
178
+ or_expr_tail
179
+ end
180
+
181
+ def or_expr_tail
182
+ op = shift '|'
183
+ return if not op
184
+ and_expr
185
+ or_expr_tail
186
+ push_binop op
187
+ end
188
+
189
+ def and_expr
190
+ rel_expr
191
+ and_expr_tail
192
+ end
193
+
194
+ def and_expr_tail
195
+ op = shift '&'
196
+ return if not op
197
+ rel_expr
198
+ and_expr_tail
199
+ push_binop op
200
+ end
201
+
202
+ def rel_expr
203
+ add_expr
204
+ rel_expr_tail
205
+ end
206
+
207
+ def rel_expr_tail
208
+ op = shift_one_of ['=','>','>=','<','<=','!=']
209
+ return if not op
210
+ add_expr
211
+ rel_expr_tail
212
+ push_binop op
213
+ end
214
+
215
+ def add_expr
216
+ mul_expr
217
+ add_expr_tail
218
+ end
219
+
220
+ def add_expr_tail
221
+ op = shift_one_of ['+','-']
222
+ return if not op
223
+ mul_expr
224
+ add_expr_tail
225
+ push_binop op
226
+ end
227
+
228
+ def mul_expr
229
+ sim_expr
230
+ mul_expr_tail
231
+ end
232
+
233
+ def mul_expr_tail
234
+ op = shift_one_of ['x','*','/','%']
235
+ return if not op
236
+ sim_expr
237
+ mul_expr_tail
238
+ push_binop op
239
+ end
240
+
241
+ def sim_expr
242
+ n = @tok.to_f
243
+ push n
244
+ next_token
245
+ end
246
+ end
247
+ end
data/lib/fexpr/main.rb ADDED
@@ -0,0 +1,42 @@
1
+ module FExpr
2
+
3
+ class Main
4
+
5
+ def main(argv)
6
+ puts real_main argv
7
+ end
8
+
9
+ # Void -> Float
10
+ def real_main(argv)
11
+
12
+ # maybe help
13
+ print_help and return 0 if argv.empty?
14
+
15
+ # maybe testing
16
+ run_test and return if argv[0] == '-test'
17
+ if argv[0][0..0] == '-'
18
+ @opt_trace = true
19
+ argv.shift
20
+ end
21
+
22
+ # cleanse the arguments
23
+ args = argv.map {|arg| arg.gsub /,/,''}
24
+
25
+ # run
26
+ evaluator = Evaluator.new args
27
+ evaluator.eval
28
+ end
29
+
30
+ private
31
+
32
+ def print_help
33
+ puts '***************************************************'
34
+ puts 'Replace integer (or int) with floating point number'
35
+ puts 'And forget about the \':\' operator'
36
+ puts '***************************************************'
37
+ sleep 2
38
+ system 'man', 'expr'
39
+ true
40
+ end
41
+ end
42
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fexpr
3
+ version: !ruby/object:Gem::Version
4
+ hash: 9
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ version: "0.1"
10
+ platform: ruby
11
+ authors:
12
+ - Jeffrey Palm
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2013-04-02 00:00:00 Z
18
+ dependencies: []
19
+
20
+ description: Floating point fexpr
21
+ email: jeff@jeffpalm.com
22
+ executables: []
23
+
24
+ extensions: []
25
+
26
+ extra_rdoc_files: []
27
+
28
+ files:
29
+ - README.md
30
+ - LICENSE
31
+ - lib/fexpr.rb
32
+ - lib/fexpr/base.rb
33
+ - lib/fexpr/main.rb
34
+ homepage: http://github.com/spudtrooper/fexpr
35
+ licenses: []
36
+
37
+ post_install_message:
38
+ rdoc_options:
39
+ - --charset=UTF-8
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ hash: 3
48
+ segments:
49
+ - 0
50
+ version: "0"
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ requirements: []
61
+
62
+ rubyforge_project: fexpr
63
+ rubygems_version: 1.8.24
64
+ signing_key:
65
+ specification_version: 2
66
+ summary: Fexpr
67
+ test_files: []
68
+