# Section 8.10.3.10:
SOURCE

###### class SOURCE

#### Formal Types

types
SAME = SOURCE ;
SOURCE = seq of Line ;
Line = seq of CHAR
inv ln ==
forall elem in set ln &
elem not in set CODE_STR.str(LIBCHARS.Line_Mark(LIBCHARS.default()))

This class implements a source of logical text lines from which all comments, blank lines and escaped linemarks have been eliminated. A further source of conditional pre-processing is available to eliminate unwanted lines. This is done in a similar manner to the pre-processing of 'if', 'elseif' etc directives done by the C language compiler pre-processing pass.

#### Reader Routine

The following reader routine shall be provided -

- line_no : CARD - this routine shall return the source text line which has most recently been 'read'. This is not necessarily the same number as the number of logical lines scanned.

#### create

This creation routine presumes that the string argument is the name of a file to be opened as source for text data.

create | (
| fname : STR
| ) : SAME

##### Formal Signature

create(fname : STR) res : [SAME]

##### Pre-condition

pre len fname > 0
and let path = FILE_PATH.create(name) in
(path <> nil)
and let dir = DIRECTORY.existent(FILE_PATH.head(path)) in
(dir <> nil)
and DIRECTORY.exists(dir, FILE_PATH.leaf(path))

##### Post-condition

post ((res <> nil)
and (comment(res) = CODE_STR.str(LIBCHARS.Space(LIBCHARS.default())))
and (escape(res) = CHAR_CODE.char(LIBCHARS.Null(LIBCHARS.default())))
or let msg : seq of CHAR be st len msg > 0 in
ERR = ERR~ ^ msg

This routine attempts to open the file with the given name for reading and, if successful, reads its contents and closes the file. If the file is not found or may not be read then void is returned after issuing an error message.

#### create

This creation routine presumes that the file path identifies the file to be opened as source for text data.

create | (
| path : FILE_PATH
| ) : SAME

##### Formal Signature

create2(path : FILE_PATH) res : [SAME]

##### Pre-condition

pre let dir = DIRECTORY.existent(FILE_PATH.head(path)) in
(dir <> nil)
and DIRECTORY.exists(dir, FILE_PATH.leaf(path))

##### Post-condition

post ((res <> nil)
and (comment(res) = CODE_STR.str(LIBCHARS.Space(LIBCHARS.default())))
and (escape(res) = CHAR_CODE.char(LIBCHARS.Null(LIBCHARS.default())))
or let msg : seq of CHAR be st len msg > 0 in
ERR = ERR~ ^ msg

This routine attempts to open the file with the given path for reading and, if successful, reads its contents and closes the file. If the file is not found or may not be read then void is returned after issuing an error message.

#### create

This creation routine presumes that the file path identifies the file which has been passed as the source for data.

create | (
| fyle : TEXT_FILE,
| path : FILE_PATH
| ) : SAME

##### Formal Signature

create3(fyle : TEXT_FILE, path : FILE_PATH) res : [SAME]

##### Pre-condition

pre TEXT_FILE.is_open(fyle)

##### Post-condition

post ((res <> nil)
and (comment(res) = CODE_STR.str(LIBCHARS.Space(LIBCHARS.default())))
and (escape(res) = CHAR_CODE.char(LIBCHARS.Null(LIBCHARS.default())))
or let msg : seq of CHAR be st len msg > 0 in
ERR = ERR~ ^ msg

This routine assumes that the given path is the source name of the open file presented as the first argument. In creating the source the file given is closed.

#### comment

This routine returns the value most recently set for the start of line comment string.

comment | : STR

##### Formal Signature

comment(self : SAME) res : STR

##### Pre-condition

Since a default value is provided on creation, the pre-condition is vacuously true.

##### Post-condition

post len res > 0

This routine returns the string currently in use as the start of line comment marker.

#### comment

This routine sets its argument as the start of line comment for further use until a subsequent call of this routine.

comment | (
| chars : STR
| )

##### Formal Signature

comment2(self : SAME, chars : STR)

##### Pre-condition

pre len chars > 0

##### Post-condition

post comment(self) = chars(1, ..., 2)

This routine establishes the first two characters of the argument as the comment characters to be used henceforth in analysing this source text.

#### escape

This routine returns the value most recently set for the escape character.

escape | : CHAR

##### Formal Signature

escape(self : SAME) res : CHAR

##### Pre-condition

Since a default value is provided on creation, the pre-condition is vacuously true.

##### Post-condition

post true

This routine returns the character currently in use as the escape character.

#### escape

This routine sets its argument as the escape character for further use until a subsequent call of this routine.

escape | (
| ch : CHAR
| )

##### Formal Signature

escape2(self : SAME, ch : CHAR)

##### Pre-condition

pre true

##### Post-condition

post escape(self) = ch

This routine establishes the argument character as the escape character to be used henceforth in analysing this source text.

#### finished

This predicate returns true if and only if there are no more text lines in the source.

finished | : BOOL

##### Formal Signature

finished(self : SAME) res : BOOL

##### Pre-condition

Since this is a predicate, the pre-condition is true.

##### Post-condition

post res =
let pplast = pp_line(self) in
(pplast = nil)
or let last = line(self) in
(last = nil)

This predicate returns true if and only if there are no more lines to be returned from this source, otherwise false.

#### line!

This iter yields a cursor indicating the next logical line in self. All blank and comment lines are removed and an escaped line-mark is ignored, allowing text to flow on as a continuation of what preceded it.

line! | : STR_CURSOR

##### Formal Signature

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) res : STR_CURSOR

##### Pre-condition

This iter effectively has a true pre-condition since it has no arguments. If the iter is called after the last line has been yielded than, of course, it quits.

pre true

##### Post-condition

This post-condition makes use of the history concept from vdm++ (see the vdm dialect notes).

post let loc_res = self(len history~ + 1) in
history = history~ ^ [loc_res]
and res = STR_CURSOR.create(loc_res)

##### Quit condition

For quit actions see the specification of the quit statement.

errs QUIT : len history = len self -> quit

This iter assembles one or more source lines into a logical line without conditional pre-processing, omitting comment lines and blank lines - stripping unwanted line marks at the end as necessary.

#### line

This routine returns a cursor indicating the next logical line in self. All blank and comment lines are removed and an escaped line-mark is ignored, allowing text to flow on as a continuation of what preceded it.

line | : STR_CURSOR

##### Formal Signature

line(self : SAME) res : [STR_CURSOR]

##### Pre-condition

pre not finished(self)

##### Post-condition

post (res = nil)
or (line_no > line_no~)

This routine assembles and returns one or more source lines into a logical line without conditional pre-processing, omitting comment lines and blank lines - stripping unwanted line marks at the end as necessary.

#### pp_line!

This iter yields a cursor indicating the next logical line in self. All blank and comment lines are removed and an escaped line-mark is ignored, allowing text to flow on as a continuation of what preceded it. Pre-processing is carried out on the source in accordance with the semantics defined for the pre-processing tags in the class CONDITIONALS.

pp_line! | : STR_CURSOR

##### Formal Signature

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.

pp_line_iter(self : SAME) res : STR_CURSOR

##### Pre-condition

This iter effectively has a true pre-condition since it has no arguments. If the iter is called after the last line has been yielded than, of course, it quits.

pre true

##### Post-condition

This post-condition makes use of the history concept from vdm++ (see the vdm dialect notes).

post let loc_res = self(len history~ + 1) in
history = history~ ^ [loc_res]
and res = STR_CURSOR.create(loc_res)

##### Quit condition

For quit actions see the specification of the quit statement.

errs QUIT : len history = len self -> quit

This iter yields a sequence of logical lines, each formed by assembling one or more source lines into a logical line with conditional pre-processing as defined by the semantics attached to the pre-processing tags defined in the class CONDITIONALS, omitting comment lines and blank lines - stripping unwanted line marks at the end as necessary.

#### pp_line

This routine returns the next single pre-processed line in the source. See the class CONDITIONALS for pre-processing details.

pp_line | : STR_CURSOR

##### Formal Signature

pp_line(self : SAME) res : [STR_CURSOR]

##### Pre-condition

pre not finished(self)

##### Post-condition

post (res = nil)
or (line_no > line_no~)

This routine assembles and returns one or more source lines into a logical line with conditional pre-processing as defined by the semantics attached to the pre-processing tags defined in the class CONDITIONALS, omitting comment lines and blank lines - stripping unwanted line marks at the end as necessary. If there is no more valid text in the source then void shall be returned.

| Language Index |  | Library Index |  | Input/Output Index

Comments or enquiries should be made to Keith Hopper. Page last modified: Friday, 24 November 2000. |