![]() |
Section 8.16.1.9:
|
![]() |
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 ; $TEXT_CURSOR_ELT_STP = set of object_type ; Pred = ELT -> BOOL state multi : $TEXT_CURSOR_ELT_STP inv multi_types == forall obj in set multi_types & sub_type($TEXT_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 required by a text cursor in addition to those inherited from $CURSOR, introducing features which permit the extraction and skipping of text components, lines, etc.
Several of the post-conditions in this class refer to substrings of some string which contain no line marks. The following functions and predicate are provided to define this. It is used in several places in the following definitions.
functions lmark () res : STP post res = CHAR_STR.str(LIBCHARS.Line_Mark(STP.index_lib(buffer))) space () res : ELT post res = CHAR_CODE.char(LIBCHARS.Space(STP.index_lib(buffer))) no_line_marks(str : STP) res : BOOL pre true post forall idx1, idx2 | idx1 in inds str idx2 in inds str & idx2 - idx1 = len lmark() and str(idx1, ..., idx2) <> lmark())
The following reader routines correspond to some components of the internal state of a cursor object. They are defined in relation to the textual concept of lines and of comments (as in some programming language source text.
This routine enables the value to be set for later incrment as scanning is done. No checking of validity is possible.
reset_line | ( |
val : CARD | |
) |
reset_line(self : SAME, val : CARD)
Since the value given the line number is purely arbitrary so far as this object is concerned, the pre-condition must be vacuously true since it is the callers responsibility to ensure that such things as overflow with later operations does not occur.
postline_no = val
This routine resets the value of the current line in the buffer to the given value. Control of this value is not defined by the scanner.
The cultural context in which the program is executing determines the end of a text line (usually operating system dependent in practice) which is to be taken as a line mark. This predicate returns true if the cursor is currently positioned at a line mark.
is_line_mark(self : SAME) res : BOOL
Since this routine is a predicate, the pre-condition is vacuously true.
post let test = self(index, ..., (index + len lmark)) in res = (test = lmark())
This predicate returns true if and only if the cursor is positioned at a line mark as determined by the buffer cultural context.
This routine sets the start of comment token to be the single element given until a further call of this or the other set_comment_start operation.
set_comment_start | ( |
val : ELT | |
) |
set_comment_start(self : SAME, val : ELT)
Since neither argument is optional, this pre-condition is vacuously true.
post comment_start = [val]
This routine sets the value of the comment start to be the single element given.
This routine sets the start of comment token to be string given until a further call of this or the other set_comment_start operation.
set_comment_start | ( |
val : STP | |
) |
set_comment_start2(self : SAME, val : STP)
pre len val > 0
post comment_start = val
This routine sets the value of the comment start to be the string given.
This routine sets the end of comment token to be the single element given until a further call of this or the other set_comment_start operation.
set_comment_end | ( |
val : ELT | |
) |
set_comment_end(self : SAME, val : ELT)
Since neither argument is optional, then this pre-condition is vacuously true.
post comment_start = [val]
This routine sets the value of the comment end to be the single element given.
This routine sets the end of comment token to be string given until a further call of this or the other set_comment_start operation.
set_comment_end | ( |
val : STP | |
) |
set_comment_end2(self : SAME, val : STP)
post comment_end = val
This routine sets the value of the comment end to be the string given.
Providing that the next element(s) in the buffer are a start comment token then this feature skips to the element beyond the end of the comment and returns true.
skip_comment(self : SAME) res : BOOL
Since this routine is a predicate, the pre-condition is vacuously true.
Note that this makes use of the feature is_done which is specified in the parent class $CURSOR.
post let startidx = (index~ + 1) in let test = self(startidx, ..., (startidx + len comment_start)) in res = ((test = comment_start) and not is_done and (len comment_end = 0 and is_line_mark(self)) or (let endidx = (index - len comment_end) in let finish = self(endidx, ..., (endidx + len comment_end)) in (finish = comment_end))) or (has_error(self) and index = index~)
This predicate returns true if and only if the next item in the buffer is the start of a comment and the cursor is positioned after the end of that comment, otherwise false is returned and the cursor position has not been changed.
This feature advances the cursor past all spaces in the string up to the occurrence of a non-space element or to the end of the string if there are no remaining non-space elements. Note that a comment is treated in this feature as a single space element. The encoding used for a space depends on the repertoire and encoding of the buffer string.
skip_space(self : SAME)
Since the argument is not optional, this pre-condition is vacuously true.
Note that this makes use of the feature is_done which is specified in the parent class $CURSOR.
post let head = buffer(1, ..., index~) in let head ^ skipped = buffer(1, ..., index) in (forall elem | elem in set elems skipped & elem = space and (is_done(self) or (buffer(index + 1) <> space))
This routine advances the cursor past all space elements (including a comment as a single space) or to the end of the string if all remaining elements are spaces.
This version of the space skipping feature advances the cursor past all space elements (treating a comment as a space) before returning self. Note that the encoding which represents a space depends on the enocding and repertoire of the buffer string.
skip_space | : SAME |
skip_space2(self : SAME) res : SAME
Since the argument is not optional, this pre-condition is vacuously true.
Note that this makes use of the feature is_done which is specified in the parent class $CURSOR.
post let head = buffer(1, ..., index~) in let head ^ skipped = buffer(1, ..., index) in (forall elem | elem in set elems skipped & elem = space and (is_done(self) or (buffer(index + 1) <> space)) and res = self
This routine advances the cursor over all space elements (treating a comment as a single space). Note that the space element is defined for the culture encoding and repertoire of the buffer string. Self is then returned.
This feature advances the cursor past all of the elements in the buffer up to and including the next end of line mark - or the end of the string if that occurs first.
skip_over_line(self : SAME)
Since the argument is not optional, this pre-condition is vacuously true.
post let head = buffer(1, ..., index~) in let head ^ skipped ^ lm = buffer(1, ..., index) in no_line_marks(skipped) and (index = len self or lm = lmark())
This routine advances the cursor past the next line mark (if any) in the buffer or up to the end of the string, whichever occurs first.
This feature advances the cursor past all non-spaces in the string up to the occurrence of a space element or to the end of the string if there are no remaining space elements. The encoding used for a space depends on the repertoire and encoding of the buffer string.
skip_word(self : SAME)
Since the argument is not optional, this pre-condition is vacuously true.
Note that this makes use of the feature is_done which is specified in the parent class $CURSOR.
post let head = buffer(1, ..., index~) in let head ^ skipped = buffer(1, ..., index) in (forall elem | elem in set elems skipped & elem <> space and (is_done(self) or (buffer(index + 1) = space))
This routine advances the cursor past all non-space elements or to the end of the string if no remaining elements are spaces.
This version of skipping advances the cursor past all non-space elements up to but not including the next space element before returning self.
skip_word | : SAME |
skip_word2(self : SAME) res : SAME
Since the argument is not optional, this pre-condition is vacuously true.
Note that this makes use of the feature is_done which is specified in the parent class $CURSOR.
post let head = buffer(1, ..., index~) in let head ^ skipped = buffer(1, ..., index) in (forall elem | elem in set elems skipped & elem <> space and (is_done(self) or (buffer(index + 1) = space)) and res = self
This routine advances the cursor up to, but not including the next space element. Self is then returned.
This feature advances the cursor past all of the elements in the buffer up to but not including the next occurrence of the argument - or the end of the string if that occurs first.
skip_to | ( |
str : STP | |
) |
skip_to5(self : SAME, str : STP)
Since the argument is not optional, this pre-condition is vacuously true.
Note that this makes use of the feature is_done which is specified in the parent class $CURSOR.
post let head = buffer(1, ..., index~) in
let head ^ skipped = buffer(1, ..., index) in (forall idx1, idx2 | and idx2 in inds skipped & idx2 - idx1 = len str and skipped(idx1, ..., idx2) <> str) and (is_done(self) or (buffer(index, ..., (index + len str)) = str))
This routine advances the cursor up to (but not beyond)the next occurrence of the argument string or to the end of the line if this occurs first.
This feature advances the cursor past all of the elements in the buffer up to but not including the next occurrence of the argument - or the end of the string if that occurs first before returning self.
skip_to | ( |
str : STP | |
) : SAME |
skip_to6(self : SAME, str : STP) res : SAME
Since the argument is not optional, this pre-condition is vacuously true.
Note that this makes use of the feature is_done which is specified in the parent class $CURSOR.
post let head = buffer(1, ..., index~) in
let head ^ skipped = buffer(1, ..., index) in (forall idx1, idx2 | idx1 in inds skipped and idx2 in inds skipped and idx2 - idx1 = len str & skipped(idx1, ..., idx2) <> str) and (is_done(self) or (buffer(index, ..., (index + len str)) = str)) and (res = self)
This routine advances the cursor up to (but not beyond) the next occurrence of the argument string or to the end of the line if this occurs first before returning self.
This feature advances the cursor past all of the elements in the buffer up to and including the next occurrence of str in the buffer - or the end of the string if that occurs first.
skip_over | ( |
str : STP | |
) |
skip_over5(self : SAME, str : STP)
Since the argument is not optional, this pre-condition is vacuously true.
Note that this makes use of the feature is_done which is specified in the parent class $CURSOR.
post let head = buffer(1, ..., index~) in let head ^ skipped = buffer(1, ..., index) in let hw_mark = len skipped - len str in (forall idx1, idx2 | idx1 in inds skipped(1, ...,hw_mark) and idx2 in inds skipped(1, ...,hw_mark) andidx2 - idx1 = len loc_lm & skipped(idx1, ..., idx2) <> str) and (is_done(self) or (skipped(hw_mark, ..., len skipped) = str))
This routine advances the cursor up to (but not beyond) the next occurrence of the argument string or to the end of the line if this occurs first.
This feature advances the cursor past all of the elements in the buffer up to and including the next occurrence of str in the buffer - or the end of the string if that occurs first.
skip_over | ( |
str : STP | |
) : SAME |
skip_over6(self : SAME, str : STP) res : SAME
Since the argument is not optional, this pre-condition is vacuously true.
Note that this makes use of the feature is_done which is specified in the parent class $CURSOR.
post let head = buffer(1, ..., index~) in let head ^ skipped = buffer(1, ..., index) in let hw_mark = len skipped - len str in (forall idx1, idx2 | idx1 in inds skipped(1, ...,hw_mark) and idx2 in inds skipped(1, ...,hw_mark) and idx2 - idx1 = len loc_lm skipped(idx1, ..., idx2) <> str) and (is_done(self) or (skipped(hw_mark, ..., len skipped) = str)) and (res = self)
This routine advances the cursor up to (but not beyond) the next occurrence of the argument string or to the end of the line if this occurs first before returning self.
This feature is the scanning primitive for a cursor character. Successive calls scan the string item by item advancing the cursor one character for each call.
get_char | : ELT |
get_char(self : SAME) res : ELT
pre not is_done(self)
post res = self(index)
This routine returns the character 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 requires that the cursor is positioned at a line mark in the buffer. This is moved over and returned. Note that the line mark is dependent on the execution environment.
get_line_mark(self : SAME) res : STP
pre is_line_mark(self)
post (index = index~ + len lmark) and res = lmark
This routine advances the cursor over the next line mark which is retrieved and returned.
This feature scans the string, retrieving elements until the first occurrence of a space character or the end of the string has been reached.
get_word | : STP |
get_word(self : SAME) res : STP
Note that this makes use of the feature is_done which is specified in the parent class $CURSOR.
post res = buffer((index~ + 1), ..., index) and (forall elem | elem in set elems res & elem <> space) and (is_done(self) or buffer(index + 1) = space
This routine scans the string from the current element, retrieving characters up to either the first space character or the end of the string has been reached.
This feature scans the string, retrieving elements until either a space is reached, the count is exceeded or the end of the string, whichever occurs first.
get_word2(self : SAME, count : CARD) res : STP
Since the arguments are not optional, this pre-condition is vacuously true.
Note that this makes use of the feature is_done which is specified in the parent class $CURSOR.
post res = buffer((index~ + 1), ..., index) and (forall elem | elem in set elems res & elem <> space) and (is_done(self) or (index - index~ = count) or buffer(index + 1) = space()
This routine returns the string starting at the current element until either the given count is reached or a space is detected or until 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_char | ( |
elem : ELT | |
) : STP |
get_upto_char(self : SAME, elem : ELT) res : STP
Since the arguments are not optional, this pre-condition is vacuously true.
Note the use of the has_error feature here. This is inherited from the patent class $CURSOR.
post (self(index) = elem and (res = self(index~, ..., index)) and forall elt | 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 scans the string seeking for an element for which the predicate argument returns true. If found then the string between the start index and the position reached is returned, otherwise an error condition is set.
get_upto4(self : SAME, predicate : Pred) : res : STP
Since the arguments are not optional, this pre-condition is vacuously true.
Note the use of the has_error feature here. This is inherited from the patent class $CURSOR.
post (predicate(self(index)) and (res = self((index~ + 1), ..., index)) and forall elt in set elems res & not predicate(elt)) or has_error(self)
This routine returns the string starting at the current element until an element satisfying the predicate is reached or the end of the string, whichever occurs first. It is an error if a suitable element 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 string sequence from the current position up to and including the next occurrence of a line mark (if any).
get_str | : STP |
get_str(self : SAME) : res : STP
Since the argument is not optional, this pre-condition is vacuously true.
Note that this makes use of the feature is_done which is specified in the parent class $CURSOR.
post (res = self((index~ + 1), ..., index) and (let head ^ tail be st len tail = len lmark in no_line_marks(head) and (is_done(self) or tail = lmark()))
This routine returns the string starting at the current element up to and including the next line mark (if any).
This feature scans the string seeking for an element which is in the string argument - which is considered as a set of elements rather than a sequence. If found then the string between the start index and the position reached is returned, otherwise an error condition is set.
get_upto_cut | ( |
cut_set : STP | |
) : STP |
get_upto_cut(self : SAME, cut_set : STP) res : STP
Since the arguments are not optional, this pre-condition is vacuously true.
Note the use of the has_error feature here. This is inherited from the parent class $CURSOR.
post (self(index) in set elems cut_set and (res = self((index~ + 1), ..., index)) and forall elt | elt in set elems res & elt not in set elems cut_set) or has_error(self)
This routine returns the string starting at the current element until an element is found which is equal to one of the elements in the argument string considered as a set of elements is reached or the end of the string, whichever occurs first. It is an error if such an element 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 scans the string seeking for an element which is in the string argument - which is considered as a set of elements rather than a sequence. If found then the string between the start index and the position reached is returned, otherwise an error condition is set.
get_upto_cut | ( |
cut_set : STP | |
start : CARD | |
) : STP |
get_upto_cut2(self : SAME, cut_set : STP, start : CARD) : res : STP
pre len cut_set > 0
Note the use of the has_error feature here. This is inherited from the parent class $CURSOR.
post (self(index - 1) in set elems cut_set and (res = self((index~ + 1), ..., index)) and forall elt | elt in set elems res(start - 1, ..., (len res - 1)) & elt not in set elems cut_set) or has_error(self)
This routine returns the string starting at the current element extending up to and including the first element found which is equal to one of the elements in the argument string considered as a set of elements or the end of the string, whichever occurs first. It is an error if such an element 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, irrespective of the current cursor position on the current line of the buffer, returns the entire line up to and including the next occurrence of a line mark (if any).
current_line | : STP |
current_line(self : SAME) : res : STP
Since the concept of a line applies to text with or without line marks, this pre-condition is vacuously true.
post let start : CARD be st (let preceding ^ head = self(start, ..., index~) in ((start = 1 and preceding = []) or preceding = lmark()) and no_line_marks(head)) in let previous = self(start, ..., index~) in let rest ^ test = self((index~ + 1), ..., index) be st ((index = len self and test = []) or test = lmark()) and no_line_marks(rest) in res = previous ^ rest ^ test
This routine returns the string which is the entire current line in the buffer - from beginning to end - including the end of line mark.
This iterator provides a facility for 'parsing' text line by line, yielding logical lines excluding escaped line marks, comment and initial blanks. It provides a similar facility to the class SOURCE in respect of arbitrary text strings. The out argument is the number of the first (non-escaped) line in the string buffer.
Note that the formal name of the iter has been changed to replace the exclamation mark iter symbol to a name acceptable to vdm tools.
line_iter(self : SAME, escape : ELT) res : STP * CARD
Since neither of the arguments are optional, this pre-condition is vacuously true.
This post-condition makes use of the history concept from vdm++ (see the vdm dialect notes).
post loc_res : STP be st let loc_cursor : SAME = create(buffer(index, ..., (index + len loc_res))) in not STP.contains(loc_res,lmark()) and is_line_mark(loc_cursor) in res = mk_(create(loc_res),line_no) and history = history~ + res
For quit actions see the specification of the quit statement.
errs QUIT : index = len self -> quit
This iter yields a string cursor for a new buffer which has been composed by assembling one or more source lines from the buffer for self into a logical line. This is done by omitting comment lines and stripping unwanted line marks at the end as necessary. The iter then returns a new string cursor indexed at the first non-space element of the line found.
![]() |
Language Index | ![]() |
Library Index | ![]() |
String Index |
Comments
or enquiries should be made toKeith Hopper. Page last modified: Sunday, 25 March 2001. |
![]() |