![]() |
Section 8.16.1.8:
|
![]() |
This abstract class defines a state component which is a set of all instantiations of objects of any class sub-typing from this class in addition to the vdm model types used wherever this class name is used. Note that SAME has to be an instantiated class, not an abstract one.
types SAME = object_type ; $CURSOR_ELT_STP = set of object_type STP = seq of ELT state multi : $CURSOR_ELT_STP inv multi_types == forall obj in set multi_types & sub_type($CURSOR_ELT_STP,obj)
NOTE | See the important note about vdm state in the notes on vdm-sl usage in this specification. |
This abstract class defines the features of generic cursor scanning objects of all string/stream kinds.
The purpose of the cursor abstraction is to provide facilities to extract or pass over subsequences of a string (which are also called sequences or streams). This permits perfectly general scanning which depends only on the structure and content of the string, not its meaning. Since the associated string is not consumed by scanning, it is possible to perform test on contents/structure in order to 'synchronise' the program with the data content.
Four reader routines are provided to permit access to some of the state of a cursor object. They do not, however, necessarily have to be implemented in that way.
This feature is provided so that any single string element may be passed over during scanning - for example after testing for validity/presence.
advance(self : SAME)
pre not has_error(self)
post has_error(self) or index = index~ + 1
This feature advances the cursor to the next string element. If the cursor had already reached the end then has_error will return true.
This feature is provided so that any single string element may be passed over during scanning - for example after testing for validity/presence. This differs from the above feature in that it also returns the cursor object itself.
advance | : SAME |
advance2(self : SAME) res : SAME
pre not has_error(self)
post res = self and (has_error(self) or index = index~ + 1)
This feature advances the cursor to the next string element. If the cursor had already reached the end then has_error will return true. The updated version of self is returned.
This feature is provided to permit more than one look-ahead when scanning the buffer. it cannot be called when the cursor is at the beginning of the string or if a previous error has been detected.
retract(self : SAME)
pre not has_error(self) and index > 0
post index = index~ - 1
This feature retracts the cursor to point to the previous string element.
This feature is provided in order to permit look ahead of more than one element when 'scanning'. In doing so it returns self.
retract | : SAME |
retract2(self : SAME) res : SAME
pre index > 0
post res = self and index = index~ - 1
This feature retracts the cursor to point to the previous string element. It is an error if the current value of the cursor indicated the beginning of the string before this routine was called. The updated cursor is returned.
This feature is provided in order to permit the next item in the buffer to be inspected without being passed over. This is a look-ahead feature.
item | : ELT |
item(self : SAME) res : ELT
pre not is_done(self)
post res = self(index)
This routine returns the string element indicated by the current position of the cursor - or void if an error condition exists. The cursor is not advanced.
This routine is provided to enable the same cursor object to be used for another string buffer, starting at the beginning again.
reassign | ( |
str : STP | |
) |
reassign(self : SAME, str : STP)
pre len str > 0
post buffer = str and index = 0 and not has_error(self)
This routine changes the contents of the buffer to which this cursor is pointing, so that the current element is the first. Any error condition is cleared.
This feature clears the buffer, resets the index and clears any error condition.
clear(self : SAME)
Since the argument is not optional and the existing state of the object is not relevant to the action, this pre-condition is vacuously true.
post buffer = [] and index = 0 and not has_error(self)
This feature resets the cursor to have an empty buffer with index reset and error condition cleared.
This feature is required to set the index of the cursor to the given value (provided, of course, that it is valid for the buffer size), clearing any error condition.
set_index(self : SAME, new_posn : CARD)
pre new_posn < STP.size(buffer)
post index = new_posn and not has_error(self)
This routine resets the index position to new_posn, provided that that is a valid index for the buffer, then clears any end of buffer condition.
This feature sets the element value which is to be associated with the skip routines until a subsequent use of this feature.
set_skip | ( |
val : ELT | |
) |
set_skip(self : SAME, val : ELT)
Since the argument is not optional and the current skip value is not relevant, this pre-condition is vacuously true.
post skip_val = val
This routine sets the value of the element used in all skipping operations - until this is next set. The initial default value depends on the element class.
This feature sets the element value which is to be associated with the skip routines until a subsequent use of this feature.The cursor is then returned.
set_skip | ( |
val : ELT | |
) |
set_skip2(self : SAME, val : ELT) res : SAME
Since the arguments are not optional and the current state of the skip value is irrelevant, then this pre-condition is vacuously true,
post res = self and skip_val = val
This routine sets the value of the element used in all skipping operations - until this is next set. Self is then returned.
This feature moves the cursor past all elements which are the same as skip_val, leaving the cursor pointing to the first one which is not that value.
skip_over(self : SAME)
Since the argument is not optional and either the cursor is in a valid position or it has completely scanned the buffer, the result of this operation is not dependent on whether or not the skip value is present in the buffer. The pre-condition is therefore vacously true.
post let head = buffer(1, ..., index~) in let head ^ skipped = buffer(1, ..., index) in (forall elem | elem in set elems skipped & elem = skip_val and buffer(index + 1) <> skip_val)
This routine skips over all elements equal to skip_val, leaving the cursor indicating the first element which does not have that value after the starting index.
This feature advances the cursor until the next element in the string is not equal to skip_val, returning self.
skip_over | : SAME |
skip_over2(self : SAME) res : SAME
Since the argument is not optional and either the cursor is in a valid position or it has completely scanned the buffer, the result of this operation is not dependent on whether or not the skip value is present in the buffer. The pre-condition is therefore vacously true.
post let head = buffer(1, ..., index~) in let head ^ skipped = buffer(1, ..., index) in (forall elem in set elems skipped & elem = skip_val and buffer(index + 1) <> skip_val) and res = self
This routine advances the cursor until an element is found which differs from the skip value, Self is then returned.
This feature moves the cursor past all elements which are different from skip_val, leaving the cursor pointing to the next occurrence of skip_val
skip_to(self : SAME)
Since the argument is not optional and either the cursor is in a valid position or it has completely scanned the buffer, the result of this operation is not dependent on whether or not the skip value is present in the buffer. The pre-condition is therefore vacously true.
post let head = buffer(1, ..., index~) in let head ^ skipped = buffer(1, ..., index) in (forall elem | elem in set elems skipped & elem <> skip_val and buffer(index + 1) = skip_val)
This routine skips up to the next occurrence of skip_val in the string leaving the cursor indicating that element.
This feature moves the cursor up to the next occurrence of skip_val in the string, returning self.
skip_to | : SAME |
skip_to2(self : SAME) res : SAME
Since the argument is not optional and either the cursor is in a valid position or it has completely scanned the buffer, the result of this operation is not dependent on whether or not the skip value is present in the buffer. The pre-condition is therefore vacously true.
post let head = buffer(1, ..., index~) in let head ^ skipped = buffer(1, ..., index) in (forall elem in set elems skipped & elem <> skip_val and buffer(index + 1) = skip_val) and res = self
This routine advances the cursor until the next occurrence of skip_val, returning self.
This feature moves the cursor past all elements which are different from the argument, leaving the cursor pointing to the next occurrence of that value.
skip_to | ( |
val : ELT | |
) |
skip_to3(self : SAME, val : ELT)
Since the arguments are not optional and either the cursor is in a valid position or it has completely scanned the buffer, the result of this operation is not dependent on whether or not the skip value is present in the buffer. The pre-condition is therefore vacuously true.
post let head = buffer(1, ..., index~) in let head ^ skipped = buffer(1, ..., index) in (forall elem in set elems skipped & elem <> val and buffer(index + 1) = val)
This routine skips up to the next occurrence of val in the string, leaving the cursor indicating that element.
This feature moves the cursor up to the next occurrence of the argument in the string, returning self.
skip_to | ( |
val : ELT | |
) : SAME |
skip_to4(self : SAME, val : ELT) res : SAME
Since the arguments are not optional and either the cursor is in a valid position or it has completely scanned the buffer, the result of this operation is not dependent on whether or not the skip value is present in the buffer. The pre-condition is therefore vacuously true.
post let head = buffer(1, ..., index~) in let head ^ skipped = buffer(1, ..., index) in (forall elem in set elems skipped & elem <> val and buffer(index + 1) = val) and res = self
This routine advances the cursor until the next occurrence of of the argument value, returning self.
This feature is provided to enable the skipping of any properly nested sub-string with the given start and finish delimiters. The cursor is positioned at the string element after the final finish-delimiter.
skip_block | ( |
start_delimiter : ELT, | |
finish_delimiter : ELT | |
) |
skip_block(self : SAME, start, finish : ELT)
Since neither self nor the delimiter arguments are optional and either the cursor is in a valid position or it has completely scanned the buffer, the result of this operation is not dependent on whether or not the delimiters are present in the buffer. The pre-condition is therefore vacuously true.
post ((self(index~ + 1) = start) and ((is_done and has_error(self)) or (self(index) = finish))) or has_error(self)
Providing that the next element in the string is equal to start_delimiter then this routine skips up to and over the next occurrence of finish_delimiter in the string. Should an occurrence of start_delimiter (not being equal to finish_delimiter) occur then this shall be called recursively. If the string is not properly nested or the finish delimiter is not found then an error has occurred.
This predicate is an alternative to testing an element directly and is of particular use when using scanning with a predicate argument.
is_value(self : SAME, val : ELT) res : BOOL
pre not has_error(self)
post res = (self(index + 1) = val)
This routine returns true if and only if the current string element has the value given as argument.
This feature returns the count of elements in the buffer which have not yet been scanned.
remaining(self : SAME) : res : CARD
Given that the string is finite and cannot be larger than the maximum number which can be represented in a program then the result is less than or equal to that value and the pre-condition must be true.
post res = STP.size(buffer) - index
This routine returns the count of elements in the string not yet scanned.
This feature is the scanning primitive for a cursor item. Successive calls scan the string item by item advancing the cursor one element for each call.
get_item | : ELT |
get_item(self : SAME) res : ELT
post res = self(index)
This routine returns the item currently indicated by the cursor (or void if the complete string has been scanned) and then advances the cursor. It is an error if the cursor cannot be advanced.
This feature scans the string, passing over elements with the value skip_val until one is found which is not that value. The value returned is formed from the remainder of the string up to but not including the next occurrence of skip_val.
get_upto | : STP |
get_upto(self : SAME) res : STP
post let skipped : seq of ELT, wanted : seq of ELT be st skipped ^ wanted = self(index~, ..., index~) in (forall elem | elem in set elems skipped & elem = skip_val) and (forall elem | elem in set elems wanted & elem <> skip_val) and (is_done or (self(index + 1) = skip_val))
This routine scans the string from the current element, skipping until a value which is not the current value of skip_val is found, then up to the next occurrence of the current value of the skip_val, returning the string scanned not including the skip element found. It is not an error if the skip element is not detected before the end of the string.
This feature scans the string, retrieving either count elements or until the remainder of the string is finished whichever occurs first.
get_upto2(self : SAME, count : CARD) res : STP
Since the purpose of this operation is to limit the number of items obtained to be no more than count, the pre-condition is vacuously true.
post (count < remaining and (index = index~ + count) or (index = STP.size(buffer))) and res = self(index~, ..., index)
This routine returns the string starting at the current element until either the given count is reached or the end of the string, whichever occurs first.
This feature scans the string seeking for the given element value. If found then the string between the start index and the position reached is returned, otherwise an error condition is set.
get_upto | ( |
elem : ELT | |
) : STP |
get_upto3(self : SAME, elem : ELT) res : STP
Since the purpose of this operation is to obtain items up to the first occurrence of the given element (if any), the pre-condition is vacuously true.
post (self(index) = elem and (res = self(index~, ..., index)) and forall elt in set elems res & elt <> elem) or has_error(self)
This routine returns the string starting at the current element until either the element with the value elem is reached or the end of the string, whichever occurs first. It is an error if elem is not detected before the end of the string. The contents of the value returned is not specified if an error has occurred.
This feature returns the unscanned portion of the buffer - which may be empty!
get_remainder | : STP |
get_remainder(self : SAME) res : STP
The operation of this feature is entirely independent of the state on entry to this routine, the pre-condition is vacuously true.
post index = STP.size(buffer) and res = self(index~ + 1, ..., index)
This routine returns the remainder of the string starting at the current element. The empty sequence may be returned if all of the string has been scanned.
This feature returns the string sequence from the current position up to (but not including) the next occurrence of the given element or to the end of the buffer, whichever occurs first. Note that it is not an error if the given element is not found.
get_rest_upto | ( |
val : ELT | |
) : STP |
get_rest_upto(self : SAME, elem : ELT) res : STP
The operation of this feature is entirely independent of the state on entry to this routine and of the element value beinglooked for to stop the 'reading', the pre-condition is vacuously true.
post res = self(index~, ..., index)) and forall elt | elt in set elems res & elt <> elem) and (self(index) = elem or is_done)
This routine returns the string starting at the current element until either the element with the value elem is reached or the end of the string, whichever occurs first. It is an error if elem is not detected before the end of the string. The contents of the value returned is not specified if an error has occurred.
This feature is provided to enable the user to retrieve any properly nested sub-string with the given start and finish delimiters. The cursor is positioned at the string element after the final finish-delimiter.
get_block | ( |
start_delimiter : ELT, | |
finish_delimiter : ELT | |
) : STP |
get_block(self : SAME, start, finish : ELT) res : STP
The operation of this feature is entirely independent of the state on entry to this routine and of the start and stop elements, the pre-condition is true, despite the need for the next element to be thstart on entry, since nothing is returned in that case or if a matching stop element is not found.
post (self(index) = start and ((is_done and has_error(self)) or (let startidx = index~ + 2, endidx = index - 1 in res = self(startidx, ..., endidx) and self(index) = finish)) or has_error(self)
Providing that the next element in the string is equal to start_delimiter then this routine returns the sequence of elements after that element and up to the next occurrence of finish_delimiter in the string, the finish delimiter is advanced over. Should an occurrence of start_delimiter (not being equal to finish_delimiter) occur then this shall be called recursively. If the string is not properly nested or the finish delimiter is not found then an error has occurred.
This feature is provided to give information on the kind of problem most recently detected while scanning. See the class definition for CURSOR_ERRORS to find the relevant semantic description.
error(self : SAME) res : [CURSOR_ERRORS]
Since this is a predicate which does not alter any state, the pre-condition is vacuously true.
post has_error(self) or res = nil
This routine returns the error code associated with the most recent scanning error.
This routine is provided to explicitly clear an error-condition in the cursor itself.
clear_error(self : SAME)
Irrespective of whether an error state currently exists or not on entry this operation performs correctly, the pre-condition is therefore vacuously true.
post not has_error(self)
This routine resets the error status of the cursor.
This feature is a predicate which returns true only if an uncleared error has been detected while scannibg.
has_error(self : SAME) res : BOOL
Since this is a predicate with no optional argument, the pre-condition is vacuously true.
post res = (error(self) = nil)
This routine returns true if and only if an uncleared error has occurred during scanning.
![]() |
Language Index | ![]() |
Library Index | ![]() |
String Index |
Comments
or enquiries should be made toKeith Hopper. Page last modified: Wednesday, 4 April 2001. |
![]() |