Back: 13. Internals Forward: 13.2 Second stage of interpretation   FastBack: 13. Internals Up: 13. Internals FastForward: 14. Writing Modules         Top: fsc2 Contents: Table of Contents Index: Index About: About This Document

13.1 First stage of interpretation

In the first stage of the interpretation the script is read in a token by token fashion, where tokens are e.g. variable or function names, numbers, braces, semicolons, section labels etc. This is mainly done by the code within the files which you'll find in the `src' directory having an extension of .l. As you will see there's such a file for each of the different sections an EDL script may contain. Actually, there are some extra ones, `split_lexer.l' is the central switch for the first stage that calls the individual tokenizers in turn on finding a new section label and also deals with error conditions that can't be handled by the section interpreters. Two extra tokenizers, `devices_list_lexer.l' and `func_list_lexer.l' are for analyzing the files with the list of device modules, `conf/Devices', and the list of functions, `conf/Functions' (they also contain some additional C code for interpreting the tokens).

Finally, there is `fsc2_clean.l'. EDL itself expects its input to be a single file in a certain format. Thus it does not deal directly with the input files (there can be more than one when there are #INCLUDE statements in an EDL script). Therefore, there's an extra program, `fsc2_clean' that translates the input EDL script into a form that the main program understands. fsc2_clean for example removes all comments, includes files for #INCLUDE statements, deals with units, adds information about line numbers and file names, deals with physical units etc., and then passes this cleaned-up input to fsc2. If you are interested what fsc2 really sees of an EDL file you can run fsc2_clean with the EDL file as its standard input, i.e.

 
fsc2_clean < edl_script.edl

Please note that the output of fsc2_clean program contains some non-printable characters. Moreover it writes the SHA1 hash value to stderr for what it did output when successfully done.

The lines of EDL script in the sections preceeding the EXPERIMENT section are executed immediately. E.g. during the handling of the DEVICES section the modules for the listed devices are loaded and the functions defined in the modules are included into fsc2s internal list of functions that can be used from within the EDL script. While reading the VARIABLES section the newly defined variables are added to fsc2s list of variables, and, if necessary, initialized.

While the tokenizers (i.e. the files with an extension of .l) are used for splitting of the input into manageable tokens, the execution of the code (now consisting of a stream of tokens) is done in the files with an extension of .y (or, to be precise, by the code generated from these files). In these files, the parsers, actions (mostly a few lines of C code) are executed for syntactically correct sets of tokens. Because actions can only be executed for input with valid syntax, these files practically define what is syntactically correct and what is not (and since the syntax differs a bit for the different sections there's a parser for each of the sections).

To give you an example, here's a very simple statement from an EDL script:

 
a = B_x + 3;

The tokenizer doesn't has too much to do in this case, it will output a list of the tokens of this line, together with some information about the class the individual tokens belong to. So, it will pass the following kind of information to the parser:

 
Floating point variable named 'a'
Equal operator
Integer variable named 'B_x'
Plus operator
Integer number with a value of 3
End of statement character: ;

The parser, in turn, has a list of all syntactically correct statements(22), together with the information what to do for these statements. One of the rules is that a statement consisting of sequence of the tokens

 
Variable, Equal operator, Variable, Plus operator,
integer number, end of statement character

is syntactically correct and that for this sequence of tokens some C code has to be executed that fetches the value of the variable B_x, adds it to the integer number and finally stores the result into the variable a. Statements that are not in the parsers list are per definitionem syntactically incorrect. For example, there is no rule on how to deal with a sequence of tokens as the one above but with the number 3 at the end missing. Because the parser looks at the statements token by token it won't complain while getting the first four tokens up to and including the plus operator. Only if the end of statement operator, the semicolon, is found directly after the plus sign it will recognize that there's no rule on how to deal with the situation, print the error message Syntax error near token ';' (plus the file name and line number) and abort.

The EXPERIMENT section is handled differently. Most important, the code of the EXPERIMENT section is not executed at this stage. It is just split up into its tokens and only some rudimentary syntax check is done, e.g. undefined variables or mismatched braces etc. are detected. Instead an internal list of all the tokens the EXPERIMENT section consists of is created. This list is later used to test and execute the EXPERIMENT section.

Writers of modules should know that the modules already get loaded when the DEVICES section (which always must be the first section) is dealt with. A module may contain a special function, called a hook function, that automatically gets called when the module has just been loaded. This allows for example to set the internal variables of the module to a well-defined state. This function may not call any functions accessing the device because neither the GPIB bus nor the serials ports (or any other devices like ISA or PCI cards) are configured at this moment.

While handling the part of the EDL script up to the start of the EXPERIMENT section, only thar functions from the modules may be called that have been explicitely declared to be usable already before the start of the EXPERIMENT section (and then are not allowed to talk to the devices during that stage). Usually such function calls will be used to define the state of the device at the start of the experiment. For example, the PREPARATIONS section may contain a line like

 
lockin_sensitivity( 100 uV );

When fsc2 interprets this line it will call the appropriate function in the module for the lock-in amplifier with a floating point number of 0.0001 as the argument (the module does not have to take care of dealing with units, they are already translated by fsc2, or, to be precise, by fsc2_clean). The module function for setting the lock-in amplifiers sensitivity should now check the argument it got passed (there may or may not be a sensitivity setting of 0.0001 and only the module knows about this). If the argument is reasonable the module should store the value as to be set when the lock-in amplifier finally gets initialized at the start of the experiment.

How to deal with wrong arguments or arguments that don't fit (e.g. if the argument is 40 uV but the lock-in amplifier has only sensitivity settings of 30 uV and 100 uV) is completely up to the writer of the module, fsc2 will accept whatever the module returns. For example the module may accept the argument after changing it to something to the next possible sensitivity setting and printing out a warning or it may bail out and tell fsc2 to stop interpreting the EDL script.

Another thing module writers should keep in mind is that this first (and also the second) stage is only run once, while the experiment itself may be run several times. Thus it is important that the values with which a device must be initialized at the start of an experiment are stored in a way that they aren't overwritten during the experiment. For example, it does not suffice to have one single variable for the lock-in amplifiers sensitivity because the sensitivity and thus the variable might get changed during the experiment.


Footnotes

(22)

Actually, the parser does not really has a list of all syntactically correct statements but contains a set of rules that define exactly how such statements may look like. One of these rules for example is that a variable name and an equal operator may be followed by either a variable, a function call or an integer or floating point number. Anything not fitting this pattern is a syntax error.


Back: 13. Internals Forward: 13.2 Second stage of interpretation   FastBack: 13. Internals Up: 13. Internals FastForward: 14. Writing Modules

This document was generated by Jens Thoms Toerring on September 6, 2017 using texi2html 1.82.