spec

Software for Diffraction

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.