clj 0.0.5.3 → 0.0.5.5

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