rubic 0.2.0 → 0.3.0
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.
- 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
|