PageRenderTime 51ms CodeModel.GetById 43ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/src/lib/regular_expression/internal/regular_expression_string_scanner.e

http://github.com/tybor/Liberty
Specman e | 244 lines | 159 code | 25 blank | 60 comment | 3 complexity | ed6bfdfe7fd7f42fc36c745ed281e68d MD5 | raw file
  1-- This file is part of a Liberty Eiffel library.
  2-- See the full copyright at the end.
  3--
  4class REGULAR_EXPRESSION_STRING_SCANNER
  5   --
  6   -- Facility to scan strings
  7   -- TODO improve it by using STRING_HANDLER and string's storage
  8   --
  9
 10feature {ANY} -- make
 11   make
 12         -- Initialise the attributes.
 13      do
 14         create last_string.make(10)
 15      end
 16
 17feature {ANY} -- basic
 18   scanned_string: ABSTRACT_STRING
 19         -- The expression being currently build.
 20
 21   set_scanned_string (string: like scanned_string)
 22         -- Set the 'scanned_string' with 'string'.
 23      do
 24         scanned_string := string
 25         clear_error
 26         goto_position(scanned_string.lower)
 27      ensure
 28         has_no_error: not has_error
 29         definition: scanned_string = string
 30         at_the_begin: position = scanned_string.lower
 31      end
 32
 33feature {ANY} -- error management
 34   has_error: BOOLEAN
 35         -- True when an error was encountered
 36
 37   clear_error
 38         -- Remove the error flag
 39      do
 40         has_error := False
 41      ensure
 42         has_no_error: not has_error
 43      end
 44
 45   last_error: STRING
 46         -- Returns a string recorded for the error.
 47      require
 48         has_error: has_error
 49      do
 50         Result := last_string
 51      ensure
 52         not_void: Result /= Void
 53      end
 54
 55   set_error (message: STRING)
 56         -- Set has_error and last_error.
 57         -- The explaining error string 'last_error'
 58         -- is created as follow: "Error at position 'position': 'message'.".
 59      require
 60         message_not_void: message /= Void
 61         has_no_error: not has_error
 62      do
 63         has_error := True
 64         last_string.clear_count
 65         last_string.append_string(once "Error at position ")
 66         position.append_in(last_string)
 67         last_string.append_string(once ": ")
 68         last_string.append_string(message)
 69         last_string.append_character('.')
 70      ensure
 71         has_error: has_error
 72      end
 73
 74feature {ANY} -- scanning
 75   position: INTEGER
 76         -- The scanned position.
 77         -- It is the position of 'last_character'.
 78
 79   last_character: CHARACTER
 80         -- The scanned character.
 81         -- The last character read from 'scanned_string'.
 82
 83   valid_last_character: BOOLEAN
 84         -- True when 'last_character' is valid.
 85         -- Is like 'scanned_string.valid_index(position)'
 86
 87   valid_previous_character: BOOLEAN
 88         -- True if the position-1 is a valid position.
 89      require
 90         scanned_string /= Void
 91      do
 92         Result := scanned_string.valid_index(position - 1)
 93      ensure
 94         definition: Result = scanned_string.valid_index(position - 1)
 95      end
 96
 97   previous_character: like last_character
 98         -- The character at position-1.
 99      require
100         valid_previous_character
101      do
102         Result := scanned_string.item(position - 1)
103      ensure
104         definition: Result = scanned_string.item(position - 1)
105      end
106
107   valid_next_character: BOOLEAN
108         -- True if the position+1 is a valid position.
109      require
110         scanned_string /= Void
111      do
112         Result := scanned_string.valid_index(position + 1)
113      ensure
114         definition: Result = scanned_string.valid_index(position + 1)
115      end
116
117   next_character: like last_character
118         -- The character at position+1.
119      require
120         valid_next_character
121      do
122         Result := scanned_string.item(position + 1)
123      ensure
124         definition: Result = scanned_string.item(position + 1)
125      end
126
127   end_of_input: BOOLEAN
128         -- True when all the characters of 'scanned_string'
129         -- are scanned.
130      do
131         Result := not valid_last_character
132      ensure
133         implies_last_character_not_valid: Result implies not valid_last_character
134      end
135
136   goto_position (pos: INTEGER)
137         -- Change the currently scanned position to 'pos'.
138         -- Updates 'last_character' and 'valid_last_character' to
139         -- reflect the new position value.
140      require
141         has_no_error: not has_error
142         scanned_string /= Void
143      do
144         position := pos
145         valid_last_character := scanned_string.valid_index(pos)
146         if valid_last_character then
147            last_character := scanned_string.item(pos)
148         end
149      ensure
150         has_no_error: not has_error
151         position_set: position = pos
152         validity_updated: valid_last_character = scanned_string.valid_index(position)
153         character_updated: valid_last_character implies last_character = scanned_string.item(position)
154      end
155
156   read_character
157         -- Reads the next character.
158      require
159         has_no_error: not has_error
160         not_at_end: not end_of_input
161      do
162         goto_position(position + 1)
163      ensure
164         next_position: position > old position
165         has_no_error: not has_error
166      end
167
168   read_integer
169         -- Reads an integer value beginning at the
170         -- currently scanned position.
171         -- The read value is stored in 'last_integer'.
172      require
173         has_no_error: not has_error
174         not_at_end: not end_of_input
175         begin_with_a_digit: last_character.is_decimal_digit
176      do
177         from
178            last_integer := last_character.decimal_value
179            read_character
180         until
181            end_of_input or else not last_character.is_decimal_digit
182         loop
183            last_integer := 10 * last_integer + last_character.decimal_value
184            read_character
185         end
186      ensure
187         has_no_error: not has_error
188         digits_eaten: end_of_input or else not last_character.is_decimal_digit
189      end
190
191   saved_position: INTEGER
192         -- The saved position (only one is currently enough).
193
194   save_position
195         -- Saves the current scanning position.
196      require
197         not_at_end: not end_of_input
198      do
199         saved_position := position
200      ensure
201         not_at_end: not end_of_input
202         position_kept: position = old position
203         saved_position_set: saved_position = position
204      end
205
206   restore_saved_position
207         -- Restore the scanning position to the last saved one.
208      do
209         goto_position(saved_position)
210      ensure
211         position_restored: position = old saved_position
212         not_at_end: not end_of_input
213      end
214
215   last_string: STRING
216         -- A string buffer.
217
218   last_integer: INTEGER
219         -- An integer buffer.
220
221invariant
222   last_string_not_void: last_string /= Void
223
224end -- class REGULAR_EXPRESSION_STRING_SCANNER
225--
226-- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
227--
228-- Permission is hereby granted, free of charge, to any person obtaining a copy
229-- of this software and associated documentation files (the "Software"), to deal
230-- in the Software without restriction, including without limitation the rights
231-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
232-- copies of the Software, and to permit persons to whom the Software is
233-- furnished to do so, subject to the following conditions:
234--
235-- The above copyright notice and this permission notice shall be included in
236-- all copies or substantial portions of the Software.
237--
238-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
239-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
240-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
241-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
242-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
243-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
244-- THE SOFTWARE.