2.2. - Internal Structure Of spec
This section briefly explains spec's internal structure to give an overview of how it is constructed.
First, consider how a user's input gets interpreted. The initial translation of characters typed at the keyboard (or read from a command file) is done by the input preprocessor, which keeps track of the input sources and handles command recall (or history) substitution.
The input text is then broken into tokens by the lexical analyzer. Tokens represent the different kinds of input objects, such as keywords, operators, variables, number constants and string constants. When the lexical analyzer recognizes a predefined macro name, its definition, possibly with argument substitution, is pushed back onto the input stream to become further input to the lexical analyzer.
The parser in spec repeatedly calls the lexical analyzer to obtain tokens. The parser contains a set of grammar rules that determine acceptable sequences of tokens. A syntax error occurs when input violates these rules. When enough input is read to satisfy a complete set of rules, the parser returns a parse tree (or mini-program) to the executor. The executor code then steps through the parse tree, calling the appropriate internal functions for each action.
The macro-definition command
def
is an exception to the above rules.
As soon as the
parser
recognizes the
def
command sequence, the macro
name and its definition are saved and made available
to the
lexical analyzer, even
while the
parser
is still building the mini-program.
A different command,
rdef
, defers storing the macro definition until the mini-program is executed.
The
rdef
command
is
useful when some flow control logic needs to be run to decide what
definition to assign to the macro.
Understanding the difference between the parse phase and execution phase of spec is important. Each time the command-level prompt is given, a new parse tree will be created. If several semicolon-separated commands are given on the same line, a separate parse tree will be created for each. However, curly brackets can be used to group any number of lines together to form just one parse tree. A significant consequence of the parse tree mechanism is limitation of the scope of a nonglobal variable to the statement block in which it is referenced.
spec may detect error conditions during each of the phases described above. Some of these errors (and the interrupt character, usually a
^C
)
reset
spec to the command-level prompt.
spec also manages auxiliary files. The state file contains the variables, macro definitions, output file names and additional parameter values unique to each user, terminal and diffractometer. The state file preserves the current situation when the user leaves the program so that the same situation can be restored when the user later returns to the program. The history file stores the user's command history. spec also creates an empty lock file to prevent a second instance of spec from running using the same state file. A points file stores the configuration and data associated with the deprecated data group facility. All these files are placed in the userfiles subdirectory of each configuration's auxiliary file area.