sdl4r 0.9.6 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/CHANGELOG +49 -2
  2. data/Rakefile +35 -5
  3. data/TODO +29 -3
  4. data/doc/classes/SDL4R.html +386 -674
  5. data/doc/classes/SDL4R/Parser.html +183 -307
  6. data/doc/classes/SDL4R/ParserTest.html +357 -0
  7. data/doc/classes/SDL4R/SDL4RTest.html +532 -0
  8. data/doc/classes/SDL4R/SDLTest.html +77 -0
  9. data/doc/classes/SDL4R/SdlBinary.html +180 -295
  10. data/doc/classes/SDL4R/SdlParseError.html +105 -180
  11. data/doc/classes/SDL4R/SdlTimeSpan.html +628 -939
  12. data/doc/classes/SDL4R/Tag.html +1236 -2036
  13. data/doc/classes/SDL4R/TagTest.html +292 -0
  14. data/doc/created.rid +1 -1
  15. data/doc/files/CHANGELOG.html +183 -184
  16. data/doc/files/LICENSE.html +496 -755
  17. data/doc/files/README.html +399 -623
  18. data/doc/files/lib/sdl4r/parser/reader_rb.html +53 -106
  19. data/doc/files/lib/sdl4r/parser/time_span_with_zone_rb.html +53 -106
  20. data/doc/files/lib/sdl4r/parser/token_rb.html +53 -106
  21. data/doc/files/lib/sdl4r/parser/tokenizer_rb.html +53 -106
  22. data/doc/files/lib/sdl4r/parser_rb.html +60 -112
  23. data/doc/files/lib/sdl4r/sdl4r_rb.html +62 -114
  24. data/doc/files/lib/sdl4r/sdl_binary_rb.html +53 -106
  25. data/doc/files/lib/sdl4r/sdl_parse_error_rb.html +53 -106
  26. data/doc/files/lib/sdl4r/sdl_time_span_rb.html +53 -106
  27. data/doc/files/lib/sdl4r/tag_rb.html +62 -114
  28. data/doc/files/lib/sdl4r_rb.html +53 -106
  29. data/doc/files/test/sdl4r/parser_test_rb.html +63 -0
  30. data/doc/files/test/sdl4r/sdl4r_test_rb.html +66 -0
  31. data/doc/files/test/sdl4r/sdl_test_rb.html +63 -0
  32. data/doc/files/test/sdl4r/tag_test_rb.html +63 -0
  33. data/doc/fr_class_index.html +19 -32
  34. data/doc/fr_file_index.html +37 -40
  35. data/doc/fr_method_index.html +4707 -114
  36. data/doc/index.html +14 -23
  37. data/doc/rdoc-style.css +323 -203
  38. data/lib/sdl4r/parser/reader.rb +26 -19
  39. data/lib/sdl4r/parser/token.rb +3 -3
  40. data/lib/sdl4r/parser/tokenizer.rb +93 -98
  41. data/lib/sdl4r/sdl_parse_error.rb +2 -2
  42. data/lib/sdl4r/tag.rb +127 -73
  43. data/test/sdl4r/parser_test.rb +109 -11
  44. data/test/sdl4r/tag_test.rb +73 -4
  45. metadata +15 -12
@@ -29,16 +29,24 @@ module SDL4R
29
29
 
30
30
  # +io+ an open IO from which the characters are read.
31
31
  def initialize(io)
32
- raise ArgumentError, "io == nil" if io.nil?
32
+ raise ArgumentError, "io == nil" unless io
33
33
 
34
34
  @io = io
35
35
  @line = nil
36
36
  @line_chars = nil
37
- @line_no = 0
37
+ @line_no = -1
38
38
  @pos = 0
39
39
  end
40
40
 
41
- attr_reader :line_no, :pos, :line;
41
+ # The current line no (zero-based)
42
+ attr_reader :line_no
43
+
44
+ # The position of the char currently pointed by this reader in the current line.
45
+ # This is not necessarily the position of the char you just got from a method, it might be
46
+ # the position of the next char, for instance.
47
+ attr_reader :pos
48
+
49
+ attr_reader :line
42
50
 
43
51
  def line_length
44
52
  return @line_chars.nil? ? 0 : @line_chars.length
@@ -65,22 +73,22 @@ module SDL4R
65
73
  end
66
74
 
67
75
  # Indicates whether the end of file has been reached.
68
- def end_of_file?
76
+ def eof?
69
77
  return @line.nil?
70
78
  end
71
79
 
72
- # Indicates whether there are more characters in the current line
80
+ # Indicates whether there are more characters in the current line after the current char
73
81
  def more_chars_in_line?
74
82
  return @pos < line_length - 1
75
83
  end
76
84
 
77
85
  # Returns whether the end of the current +line+ as been reached.
78
- def end_of_line?
86
+ def eol?
79
87
  return @pos >= line_length
80
88
  end
81
89
 
82
90
  # Skips the current line by going just after its end.
83
- def skip_line
91
+ def skip_to_eol
84
92
  @pos = line_length
85
93
  end
86
94
 
@@ -107,24 +115,27 @@ module SDL4R
107
115
  return get_line_char(@pos)
108
116
  end
109
117
 
110
- # Go to the next character in the stream.
118
+ # Go to the next character in the line. This method doesn't skip to the next line once the
119
+ # reached eol.
111
120
  def skip_char
112
121
  @pos += 1 if @pos < line_length
113
122
  end
114
123
 
115
- # Go to the next character and returns it (or nil if end-of-line or -file has been reached).
124
+ # Returns the current char and go to the next.
125
+ # Returns nil if end-of-line or -file has been reached.
116
126
  def read_char
127
+ c = current_char
117
128
  skip_char()
118
- return current_char
129
+ c
119
130
  end
120
131
 
121
132
  # Returns to the previous char if possible.
122
133
  def previous_char
123
- @pos -= 1 if @pos >= -1
134
+ @pos -= 1 if @pos >= 1
124
135
  end
125
136
 
126
- # Returns the next index of the expression (string, regexp, fixnum) in the current line, starting
127
- # from after the current position if no position is specified.
137
+ # Returns the next index of the expression (string, regexp, fixnum) in the current line,
138
+ # starting from after the current position if no position is specified.
128
139
  def find_next_in_line(searched, start_pos = nil)
129
140
  start_pos = @pos + 1 unless start_pos
130
141
  return @line.index(searched, start_pos)
@@ -149,12 +160,8 @@ module SDL4R
149
160
  def read_raw_line
150
161
  @line = @io.gets()
151
162
 
152
- # We ensure that only \n is used as an end-of-line by replacing \r and \r\n.
153
- if @line
154
- if not @line.gsub!(/\r\n/m, "\n")
155
- @line.gsub!(/\r/m, "\n")
156
- end
157
- end
163
+ # Remove a possible \r at the end of line
164
+ @line.gsub!(/\r+$/, "") if @line
158
165
 
159
166
  @pos = 0;
160
167
  @line_chars = nil
@@ -33,7 +33,7 @@ module SDL4R
33
33
  def initialize(text, line = -1, position = -1)
34
34
  @text = text
35
35
  @line = line
36
- @pos = position
36
+ @position = position
37
37
  @size = text.length
38
38
 
39
39
  begin
@@ -92,7 +92,7 @@ module SDL4R
92
92
  end
93
93
 
94
94
  rescue ArgumentError
95
- raise SdlParseError.new($!.message, @line, @pos)
95
+ raise SdlParseError.new($!.message, @line, @position)
96
96
  end
97
97
 
98
98
  @type = :IDENTIFIER if @type.nil? # if all hope is lost, it's an identifier
@@ -116,7 +116,7 @@ module SDL4R
116
116
  end
117
117
 
118
118
  def to_s
119
- @type.to_s + " " + @text + " pos:" + @pos.to_s
119
+ @type.to_s + " " + @text + " pos:" + @position.to_s
120
120
  end
121
121
 
122
122
  # This special parse method is used only by the Token class for
@@ -45,9 +45,9 @@ module SDL4R
45
45
 
46
46
  @reader = Parser::Reader.new(io)
47
47
  @token_start = 0
48
- @startEscapedQuoteLine = false
48
+ @starting_escaped_quote_line = false
49
49
  @tokens = nil
50
- @tokenText = nil
50
+ @token_text = nil
51
51
  end
52
52
 
53
53
  # Closes this Tokenizer and its underlying +Reader+.
@@ -55,19 +55,12 @@ module SDL4R
55
55
  @reader.close
56
56
  end
57
57
 
58
- # Close the reader and throw a SdlParseError.
58
+ # Raises a SdlParseError.
59
59
  def parse_error(description, line_no = nil, position = nil)
60
- begin
61
- @reader.close()
62
- rescue IOError
63
- # no recourse
64
- end
60
+ line_no = @reader.line_no unless line_no
61
+ position = @reader.pos - 1 unless position # @reader.pos points to the *next* position
65
62
 
66
- line_no = @reader.line_no if line_no.nil?
67
- position = @reader.pos if position.nil?
68
-
69
- # We add one because editors typically start with line 1 and position 1
70
- # rather than 0...
63
+ # We add one because editors typically start with line 1 rather than 0...
71
64
  raise SdlParseError.new(description, line_no + 1, position + 1, @reader.line)
72
65
  end
73
66
 
@@ -111,26 +104,31 @@ module SDL4R
111
104
  #
112
105
  # Returns a logical line as a list of Tokens.
113
106
  # Returns an empty array if the line was empty.
107
+ # Returns +nil+ if the end of the stream has been reached.
114
108
  #
115
109
  def read_line_tokens_even_if_empty
110
+ # Reset of the token-related fields
116
111
  @tokens = nil
117
- @tokenText = nil
112
+ @token_text = nil
118
113
  @token_start = nil
119
114
 
120
- @reader.read_line() if @reader.end_of_line?
121
- return @tokens unless @reader.line
115
+ if @reader.eol? and not @reader.read_line()
116
+ return nil
117
+ end
122
118
 
123
119
  @tokens = []
124
120
  @token_start = @reader.pos
125
121
 
126
- while not @reader.end_of_line?
127
- if @tokenText
128
- @tokens << Token.new(@tokenText, @reader.line_no, @token_start)
129
- @tokenText = nil
122
+ until @reader.eol?
123
+ if @token_text
124
+ @tokens << Token.new(@token_text, @reader.line_no, @token_start)
125
+ @token_text = nil
126
+ @token_start = @reader.pos
130
127
  end
131
128
 
132
129
  c = @reader.current_char
133
130
  next_c = @reader.get_line_char(@reader.pos + 1)
131
+
134
132
  case c
135
133
  when "\""
136
134
  # handle "" style strings including line continuations
@@ -142,7 +140,7 @@ module SDL4R
142
140
  when "{", "}", "=", ":", ";"
143
141
  # handle punctuation
144
142
  punctuation_token = Token.new(c, @reader.line_no, @reader.pos)
145
- @tokenText = nil
143
+ @token_text = nil
146
144
 
147
145
  if punctuation_token.type == :SEMICOLON
148
146
  @reader.skip_char()
@@ -153,13 +151,13 @@ module SDL4R
153
151
 
154
152
  when "#"
155
153
  # skip : hash comment at end of line
156
- @reader.skip_line()
154
+ @reader.skip_to_eol()
157
155
 
158
156
  when "/"
159
157
  # handle // and /**/ style comments
160
158
  if next_c == "/"
161
159
  # skip : // comment
162
- @reader.skip_line()
160
+ @reader.skip_to_eol()
163
161
  else
164
162
  handle_slash_comment()
165
163
  end
@@ -177,12 +175,13 @@ module SDL4R
177
175
 
178
176
  when "\\"
179
177
  # line continuations (outside a string literal)
180
- handle_line_continuation();
178
+ handle_line_continuation()
179
+ next # otherwise 1st char of the continuation line is skipped by skip_char()
181
180
 
182
181
  when /^[0-9\-\.]$/
183
182
  if c == "-" and next_c == "-"
184
183
  # -- comments : ignore
185
- @reader.skip_line()
184
+ @reader.skip_to_eol()
186
185
  else
187
186
  # handle numbers, dates, and time spans
188
187
  handle_number_date_or_time_span()
@@ -194,9 +193,8 @@ module SDL4R
194
193
  # So, we implement a subset of these characters.
195
194
  handle_identifier()
196
195
 
197
- when "\n", "\r"
198
- # end of line
199
- @reader.skip_line()
196
+ when "\n", "\r" # end of line
197
+ @reader.skip_to_eol()
200
198
 
201
199
  else
202
200
  parse_error("Unexpected character '#{c}'")
@@ -205,45 +203,44 @@ module SDL4R
205
203
  @reader.skip_char()
206
204
  end
207
205
 
208
- if @tokenText
209
- @tokens << Token.new(@tokenText, @reader.line_no, @token_start)
206
+ if @token_text
207
+ @tokens << Token.new(@token_text, @reader.line_no, @token_start)
210
208
  end
211
209
 
212
210
  return @tokens
213
211
  end
214
212
 
215
- # Adds the current escaped character (represented by ((|c|))) to @tokenText.
213
+ # Adds the current escaped character (represented by ((|c|))) to @token_text.
216
214
  # This method assumes the previous char was a backslash.
217
215
  #
218
216
  def add_escaped_char_in_string(c)
219
217
  case c
220
218
  when "\\", "\""
221
- @tokenText << c
219
+ @token_text << c
222
220
  when "n"
223
- @tokenText << ?\n
221
+ @token_text << ?\n
224
222
  when "r"
225
- @tokenText << ?\r
223
+ @token_text << ?\r
226
224
  when "t"
227
- @tokenText << ?\t
225
+ @token_text << ?\t
228
226
  else
229
- parse_error("Illegal escape character in string literal: '#{c.chr}'.")
227
+ parse_error("Illegal escape character in string literal: '#{c}'.")
230
228
  end
231
229
  end
232
230
 
233
231
  def handle_double_quote_string
234
232
  escaped = false
235
- @startEscapedQuoteLine = false
233
+ @starting_escaped_quote_line = false
236
234
 
237
- @tokenText = "\""
238
- @reader.skip_char()
235
+ @token_text = @reader.read_char()
239
236
 
240
- while not @reader.end_of_line?
237
+ until @reader.eol?
241
238
  c = @reader.current_char
242
239
 
243
- if "\s\t".include?(c) and @startEscapedQuoteLine
244
- # we continue
240
+ if "\s\t".include?(c) and @starting_escaped_quote_line
241
+ # skip the heading spaces (indentation) of a continued line
245
242
  else
246
- @startEscapedQuoteLine = false;
243
+ @starting_escaped_quote_line = false
247
244
 
248
245
  if escaped
249
246
  add_escaped_char_in_string(c)
@@ -255,15 +252,15 @@ module SDL4R
255
252
  handle_escaped_double_quoted_string()
256
253
  next # as we are at the beginning of a new line
257
254
  else
258
- escaped = true;
255
+ escaped = true
259
256
  end
260
257
 
261
258
  else
262
- @tokenText << c
263
- if c == "\""
259
+ @token_text << c
260
+ if c == '"'
264
261
  # end of double-quoted string detected
265
- @tokens << Token.new(@tokenText, @reader.line_no, @token_start)
266
- @tokenText = nil
262
+ @tokens << Token.new(@token_text, @reader.line_no, @token_start)
263
+ @token_text = nil
267
264
  return
268
265
  end
269
266
  end
@@ -273,21 +270,24 @@ module SDL4R
273
270
  end
274
271
 
275
272
  # detection of ill-terminated literals
276
- if @tokenText =~ /^".*[^"]$/
273
+ if @token_text =~ /^".*[^"]$/
277
274
  parse_error(
278
- "String literal \"#{@tokenText}\" not terminated by end quote.", @reader.line_no, @reader.line_length);
279
- elsif @tokenText == "\""
280
- parse_error("Orphan quote (unterminated string)", @reader.line_no, @reader.line_length);
275
+ "String literal \"#{@token_text}\" not terminated by end quote.",
276
+ @reader.line_no,
277
+ @reader.line_length)
278
+ else#if @token_text == '"'
279
+ parse_error("Orphan quote (unterminated string)", @reader.line_no, @reader.line_length)
281
280
  end
281
+ puts "end of chars"
282
282
  end
283
283
 
284
284
  def handle_escaped_double_quoted_string
285
285
  # '\' can be followed by whitespaces
286
286
  if @reader.rest_of_line =~ /^\\\s*$/
287
287
  @reader.read_line()
288
- parse_error("Escape at end of file.") if @reader.end_of_file?
288
+ parse_error("Escape at end of file.") if @reader.eof?
289
289
 
290
- @startEscapedQuoteLine = true
290
+ @starting_escaped_quote_line = true
291
291
 
292
292
  else
293
293
  parse_error(
@@ -297,22 +297,18 @@ module SDL4R
297
297
  end
298
298
 
299
299
  def handle_character_literal
300
- if not @reader.more_chars_in_line?
301
- parse_error("Got ' at end of line")
302
- end
300
+ @reader.skip_char # skip the starting quote
301
+
302
+ parse_error("Got ' at end of line") if @reader.eol?
303
303
 
304
304
  c2 = @reader.read_char()
305
305
 
306
306
  if c2 == "\\"
307
- if @reader.end_of_line?
308
- parse_error("Got '\\ at end of line")
309
- end
307
+ parse_error("Got '\\ at end of line") if @reader.eol?
310
308
 
311
309
  c3 = @reader.read_char()
312
310
 
313
- if not @reader.more_chars_in_line?
314
- parse_error("Got '\\#{c3} at end of line")
315
- end
311
+ parse_error("Got '\\#{c3} at end of line") if @reader.eol?
316
312
 
317
313
  case c3
318
314
  when "\\"
@@ -329,17 +325,16 @@ module SDL4R
329
325
  parse_error("Illegal escape character #{@reader.current_char}")
330
326
  end
331
327
 
332
- @reader.skip_char()
333
- if @reader.current_char != "'"
328
+ if @reader.read_char != "'"
334
329
  expecting_but_got("single quote (')", "\"#{@reader.current_char}\"")
335
330
  end
331
+
336
332
  else
337
333
  @tokens << Token.new("'#{c2}'", @reader.line_no, @reader.pos)
338
- if not @reader.more_chars_in_line?
339
- parse_error("Got '#{c2} at end of line")
340
- end
341
- @reader.skip_char()
342
- if @reader.current_char != "'"
334
+
335
+ parse_error("Got '#{c2} at end of line") if @reader.eol?
336
+
337
+ if @reader.read_char != "'"
343
338
  expecting_but_got(
344
339
  "quote (')", "\"#{@reader.current_char}\"", @reader.line_no, @reader.pos)
345
340
  end
@@ -360,7 +355,7 @@ module SDL4R
360
355
  # handle multiline comments
361
356
  loop do
362
357
  @reader.read_raw_line()
363
- if @reader.end_of_file?
358
+ if @reader.eof?
364
359
  parse_error("/* comment not terminated.", @reader.line_no, -2)
365
360
  end
366
361
 
@@ -383,31 +378,31 @@ module SDL4R
383
378
  if end_index
384
379
  # handle end quote on same line
385
380
  @tokens << Token.new(@reader.substring(@reader.pos, end_index), @reader.line_no, @reader.pos)
386
- @tokenText = nil
381
+ @token_text = nil
387
382
  @reader.skip_to(end_index)
388
383
 
389
384
  else
390
- @tokenText = @reader.rest_of_line
385
+ @token_text = @reader.rest_of_line
391
386
  @token_start = @reader.pos
392
387
  # handle multiline quotes
393
388
  loop do
394
389
  @reader.read_raw_line()
395
- if @reader.end_of_file?
390
+ if @reader.eof?
396
391
  parse_error("` quote not terminated.", @reader.line_no, -2)
397
392
  end
398
393
 
399
394
  end_index = @reader.find_next_in_line("`", 0)
400
395
  if end_index
401
- @tokenText << @reader.substring(0, end_index)
396
+ @token_text << @reader.substring(0, end_index)
402
397
  @reader.skip_to(end_index)
403
398
  break
404
399
  else
405
- @tokenText << @reader.line
400
+ @token_text << @reader.line
406
401
  end
407
402
  end
408
403
 
409
- @tokens << Token.new(@tokenText, @reader.line_no, @token_start)
410
- @tokenText = nil
404
+ @tokens << Token.new(@token_text, @reader.line_no, @token_start)
405
+ @token_text = nil
411
406
  end
412
407
  end
413
408
 
@@ -417,30 +412,30 @@ module SDL4R
417
412
  if end_index
418
413
  # handle end quote on same line
419
414
  @tokens << Token.new(@reader.substring(@reader.pos, end_index), @reader.line_no, @reader.pos)
420
- @tokenText = nil
415
+ @token_text = nil
421
416
  @reader.skip_to(end_index)
422
417
  else
423
- @tokenText = @reader.substring(@reader.pos)
418
+ @token_text = @reader.substring(@reader.pos)
424
419
  @token_start = @reader.pos
425
420
  # handle multiline quotes
426
421
  loop do
427
422
  @reader.read_raw_line()
428
- if @reader.end_of_file?
423
+ if @reader.eof?
429
424
  parse_error("[base64] binary literal not terminated.", @reader.line_no, -2)
430
425
  end
431
426
 
432
427
  end_index = @reader.find_next_in_line("]", 0)
433
428
  if end_index
434
- @tokenText << @reader.substring(0, end_index)
429
+ @token_text << @reader.substring(0, end_index)
435
430
  @reader.skip_to(end_index)
436
431
  break
437
432
  else
438
- @tokenText << @reader.line
433
+ @token_text << @reader.line
439
434
  end
440
435
  end
441
436
 
442
- @tokens << Token.new(@tokenText, @reader.line_no, @token_start)
443
- @tokenText = nil
437
+ @tokens << Token.new(@token_text, @reader.line_no, @token_start)
438
+ @token_text = nil
444
439
  end
445
440
  end
446
441
 
@@ -452,7 +447,7 @@ module SDL4R
452
447
  parse_error("Line continuation (\\) before end of line")
453
448
  else
454
449
  @line = @reader.read_line()
455
- if @line.nil?
450
+ unless @line
456
451
  parse_error("Line continuation at end of file.", @reader.line_no, @reader.pos)
457
452
  end
458
453
  end
@@ -460,15 +455,15 @@ module SDL4R
460
455
 
461
456
  def handle_number_date_or_time_span
462
457
  @token_start = @reader.pos
463
- @tokenText = ""
458
+ @token_text = ""
464
459
 
465
- while not @reader.end_of_line?
460
+ until @reader.eol?
466
461
  c = @reader.current_char
467
462
 
468
463
  if c =~ /[\w\.\-+:]/
469
- @tokenText << c
464
+ @token_text << c
470
465
  elsif c == "/" and not @reader.get_line_char(@reader.pos + 1) == "*"
471
- @tokenText << c
466
+ @token_text << c
472
467
  else
473
468
  @reader.previous_char()
474
469
  break
@@ -477,21 +472,21 @@ module SDL4R
477
472
  @reader.skip_char()
478
473
  end
479
474
 
480
- @tokens << Token.new(@tokenText, @reader.line_no, @token_start)
481
- @tokenText = nil
475
+ @tokens << Token.new(@token_text, @reader.line_no, @token_start)
476
+ @token_text = nil
482
477
  end
483
478
 
484
479
  def handle_identifier
485
- @token_start = @reader.pos;
486
- @tokenText = ""
480
+ @token_start = @reader.pos
481
+ @token_text = ""
487
482
 
488
- while not @reader.end_of_line?
483
+ until @reader.eol?
489
484
  c = @reader.current_char
490
485
 
491
486
  # FIXME here we are stricter than the Java version because there is no
492
487
  # easy way to implement Character.isJavaIdentifierPart() in Ruby :)
493
488
  if c =~ /[\w_$-\.]/
494
- @tokenText << c
489
+ @token_text << c
495
490
  else
496
491
  @reader.previous_char()
497
492
  break
@@ -500,8 +495,8 @@ module SDL4R
500
495
  @reader.skip_char()
501
496
  end
502
497
 
503
- @tokens << Token.new(@tokenText, @reader.line_no, @token_start)
504
- @tokenText = nil
498
+ @tokens << Token.new(@token_text, @reader.line_no, @token_start)
499
+ @token_text = nil
505
500
  end
506
501
 
507
502
  end