clj 0.0.5.3 → 0.0.5.5

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.
Files changed (2) hide show
  1. data/lib/clj/parser.rb +61 -48
  2. metadata +6 -6
data/lib/clj/parser.rb CHANGED
@@ -15,6 +15,10 @@ class Clojure
15
15
  class Parser
16
16
  NUMBERS = '0' .. '9'
17
17
 
18
+ STRING_REGEX = %r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n
19
+ UNICODE_REGEX = /u([0-9|a-f|A-F]{4})/
20
+ OCTAL_REGEX = /o([0-3][0-7]?[0-7]?)/
21
+
18
22
  # Unescape characters in strings.
19
23
  UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
20
24
  UNESCAPE_MAP.update({
@@ -81,7 +85,7 @@ private
81
85
  def read_nil (ch)
82
86
  check = @source.read(2)
83
87
 
84
- if check.bytesize != 2
88
+ if check.length != 2
85
89
  raise SyntaxError, 'unexpected EOF'
86
90
  elsif check != 'il'
87
91
  raise SyntaxError, "expected nil, found n#{check}"
@@ -94,7 +98,7 @@ private
94
98
  if ch == 't'
95
99
  check = @source.read(3)
96
100
 
97
- if check.bytesize != 3
101
+ if check.length != 3
98
102
  raise SyntaxError, 'unexpected EOF'
99
103
  elsif check != 'rue'
100
104
  raise SyntaxError, "expected true, found t#{check}"
@@ -104,7 +108,7 @@ private
104
108
  else
105
109
  check = @source.read(4)
106
110
 
107
- if check.bytesize != 4
111
+ if check.length != 4
108
112
  raise SyntaxError, 'unexpected EOF'
109
113
  elsif check != 'alse'
110
114
  raise SyntaxError, "expected false, found f#{check}"
@@ -121,15 +125,15 @@ private
121
125
  piece << ch
122
126
  end
123
127
 
124
- revert(ch)
128
+ revert if ch
125
129
 
126
130
  if piece.include? '/'
127
131
  Rational(piece)
128
- elsif piece.include? 'r'
129
- base, number = piece.split('r', 2)
132
+ elsif piece.include? 'r' or piece.include? 'R'
133
+ base, number = piece.split(/r/i, 2)
130
134
 
131
135
  number.to_i(base.to_i)
132
- elsif piece.include? '.' or piece.include? 'e' or piece.end_with? 'M'
136
+ elsif piece.include? '.' or piece.include? 'e' or piece.include? 'E' or piece.end_with? 'M'
133
137
  if piece.end_with? 'M'
134
138
  piece[-1] = ''
135
139
 
@@ -147,13 +151,27 @@ private
147
151
  end
148
152
 
149
153
  def read_char (ch)
150
- ch = @source.read(1)
151
-
152
- unescape(if ch == 'u' && lookahead(1) =~ /[0-9a-fA-F]/
153
- "\\u#{@source.read(4)}"
154
+ if (ahead = lookahead(2)) && (!ahead[1] || both?(ahead[1]))
155
+ @source.read(1)
156
+ elsif (ahead = lookahead(8)) && ahead[0, 7] == 'newline' && (!ahead[7] || both?(ahead[7]))
157
+ @source.read(7) and "\n"
158
+ elsif (ahead = lookahead(6)) && ahead[0, 5] == 'space' && (!ahead[5] || both?(ahead[5]))
159
+ @source.read(5) and ' '
160
+ elsif (ahead = lookahead(4)) && ahead[0, 3] == 'tab' && (!ahead[3] || both?(ahead[3]))
161
+ @source.read(3) and "\t"
162
+ elsif (ahead = lookahead(10)) && ahead[0, 9] == 'backspace' && (!ahead[9] || both?(ahead[9]))
163
+ @source.read(9) and "\b"
164
+ elsif (ahead = lookahead(9)) && ahead[0, 8] == 'formfeed' && (!ahead[8] || both?(ahead[8]))
165
+ @source.read(8) and "\f"
166
+ elsif (ahead = lookahead(7)) && ahead[0, 6] == 'return' && (!ahead[6] || both?(ahead[6]))
167
+ @source.read(6) and "\r"
168
+ elsif (ahead = lookahead(6)) && ahead[0, 5] =~ UNICODE_REGEX && (!ahead[5] || both?(ahead[5]))
169
+ [@source.read(5)[1, 4].to_i(16)].pack('U')
170
+ elsif (ahead = lookahead(5)) && ahead[0, 4] =~ OCTAL_REGEX && (!ahead[4] || both?(ahead[4]))
171
+ @source.read(4)[1, 3].to_i(8).chr
154
172
  else
155
- ch
156
- end)
173
+ raise SyntaxError, 'unknown character type'
174
+ end
157
175
  end
158
176
 
159
177
  def read_keyword (ch)
@@ -163,7 +181,7 @@ private
163
181
  result << ch
164
182
  end
165
183
 
166
- revert(ch)
184
+ revert if ch
167
185
 
168
186
  result.to_sym
169
187
  end
@@ -181,7 +199,27 @@ private
181
199
  end
182
200
  end
183
201
 
184
- unescape(result)
202
+ result.gsub(STRING_REGEX) {|escape|
203
+ if u = UNESCAPE_MAP[$&[1]]
204
+ next u
205
+ end
206
+
207
+ bytes = EMPTY_8BIT_STRING.dup
208
+
209
+ i = 0
210
+ while escape[6 * i] == ?\\ && escape[6 * i + 1] == ?u
211
+ bytes << escape[6 * i + 2, 2].to_i(16) << escape[6 * i + 4, 2].to_i(16)
212
+
213
+ i += 1
214
+ end
215
+
216
+ if bytes.respond_to? :force_encoding
217
+ bytes.force_encoding 'UTF-16be'
218
+ bytes.encode 'UTF-8'
219
+ else
220
+ bytes
221
+ end
222
+ }
185
223
  end
186
224
 
187
225
  def read_instant (ch)
@@ -274,50 +312,25 @@ private
274
312
  end
275
313
 
276
314
  def unescape (string)
277
- string.gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) {|escape|
278
- if u = UNESCAPE_MAP[$&[1]]
279
- next u
280
- end
281
-
282
- bytes = EMPTY_8BIT_STRING.dup
283
-
284
- i = 0
285
- while escape[6 * i] == ?\\ && escape[6 * i + 1] == ?u
286
- bytes << escape[6 * i + 2, 2].to_i(16) << escape[6 * i + 4, 2].to_i(16)
287
-
288
- i += 1
289
- end
290
-
291
- if bytes.respond_to? :force_encoding
292
- bytes.force_encoding 'UTF-16be'
293
- bytes.encode 'UTF-8'
294
- else
295
- bytes
296
- end
297
- }
315
+ string
298
316
  end
299
317
 
300
- def lookahead (length = nil)
301
- original = @source.tell
302
- result = @source.read(length)
318
+ def lookahead (length)
319
+ result = @source.read(length)
303
320
 
304
- @source.seek(original)
321
+ @source.seek(-result.length, IO::SEEK_CUR)
305
322
 
306
323
  result
307
324
  end
308
325
 
309
- def ignore (ungetc = true)
326
+ def ignore (rev = true)
310
327
  while ignore?(ch = @source.read(1)); end
311
328
 
312
- return false unless ch
313
-
314
- ungetc ? revert(ch) : ch
329
+ rev ? revert : ch if ch
315
330
  end
316
331
 
317
- def revert (ch)
318
- return unless ch
319
-
320
- @source.seek -1, IO::SEEK_CUR
332
+ def revert (n = 1)
333
+ @source.seek -n, IO::SEEK_CUR
321
334
  end
322
335
 
323
336
  def ignore? (ch)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clj
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5.3
4
+ version: 0.0.5.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-14 00:00:00.000000000 Z
12
+ date: 2012-02-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &20645440 !ruby/object:Gem::Requirement
16
+ requirement: &13013480 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *20645440
24
+ version_requirements: *13013480
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &20644240 !ruby/object:Gem::Requirement
27
+ requirement: &13012980 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *20644240
35
+ version_requirements: *13012980
36
36
  description:
37
37
  email: meh@paranoici.org
38
38
  executables: []