rubic 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,7 +21,7 @@ rule
21
21
  []
22
22
  }
23
23
  | IDENT
24
- | NUMBER
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 'strscan'
252
+ require 'rubic/lexer'
253
+ require 'rubic/util'
130
254
 
131
255
  module Rubic
132
256
 
133
257
  ---- inner
134
- EOT = [false, nil] # end of token
135
- SYM_CHARS = Regexp.escape("+-*/<>=?")
258
+ include Rubic::Util
136
259
 
137
260
  def parse(str)
138
- @s = StringScanner.new(str)
261
+ @lexer = Rubic::Lexer.new(str)
139
262
  do_parse
140
263
  end
141
264
 
265
+ private
266
+
142
267
  def next_token
143
- @s.skip(/\s+/)
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)
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Rubic
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
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.2.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-04-20 00:00:00.000000000 Z
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