fexpr 0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+