# Section 8.16.1.8:
$CURSOR

###### abstract class $CURSOR{ELT < $IS_EQ, STP < $STRING{ELT}}

#### Formal Definitions

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.

#### Reader Routines

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.

- index : CARD - this is the cursor 'pointer' itself.
- buffer : STP - this, as its name suggests is the buffer itself.
- skip_val : ELT - This is a distinguished element value which is used in skipping operations.
- is_done : BOOL - this returns true if and only if the cursor has passed the last item in the buffer.

#### advance

This feature is provided so that any single string element may be passed over during scanning - for example after testing for validity/presence.

advance |

##### Formal Signature

advance(self : SAME)

##### Pre-condition

pre not has_error(self)

##### Post-condition

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.

#### advance

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

##### Formal Signature

advance2(self : SAME) res : SAME

##### Pre-condition

pre not has_error(self)

##### Post-condition

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.

#### retract

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 |

##### Formal Signature

retract(self : SAME)

##### Pre-condition

pre not has_error(self)
and index > 0

##### Post-condition

post index = index~ - 1

This feature retracts the cursor to point to the previous string element.

#### retract

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

##### Formal Signature

retract2(self : SAME) res : SAME

##### Pre-condition

pre index > 0

##### Post-condition

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.

#### item

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

##### Formal Signature

item(self : SAME) res : ELT

##### Pre-condition

pre not is_done(self)

##### Post-condition

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.

#### reassign

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
| )

##### Formal Signature

reassign(self : SAME, str : STP)

##### Pre-condition

pre len str > 0

##### Post-condition

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.

#### clear

This feature clears the buffer, resets the index and clears any error condition.

clear |

##### Formal Signature

clear(self : SAME)

##### Pre-condition

pre true

##### Post-condition

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.

#### set_index

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 | (
| new_posn : CARD
| )

##### Formal Signature

set_index(self : SAME, new_posn : CARD)

##### Pre-condition

pre new_posn < STP.size(buffer)

##### Post-condition

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.

#### set_skip

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
| )

##### Formal Signature

set_skip(self : SAME, val : ELT)

##### Pre-condition

pre true

##### Post-condition

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.

#### set_skip

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
| )

##### Formal Signature

set_skip2(self : SAME, val : ELT) res : SAME

##### Pre-condition

pre true

##### Post-condition

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.

#### skip_over

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 |

##### Formal Signature

skip_over(self : SAME)

##### Pre-condition

pre true

##### Post-condition

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)

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.

#### skip_over

This feature advances the cursor until the next element in the string is not equal to skip_val, returning self.

skip_over | : SAME

##### Formal Signature

skip_over2(self : SAME) res : SAME

##### Pre-condition

pre true

##### Post-condition

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.

#### skip_to

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 |

##### Formal Signature

skip_to(self : SAME)

##### Pre-condition

pre true

##### Post-condition

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)

This routine skips up to the next occurrence of skip_val in the string leaving the cursor indicating that element.

#### skip_to

This feature moves the cursor up to the next occurrence of skip_val in the string, returning self.

skip_to | : SAME

##### Formal Signature

skip_to2(self : SAME) res : SAME

##### Pre-condition

pre true

##### Post-condition

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.

#### skip_to

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
| )

##### Formal Signature

skip_to3(self : SAME, val : ELT)

##### Pre-condition

pre true

##### Post-condition

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.

#### skip_to

This feature moves the cursor up to the next occurrence of the argument in the string, returning self.

skip_to | (
| val : ELT
| ) : SAME

##### Formal Signature

skip_to4(self : SAME, val : ELT) res : SAME

##### Pre-condition

pre true

##### Post-condition

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.

#### skip_block

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
| )

##### Formal Signature

skip_block(self : SAME, start, finish : ELT)

##### Pre-condition

pre true

##### Post-condition

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.

#### is_value

This predicate is an alternative to testing an element directly and is of particular use when using scanning with a predicate argument.

is_value | (
| val : ELT
| ) : BOOL

##### Formal Signature

is_value(self : SAME, val : ELT) res : BOOL

##### Pre-condition

pre not has_error(self)

##### Post-condition

post res = (self(index + 1) = val)

This routine returns true if and only if the current string element has the value given as argument.

#### remaining

This feature returns the count of elements in the buffer which have not yet been scanned.

remaining | : CARD

##### Formal Signature

remaining(self : SAME) : res : CARD

##### Pre-condition

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.

pre true

##### Post-condition

post res = STP.size(buffer) - index

This routine returns the count of elements in the string not yet scanned.

#### get_item

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

##### Formal Signature

get_item(self : SAME) res : ELT

##### Pre-condition

pre true

##### Post-condition

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.

#### get_upto

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

##### Formal Signature

get_upto(self : SAME) res : STP

##### Pre-condition

pre true

##### Post-condition

post let skipped : seq of ELT,
wanted : seq of ELT be st
skipped ^ wanted = self(index~, ..., index~) in
(forall elem in set elems skipped &
elem = skip_val)
and (forall 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.

#### get_upto

This feature scans the string, retrieving either count elements or until the remainder of the string is finished whichever occurs first.

get_upto | (
| count : CARD
| ) : STP

##### Formal Signature

get_upto2(self : SAME, count : CARD) res : STP

##### Pre-condition

pre true

##### Post-condition

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.

#### get_upto

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

##### Formal Signature

get_upto3(self : SAME, elem : ELT) res : STP

##### Pre-condition

pre true

##### Post-condition

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.

#### get_remainder

This feature returns the unscanned portion of the buffer - which may be empty!

get_remainder | : STP

##### Formal Signature

get_remainder(self : SAME) res : STP

##### Pre-condition

pre true

##### Post-condition

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.

#### get_rest_upto

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

##### Formal Signature

get_rest_upto(self : SAME, elem : ELT) res : STP

##### Pre-condition

pre true

##### Post-condition

post res = self(index~, ..., index))
and forall 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.

#### get_block

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

##### Formal Signature

get_block(self : SAME, start, finish : ELT) res : STP

##### Pre-condition

pre true

##### Post-condition

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 isadvanced 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.

#### error

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 | : CURSOR_ERRORS

##### Formal Signature

error(self : SAME) res : [CURSOR_ERRORS]

##### Pre-condition

pre true

##### Post-condition

post has_error(self)
or res = nil

This routine returns the error code associated with the most recent scanning error.

#### clear_error

This routine is provided to explicitly clear an error-condition in the cursor itself.

clear_error |

##### Formal Signature

clear_error(self : SAME)

##### Pre-condition

pre true

##### Post-condition

post not has_error(self)

This routine resets the error status of the cursor.

#### has_error

This feature is a predicate which returns true only if an uncleared error has been detected while scannibg.

has_error | : BOOL

##### Formal Signature

has_error(self : SAME) res : BOOL

##### Pre-condition

pre true

##### Post-condition

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 to Keith Hopper. Page last modified: Friday, 24 November 2000. |