rubic 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +4 -8
- data/bin/rubic +24 -6
- data/lib/rubic/builtin/number.rb +349 -37
- data/lib/rubic/environment.rb +10 -0
- data/lib/rubic/interpreter.rb +10 -1
- data/lib/rubic/lexer.rb +117 -0
- data/lib/rubic/parser.rb +1224 -212
- data/lib/rubic/parser.y +131 -41
- data/lib/rubic/util.rb +42 -0
- data/lib/rubic/version.rb +1 -1
- metadata +4 -2
data/lib/rubic/parser.y
CHANGED
@@ -21,7 +21,7 @@ rule
|
|
21
21
|
[]
|
22
22
|
}
|
23
23
|
| IDENT
|
24
|
-
|
|
24
|
+
| number
|
25
25
|
| STRING
|
26
26
|
| define
|
27
27
|
| cond
|
@@ -29,6 +29,8 @@ rule
|
|
29
29
|
| lambda
|
30
30
|
| let
|
31
31
|
| quote
|
32
|
+
| set
|
33
|
+
| begin
|
32
34
|
|
33
35
|
seq : expr
|
34
36
|
{
|
@@ -123,59 +125,147 @@ rule
|
|
123
125
|
{
|
124
126
|
[:quote, val[1]]
|
125
127
|
}
|
128
|
+
|
129
|
+
/* set expression */
|
130
|
+
set : '(' KW_SET_BANG IDENT expr ')'
|
131
|
+
{
|
132
|
+
[:set!, val[2], val[3]]
|
133
|
+
}
|
134
|
+
|
135
|
+
/* begin expression */
|
136
|
+
begin : '(' KW_BEGIN seq ')'
|
137
|
+
{
|
138
|
+
[:begin, *val[2]]
|
139
|
+
}
|
140
|
+
|
141
|
+
number : binary NUM_END { val[0] }
|
142
|
+
| octal NUM_END { val[0] }
|
143
|
+
| decimal NUM_END { val[0] }
|
144
|
+
| hexadecimal NUM_END { val[0] }
|
145
|
+
|
146
|
+
binary : b_prefix b_complex
|
147
|
+
{ val[0].nil? ? val[1] : (val[0] ? inexact_to_exact(val[1]) : exact_to_inexact(val[1])) }
|
148
|
+
b_complex : b_real
|
149
|
+
| b_real '@' b_real { normalize_number Complex.polar(val[0], val[2]) }
|
150
|
+
| b_real '+' b_ureal 'i' { normalize_number Complex(val[0], val[2]) }
|
151
|
+
| b_real '-' b_ureal 'i' { normalize_number Complex(val[0], -val[2]) }
|
152
|
+
| b_real '+' 'i' { Complex(val[0], 1) }
|
153
|
+
| b_real '-' 'i' { Complex(val[0], -1) }
|
154
|
+
| '+' b_ureal 'i' { normalize_number Complex(0, val[1]) }
|
155
|
+
| '-' b_ureal 'i' { normalize_number Complex(0, -val[1]) }
|
156
|
+
| '+' 'i' { Complex(0, 1) }
|
157
|
+
| '-' 'i' { Complex(0, -1) }
|
158
|
+
b_real : sign b_ureal { val[0] == '-' ? -val[1] : val[1] }
|
159
|
+
b_ureal : b_uint
|
160
|
+
| b_uint '/' b_uint { normalize_number Rational(val[0], val[2]) }
|
161
|
+
b_uint : b_chars { val[0].to_i(2) }
|
162
|
+
b_chars : b_char
|
163
|
+
| b_chars b_char { val[0] << val[1] }
|
164
|
+
b_char : '0' | '1'
|
165
|
+
b_prefix : NUM_PREFIX_B exactness { val[1] }
|
166
|
+
| exactness NUM_PREFIX_B { val[0] }
|
167
|
+
|
168
|
+
octal : o_prefix o_complex
|
169
|
+
{ val[0].nil? ? val[1] : (val[0] ? inexact_to_exact(val[1]) : exact_to_inexact(val[1])) }
|
170
|
+
o_complex : o_real
|
171
|
+
| o_real '@' o_real { normalize_number Complex.polar(val[0], val[2]) }
|
172
|
+
| o_real '+' o_ureal 'i' { normalize_number Complex(val[0], val[2]) }
|
173
|
+
| o_real '-' o_ureal 'i' { normalize_number Complex(val[0], -val[2]) }
|
174
|
+
| o_real '+' 'i' { Complex(val[0], 1) }
|
175
|
+
| o_real '-' 'i' { Complex(val[0], -1) }
|
176
|
+
| '+' o_ureal 'i' { normalize_number Complex(0, val[1]) }
|
177
|
+
| '-' o_ureal 'i' { normalize_number Complex(0, -val[1]) }
|
178
|
+
| '+' 'i' { Complex(0, 1) }
|
179
|
+
| '-' 'i' { Complex(0, -1) }
|
180
|
+
o_real : sign o_ureal { val[0] == '-' ? -val[1] : val[1] }
|
181
|
+
o_ureal : o_uint
|
182
|
+
| o_uint '/' o_uint { normalize_number Rational(val[0], val[2]) }
|
183
|
+
o_uint : o_chars { val[0].to_i(8) }
|
184
|
+
o_chars : o_char
|
185
|
+
| o_chars o_char { val[0] << val[1] }
|
186
|
+
o_char : '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7'
|
187
|
+
o_prefix : NUM_PREFIX_O exactness { val[1] }
|
188
|
+
| exactness NUM_PREFIX_O { val[0] }
|
189
|
+
|
190
|
+
decimal : d_prefix d_complex
|
191
|
+
{ val[0].nil? ? val[1] : (val[0] ? inexact_to_exact(val[1]) : exact_to_inexact(val[1])) }
|
192
|
+
d_complex : d_real
|
193
|
+
| d_real '@' d_real { normalize_number Complex.polar(val[0], val[2]) }
|
194
|
+
| d_real '+' d_ureal 'i' { normalize_number Complex(val[0], val[2]) }
|
195
|
+
| d_real '-' d_ureal 'i' { normalize_number Complex(val[0], -val[2]) }
|
196
|
+
| d_real '+' 'i' { Complex(val[0], 1) }
|
197
|
+
| d_real '-' 'i' { Complex(val[0], -1) }
|
198
|
+
| '+' d_ureal 'i' { normalize_number Complex(0, val[1]) }
|
199
|
+
| '-' d_ureal 'i' { normalize_number Complex(0, -val[1]) }
|
200
|
+
| '+' 'i' { Complex(0, 1) }
|
201
|
+
| '-' 'i' { Complex(0, -1) }
|
202
|
+
d_real : sign d_ureal { val[0] == '-' ? -val[1] : val[1] }
|
203
|
+
d_ureal : d_uint
|
204
|
+
| d_uint '/' d_uint { normalize_number Rational(val[0], val[2]) }
|
205
|
+
| d_decimal
|
206
|
+
d_decimal : d_uint suffix { val[0].to_f * (10 ** val[1]) }
|
207
|
+
| '.' d_chars suffix { "0.#{val[1]}".to_f * (10 ** val[2]) }
|
208
|
+
| d_chars '.' d_chars suffix
|
209
|
+
{ "#{val[0]}.#{val[2]}".to_f * (10 ** val[3]) }
|
210
|
+
| d_chars '.' suffix { val[0].to_f * (10 ** val[2]) }
|
211
|
+
d_uint : d_chars { val[0].to_i(10) }
|
212
|
+
d_chars : d_char
|
213
|
+
| d_chars d_char { val[0] << val[1] }
|
214
|
+
d_char : '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
|
215
|
+
d_prefix : NUM_PREFIX_D exactness { val[1] }
|
216
|
+
| exactness NUM_PREFIX_D { val[0] }
|
217
|
+
| exactness
|
218
|
+
|
219
|
+
hexadecimal : h_prefix h_complex
|
220
|
+
{ val[0].nil? ? val[1] : (val[0] ? to_exact(val[1]) : exact_to_inexact(val[1])) }
|
221
|
+
h_complex : h_real
|
222
|
+
| h_real '@' h_real { normalize_number Complex.polar(val[0], val[2]) }
|
223
|
+
| h_real '+' h_ureal 'i' { normalize_number Complex(val[0], val[2]) }
|
224
|
+
| h_real '-' h_ureal 'i' { normalize_number Complex(val[0], -val[2]) }
|
225
|
+
| h_real '+' 'i' { Complex(val[0], 1) }
|
226
|
+
| h_real '-' 'i' { Complex(val[0], -1) }
|
227
|
+
| '+' h_ureal 'i' { normalize_number Complex(0, val[1]) }
|
228
|
+
| '-' h_ureal 'i' { normalize_number Complex(0, -val[1]) }
|
229
|
+
| '+' 'i' { Complex(0, 1) }
|
230
|
+
| '-' 'i' { Complex(0, -1) }
|
231
|
+
h_real : sign h_ureal { val[0] == '-' ? -val[1] : val[1] }
|
232
|
+
h_ureal : h_uint
|
233
|
+
| h_uint '/' h_uint { normalize_number Rational(val[0], val[2]) }
|
234
|
+
h_uint : h_chars { val[0].to_i(16) }
|
235
|
+
h_chars : h_char
|
236
|
+
| h_chars h_char { val[0] << val[1] }
|
237
|
+
h_char : '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
|
238
|
+
| 'a' | 'b' | 'c' | 'd' | 'e' | 'f'
|
239
|
+
h_prefix : NUM_PREFIX_X exactness { val[1] }
|
240
|
+
| exactness NUM_PREFIX_X { val[0] }
|
241
|
+
|
242
|
+
suffix : /* empty */
|
243
|
+
{ 0 }
|
244
|
+
| exponent_marker sign d_chars
|
245
|
+
{ val[1] == '-' ? -val[2].to_i : val[2].to_i }
|
246
|
+
exponent_marker : 'e'
|
247
|
+
sign : /* empty */ | U_PLUS | U_MINUS
|
248
|
+
exactness : /* empty */ | NUM_PREFIX_E | NUM_PREFIX_I
|
126
249
|
end
|
127
250
|
|
128
251
|
---- header
|
129
|
-
require '
|
252
|
+
require 'rubic/lexer'
|
253
|
+
require 'rubic/util'
|
130
254
|
|
131
255
|
module Rubic
|
132
256
|
|
133
257
|
---- inner
|
134
|
-
|
135
|
-
SYM_CHARS = Regexp.escape("+-*/<>=?")
|
258
|
+
include Rubic::Util
|
136
259
|
|
137
260
|
def parse(str)
|
138
|
-
@
|
261
|
+
@lexer = Rubic::Lexer.new(str)
|
139
262
|
do_parse
|
140
263
|
end
|
141
264
|
|
265
|
+
private
|
266
|
+
|
142
267
|
def next_token
|
143
|
-
@
|
144
|
-
return EOT if @s.eos?
|
145
|
-
|
146
|
-
case
|
147
|
-
when @s.scan(/[0-9]+(\.[0-9]+)?/)
|
148
|
-
[:NUMBER, @s[0].include?('.') ? @s[0].to_f : @s[0].to_i]
|
149
|
-
when @s.scan(/[()']/)
|
150
|
-
[@s[0], nil]
|
151
|
-
when @s.scan(/[A-Za-z_#{SYM_CHARS}][A-Za-z0-9_#{SYM_CHARS}]*/o)
|
152
|
-
case @s[0] # keyword check
|
153
|
-
when 'define'
|
154
|
-
[:KW_DEFINE, nil]
|
155
|
-
when 'cond'
|
156
|
-
[:KW_COND, nil]
|
157
|
-
when 'else'
|
158
|
-
[:KW_ELSE, nil]
|
159
|
-
when 'if'
|
160
|
-
[:KW_IF, nil]
|
161
|
-
when 'and'
|
162
|
-
[:KW_AND, nil]
|
163
|
-
when 'or'
|
164
|
-
[:KW_OR, nil]
|
165
|
-
when 'lambda'
|
166
|
-
[:KW_LAMBDA, nil]
|
167
|
-
when 'let'
|
168
|
-
[:KW_LET, nil]
|
169
|
-
when 'quote'
|
170
|
-
[:KW_QUOTE, nil]
|
171
|
-
else
|
172
|
-
[:IDENT, @s[0].to_sym]
|
173
|
-
end
|
174
|
-
when @s.scan(/"([^"]*)"/)
|
175
|
-
[:STRING, @s[1]]
|
176
|
-
else
|
177
|
-
raise Rubic::ParseError, "unknown character #{@s.getch}"
|
178
|
-
end
|
268
|
+
@lexer.next_token
|
179
269
|
end
|
180
270
|
|
181
271
|
def on_error(t, val, vstack)
|
data/lib/rubic/util.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module Rubic
|
2
|
+
module Util
|
3
|
+
def inexact_to_exact(num)
|
4
|
+
case num
|
5
|
+
when Complex
|
6
|
+
r = inexact_to_exact(num.real)
|
7
|
+
i = inexact_to_exact(num.imag)
|
8
|
+
normalize_number Complex(r, i)
|
9
|
+
when Float
|
10
|
+
normalize_number num.rationalize
|
11
|
+
when Rational, Integer
|
12
|
+
num
|
13
|
+
else
|
14
|
+
raise TypeError, "unexpected type of number: #{num.class}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def exact_to_inexact(num)
|
19
|
+
case num
|
20
|
+
when Complex
|
21
|
+
r = exact_to_inexact(num.real)
|
22
|
+
i = exact_to_inexact(num.imag)
|
23
|
+
normalize_number Complex(r, i)
|
24
|
+
when Float, Rational, Integer
|
25
|
+
num.to_f
|
26
|
+
else
|
27
|
+
raise TypeError, "unexpected type of number: #{num.class}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def normalize_number(num)
|
32
|
+
case num
|
33
|
+
when Complex
|
34
|
+
num.imag.zero? ? num.real : num
|
35
|
+
when Rational
|
36
|
+
num.denominator == 1 ? num.numerator : num
|
37
|
+
else
|
38
|
+
num
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/rubic/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- notozeki
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-06-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -119,8 +119,10 @@ files:
|
|
119
119
|
- lib/rubic/environment.rb
|
120
120
|
- lib/rubic/inspector.rb
|
121
121
|
- lib/rubic/interpreter.rb
|
122
|
+
- lib/rubic/lexer.rb
|
122
123
|
- lib/rubic/parser.rb
|
123
124
|
- lib/rubic/parser.y
|
125
|
+
- lib/rubic/util.rb
|
124
126
|
- lib/rubic/version.rb
|
125
127
|
- rubic.gemspec
|
126
128
|
homepage: https://github.com/notozeki/rubic
|