sdl4r 0.9.9 → 0.9.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/CHANGELOG +70 -1
  2. data/LICENSE +499 -497
  3. data/Rakefile +38 -28
  4. data/TODO +194 -45
  5. data/doc/classes/SDL4R/AbbreviationTimezoneProxy.html +151 -0
  6. data/doc/classes/SDL4R/ConstantTimezone.html +129 -0
  7. data/doc/classes/SDL4R/Element.html +148 -0
  8. data/doc/classes/SDL4R/Reader.html +683 -0
  9. data/doc/classes/SDL4R/RelativeTimezone.html +187 -0
  10. data/doc/classes/SDL4R/SdlBinary.html +188 -0
  11. data/doc/classes/SDL4R/SdlParseError.html +110 -0
  12. data/doc/classes/SDL4R/SdlTimeSpan.html +651 -0
  13. data/doc/classes/SDL4R/Serializer.html +557 -0
  14. data/doc/classes/SDL4R/Serializer/Ref.html +138 -0
  15. data/doc/classes/SDL4R/TZAbbreviationDB/Record.html +117 -0
  16. data/doc/classes/SDL4R/Tag.html +1274 -0
  17. data/doc/classes/SDL4R/Token.html +131 -0
  18. data/doc/created.rid +1 -0
  19. data/doc/files/CHANGELOG.html +290 -0
  20. data/doc/files/LICENSE.html +53 -0
  21. data/doc/files/README.html +405 -0
  22. data/doc/files/lib/sdl4r/abbreviation_timezone_proxy_rb.html +63 -0
  23. data/doc/files/lib/sdl4r/constant_timezone_rb.html +54 -0
  24. data/doc/files/lib/sdl4r/element_rb.html +54 -0
  25. data/doc/files/lib/sdl4r/reader_rb.html +68 -0
  26. data/doc/files/lib/sdl4r/relative_timezone_rb.html +62 -0
  27. data/doc/files/lib/sdl4r/sdl4r_rb.html +66 -0
  28. data/doc/files/lib/sdl4r/sdl4r_tzinfo_rb.html +64 -0
  29. data/doc/files/lib/sdl4r/sdl4r_version_rb.html +54 -0
  30. data/doc/files/lib/sdl4r/sdl_binary_rb.html +54 -0
  31. data/doc/files/lib/sdl4r/sdl_parse_error_rb.html +54 -0
  32. data/doc/files/lib/sdl4r/sdl_time_span_rb.html +54 -0
  33. data/doc/files/lib/sdl4r/serializer_rb.html +62 -0
  34. data/doc/files/lib/sdl4r/tag_rb.html +66 -0
  35. data/doc/files/lib/sdl4r/token_rb.html +54 -0
  36. data/doc/files/lib/sdl4r/tokenizer_rb.html +64 -0
  37. data/doc/files/lib/sdl4r/tz_abbreviation_db_rb.html +67 -0
  38. data/doc/files/lib/sdl4r_rb.html +54 -0
  39. data/doc/files/lib/sdl4r_tzinfo_rb.html +54 -0
  40. data/doc/fr_class_index.html +23 -0
  41. data/doc/fr_file_index.html +40 -0
  42. data/doc/fr_method_index.html +4711 -0
  43. data/doc/index.html +15 -0
  44. data/doc/rdoc-style.css +328 -0
  45. data/lib/sdl4r.rb +3 -1
  46. data/lib/sdl4r/abbreviation_timezone_proxy.rb +38 -0
  47. data/lib/sdl4r/constant_timezone.rb +58 -0
  48. data/{test/sdl4r/sdl_test.rb → lib/sdl4r/element.rb} +19 -14
  49. data/lib/sdl4r/reader.rb +772 -0
  50. data/lib/sdl4r/relative_timezone.rb +156 -0
  51. data/lib/sdl4r/sdl4r.rb +187 -45
  52. data/lib/sdl4r/sdl4r_tzinfo.rb +75 -0
  53. data/lib/sdl4r/sdl4r_version.rb +24 -0
  54. data/lib/sdl4r/sdl_parse_error.rb +1 -1
  55. data/lib/sdl4r/sdl_time_span.rb +5 -1
  56. data/lib/sdl4r/serializer.rb +473 -60
  57. data/lib/sdl4r/tag.rb +126 -51
  58. data/lib/sdl4r/token.rb +49 -0
  59. data/lib/sdl4r/tokenizer.rb +431 -0
  60. data/lib/sdl4r/tz_abbreviation_db.rb +266 -0
  61. data/read_jprof.html +16934 -0
  62. data/read_jprof_pull.html +14451 -0
  63. data/read_prof.html +4983 -0
  64. data/read_prof_pull.html +4896 -0
  65. data/test/sdl4r/parser_test.rb +577 -503
  66. data/test/sdl4r/read_jprof.rb +58 -0
  67. data/test/sdl4r/read_prof.rb +70 -0
  68. data/test/sdl4r/reader_test.rb +173 -0
  69. data/test/sdl4r/relative_timezone_test.rb +102 -0
  70. data/test/sdl4r/sdl4r_test.rb +611 -528
  71. data/test/sdl4r/sdl4r_tzinfo_test.rb +108 -0
  72. data/test/sdl4r/sdl_test_case.rb +60 -0
  73. data/test/sdl4r/serializer_test.rb +448 -11
  74. data/test/sdl4r/tag_test.rb +84 -5
  75. data/test/sdl4r/tokenizer_test.rb +128 -0
  76. metadata +69 -11
  77. data/lib/sdl4r/parser.rb +0 -648
  78. data/lib/sdl4r/parser/reader.rb +0 -184
  79. data/lib/sdl4r/parser/time_span_with_zone.rb +0 -57
  80. data/lib/sdl4r/parser/token.rb +0 -138
  81. data/lib/sdl4r/parser/tokenizer.rb +0 -507
@@ -1,184 +0,0 @@
1
- #!/usr/bin/env ruby -w
2
- # encoding: UTF-8
3
-
4
- #--
5
- # Simple Declarative Language (SDL) for Ruby
6
- # Copyright 2005 Ikayzo, inc.
7
- #
8
- # This program is free software. You can distribute or modify it under the
9
- # terms of the GNU Lesser General Public License version 2.1 as published by
10
- # the Free Software Foundation.
11
- #
12
- # This program is distributed AS IS and WITHOUT WARRANTY. OF ANY KIND,
13
- # INCLUDING MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
14
- # See the GNU Lesser General Public License for more details.
15
- #
16
- # You should have received a copy of the GNU Lesser General Public License
17
- # along with this program; if not, contact the Free Software Foundation, Inc.,
18
- # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
- #++
20
-
21
- module SDL4R
22
-
23
- class Parser
24
-
25
- # Gives access to the characters read to the Parser.
26
- # This class was designed to gather the handling of the UTF-8 issues in one place and shield the
27
- # Parser class from these problems.
28
- class Reader # :nodoc: all
29
-
30
- # +io+ an open IO from which the characters are read.
31
- def initialize(io)
32
- raise ArgumentError, "io == nil" unless io
33
-
34
- @io = io
35
- @line = nil
36
- @line_chars = nil
37
- @line_no = -1
38
- @pos = 0
39
- end
40
-
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
50
-
51
- def line_length
52
- return @line_chars.nil? ? 0 : @line_chars.length
53
- end
54
-
55
- # Reads next line in stream skipping comment lines and blank lines.
56
- #
57
- # Returns the next line or nil at the end of the file.
58
- def read_line
59
- @line_chars = nil
60
-
61
- while @line = read_raw_line()
62
- # Skip empty and commented lines
63
- break unless @line.empty? or @line =~ /^#/
64
- end
65
-
66
- return @line
67
- end
68
-
69
- # Returns the string that goes from the current position of this Reader to the end of the line
70
- # or nil if the current position doesn't allow that.
71
- def rest_of_line
72
- return @line[@pos..-1]
73
- end
74
-
75
- # Indicates whether the end of file has been reached.
76
- def eof?
77
- return @line.nil?
78
- end
79
-
80
- # Indicates whether there are more characters in the current line after the current char
81
- def more_chars_in_line?
82
- return @pos < line_length - 1
83
- end
84
-
85
- # Returns whether the end of the current +line+ as been reached.
86
- def eol?
87
- return @pos >= line_length
88
- end
89
-
90
- # Skips the current line by going just after its end.
91
- def skip_to_eol
92
- @pos = line_length
93
- end
94
-
95
- # Skips the whitespaces that follow the current position.
96
- def skip_whitespaces
97
- while (@pos + 1) < line_length and
98
- (@line[@pos + 1] == ?\s or @line[@pos + 1] == ?\t)
99
- @pos += 1
100
- end
101
- end
102
-
103
- # Returns the character at position +pos+ in the current line.
104
- # Returns nil if there is no current line or if +pos+ is after the end of the line.
105
- def get_line_char(pos)
106
- if @line_chars and pos < line_length
107
- return @line_chars[pos]
108
- else
109
- return nil
110
- end
111
- end
112
-
113
- # Returns the character at the current position or nil after end-of-line or end-of -file.
114
- def current_char
115
- return get_line_char(@pos)
116
- end
117
-
118
- # Go to the next character in the line. This method doesn't skip to the next line once the
119
- # reached eol.
120
- def skip_char
121
- @pos += 1 if @pos < line_length
122
- end
123
-
124
- # Returns the current char and go to the next.
125
- # Returns nil if end-of-line or -file has been reached.
126
- def read_char
127
- c = current_char
128
- skip_char()
129
- c
130
- end
131
-
132
- # Returns to the previous char if possible.
133
- def previous_char
134
- @pos -= 1 if @pos >= 1
135
- end
136
-
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.
139
- def find_next_in_line(searched, start_pos = nil)
140
- start_pos = @pos + 1 unless start_pos
141
- return @line.index(searched, start_pos)
142
- end
143
-
144
- # Skips the specified position in the current line.
145
- def skip_to(new_pos)
146
- @pos = new_pos
147
- end
148
-
149
-
150
- # Returns a subpart of the current line starting from +from+ and stopping at +to+ (excluded).
151
- def substring(from, to = -1)
152
- return @line[from..to]
153
- end
154
-
155
- # Reads and returns a "raw" line including lines with comments and blank lines.
156
- #
157
- # Returns the next line or nil if at the end of the file.
158
- #
159
- # This method changes the value of @line, @lineNo and @pos.
160
- def read_raw_line
161
- @line = @io.gets()
162
-
163
- # Remove a possible \r at the end of line
164
- @line.gsub!(/\r+$/, "") if @line
165
-
166
- @pos = 0;
167
- @line_chars = nil
168
- if @line
169
- @line_no += 1
170
- @line_chars = @line.scan(/./m)
171
- end
172
- return @line
173
- end
174
-
175
- # Closes this Reader and its underlying +IO+.
176
- def close
177
- @io.close
178
- end
179
-
180
- end
181
-
182
- end
183
-
184
- end
@@ -1,57 +0,0 @@
1
- #!/usr/bin/env ruby -w
2
- # encoding: UTF-8
3
-
4
- #--
5
- # Simple Declarative Language (SDL) for Ruby
6
- # Copyright 2005 Ikayzo, inc.
7
- #
8
- # This program is free software. You can distribute or modify it under the
9
- # terms of the GNU Lesser General Public License version 2.1 as published by
10
- # the Free Software Foundation.
11
- #
12
- # This program is distributed AS IS and WITHOUT WARRANTY. OF ANY KIND,
13
- # INCLUDING MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
14
- # See the GNU Lesser General Public License for more details.
15
- #
16
- # You should have received a copy of the GNU Lesser General Public License
17
- # along with this program; if not, contact the Free Software Foundation, Inc.,
18
- # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
- #++
20
-
21
- module SDL4R
22
-
23
- class Parser
24
-
25
- # An intermediate object used to store a timeSpan or the time
26
- # component of a date/time instance. The types are disambiguated at a later stage.
27
- #
28
- # +seconds+ can have a fraction
29
- # +time_zone_offset+ is a fraction of a day (equal to nil if not specified)
30
- class TimeSpanWithZone # :nodoc: all
31
-
32
- private
33
-
34
- SECONDS_IN_DAY = 24 * 60 * 60
35
-
36
- public
37
-
38
- def initialize(day, hour, minute, second, time_zone_offset)
39
- @day = day
40
- @hour = hour
41
- @min = minute
42
- @sec = second
43
- @time_zone_offset = time_zone_offset
44
- end
45
-
46
- attr_reader :day, :hour, :min, :sec, :time_zone_offset
47
-
48
- # Returns the UTC offset as a fraction of a day on the current machine
49
- def TimeSpanWithZone.default_time_zone_offset
50
- return Rational(Time.now.utc_offset, SECONDS_IN_DAY)
51
- end
52
-
53
- end
54
-
55
- end
56
-
57
- end
@@ -1,138 +0,0 @@
1
- #!/usr/bin/env ruby -w
2
- # encoding: UTF-8
3
-
4
- #--
5
- # Simple Declarative Language (SDL) for Ruby
6
- # Copyright 2005 Ikayzo, inc.
7
- #
8
- # This program is free software. You can distribute or modify it under the
9
- # terms of the GNU Lesser General Public License version 2.1 as published by
10
- # the Free Software Foundation.
11
- #
12
- # This program is distributed AS IS and WITHOUT WARRANTY. OF ANY KIND,
13
- # INCLUDING MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
14
- # See the GNU Lesser General Public License for more details.
15
- #
16
- # You should have received a copy of the GNU Lesser General Public License
17
- # along with this program; if not, contact the Free Software Foundation, Inc.,
18
- # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
- #++
20
-
21
- module SDL4R
22
-
23
- require File.dirname(__FILE__) + '/time_span_with_zone'
24
-
25
- class Parser
26
-
27
- # An SDL token.
28
- #
29
- # @author Daniel Leuck, Philippe Vosges
30
- #
31
- class Token # :nodoc: all
32
-
33
- def initialize(text, line = -1, position = -1)
34
- @text = text
35
- @line = line
36
- @position = position
37
- @size = text.length
38
-
39
- begin
40
- @type = nil
41
- @object = nil
42
-
43
- if text =~ /^["`]/
44
- @type = :STRING
45
- @object = Parser.parse_string(text)
46
-
47
- elsif text =~ /^'/
48
- @type = :CHARACTER
49
- @object = text[1...-1]
50
-
51
- elsif text == "null"
52
- @type = :NULL
53
- @object = nil
54
-
55
- elsif text =~ /^true$|^on$/
56
- @type = :BOOLEAN
57
- @object = true
58
-
59
- elsif text =~ /^false$|^off$/
60
- @type = :BOOLEAN
61
- @object = false
62
-
63
- elsif text =~ /^\[/
64
- @type=:BINARY
65
- @object = Parser.parse_binary(text)
66
-
67
- elsif text =~ /^-?\d+\/\d+\/\d+$/
68
- @type = :DATE;
69
- @object = Parser.parse_date_time(text)
70
-
71
- elsif text =~ /^-?\d+d?:\d+/
72
- @type = :TIME
73
- @object = parse_time_span_with_zone(text)
74
-
75
- elsif text =~ /^[\d\-\.]/
76
- @type = :NUMBER
77
- @object = Parser.parse_number(text)
78
-
79
- else
80
- case text[0]
81
- when ?{
82
- @type = :START_BLOCK
83
- when ?}
84
- @type = :END_BLOCK
85
- when ?=
86
- @type = :EQUALS
87
- when ?:
88
- @type = :COLON
89
- when ?;
90
- @type = :SEMICOLON
91
- end
92
- end
93
-
94
- rescue ArgumentError
95
- raise SdlParseError.new($!.message, @line, @position)
96
- end
97
-
98
- @type = :IDENTIFIER if @type.nil? # if all hope is lost, it's an identifier
99
-
100
- @punctuation =
101
- @type == :COLON || @type == :SEMICOLON || @type == :EQUALS ||
102
- @type == :START_BLOCK || @type == :END_BLOCK
103
- @literal = @type != :IDENTIFIER && !@punctuation
104
- end
105
-
106
- attr_reader :text, :type, :line, :position
107
-
108
- def literal?
109
- @literal
110
- end
111
-
112
- # Returns the Ruby object corresponding to this literal (or nil if it is
113
- # not a literal).
114
- def object_for_literal
115
- return @object
116
- end
117
-
118
- def to_s
119
- @type.to_s + " " + @text + " pos:" + @position.to_s
120
- end
121
-
122
- # This special parse method is used only by the Token class for
123
- # tokens which are ambiguously either a TimeSpan or the time component
124
- # of a date/time type
125
- def parse_time_span_with_zone(literal)
126
- raise ArgumentError("time span or date literal is nil") if literal.nil?
127
-
128
- days, hours, minutes, seconds, time_zone_offset =
129
- Parser.parse_time_span_and_time_zone(literal, true, true)
130
-
131
- return Parser::TimeSpanWithZone.new(days, hours, minutes, seconds, time_zone_offset)
132
- end
133
-
134
- end
135
-
136
- end
137
-
138
- end
@@ -1,507 +0,0 @@
1
- #!/usr/bin/env ruby -w
2
- # encoding: UTF-8
3
-
4
- #--
5
- # Simple Declarative Language (SDL) for Ruby
6
- # Copyright 2005 Ikayzo, inc.
7
- #
8
- # This program is free software. You can distribute or modify it under the
9
- # terms of the GNU Lesser General Public License version 2.1 as published by
10
- # the Free Software Foundation.
11
- #
12
- # This program is distributed AS IS and WITHOUT WARRANTY. OF ANY KIND,
13
- # INCLUDING MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
14
- # See the GNU Lesser General Public License for more details.
15
- #
16
- # You should have received a copy of the GNU Lesser General Public License
17
- # along with this program; if not, contact the Free Software Foundation, Inc.,
18
- # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
- #++
20
-
21
-
22
- module SDL4R
23
-
24
- require File.dirname(__FILE__) + '/reader'
25
- require File.dirname(__FILE__) + '/token'
26
-
27
- class Parser
28
-
29
- # Tokenizer of the SDL parser
30
- class Tokenizer # :nodoc: all
31
-
32
- TOKEN_TYPES = [
33
- :IDENTIFIER,
34
-
35
- # punctuation
36
- :COLON, :SEMICOLON, :EQUALS, :START_BLOCK, :END_BLOCK,
37
-
38
- # literals
39
- :STRING, :CHARACTER, :BOOLEAN, :NUMBER, :DATE, :TIME, :BINARY, :NULL ]
40
-
41
-
42
- # Creates an SDL tokenizer on the specified +IO+.
43
- def initialize(io)
44
- raise ArgumentError, "io == nil" if io.nil?
45
-
46
- @reader = Parser::Reader.new(io)
47
- @token_start = 0
48
- @starting_escaped_quote_line = false
49
- @tokens = nil
50
- @token_text = nil
51
- end
52
-
53
- # Closes this Tokenizer and its underlying +Reader+.
54
- def close
55
- @reader.close
56
- end
57
-
58
- # Raises a SdlParseError.
59
- def parse_error(description, line_no = nil, position = nil)
60
- line_no = @reader.line_no unless line_no
61
- # @reader.pos points to the *next* position (thence the "pos - 1")
62
- position = @reader.pos - 1 unless position and position >= 0
63
-
64
- # We add one because editors typically start with line 1 rather than 0...
65
- raise SdlParseError.new(description, line_no + 1, position + 1, @reader.line)
66
- end
67
-
68
- # Close the reader and throw a SdlParseError using the format
69
- # Was expecting X but got Y.
70
- #
71
- def expecting_but_got(expecting, got, line, position)
72
- parse_error("Was expecting #{expecting} but got #{got}", line, position)
73
- end
74
-
75
- # Returns the next line as tokens or nil if the end of the stream has been reached.
76
- # This method handles line continuations both within and outside String literals.
77
- # The line of tokens is assigned to @tokens.
78
- #
79
- # Returns a logical line as a list of Tokens.
80
- #
81
- def read_line_tokens
82
- begin
83
- read_line_tokens_even_if_empty()
84
- end until @tokens.nil? or !@tokens.empty?
85
- return @tokens
86
- end
87
-
88
- def line_no
89
- @reader.line_no
90
- end
91
-
92
- def pos
93
- @reader.pos
94
- end
95
-
96
- def line
97
- @reader.line
98
- end
99
-
100
- private
101
-
102
- # Returns the next line as tokens or nil if the end of the stream has been reached.
103
- # This method handles line continuations both within and outside String literals.
104
- # The line of tokens is assigned to @tokens.
105
- #
106
- # Returns a logical line as a list of Tokens.
107
- # Returns an empty array if the line was empty.
108
- # Returns +nil+ if the end of the stream has been reached.
109
- #
110
- def read_line_tokens_even_if_empty
111
- # Reset of the token-related fields
112
- @tokens = nil
113
- @token_text = nil
114
- @token_start = nil
115
-
116
- if @reader.eol? and not @reader.read_line()
117
- return nil
118
- end
119
-
120
- @tokens = []
121
- @token_start = @reader.pos
122
-
123
- until @reader.eol?
124
- if @token_text
125
- @tokens << Token.new(@token_text, @reader.line_no, @token_start)
126
- @token_text = nil
127
- @token_start = @reader.pos
128
- end
129
-
130
- c = @reader.current_char
131
- next_c = @reader.get_line_char(@reader.pos + 1)
132
-
133
- case c
134
- when "\""
135
- # handle "" style strings including line continuations
136
- handle_double_quote_string()
137
-
138
- when "'"
139
- handle_character_literal()
140
-
141
- when "{", "}", "=", ":", ";"
142
- # handle punctuation
143
- punctuation_token = Token.new(c, @reader.line_no, @reader.pos)
144
- @token_text = nil
145
-
146
- if punctuation_token.type == :SEMICOLON
147
- @reader.skip_char()
148
- break
149
- else
150
- @tokens << punctuation_token
151
- end
152
-
153
- when "#"
154
- # skip : hash comment at end of line
155
- @reader.skip_to_eol()
156
-
157
- when "/"
158
- # handle // and /**/ style comments
159
- if next_c == "/"
160
- # skip : // comment
161
- @reader.skip_to_eol()
162
- else
163
- handle_slash_comment()
164
- end
165
-
166
- when "`"
167
- # handle multiline `` style strings
168
- handle_back_quote_string()
169
-
170
- when "["
171
- # handle binary literals
172
- handle_binary_literal()
173
-
174
- when "\s", "\t"
175
- @reader.skip_whitespaces()
176
-
177
- when "\\"
178
- # line continuations (outside a string literal)
179
- handle_line_continuation()
180
- next # otherwise 1st char of the continuation line is skipped by skip_char()
181
-
182
- when /^[0-9\-\.]$/
183
- if c == "-" and next_c == "-"
184
- # -- comments : ignore
185
- @reader.skip_to_eol()
186
- else
187
- # handle numbers, dates, and time spans
188
- handle_number_date_or_time_span()
189
- end
190
-
191
- when /^[a-zA-Z\$_]$/
192
- # FIXME Here, the Java code specifies isJavaIdentifierStart() but
193
- # this is not easily implemented (at least as of Ruby 1.8).
194
- # So, we implement a subset of these characters.
195
- handle_identifier()
196
-
197
- when "\n", "\r" # end of line
198
- @reader.skip_to_eol()
199
-
200
- else
201
- parse_error("Unexpected character '#{c}'")
202
- end
203
-
204
- @reader.skip_char()
205
- end
206
-
207
- if @token_text
208
- @tokens << Token.new(@token_text, @reader.line_no, @token_start)
209
- end
210
-
211
- return @tokens
212
- end
213
-
214
- # Adds the current escaped character (represented by ((|c|))) to @token_text.
215
- # This method assumes the previous char was a backslash.
216
- #
217
- def add_escaped_char_in_string(c)
218
- case c
219
- when "\\", "\""
220
- @token_text << c
221
- when "n"
222
- @token_text << ?\n
223
- when "r"
224
- @token_text << ?\r
225
- when "t"
226
- @token_text << ?\t
227
- else
228
- parse_error("Illegal escape character in string literal: '#{c}'.")
229
- end
230
- end
231
-
232
- def handle_double_quote_string
233
- escaped = false
234
- @starting_escaped_quote_line = false
235
-
236
- @token_text = @reader.read_char()
237
-
238
- until @reader.eol?
239
- c = @reader.current_char
240
-
241
- if "\s\t".include?(c) and @starting_escaped_quote_line
242
- # skip the heading spaces (indentation) of a continued line
243
- else
244
- @starting_escaped_quote_line = false
245
-
246
- if escaped
247
- add_escaped_char_in_string(c)
248
- escaped = false
249
-
250
- elsif c == "\\"
251
- # check for String broken across lines
252
- if @reader.rest_of_line =~ /^\\\s*$/
253
- handle_escaped_double_quoted_string()
254
- next # as we are at the beginning of a new line
255
- else
256
- escaped = true
257
- end
258
-
259
- else
260
- @token_text << c
261
- if c == '"'
262
- # end of double-quoted string detected
263
- @tokens << Token.new(@token_text, @reader.line_no, @token_start)
264
- @token_text = nil
265
- return
266
- end
267
- end
268
- end
269
-
270
- @reader.skip_char()
271
- end
272
-
273
- # detection of ill-terminated literals
274
- if @token_text =~ /^".*[^"]$/
275
- parse_error(
276
- "String literal \"#{@token_text}\" not terminated by end quote.",
277
- @reader.line_no,
278
- @reader.line_length)
279
- else#if @token_text == '"'
280
- parse_error("Orphan quote (unterminated string)", @reader.line_no, @reader.line_length)
281
- end
282
- puts "end of chars"
283
- end
284
-
285
- def handle_escaped_double_quoted_string
286
- # '\' can be followed by whitespaces
287
- if @reader.rest_of_line =~ /^\\\s*$/
288
- @reader.read_line()
289
- parse_error("Escape at end of file.") if @reader.eof?
290
-
291
- @starting_escaped_quote_line = true
292
-
293
- else
294
- parse_error(
295
- "Malformed string literal - escape followed by whitespace " +
296
- "followed by non-whitespace.")
297
- end
298
- end
299
-
300
- def handle_character_literal
301
- @reader.skip_char # skip the starting quote
302
-
303
- parse_error("Got ' at end of line") if @reader.eol?
304
-
305
- c2 = @reader.read_char()
306
-
307
- if c2 == "\\"
308
- parse_error("Got '\\ at end of line") if @reader.eol?
309
-
310
- c3 = @reader.read_char()
311
-
312
- parse_error("Got '\\#{c3} at end of line") if @reader.eol?
313
-
314
- case c3
315
- when "\\"
316
- @tokens << Token.new("'\\'", @reader.line_no, @reader.pos)
317
- when "'"
318
- @tokens << Token.new("'''", @reader.line_no, @reader.pos)
319
- when "n"
320
- @tokens << Token.new("'\n'", @reader.line_no, @reader.pos)
321
- when "r"
322
- @tokens << Token.new("'\r'", @reader.line_no, @reader.pos)
323
- when "t"
324
- @tokens << Token.new("'\t'", @reader.line_no, @reader.pos)
325
- else
326
- parse_error("Illegal escape character #{@reader.current_char}")
327
- end
328
-
329
- if @reader.read_char != "'"
330
- expecting_but_got("single quote (')", "\"#{@reader.current_char}\"")
331
- end
332
-
333
- else
334
- @tokens << Token.new("'#{c2}'", @reader.line_no, @reader.pos)
335
-
336
- parse_error("Got '#{c2} at end of line") if @reader.eol?
337
-
338
- if @reader.read_char != "'"
339
- expecting_but_got(
340
- "quote (')", "\"#{@reader.current_char}\"", @reader.line_no, @reader.pos)
341
- end
342
- end
343
- end
344
-
345
- def handle_slash_comment
346
- if not @reader.more_chars_in_line?
347
- parse_error("Got slash (/) at end of line.")
348
- end
349
-
350
- if @reader.get_line_char(@reader.pos + 1) == "*"
351
- end_index = @reader.find_next_in_line("*/")
352
- if end_index
353
- # handle comment on same line
354
- @reader.skip_to(end_index + 1)
355
- else
356
- # handle multiline comments
357
- loop do
358
- @reader.read_raw_line()
359
- if @reader.eof?
360
- parse_error("/* comment not terminated.", @reader.line_no, -2)
361
- end
362
-
363
- end_index = @reader.find_next_in_line("*/", 0)
364
-
365
- if end_index
366
- @reader.skip_to(end_index + 1)
367
- break
368
- end
369
- end
370
- end
371
- elsif @reader.get_line_char(@reader.pos + 1) == "/"
372
- parse_error("Got slash (/) in unexpected location.")
373
- end
374
- end
375
-
376
- def handle_back_quote_string
377
- end_index = @reader.find_next_in_line("`")
378
-
379
- if end_index
380
- # handle end quote on same line
381
- @tokens << Token.new(@reader.substring(@reader.pos, end_index), @reader.line_no, @reader.pos)
382
- @token_text = nil
383
- @reader.skip_to(end_index)
384
-
385
- else
386
- @token_text = @reader.rest_of_line
387
- @token_start = @reader.pos
388
- # handle multiline quotes
389
- loop do
390
- @reader.read_raw_line()
391
- if @reader.eof?
392
- parse_error("` quote not terminated.", @reader.line_no, -2)
393
- end
394
-
395
- end_index = @reader.find_next_in_line("`", 0)
396
- if end_index
397
- @token_text << @reader.substring(0, end_index)
398
- @reader.skip_to(end_index)
399
- break
400
- else
401
- @token_text << @reader.line
402
- end
403
- end
404
-
405
- @tokens << Token.new(@token_text, @reader.line_no, @token_start)
406
- @token_text = nil
407
- end
408
- end
409
-
410
- def handle_binary_literal
411
- end_index = @reader.find_next_in_line("]")
412
-
413
- if end_index
414
- # handle end quote on same line
415
- @tokens << Token.new(@reader.substring(@reader.pos, end_index), @reader.line_no, @reader.pos)
416
- @token_text = nil
417
- @reader.skip_to(end_index)
418
- else
419
- @token_text = @reader.substring(@reader.pos)
420
- @token_start = @reader.pos
421
- # handle multiline quotes
422
- loop do
423
- @reader.read_raw_line()
424
- if @reader.eof?
425
- parse_error("[base64] binary literal not terminated.", @reader.line_no, -2)
426
- end
427
-
428
- end_index = @reader.find_next_in_line("]", 0)
429
- if end_index
430
- @token_text << @reader.substring(0, end_index)
431
- @reader.skip_to(end_index)
432
- break
433
- else
434
- @token_text << @reader.line
435
- end
436
- end
437
-
438
- @tokens << Token.new(@token_text, @reader.line_no, @token_start)
439
- @token_text = nil
440
- end
441
- end
442
-
443
- # handle a line continuation (not inside a string)
444
- def handle_line_continuation
445
- # backslash line continuation outside of a String literal
446
- # can only occur at the end of a line
447
- if not @reader.rest_of_line =~ /^\\\s*$/
448
- parse_error("Line continuation (\\) before end of line")
449
- else
450
- @line = @reader.read_line()
451
- unless @line
452
- parse_error("Line continuation at end of file.", @reader.line_no, @reader.pos)
453
- end
454
- end
455
- end
456
-
457
- def handle_number_date_or_time_span
458
- @token_start = @reader.pos
459
- @token_text = ""
460
-
461
- until @reader.eol?
462
- c = @reader.current_char
463
-
464
- if c =~ /[\w\.\-+:]/
465
- @token_text << c
466
- elsif c == "/" and not @reader.get_line_char(@reader.pos + 1) == "*"
467
- @token_text << c
468
- else
469
- @reader.previous_char()
470
- break
471
- end
472
-
473
- @reader.skip_char()
474
- end
475
-
476
- @tokens << Token.new(@token_text, @reader.line_no, @token_start)
477
- @token_text = nil
478
- end
479
-
480
- def handle_identifier
481
- @token_start = @reader.pos
482
- @token_text = ""
483
-
484
- until @reader.eol?
485
- c = @reader.current_char
486
-
487
- # FIXME here we are stricter than the Java version because there is no
488
- # easy way to implement Character.isJavaIdentifierPart() in Ruby :)
489
- if c =~ /[\w_$-\.]/
490
- @token_text << c
491
- else
492
- @reader.previous_char()
493
- break
494
- end
495
-
496
- @reader.skip_char()
497
- end
498
-
499
- @tokens << Token.new(@token_text, @reader.line_no, @token_start)
500
- @token_text = nil
501
- end
502
-
503
- end
504
-
505
- end
506
-
507
- end