TITLE: LTX2X: A LaTeX to X Auto-tagger AUTHOR(S): Peter R. Wilson Catholic University of America (This work was performed while a Guest Researcher at the National Institute of Standards and Technology) Email: pwilson@cme.nist.gov DATE: January 1997 ABSTRACT: L2X is a table-driven program that will replace LaTeX commands by user defined text. This report describes the beta version of the system. L2X supports both a declaritive command style and an interpreted procedural language tentatively called EXPRESS-A. Details are given of the program functionality including examples. System installation instructions are provided. SECTION: Introduction (sec:introduction) LaTeX [ LAMPORT94], which is built on top of TeX [ KNUTH84a], is a document tagging system that is very popular in the academic and scientific publishing communities because of the high quality typeset material that the system outputs for normal text and especially for mathematics. In particular, many of the documents forming the International Standard ISO 10303, commonly referred to as STEP [ STEPIS], have been written using LaTeX as the document tagging language. Lately there have been moves towards converting the STEP documents to embody SGML [ GOLDFARB90] rather than LaTeX markup. This has led to an interest in the automatic conversion from LaTeX to SGML documents. The L2X system is an initial attempt to provide a generic capability for converting LaTeX tags into other kinds of tags. The L2X system described below is in a beta release state. That is, there is probably some more work to be done on it but experience from use is needed to determine desirable additional functionality. However, the code has been stable for some time. Bug reports or suggested enhancements (especially if the suggestions are accompanied by working code) are encouraged, as are constructive comments about this document. Essentially, L2X reads a file containing LaTeX markup, replaces the LaTeX commands by user-defined text, and writes the result out to another file. The program operates from a command table that specifies the replacement text. In general, no programming knowledge or skills are required to write a command table, which L2X will then interpret. Some knowledge of LaTeX is required, but no more than is necessary for authoring a LaTeX document. L2X has proved capable of performing such functions as: o Conversion of documents marked up according to a specific LaTeX documentclass to documents tagged according to a specific SGML DTD. o Removal of LaTeX commands to produce deTeXed source. o Conversion of simple LaTeX documents to HTML [ MUSCIANO96] tagged documents for publication on the World Wide Web. The remainder of this introduction gives an overview of the L2X program. The command table is described in more detail in section (sec:command-table) and information on running the L2X program is provided in section (sec:program). Section (sec:expressa) gives an overview of the EXPRESS-A language. (Footnote: The overview is necessarily rather brief as I am shortly moving to a new place of employment and EXPRESS-A is the latest addition to the system.) Although the functionality available through the command table facility is suitable for many tasks, especially since an interpreter for the EXPRESS-A general programming language is included within L2X, section (sec:special) gives details on how the system can be extended for cases where this proves to be inadequate. The report ends with several appendices. An example command table for deTeXing a document is reproduced in (sec:detexing) and some of the issues in converting from LaTeX to HTML are discussed in (sec:htmling). The known limitations of L2X are listed in (sec:limitations) and a summary of the command table facilities are given in (sec:summary). Appendix (sec:install) provides instructions on installing the L2X program, together with copyright and warranty information. Finally, (sec:ctabgrammar) and (sec:expgrammar)provide grammars for the command table and EXPRESS-A, respectively. SUB-SECTION: Overview The intent of Leslie Lamport, the author of LaTeX, was to provide a document tagging system that enabled the capture of the logical structure of a document. This system uses Donald Knuth's TeX system as its typesetting engine [ KNUTH84a], and thus has an inherent capability for high quality typesetting. All LaTeX commands are distinguished by starting with a backslash (\). Generally speaking, the name of a command is a string of alphabetic characters (e.g. \acommand). Commands may take arguments. Required arguments are enclosed in curly braces (i.e. { and }). Optional arguments are enclosed in square brackets (i.e. [ and ]). The general syntax for a command is the command name (preceded by a backslash) followed by the argument list with a maximum (Footnote: Under very unusual circumstances this limit may be exceeded.) of nine arguments. The L2X program reads a LaTeX document file and outputs a transformation of this file. By default it outputs the normal text while for each LaTeX command and argument performs some user-specified actions; typically these actions involve the output of specific text corresponding to the particular command. The actions are specified in a command table file, written by the user, which is read into the L2X system before document processing is begun. A command table consists of a listing of the LaTeX commands of interest together with the desired actiond for each of these commands and their arguments. Different effects may be easily obtained by changing the command table file. For example, a simple command table file may be written that will delete all the LaTeX commands from a document, resulting in a plain ASCII file with no embedded markup. (Footnote: To afficionados, this process is known as de-TeX ing.) A more complex command table may be written that will replace LaTeX tags with appropriate SGML tags. In some circles it is traditional to introduce a programming language by providing an example program that prints `Hello world'. In contrast, the following command table file called bye.ct, when used in conjunction with a typical vanilla LaTeX file, will transform the LaTeX file to a file that consists only of the words `Goodbye document'. C= bye.ct "Goodbye document" for ltx2x TYPE= COMMAND NAME= \documentclass START_TAG= "Goodbye document" PC_AT_END= NO_PRINT END_TYPE C= just in case a LaTeX v2.09 document TYPE= COMMAND NAME= \documentstyle START_TAG= "Goodbye document" PC_AT_END= NO_PRINT END_TYPE C= just in case there is no \documentclass/style command TYPE= BEGIN_DOCUMENT START_TAG= "Goodbye document" PC_AT_END= NO_PRINT END_TYPE TYPE= OTHER_COMMAND PRINT_CONTROL= NO_PRINT END_TYPE TYPE= OTHER_BEGIN PRINT_CONTROL= NO_PRINT END_TYPE TYPE= OTHER_END PRINT_CONTROL= NO_PRINT END_TYPE END_CTFILE= end of bye.ct Essentially the command table instructs L2X what to print for each LaTeX command. A command table file consists of a series of commands, one per line and introduced by a keyword such as TYPE=. Keywords are case insensitive but by convention are written in upper case. Comments in a command table are introduced by the keyword C=. The main body of a command table consists of the specification of LaTeX commands of interest and the actions to be taken for these. Each specification commences with the keyword TYPE= and is completed by the keyword END_TYPE, the relevant actions being listed between these two keywords. L2X treats some LaTeX commands specially; among these are \begin{document} and \end{document}. In a command table these are specified by the types TYPE= BEGIN_DOCUMENT and TYPE= END_DOCUMENT. The actions at \begin{document} are firstly to print the string `Goodbye document' (specified in the line START_TAG= "Goodbye document") and secondly to stop printing any output (specified in the line PC_AT_END= NO_PRINT). By not specifying the END_DOCUMENT entry, the default action is used for the \end{document} command. The command table entries for the commands \documentclass and \documentstyle specify that, if either of these is in the source document, then it is to be replaced by the text string "Goodbye document", and then all further printing is to be switched off. The other three entries in the command table specify the actions for any other kind of LaTeX command. The keyword OTHER_BEGIN signifies a LaTeX command of the form \begin{name} and OTHER_END signifies a command of the form \end{name}. The keyword OTHER_COMMAND signifies any other kind of LaTeX command (e.g., \acommand ... ). The actions declared for these are all PRINT_CONTROL= NO_PRINT which shuts off any printing of the command or its arguments. In the command table bye.ct these are only included to prevent printing before the \begin{document}. To run L2X with the above command table, type the following (where > is assumed to be the system prompt): > ltx2x -f bye.ct input.tex output.tex where bye.ct is the name of the command table, and input.tex and output.tex are the names of the input LaTeX file and the resulting processed file respectively. As an example of a more useful command table file, the following one called decomm.ct will remove all LaTeX comments from a typical LaTeX source file. C= decomm.ct Command table file for ltx2x to de-comment LaTeX source C= ------------------------------------ set newline characters ESCAPE_CHAR= ? NEWLINE_CHAR= N C= ----------------------------------- built in commands TYPE= BEGIN_DOCUMENT START_TAG= "\begin{document}" END_TYPE TYPE= END_DOCUMENT START_TAG= "\end{document}" END_TYPE TYPE= BEGIN_VERB START_TAG= "\verb|" END_TYPE TYPE= END_VERB START_TAG= "|" END_TYPE TYPE= BEGIN_VERBATIM START_TAG= "\begin{verbatim}" END_TYPE TYPE= END_VERBATIM START_TAG= "\end{verbatim}" END_TYPE TYPE= LBRACE START_TAG= "{" END_TYPE TYPE= RBRACE START_TAG= "}" END_TYPE TYPE= PARAGRAPH START_TAG= "?N?N " END_TYPE C= ------------------- define '\item' tags within lists TYPE= BEGIN_LIST_ENV NAME= itemize START_TAG= "\begin{itemize}" START_ITEM= "\item " END_TYPE TYPE= BEGIN_LIST_ENV NAME= enumerate START_TAG= "\begin{enumerate}" START_ITEM= "\item " END_TYPE TYPE= BEGIN_LIST_ENV NAME= description START_TAG= "\begin{description}" START_ITEM= "\item" START_ITEM_PARAM= "[" END_ITEM_PARAM= "] " END_TYPE TYPE= END_LIST_ENV NAME= itemize END_TYPE TYPE= END_LIST_ENV NAME= enumerate END_TYPE TYPE= END_LIST_ENV NAME= description END_TYPE C= --------------------- pass through all other LaTeX commands TYPE= OTHER_COMMAND END_TYPE TYPE= OTHER_BEGIN END_TYPE TYPE= OTHER_END END_TYPE END_CTFILE= end of file decomm.ct In the above command table file, the first pair of commands (ESCAPE_CHAR= and NEWLINE_CHAR=) define the character pair that are to be used to signify a `newline' within a tag. An example of their use is later in the file in the PARAGRAPH command type. As indicated above, L2X treats some LaTeX commands specially. These are listed next in the command table. The special LaTeX commands are the begin and end of the document and verbatim environments, together with the \verb command, left and right braces, the \ command, and the L2X PARAGRAPH specification. There are default actions for these, but apart from the \ command the defaults are not appropriate in this case. Above, the actions are to replace the LaTeX command by the string forming the LaTeX command. The exception is that paragraphs (the PARAGRAPH specification) should start with at least one blank line and be indented some spaces. The LaTeX \item command is used within lists. L2X has to be told how to treat the \item command within each kind of list. This has been done above for the itemize, enumerate and description environments. The final instructions in the command table file tell L2X to pass through the text of all other commands and their arguments. The end of the command table file is either the physical end of the file or the command END_CTFILE=, whichever comes first. The END_CTFILE= command acts like the C= command in that arbitrary text can be put after the command. To use the decomm.ct command table to de-comment a LaTeX file, type the following (where > is assumed to be the system prompt): > ltx2x -f decomm.ct input.tex output.tex where input.tex and output.tex are the names of the input LaTeX file for de-commenting and the resulting de-commented version respectively. SECTION: The command table file (sec:command-table) By default, L2X does not output any LaTeX comments. Otherwise, whenever it comes across a LaTeX command it looks at the data in the command table file to determine what actions it should take. The two most typical actions are either to print out the command as read in, or to replace the command by some (possibly empty) text. Each line in a command table file is either blank or starts with a keyword followed by one or more blanks. For example, a comment in the file is a line that starts with C= ; the remainder of the line is any comment text. Comments may be placed anywhere in the file. SUB-SECTION: Special print characters in tags L2X is written in C [ KERNIGHAN88]. The C language enables certain non-printing characters to be defined. These are typically written in the form \c where \ is the C escape character and c is a particular character. L2X understands some of these special printing characters and the command table enables these to be given non-default values. The default escape character (\) may be redefined via the ESCAPE_CHAR= command. For example, ESCAPE_CHAR= ? will make the question mark character the escape character. Typically, the escape character is changed in most command table s to avoid clashing with the LaTeX \ character. The following commands can be used to redefine the C special characters. Each of these commands takes a single character as its value. If a relevant command is not given, then the default value is used. NEWLINE_CHAR= : a new line (default is n) HORIZONTAL_TAB_CHAR= : horizontal tab (default is t) VERTICAL_TAB_CHAR= : vertical tab (default is v) BACKSPACE_CHAR= : backspace (default is b) CARRIAGE_RETURN_CHAR= : carriage return (default is r) FORMFEED_CHAR= : formfeed (default is f) AUDIBLE_ALLERT_CHAR= : beep the terminal (default is a) HEX_CHAR= : following characters form the hexadecimal number of the character to be printed (default is x) (e.g. ?xA3) These command lines are all optional within a command table and their ordering is immaterial. However, if any are present then they must be at the beginning of the command table. The above special characters are useful when specifying the replacement text for LaTeX commands. SUB-SECTION: LaTeX command types The commands for controlling the actions performed on LaTeX commands are enclosed between the command lines TYPE= and END_TYPE, as below. TYPE= CommandType C= a possibly empty set of commands END_TYPE where CommandType is an L2X keyword signifying the kind of LaTeX command being specified. SUB-SUB-SECTION: Built in command types Some LaTeX commands are pre-defined within L2X. Default actions are provided for these but it is recommended that type specifications for each of these commands be put in the command table anyway. The keywords for these commands are: BEGIN_DOCUMENT : Corresponds to the LaTeX command \begin{document}. END_DOCUMENT : Corresponds to the LaTeX command \end{document}. BEGIN_VERBATIM : Corresponds to the LaTeX commands \begin{verbatim} and \begin{verbatim*}. END_VERBATIM : Corresponds to the LaTeX commands \end{verbatim} and \end{verbatim*}. BEGIN_VERB : Corresponds to the LaTeX commands \verb and \verb*, together with the succeeding character. END_VERB : Corresponds to the appearance of the character that completes the LaTeX commands \verb and \verb*. LBRACE : Corresponds to the LaTeX left brace character {. RBRACE : Corresponds to the LaTeX right brace character }. BEGIN_DOLLAR : Corresponds to the LaTeX $ symbol signalling the start of an in-text math formula. END_DOLLAR : Corresponds to the LaTeX $ symbol signalling the end of an in-text math formula. PARAGRAPH : Corresponds to the LaTeX protocol of a blank line signalling the start/end of a paragraph. SLASH_SPACE : Corresponds to the LaTeX \ command. OTHER_COMMAND : Corresponds to any LaTeX command of the form \command not specified elsewhere within the command table. OTHER_BEGIN : Corresponds to any LaTeX command of the form \begin{environment} not specified elsewhere within the command table. OTHER_END : Corresponds to any LaTeX command of the form \end{environment} not specified elsewhere within the command table. The ordering of these built in type specifications is immaterial. If any of the above are not specified within the command table then L2X will use their default action. With the exception of the SLASH_SPACE command type, the default action is to do nothing (i.e., produce no output). The default action for the SLASH_SPACE command type is to output a space. SUB-SUB-SECTION: Optional command types For the purposes of L2X, LaTeX commands are divided into various classes. The keywords for these clases, and the class descriptions, are listed below. TEX_CHAR : Corresponding to LaTeX's special characters (with the exception of the $, { and } characters). CHAR_COMMAND : Corresponding to LaTeX commands of the type \c where c is a single non-alphabetic character. COMMAND : Corresponding to LaTeX commands of the type \command, where command is the name of the command (except for \begin, \end and \item). BEGIN_ENV : Corresponding to LaTeX commands of the type \begin{environment} where environment is the name of the environment, except for those list environments whose bodies consist of \item commands. END_ENV : Corresponding to LaTeX commands of the type \end{environment}, with the same restrictions as for BEGIN_ENV. BEGIN_LIST_ENV : Corresponding to LaTeX commands of the type \begin{environment} where environment is the name of an environment whose body consists of \item commands. END_LIST_ENV : Corresponding to LaTeX commands of the type \end{environment} to match BEGIN_LIST_ENV. VCOMMAND : Corresponding to a LaTeX \verb-like command. BEGIN_VENV : Corresponding to the start of a verbatim-like environment. END_VENV : Corresponding to the end of a verbatim-like environment. SECTIONING : Corresponding to LaTeX commands of the type \command, where command is a document sectioning command such as chapter or subsection. SPECIAL : Reserved for possible future use. SPECIAL_COMMAND : Corresponding to the COMMAND keyword, except that some special output processing is to be defined. SPECIAL_BEGIN_ENV : Corresponding to the BEGIN_ENV keyword, except that some special output processing is to be defined. SPECIAL_END_ENV : Corresponding to the END_ENV keyword, except that some special output processing is to be defined. SPECIAL_BEGIN_LIST : Corresponding to the BEGIN_LIST_ENV keyword, except that some special output processing is to be defined. SPECIAL_END_LIST : Corresponding to the END_LIST_ENV keyword, except that some special output processing is to be defined. SPECIAL_SECTIONING : Corresponding to the SECTIONING keyword, except that some special output processing is to be defined. _PICTURE_ : Corresponding to some of the LaTeX picture drawing commands. COMMAND_... : Corresponding to some of the LaTeX commands whose arrangements of required and optional arguments are untypical. The ordering of these types within a command table is immaterial. Each of the above type specifications requires a NAME= command, whose value is the name of the relevant command or environment being specified. For example, the following is a (partial) specification of the figure environment and the caption command. TYPE= BEGIN_ENV NAME= figure END_TYPE TYPE= END_ENV NAME= figure END_TYPE TYPE= COMMAND NAME= \caption END_TYPE SUB-SECTION: Command action tags When L2X reads a LaTeX command it performs the following actions: (#) Looks up the name of the command or environment in the command table. If it is not found, then the appropriate default type is used. (#) Sets the printing mode according to the PC_AT_START= command. (#) Performs the actions specified in the command table by the START_TAG= command. (#) Processes any specified arguments to the command. (#) Performs the actions specified in the command table by the END_TAG= command. (#) Sets the printing mode according to the PC_AT_END= command. NOTES : : (#) Except for the default processing of OTHER_ types, it does not output the command itself. (#) If a tag action is not specified, then the default action is null (e.g., nothing will appear in the output). Within a command table all text strings for output are enclosed within double quotes. For example: START_TAG= "Some "text" string\n another line of text." Assuming that \n means a newline, when this string action is performed by L2X it will appear in the output file as: Some "text" string another line of text. A text string starts with the first double quote and ends with the last double quote on the command line. A text string has to be written on a single line within the command table. C language special print characters can be embedded within the text string (e.g. the \n for a newline in the above example). Remember that the first section of the command table is used for specifying the particular command table version of these. If a text string is too long to fit comfortably on a single line in the command table, it may be continued via the STRING: command. As many of these can be used in succession as required (subject to internal limitations within L2X). For instance, START_TAG= "Some "text" string\n" STRING: "another line of text." has the same effect as the previous example. The following specification is designed to write out the contents of the \caption command (Footnote: Strictly speaking, the specification does not do this exactly, but this simplified illustration will be corrected in the next sections.) , preceded by the word `CAPTION' and followed by at least one blank line (assuming that the escape character has been set to ?). TYPE= COMMAND NAME= \caption START_TAG= "?n CAPTION " END_TAG= "?n?n" END_TYPE Assuming that somewhere in a LaTeX file there is the command stuff \caption{This is a caption.} more stuff then the expected effect (see footnote) is stuff CAPTION This is a caption. more stuff SUB-SECTION: Argument actions LaTeX commands can take arguments. The text for a required argument is enclosed in curly braces, while the text for an optional argument is enclosed in square brackets. L2X can be directed to perform actions at the start and end of each argument. The number of required arguments is specified by the command line REQPARAMS= where the value of the command is a digit between 1 and 9 inclusive. L2X assumes that a command can have only one optional argument, and that this is either first or last in the argument list. The potential presence of an optional argument is indicated by the command line OPT_PARAM=, where the value is either the keyword FIRST (for first in the list) or LAST (for last in the list). The actions to be performed at the start and end of each required argument are specified via the commands START_TAG_1= and END_TAG_1= for the first required argument, through START_TAG_9= and END_TAG_9= for the ninth argument. The actions to be performed at the start and end of the optional argument are specified by the command lines START_OPT= and END_OPT=. The argument delimiters (the braces or brackets) are not printed. In the simplest case, the action is to print a specified text string (enclosed in double quotes, and continued with STRING: commands if necessary). Other kinds of actions are also possible. An unspecified tag defaults to doing no action. SUB-SUB-SECTION: Print options SUB-SUB-SUB-SECTION: Argument processing By default, L2X processes (i.e. outputs as appropriate) the text of a argument. Printing of the argument text may be disabled, if required. The command line that controls argument printing is of the form PRINT_P1= through PRINT_P9= for required arguments and PRINT_OPT= for the optional argument. The value of these commands is one from several keywords, the most common being NO_PRINT; this switches off printing of the text of the indicated argument. Default printing is resumed after the indicated argument. Continuing the caption example from earlier, we can now complete it. The full syntax of the LaTeX command is: \caption[optional table of contents entry]{Caption in the text} That is, it has one required argument, which prints the caption text both in the body of the document and in the table of contents, unless the first optional argument is present, in which case its value gets printed in the table of contents instead. Assume that an instance of the caption command in a document is: Some stuff \caption[Short caption]{Long caption for the body of the text.} More stuff Recall the previous command table caption specification. The actual output from processing this would be Some stuff CAPTION [Short caption]{Long caption for the body of the text.} More stuff because, unless L2X is told that there are command arguments and how they should be treated, it will just print them out together with their surrounding delimiters. The following command table entry will give more acceptable results. TYPE= COMMAND NAME= \caption START_TAG= "?n CAPTION " END_TAG= "?n?n" OPT_PARAM= FIRST PRINT_OPT= NO_PRINT REQPARAMS= 1 END_TYPE For the above captioning instance, the output will now be: Some stuff CAPTION Long caption for the body of the text. More stuff The default print mode is to print text to the output file. The keywords that can be used to control argument printing are: NO_PRINT : Do not print anything. TO_SYSBUF : Print to the L2X system buffer. TO_BUFFER num : Print to the L2X buffer number num. TO_FILE name : Print to the file called name. NO_OP : Skip all processing of the argument. Note that even if the print mode is set to NO_PRINT, the argument text will still be processed. Only the NO_OP specification temporarly turns off the processing. SUB-SUB-SUB-SECTION: General printing Just as the printing mode can be set for each argument, it can also be set at the start and end of processing a LaTeX command or environment. The specifications PC_AT_START= and PC_AT_END= can be used to set the printing mode at the start of processing a command and at the end, respectively. The keywords that can be used in these specifications are: NO_PRINT : Do not print anything. TO_SYSBUF : Print to the L2X system buffer. TO_BUFFER num : Print to the L2X buffer number num. TO_FILE name : Print to the file called name. RESET : Reset the print mode back to what it was. Unlike the argument printing controls, the print mode is not automatically reset. This has to be explicitly specified. As an example, assume that it is required to remove all figure environments from a LaTeX source and put them into a file on their own. The following command table code could be used to accomplish this. TYPE= BEGIN_ENV NAME= figure PC_AT_START= TO_FILE allfigs.tex START_TAG= "?n\begin{figure}" END_TYPE TYPE= END_ENV NAME= figure START_TAG= "\end{figure}" PC_AT_END= RESET END_TYPE When a LaTeX figure environment is started, printing is switched to go to the file called allfigs.tex. At the end of the figure environment, the print mode is reset back to what it was before the environment began. If at the first figure environment the allfigs.tex file did not exist, then L2X would create it automatically. SUB-SUB-SUB-SECTION: Read actions As noted above, one of the actions that can be specified for a LaTeX comand's argument is to set the print mode for printing to a buffer or a file. Similarly there are actions which will read from a buffer or a file and print the contents. Within an argument tag these kinds of actions are specified via the keyword SOURCE:. This can take one of several values: SYSBUF : Print the contents of the L2X system buffer. BUFFER num : Print the contents of the L2X buffer number num. FILE name : Print the contents of the file called name. In a previous example, the LaTeX figure environments were all written to the file allfig.tex. This file could be read in again just before the end of the document so that all figures will be typeset after everything else. TYPE= END_DOCUMENT END_TAG= "?n % figures collected here by LTX2X ?n" SOURCE: FILE allfigs.tex STRING: "?n\end{document}?n" END_TYPE As another example of the use of the print actions consider the LaTeX \maketitle command. This typesets the arguments of the \title, \author and \date commands, which must have been previously specified but not necessarily in this ordering. Here is one way this can be simulated using L2X. TYPE= COMMAND NAME= \title START_TAG= RESET_BUFFER: 1 REQPARAMS= 1 PRINT_P1= TO_BUFFER 1 END_TYPE TYPE= COMMAND NAME= \author START_TAG= RESET_BUFFER: 2 REQPARAMS= 1 PRINT_P1= TO_BUFFER 2 END_TYPE TYPE= COMMAND NAME= \date START_TAG= RESET_BUFFER: 3 REQPARAMS= 1 PRINT_P1= TO_BUFFER 3 END_TYPE TYPE= COMMAND NAME= \maketitle START_TAG= "?n" SOURCE: BUFFER 1 STRING: "?n?n" SOURCE: BUFFER 2 STRING: "?n?n" SOURCE: BUFFER 3 STRING: "?n?n" END_TAG= RESET_BUFFER: 1 RESET_BUFFER: 2 RESET_BUFFER: 3 END_TYPE For the \title command, the print mode for its argument is set for printing to the buffer number 1. The single action at the start of the command is to make sure that buffer 1 is empty (the line RESET_BUFFER: 1). The actions for the \author and \date commands are similar, except that they print their argument texts to buffers 2 and 3 respectively. The \maketitle command takes no arguments, so all actions must be placed under START_TAG= and/or END_TAG=. There are a set of actions specified for START_TAG=. Firstly a newline is printed and this is followed by the contents of buffer 1 (i.e., the text of the argument of the \title command). Then two new lines are printed, followed by the contents of buffer 2 (the author). Finally another two newlines are printed, the contents of buffer 3 (the date), and another two newlines. The actions for END_TAG= are to clear the contents of the three buffers. Just to extend the example, here is a specification for the LaTeX \thanks command. L2X is not designed to do footnoting (as it does not do page breaking) so instead the thanks text will be placed inside parentheses on a new line. TYPE= COMMAND NAME= \thanks START_TAG= "?n (" REQPARAMS= 1 END_TAG= ") " END_TYPE Given these command table specification and the following portion of a LaTeX document \date{29 February 2000} \title{The Calculation of Leap Days\thanks{Originally published in JIR}} \author{A. N. Other} ... \maketitle then output from L2X will be: The Calculation of Leap Days (Originally published in JIR) A. N. Other 29 February 2000 Note that as the \thanks command appears within the argument of the \title command, it is written to the same place as the text of the argument of \title. Thus, it also gets written to the output file when \maketitle is processed. SUB-SUB-SECTION: Print switching There are individual actions that enable the printing destination to be changed at will within the action set for any particular tag. SWITCH_TO_BUFFER: num : Direct any following printing to the L2X buffer number num. SWITCH_TO_FILE: name : Direct any following printing to the file called name. SWITCH_TO_SYSBUF : Direct any following printing to the L2X system buffer. SWITCH_BACK: : Undo the effect of the last SWITCH_TO... action. As an example of the utility of this type of action, consider again the LaTeX \maketitle command. When LaTeX processes this command, it typesets the date as specified by the \date command, or if this has not been specified then it prints the current date instead. We can arrange for L2X to do something similar by adding the following to the command table shown earlier for the \date and \maketitle commands. TYPE= COMMAND NAME= \documentclass OPT_PARAM= FIRST REQPARAMS= 1 PRINT_OPT= NO_PRINT PRINT_P1= NO_PRINT START_TAG= c= Initialise buffer 3 to `Today' RESET_BUFFER: 3 SWITCH_TO_BUFFER: 3 STRING: "Today" SWITCH_BACK: END_TYPE At the start of the document, the above actions put the string Today into BUFFER 3, having first ensured that it is empty. If the LaTeX source includes a \date command, then the contents of the buffer will be overwritten, otherwise it will be as initialised. In any event, when the \maketitle command is processed, the value output for the date will be either Today or whatever the argument was of the \date command. SUB-SUB-SECTION: Notes on the use of buffers and files Resetting a buffer or a file always has the effect of emptying it of an prior contents. When printing from a buffer or a file, the entire contents are printed. There is no limit to the number of times that a buffer or a file can be used as a printing source. When printing to a buffer, the new strings are appended at the end of the current contents of the buffer, at least until it overflows. Unlike the behaviour of files, this is independant of any intervening prints from the buffer. When printing to a file, the new strings are appended at the end of the current contents of the file. However, if a file is printed to after it has been printed from, the prior contents of the file are lost, and the new string is added at the start of the file. In general, it is safest to treat files as either read-only or write-only. SUB-SUB-SECTION: User specified modes Consider the LaTeX command \\. In normal text this signifies that a line break must occur. In a tabular environment, though, it signifies the end of a row in a table. Suppose that in the L2X procesing of a tabular environment it is required to start and end each row with a vertical bar and to seperate each column also with a vertical bar. However, in normal text a \\ command should just translate into a newline. Just to complicate matters further, assume that in an eqnarray environment, the & column seperator is to be translated to some spaces, and that the string `(X)' is to be put at the end of every row. In other words, we need to process some commands differently according to where they appear in the LaTeX source. An L2X command table provides this capability through mode setting and mode-dependent actions. Here is an example of using this facility to solve the requirements outlined above. TYPE= BEGIN_ENV NAME= tabular C= starting actions, etc., here END_TAG= SET_MODE: tabular END_TYPE TYPE= END_ENV NAME= tabular START_TAG= RESET_MODE: END_TYPE TYPE= BEGIN_ENV NAME= eqnarry C= starting actions, etc., here END_TAG= SET_MODE: eqn END_TYPE TYPE= END_ENV NAME= eqnarray START_TAG= " (X)?n" RESET_MODE: END_TYPE TYPE= TEX_CHAR NAME= & START_TAG= " | " IN_MODE= eqn START_TAG= " " END_MODE END_TYPE TYPE= CHAR_COMMAND NAME= \\ START_TAG= "?n" IN_MODE= tabular START_TAG= " |?n" STRING: " | " END_MODE IN_MODE= eqn START_TAG= " (X)?n" END_MODE END_TYPE Let us look at the specification for the \tabular environment first. The END_TAG= action is specified by the single command line SET_MODE: tabular, where tabular is any convenient name for identifying a mode. Thus, this will set the mode to be tabular. The action at the end of the environment is to reset the mode (RESET_MODE:) to whatever its previous value was. It is assumed that the last row in any tabular environment is finished by \\. Similar actions are performed for the eqnarray environment, except that the mode is called eqn instead of tabular. The other difference is that it is assumed that the last row is not ended by \\, so the end of the eqnarray environment has to also act like the \\. Turning now to the specification for the & command, the first part of the specification identifies the type and name of the LaTeX command. This is then followed by the mode-independent set of actions, which in this case consists of printing a vertical bar with some spaces on either side of it. Following these are any mode-dependent actions, bracketed between IN_MODE= and END_MODE. The value for IN_MODE= is the name of the relevent mode. In this case the only mode-dependent action occurs when MODE eqn is in effect and it is to print some spaces instead of the default spaces and vertical bar. The specification for the \\ command has its set of mode-independent default actions, namely just to print a newline, and two sets of mode-dependent actions. When the tabular mode is in effect, it prints some spaces, a vertical bar, a newline, more spaces, a vertical bar, and finally some more spaces. On the other hand, when the eqn mode is in effect, it prints some spaces, the string `(X)' and a newline. If a mode is in effect that is not defined within the specification (e.g., mode anon) it performs the default mode-independent actions. As a perhaps more practical example, the following command table code will convert simple LaTeX tabular environments to appropriate mark-up for HTML tables. It is assumed that the tabular environment is always within a table environment. To set the perspective a little, here is the code for a simple table in LaTeX: \begin{table}[tbp] \centering \caption{A simple table typeset by \LaTeX.} \label{tab:lxtab} \begin{tabular}{|l||r|r||r|r|} \hline Stock & \multicolumn{2}{c||}{1994} & \multicolumn{2}{c|}{1995} \\ \cline{2-5} & low & high & low & high \\ \hline ABC & 27 & 36 & 23 & 45 \\ DEF & 53 & 72 & 19 & 54 \\ GHI & 28 & 49 & 17 & 79 \\ \hline \end{tabular} \end{table} This will be typeset as shown in table (tab:lxtab). CAPTION: A simple table typeset by LaTeX. (Table: tab:lxtab) Stock | 1994 | 1995 | low | high | low | high ABC | 27 | 36 | 23 | 45 DEF | 53 | 72 | 19 | 54 GHI | 28 | 49 | 17 | 79 The corresponding HTML code for the table after translation is:
Stock | 1994 | 1995 | ||
low | high | low | high | |
ABC | 27 | 36 | 23 | 45 |
DEF | 53 | 72 | 19 | 54 |
GHI | 28 | 49 | 17 | 79 |
...the browser honours the line breaks but does not switch off the meanings of the special characters. In LaTeX, the \verb command switches off all special characters but prohibits any line breaking. The verbatim environment both honours line breaks and switches off all special characters. The difficulty with this particular document is that I want to show author-formatted HTML source, and that is not easly possible, unlike using the LaTeX verbatim environment for showing user-formatted LaTeX source. The problem was solved through the use of two LaTeX environments. The first of these is latexonly which is used for input that is to be processed normally by LaTeX but which is to be totally ignored by L2X. The other environment is htmlverbatim which is used for input that is to be totally ignored by LaTeX but which is to be processed by L2X into an HTML
environment. A package file has been written which provides some addtional commands and environments. % ltx2html.sty --- Some useful commands and environments when using % ltx2x to convert from LaTeX to HTML tagging. % % Author: Peter Wilson August 1996 % \ProvidesPackage{ltx2html}[1996/08/29 ltx2x HTMLing] \RequirePackage{html} % the package file for the Perl program % latex2html % The document title for the WWW browser. % If used, must be placed in the preamble. \newcommand{\mltitle}[1]{} % argument is for processing by LaTeX only \providecommand{\latex}[1]{#1} % argument is for HTML processing only \providecommand{\html}[1]{} % print argument as an SGML/HTML start tag \newcommand{\ST}[1]{\texttt{<#1>}} % print argument as an SGML/HTML end tag \newcommand{\ET}[1]{\texttt{#1>}} % print HTML special characters \newcommand{\Amp}{\&} \newcommand{\GT}{\texttt{>}} \newcommand{\LT}{\texttt{<}} \newcommand{\HASH}{\#} % treat contents as a LaTeX comment but % translate contents into an HTML "verbatim" environment % Use as: \begin{htmlverbatim} ... \end{htmlverbatim} \excludecomment{htmlverbatim} \endinput | \excludecomment{htmlverbatim} \endinput The command table entries for some of these are: TYPE= COMMAND NAME= \Amp START_TAG= "&" END_TYPE TYPE= COMMAND NAME= \GT START_TAG= ">" END_TYPE TYPE= COMMAND NAME= \LT START_TAG= "<" END_TYPE TYPE= COMMAND NAME= \HASH START_TAG= "#" END_TYPE TYPE= COMMAND NAME= \ST START_TAG= "<" END_TAG= ">" REQPARAMS= 1 END_TYPE TYPE= COMMAND NAME= \ET START_TAG= "</" END_TAG= ">" REQPARAMS= 1 END_TYPE Finally, as an example, this is how some of the prior example text could be written in the source of this document. \begin{latexonly} \begin{verbatim}LaTeX to X translator LTX2X: A LaTeX to X Auto-tagger
... \end{verbatim} \end{latexonly} \begin{htmlverbatim}LaTeX to X translator\ET{title} \ET{head} LTX2X: A LaTeX to X Auto-tagger \ET{h1} ... \end{htmlverbatim} | Reading the LaTeX source of this document will reveal some other details. Admittedly the problem was compounded by the fact that this document contains demonstrations of both LaTeX and HTML commands which will be processed through both LaTeX and HTML browsers, thus a modicum of care is required to appropriately process both sets of special characters. SECTION: Known limitations (sec:limitations) L2X does not do everything that it might (and probably never will). The following are some of the things that it does not do. o It does not understand the LaTeX \input or \include commands --- it just reads the source file as given. It may be useful to pre-process the source file through a program that will automatically incorporate included files into a LaTeX root file [ PRW94b]. o The \newcommand and friends do not readily fit into the command patterns that L2X can deal with. In particular, if it comes across a \newcommand specification for a command that is specified in the command table, interesting results might occur (for example, all the following output could be thrown away if the command takes any arguments). For instance, if the document and the command table contain: \newcommand{\lx}{LTX2X} .... The \lx\ program ... TYPE= COMMAND NAME= \lx START_TAG= "LTX2X" END_TYPE then there is usually no problem. On the other hand, if the document and the command table contain: \newcommand{\fd}[1]{\texttt{#1}} .... where \fd{InputFile} is the name ... TYPE= COMMAND NAME= \fd REQPARAMS= 1 END_TYPE then there may be a problem, which might be as `minor' as L2X reporting a parse error when it has reached \newcommand{\fd} in the input file and then carrying on, or it may be more serious. o There is a slight problem with optional arguments. L2X always takes the first close bracket (]) after the opening bracket as signalling the end of the argument text. This occurs even if the close bracket is enclosed in braces (i.e. {]}). Opening brackets within optional argument text are handled correctly. o It cannot sensibly handle LaTeX constructs of the form {\em emph text}. That is, except for command arguments, it does not recognize {...} as a grouping construct, so cannot successfully tag the end of the emph text in the example. On the other hand, if constructs like \emph{emph text} or \begin{em}emph text\end{em} are used instead, start and end tags can be generated, given appropriate specifications in the command table. o It assumes that all commands that take arguments are written so that each argument is enclosed in braces. For example, the superscripting command should be written as ^{2} and not as ^2. Similarly, accent commands should be written as \={o} rather than \=o, and so on. o There has not been time to test all aspects of the EXPRESS-A interpreter. It is possible that this may not perform quite as advertised. In particular dynamic aggregates have not been fully implemented. For example: LIST OF INTEGER; appears to be handled correctly. More complicated constructs involving dynamic aggregates, such as ARRAY [1:7] OF LIST OF ARRAY [-21:21] OF INTEGER; have not been tested. It is improbable that BAG will work; the status of SET is similar and additionally the uniqueness test for set membership has not been implemented. o No doubt other limitations will come to light as L2X gets more use. On the other hand, L2X has been able to handle a broader range of cases than it was designed to address. SECTION: Command table summary (sec:summary) This section summarizes the commands and specifications available for defining a command table. SUB-SECTION: Special print characters The combination of an escape character and another character can be used to specify certain non-visible characters within a tag string. The commands are given in Table (tab:spc). CAPTION: Special print character commands. (Table: tab:spc) Command | Default AUDIBLE_ALERT_CHAR= | a BACKSPACE_CHAR= | b CARRIAGE_RETURN_CHAR= | r ESCAPE_CHAR= | \ FORMFEED_CHAR= | f HEX_CHAR= | x HORIZONTAL_TAB_CHAR= | t NEWLINE_CHAR= | n VERTICAL_TAB_CHAR= | v These commands take one character as their value. If any commands are not specified, then the default value is used. These commands, if used, must be at the beginning of the command table before any TYPE= commands, although their ordering is not significant among themselves. SUB-SECTION: EXPRESS-A code initialization The keyword CODE_SETUP= indicates that the following part of the command table, up until the END_CODE keyword, contains EXPRESS-A code declarations and/or statements. If used, this block must come before any of the TYPE= commands. SUB-SECTION: Comments and file inclusion A comment within a command table file is any line starting with C= . A file can be included within another command table file with the command line INCLUDE= FileName where FileName is the name of the file to be included. The INCLUDE= command cannot appear between the command pair TYPE= and its following END_TYPE. The end of a command table file is either the physical end of the file or the command END_CTFILE=, whichever occurs first. SUB-SECTION: Command types All command type specifications have the general form: TYPE= CommandType NAME= CommandName C= a possibly empty list of mode-independent commands C= possibly sets of mode-dependent commands END_TYPE where CommandType is a keyword identifying the kind of command being specified and CommandName is the identifier of a LaTeX command or environment. The potential set of commands that can be used between the TYPE= and END_TYPE commands depends on the kind of command being specified, but the special print character commands, Table (tab:spc), and the INCLUDE= command cannot appear within a type specification. All command specifications, except for the built in command types (see Table (tab:rct)), must include at least a NAME= command. The ordering of commands within a type specification is not significant. The ordering of type specifications within a command table file is not significant. The NAME= command takes as its value the name of a LaTeX command or environment. The name must be written exactly as it would appear in a LaTeX source file. That is, \command for any command except \begin{} or \end{}, and as env for an environment begun as \begin{env} or ended by \end{env}. SUB-SUB-SECTION: Built in command types Table (tab:rct) lists the keywords for the built in command types. CAPTION: Built in command type keywords. (Table: tab:rct) Keyword | LaTeX command BEGIN_DOCUMENT | \begin{document} BEGIN_DOLLAR | $ at start of in-text math BEGIN_VERB | \verb or \verb* and its following character BEGIN_VERBATIM | \begin{verbatim} or \begin{verbatim*} END_DOCUMENT | \end{document} END_DOLLAR | $ at end of in-text math END_VERB | the ending character for \verb or \verb* END_VERBATIM | \end{verbatim} or \end{verbatim*} LBRACE | { OTHER_BEGIN | of the form \begin{env} not specified elsewhere OTHER_COMMAND | of the form \comm not specified elsewhere OTHER_END | of the form \end{env} not specified elsewhere PARAGRAPH | blank source line RBRACE | } SLASH_SPACE | \ The built in command type specifications can only sensibly use two kinds of actions --- those specified at the start of the command (e.g., PC_AT_START= and START_TAG=) and/or actions at the end of the command (e.g., PC_AT_END and END_TAG=). The NAME= command must not be used. The OTHER_ types are an exception to the above, in that they can include the command line PRINT_CONTROL= NO_PRINT. L2X checks the command table for the presence of these required types. If one or more have not been specified, then they are automatically added to the command table with default values (e.g. empty strings) for the tags, and a warning message is printed giving the default value(s). SUB-SUB-SECTION: Optional command types For discussion purposes, the optional command types have been tabulated in different categories. The basic distinction between these categories is the sets of commands that are permissible within the command specification. At a minimum, all the specifications must include a NAME= command and must not contain any PRINT_CONTROL= or INCLUDE= commands or the special print character commands listed in Table (tab:spc). The keywords for the general command types are given Table (tab:gct). CAPTION: General command type keywords. (Table: tab:gct) Keyword | LaTeX command form TEX_CHAR | LaTeX special characters (except { } $) CHAR_COMMAND | \c, where c is non-alphabetic COMMAND | \command except for sectioning or picture commands BEGIN_ENV | \begin{env} except for \item lists END_ENV | \end{env} except for \item lists VCOMMAND | a \verb-like command BEGIN_VENV | start of a verbatim-like environment END_VENV | end of a verbatim-like environment A general command type specification can include any of the tagging and print option commands. They cannot contain a SECTION_LEVEL= command, nor can they contain any of the _ITEM_ commands. The keywords for the specific command types are given in Table (tab:sct). CAPTION: Specific command type keywords. (Table: tab:sct) Keyword | LaTeX command form BEGIN_LIST_ENV | \begin{env} for \item lists BEGIN_PICTURE_CC | \begin{pic}()() END_LIST_ENV | \end{env} for \item lists END_PICTURE | \end{pic} PICTURE_CCPP | \pic()(){}{} PICTURE_CO | \pic()[] PICTURE_COP | \pic()[]{} PICTURE_CP | \pic(){} PICTURE_OCC | \pic[]()() PICTURE_OCCC | \pic[]()()() PICTURE_OCO | \pic[]()[] PICTURE_PCOP | \pic{}()[]{} SECTIONING | \command for a document section COMMAND_OOP | \com[][]{} COMMAND_OOOPP | \com[][][]{}{} COMMAND_OPO | \com[]{}[] COMMAND_POOOP | \com{}[][][]{} COMMAND_POOP | \com{}[][]{} COMMAND_POOPP | \com{}[][]{}{} A BEGIN_LIST_ENV specification should include at least a START_ITEM= command. The other _ITEM_ commands are optional. Other commands follow the rules for the general command types. The potential commands for the _PICTURE_ commands are the same as for the general commands, with the exception that commands related to optional argument processing are not available for use. A SECTIONING command specification must include a SECTIONING_LEVEL= command. Other commands follow the rules for the general command types. The keywords for the special command types are given in Table (tab:specct). CAPTION: Special command type keywords. (Table: tab:specct) Keyword | LaTeX command form SPECIAL | reserved for possible future use SPECIAL_BEGIN_ENV | \begin{env} except for \item lists SPECIAL_BEGIN_LIST | \begin{env} for \item lists SPECIAL_COMMAND | \command SPECIAL_END_ENV | \end{env} except for \item lists SPECIAL_END_LIST | \end{env} for \item lists SPECIAL_SECTIONING | \command for a document section Apart from the general restrictions on the allowed commands within a specification, there are no restrictions on the commands that can be included within the specification of a SPECIAL_ command. It is up to the creator of the special to decide what is appropriate. However, each SPECIAL_ specification must include the command SPECIAL_TOKEN= N where N is an integer number (with 10000 <= N <= 32767 for a grammar special, or N > 50000 for a code special) that has been specified within L2X as being identified with the grammar and actions corresponding to the value of the NAME= command for the SPECIAL_. SUB-SECTION: Tag specification commands SUB-SUB-SECTION: Arguments The commands relating to the specification of LaTeX command arguments are given in Table (tab:param). CAPTION: Argument commands. (Table: tab:param) Command | Value OPT_PARAM= | FIRST or LAST REQPARAMS= | Integer. The number of required arguments The OPT_PARAM= command specifies that the LaTeX command takes one optional argument and it is the FIRST or LAST in the argument list. The REQPARAMS= command specifies that the LaTeX command has Integer number of required arguments. Integer must be between one and nine (Footnote: Or eight if OPT_PARAM= is specified.) inclusive. Absence of these commands implies that the relevant LaTeX command has no arguments of the unspecified kind. SUB-SUB-SECTION: Tag actions The commands for specifying the tag actions are summarized in Table (tab:tag). The _ITEM_ commands can only be used within a BEGIN_LIST_ENV or a SPECIAL_ command specification. CAPTION: Tag commands. (Table: tab:tag) Command | Application END_ITEM= | actions after \item text END_ITEM_PARAM= | actions after \item optional argument END_OPT= | actions after optional argument END_TAG= | actions after all arguments processed END_TAG_n= | actions after n'th required argument START_ITEM= | actions before \item START_ITEM_PARAM= | actions before \item optional argument START_OPT= | actions before optional argument START_TAG= | actions at start of command START_TAG_n= | actions before n'th required argument Each of these commands can specify a list of actions to be performed; typically this is just to print a text string. A string is any set of characters enclosed in double quote marks. The string can include any special printing characters. The text string starts immediately after the first double quote and ends immediately before the last double quote. The string cannot include a physical linebreak within the command table file. If the first action is to print a string then the string may be placed on the same line as the keyword. The actions are listed one per line and are performed in the order they are listed. Table (tab:tagaction) lists the action commands. CAPTION: Tag actions. (Table: tab:tagaction) Keyword | Value | Application STRING: | text string | Print the string SOURCE: | BUFFER num | Print the contents of buffer number num SOURCE: | FILE name | Print the contents of file name SOURCE: | SYSBUF | Print the contents of the system buffer RESET_BUFFER: | num | Reset the buffer num RESET_FILE: | name | Reset the file name RESET_SYSBUF: | | Reset the system buffer SWITCH_TO_BUFFER: | num | Print to buffer number num SWITCH_TO_FILE: | name | Print to file called name SWITCH_TO_SYSBUF: | | Print to the system buffer SWITCH_BACK: | | Reset the print mode SET_MODE: | name | Set the mode to name RESET_MODE: | | Reset the mode to its prior value CODE: | | Start of a set of EXPRESS-A statements SUB-SUB-SECTION: Print control The print control commands are summarized in Table (tab:print). These are used to set the print mode at the start and end of a command, and for each argument. The exception is the PRINT_CONTROL= command which can only be used within an OTHER_ command type specification, and which is the only print control that can be specified for the OTHER_ commands. CAPTION: Print control commands. (Table: tab:print) Command | Application PRINT_CONTROL= | printing of OTHER_ commands PC_AT_START= | set printing at start of command PC_AT_END= | set printing at end of command PRINT_OPT= | printing of optional argument PRINT_Pn= | printing of n'th required argument The values that these commands may take are given in Table (tab:pcvalues). These direct where any print output is to be directed. The default is to send all output the the file named as the output on the command line when starting L2X. CAPTION: Print control values. (Table: tab:pcvalues) Value | Application NO_PRINT | Do not print at all TO_SYSBUF | Print to the system buffer TO_BUFFER num | Print to buffer number num TO_FILE name | Print to file called name NO_OP | Do not do any processing RESET | Reset the print mode NO_PRINT and NO_OP both produce no printed output. However, in the NO_OP case the lexer handles all the processing, and effectively just ignores the source document text. In the NO_PRINT case, the source text is processed as normal, but the printing is directed to a black hole. SUB-SUB-SECTION: Sectioning SECTIONING command specifications require a SECTIONING_LEVEL= command. The values that this can take are listed in Table (tab:level). CAPTION: Sectioning level values. (Table: tab:level) Value | Application PART | sectioning equivalent to \part CHAPTER | sectioning equivalent to \chapter SECT | sectioning equivalent to \section SUBSECT | sectioning equivalent to \subsection SUBSUBSECT | sectioning equivalent to \subsubsection PARA | sectioning equivalent to \paragraph SUBPARA | sectioning equivalent to \subprargraph A sectioning command specification uses the END_TAG= text tag differently from its use by any other specification. In this case, the tag is printed at the closure of the text forming the body of the section of the document. A document section is considered to be closed when it is followed by a higher level sectioning command. The values in Table (tab:level) are listed in decreasing level. That is, a section at level CHAPTER is at a higher level than a section at level PARA. NOTE : For the use of writers of SPECIAL_ command specifications, SECTIONING_LEVEL= can be given some additional values. These are PARTm2 and PARTm1 for levels respectively two and one higher than PART, and SUBPARAp1 and SUBPARAp2 for levels respectively one and two lower than SUBPARA. SECTION: System installation (sec:install) This section describes how to install the L2X program and some of the internal size limits within L2X. The basic L2X system requires the following source files: l2x.l : the lexer source. l2x.y : the parser source. l2xlib.c, l2xlib.h : main program and support functions. l2xlibtc.h : header file containing keywords and their representations as strings. l2xcom.h : header file for all system components (except for getopt, srchenv and the interpreter). l2xacts.c, l2xacts.h : standard action functions. l2xusrlb.c, l2xusrlb.h : special actions and user-defined functions. strtypes.h : header file with some type definitions. getopt.c, getopt.h : functions for handling command line options [Chapter 6 LIBES93]. srchenv.c, srchenv.h : functions for searching directories for files [page 747 HOLUB90]. The EXPRESS-A interpreter also requires the following files: l2xistup.c : the interface between the main part of L2X and the interpreter. l2xicmon.h : header file for the interface. l2xirtne.c, l2xistd.c, l2xidecl.c, l2xistmt.c, l2xiexpr.c : the files that contain the code for parsing EXPRESS-A. Respectively they deal with functions and procedures, the built-in functions, declarations, statements, and expressions. l2xiprse.h : header file for parsing. l2xixutl.c, l2xiexec.h : utility routines supporting the execution module and for managing the interpreter's stack. l2xixstd.c, l2xixstm.c, l2xixxpr.c : functions for executing the EXPRESS-A built in functions, statements and expressions. l2xirexp.c, l2xirexpr.h : general functions for processing and executing regular expressions. listsetc.c, listsetc.h : general functions for processing lists. l2xiscan.c, l2xiscan.h : lexing routines for the interpreter. l2xisymt.c, l2xisymt.h : routines for managing the interpreter's symbol tables. l2xidbug.c : the source level debugger. l2xierr.c, l2xierr.h : EXPRESS-A language error handling and diagnostic output for the user. l2xiidbg.c, l2xiidbg.h, l2xisdcl.c : diagnostics for a developer of the interpreter. licomsym.h : general header file for the interpreter modules. l2xidftc.h, l2xiertc.h, l2xisctc.h, l2xisftc.h : header files containing keywords and their representations as strings. The following files may be useful: man : the manpage printct.c : a program to print and update command table files; ltx2html.sty : a LaTeX package file to assist in retagging a LaTeX document to an HTML document. Essentially, installing L2X consists of processing the file l2x.l through a lexer generator, processing the file l2x.y through a parser generator, and then compiling the results together with the other supplied source files. The lexer source file l2x.l and the parser source file l2x.y have to be processed by flex (or equivalent) and bison (or equivalent) respectively to generate C code. This code, together with the code in the other source files must then be compiled and linked to form the executable. The executable must then, after suitable testing, be moved to its final place in your system and the manpage (file man) also copied to its final position in your directory structure. Included in the L2X distribution are several command table files. One is detex.ct which provides an example of commands for de-TeX ing a document. (Footnote: You may wish to try using detex.ct on the LaTeX source of this document to see what the effect is. This can also serve as a check on the system installation.) Another is remcom.ct which provides an example of commands to remove comments from a LaTeX document. The command table file bye.ct replaces a LaTeX document by "Goodbye document". Another is ltx2x.ct which does nothing except try and include another file named ZiLcH, which presumably is not on anyone's system. Running L2X with this file will prompt for another name of a file if it cannot find ZiLcH; enter an existing file (like detex.ct) at the prompt. (Footnote: This is one way of setting up L2X for interactive specification of the desired command table file(s).) The command table file l2h.ct has proven to be adequate for converting the LaTeX source of this manual, and other LaTeX documents without pictures and only limited mathematics, into an ASCII file with HTML tags instead. The file fun.ct contains some test code for the EXPRESS-A interpreter. The contents are similar to the example shown at the end of section (sec:expressa). The l2xusrlb files are skeletons. The system does include the functions and parser constructs for the \GRAMMspecial and \CODEspecial commands used as examples previously. The last two entries in remcom.ct are the specification of these, and the implementation is as described previously. SUB-SECTION: Command table printing The grammar of the command table has been changed slightly since the initial release of L2X. The utility C program in printct.c may be used to: o Pretty-print a command table; o Convert an original command table to one that conforms to the new grammar. The syntax for running printct is: printct [-D dir_cat_char] [-P path_seperators] [-f table_file] [-t] where elements in square brackets are options. These options are identical to the corresponding ones for L2X and are as follows: -f : By default, printct reads the command table from a file called ltx2x.ct. If the required command table is in a file with another name this option is used to change from the default file. For example, > printct reads a command table from ltx2x.ct, while > printct -f detex.ct reads a command table from file detex.ct. -t : This generates some diagnostics related to the processing of the command table file. -D : The value of this option is the character that the operating system uses to catenate directory names to form a path (see (sec:search)). The default value is a slash (i.e. /). The default could be changed to a backslash, for example, by -D \. -P : The environment variable (see (sec:search)) contains a list of directories (also known as path names). In the operating system that I use, these are separated by the colon (:) character which, together with the semi-colon and space characters, form the L2X default separators. The path separator characters can be changed with this option. For example, -P : will make the separators be a colon or a space (space is automatically included in the separator list). printct only reads a single command table file and outputs the pretty-printed and updated version to file printct.lis. It performs a very limited amount of error checking and writes error messages and statistics to the file printct.err. SUB-SECTION: A make file Here is a UNIX make file [ ORAM91] for the L2X system. # makefile for program ltx2x --- LaTeX to X autotagger # ##################### Change the following for your setup # The compiler CC = cc # We use flex (or equivalent, but not lex) to generate the lexer LEX = flex # and the options LEXFLAGS = -v # We use bison (or equivalent) to generate the parser YACC = bison # and the options YACCFLAGS = -y -d -v # Libraries to be used LIBS = -ly -ll -lm # The root directory for the installation (e.g., /usr/local ) ROOTDIR = /proj/ltx/teTeX033 # Where to place the running code (e.g. /usr/local/bin ) BINDIR = ${ROOTDIR}/bin # Where to place the manpage (e.g., /usr/local/man/man1 ) MANEXT = 1 MANDIR = ${ROOTDIR}/man/man${MANEXT} # Just in case you want to change the name of the binary # (and then you should also change the man page and documentation). # So, do not change this. PROG = ltx2x # Where to place the user documentation (e.g., /usr/local/doc/ltx2x ) DOCDIR = ${ROOTDIR}/doc/${PROG} # Where to place the example command tables (e.g., /usr/local/lib/config/ltx2x ) CTDIR = ${ROOTDIR}/lib/config/${PROG} # The file copy command (copy but do not delete original) COPY = cp # The file move command (move and delete original) MOVE = mv # The file delete command DELETE = rm # The make directory (hierarchy) command MAKEDIR = mkdirhier # The stream editor command SED = sed # Command to write to the terminal (stdout) ECHO = echo ################### You should not have to change anything after this # The source modules L2XSRCS = l2xytab.c l2xlexyy.c l2xlib.c l2xacts.c l2xusrlb.c getopt.c srchenv.c INTSRCS = l2xirtne.c l2xistd.c l2xidecl.c l2xistmt.c l2xiexpr.c l2xiscan.c l2xisymt.c l2xierr.c l2xiidbg.c l2xistup.c l2xistm.c l2xixxpr.c l2xixstd.c l2xidbug.c l2xisdcl.c l2xirexp.c listsetc.c # The object modules L2XOBJS = l2xytab.o l2xlexyy.o l2xlib.o l2xacts.o l2xusrlb.o getopt.o srchenv.o INTSRCS = l2xirtne.o l2xistd.o l2xidecl.o l2xistmt.o l2xiexpr.o l2xiscan.o l2xisymt.o l2xierr.o l2xiidbg.o l2xistup.o l2xistm.o l2xixxpr.o l2xixstd.o l2xidbug.o l2xisdcl.o l2xirexp.o listsetc.o OBJS = ${L2XOBJS} ${INTOBJS} # Link object code together into PROG ltx2x : ${OBJS} ${CC} -o ${PROG} ${OBJS} ${LIBS} # Compile C source code into object code getopt.o : getopt.c getopt.h ${CC} -c getopt.c l2xytab.o : l2xytab.c l2xlib.h l2xusrlb.h l2xacts.h strtypes.h l2xcom.h ${CC} -c l2xytab.c l2xlexyy.o : l2xlexyy.c l2xytab.h l2xlib.h l2xusrlb.h l2xcom.h ${CC} -c l2xlexyy.c l2xlib.o : l2xlib.c getopt.h l2xytab.h strtypes.h l2xcom.h ${CC} -c l2xlib.c l2xusrlb.o : l2xusrlb.c l2xlib.h l2xytab.h strtypes.h l2xcom.h ${CC} -c l2xusrlb.c l2xacts.o : l2xacts.c l2xusrlb.h l2xlib.h l2xytab.h strtypes.h l2xcom.h ${CC} -c l2xacts.c srchenv.o : srchenv.c srchenv.h ${CC} -c srchenv.c # Generate C code for parsing l2xytab.c l2xytab.h: l2x.y @ ${ECHO} "Expect 10 shift/reduce conflicts to be reported" ${YACC} ${YACCFLAGS} l2x.y ${MOVE} y.tab.c l2xytab.c ${MOVE} y.tab.h l2xytab.h # Generate C code for lexing l2xlexyy.c : l2x.l ${LEX} ${LEXFLAGS} l2x.l ${MOVE} lex.yy.c l2xlexyy.c # the interpreter modules # compiler flags for analyze and execute modules ANLFLAG = -Danalyze RUNFLAG = -Dtrace # interpreter header files SOMEH = l2xicmon.h l2xierr.h l2xiscan.h l2xisymt.h licomsym.h l2xiidbg.h MOSTH = ${SOMEH} l2xiprse.h ALLH = ${MOSTH} l2xicpr.h l2xiexec.h # interpreter interface l2xistup.o : l2xistup.c ${ALLH} ${CC} -c ${ANLFLAG} ${RUNFLAG} l2xistup.c # the parser module l2xirtne.o : l2xirtne.c ${ALLH} ${CC} -c ${ANLFLAG} l2xirtne.c l2xistd.o : l2xistd.c ${MOSTH} ${CC} -c ${ANLFLAG} ${RUNFLAG} l2xistup.c l2xistup.o : l2xistup.c ${ALLH} ${CC} -c l2xistd.c l2xidecl.o : l2xidecl.c ${MOSTH} l2xicpr.h ${CC} -c ${ANLFLAG} l2xisdecl.c l2xistmt.o : l2xistmt.c ${ALLH} ${CC} -c ${ANLFLAG} l2xistmt.c l2xiexpr.o : l2xiexpr.c ${MOSTH} l2xicpr.h ${CC} -c ${ANLFLAG} l2xiexpr.c # the scanner module l2xiscan.o : l2xiscan.c ${SOMEH} l2xicpr.h ${CC} -c ${ANLFLAG} l2xiscan.c # symbol table module l2xisymt.o : l2xisymt.c l2xicmon.h l2xierr.h l2xisymt.h licomsym.h l2xiidbg.h ${CC} -c l2xisymt.c # executor module l2xixutl.o : l2xixutl.c ${MOSTH} l2xiexec.h listsetc.h ${CC} -c ${RUNFLAG} l2xixutl.c l2xixstm.o : l2xixstm.c ${MOSTH} l2xiexec.h listsetc.h ${CC} -c ${RUNFLAG} l2xixstm.c l2xixxpr.o : l2xixxpr.c ${MOSTH} l2xiexec.h listsetc.h ${CC} -c ${RUNFLAG} l2xixxpr.c l2xixstd.o : l2xixstd.c ${MOSTH} l2xiexec.h listsetc.h ${CC} -c ${RUNFLAG} l2xixstd.c l2xidbug.o : l2xidbug.c ${SOMEH} l2xiexec.h listsetc.h ${CC} -c ${RUNFLAG} l2xidbug.c # error and miscellaneous l2xisdcl.o : l2xisdcl.c ${SOMEH} ${CC} -c ${ANLFLAG} ${RUNFLAG} l2xisdcl.c l2xiidbg.o : l2xiidbg.c ${SOMEH} l2xiexec.h ${CC} -c l2xiidbg.c l2xirexp.o : l2xirexp.c l2xirexp.h ${CC} -c l2xirexp.c listsetc.o : listsetc.c listsetc.h ${CC} -c listsetc.c # only call make install if BINDIR has been set install : ltx2x ${MAKEDIR} ${BINDIR} ${MOVE} ${PROG} ${BINDIR} # Edit the file man to replace DOCUMENTDIR by the actual directory # where the user manual is to be placed, and CTDIR by the location # of the example command table files. # Then copy the manpage to the proper place manpage : ${SED} 's!DOCUMENTDIR!${DOCDIR}!; s!CTDIR!${CTDIR}!' man > tman ${MAKEDIR} ${MANDIR} ${COPY} tman ${MANDIR}/${PROG}.${MANEXT} # Copy the user manuals to the proper place doc : ${MAKEDIR} ${DOCDIR} ${COPY} ltx2x.tex ${DOCDIR}/${PROG}.tex ${COPY} ltx2x.ps ${DOCDIR}/${PROG}.ps ${COPY} ltx2x.txt ${DOCDIR}/${PROG}.txt ${COPY} ltx2x.html ${DOCDIR}/${PROG}.html # Copy the example command tables to their final location ctables : ${MAKEDIR} ${CTDIR} ${COPY} ltx2x.ct ${CTDIR}/ltx2x.ct ${COPY} detex.ct ${CTDIR}/detex.ct ${COPY} remcom.ct ${CTDIR}/remcom.ct ${COPY} l2h.ct ${CTDIR}/l2h.ct ${COPY} bye.ct ${CTDIR}/bye.ct ${COPY} fun.ct ${CTDIR}/fun.ct # Do almost everything except clean up all : ltx2x install manpage doc ctables # call make clean to remove the object files, info from YACC, # and the edited version of the manpage clean : ${DELETE} *.o ${DELETE} y.output ${DELETE} tman # Compile the command table printer printct : printct.o getopt.o srchenv.o ${CC} -o printct printct.o getopt.o srchenv.o printct.o : printct.c getopt.h strtypes.h l2xcom.h ${CC} -c printct.c If you use the above makefile then the first part should be edited to reflect your system's configuration. You could do make all which should do everything for you, except the cleaning up. A more conservative approach is recommended. First just do make which will generate the executable. This can then be tested. When all is well do make install and make manpage which will put the executable and the manpage into their final positions. Finally, make clean will remove the intermediate files generated during the build process. The above make file uses flex as the lexer generator. You can use your favorite one instead but it must, unlike lex, support exclusive start states. Also, bison is used above as the parser generator. Again, you can use your favorite one. As far as I am aware, there is nothing remarkable about the grammar, except that during early development I exceeded the size limits of yacc. The grammar has been simplified since then, so this may no longer be a problem. NOTE: If bison is used it reports that there are 10 shift/reduce conflicts. It appears that these can be safely ignored. One compilation problem has been noted by Uwe Sassenberg (Footnote:
) on AIX 3.2 and IRIX 5.3 systems, but I could not reproduce it on a SunOS 4.1.3 system. This is when the main procedure of L2X is processing the optional command line arguments. For some reason it had difficulties with the C EOF. The symptom was that the program compiled but when it was run it sat there absorbing CPU cycles and doing nothing as it had got into an infinite while loop. The cure was to insert the following line of code in file l2xlib.c: main(argc,argv) ... /* get command line optional parameters */ opterr = 1; /* getopt prints errors if opterr is 1 */ while (EOF != (optchar = getopt(argc,argv, "l:ty:f:cp:wE:P:D:"))) { /* insert this line of code: if (optchar == 255) break; end insert */ switch(optchar) { ... This code line which you may need to insert is supplied as a comment in the distributed source. SUB-SECTION: Limits and errors The L2X system has some built-in limits which are defined in l2xlib.c. The following is a listing of the relevant sizes. CLAUSE_STACK_SIZE : The maximum nesting depth of document sectioning. This is set somewhat larger than the number of standard LaTeX sectioning command types. (Default 10) EVERY_N_LINES : Controls the frequency of printing processed line numbers to the terminal. (Default 100) LIST_STACK_SIZE : The maximum nesting depth of list environments. This is set somewhat larger than the standard LaTeX nesting depth. (Default 10) MAX_BUFFER : The maximum number of characters that can be held in the system buffer, and also the maximum number of characters in a pretty-printed output line. (Default 2000) MAX_CT_STACK : The maximum nesting depth for included command table files. (Default 20) MAX_ERRORS : The maximum number of non-fatal errors discovered in command table processing or in source file processing before L2X quits. (Default 10) MAX_LINE : The maximum number of characters in a line of a LaTeX source file. (Default 2000) MAX_PRINT_STACK : The maximum nesting depth for print control commands. (Default 100) MAX_TABLE_ENTRIES : The maximum number of TYPE specifications in a command table (including the built in type specifications). (Default 1000) MAX_TABLE_LINE : The maximum number of characters in a line in a command table file. (Default 254) MAX_USER_BUFFS : The maximum number of user buffers. (Default 20) MAX_UBUFF_LEN : The maximum number of characters that can be stored in a user buffer. (Default 510) MAX_USER_FILES : The maximum number of user files. (Default 16) L2X prints out a summary of the program statistices at the end of the ltx2x.err file. If the limits are not suitable for your purposes, then they may be changed and the system rebuilt. L2X can produce a variety of error and warning messages, for example when any of the above limits are exceeded. Some of the messages are related to command table processing, while others are related to LaTeX document processing. Both these kinds of messages are targeted to the normal end user. There is another set of messages that are aimed at the implementor of new SPECIAL_ commands. An implementor may also find some of the debugging options useful if things really fall apart. SUB-SECTION: Availability Source code and documentation for L2X is available from the NIST SOLIS (SC4 On-Line Information Service) system [ RINAUDOT94] in directory /subject/sc4/editing/latex/programs/ltx2x. SOLIS can be accessed by: o Anonymous ftp to ftp.cme.nist.gov (cd to /pub/subject/sc4...) http://www.nist.gov/sc4 o URL Any comments should be directed to apde@cme.nist.gov. SUB-SUB-SECTION: Copyright Development of this software was funded by the United States Government and is not subject to copyright. It was developed by the Manufacturing Systems Integration Division (MSID) of the Manufacturing Engineering Laboratory (MEL) of the National Institute of Standards and Technology (NIST). SUB-SUB-SECTION: Disclaimer There is no warranty for the L2X software. If the L2X software is modified by someone else and passed on, NIST requests that the software's recipients be notified that what they have is not what NIST distributed. Policies : (#) Anyone may copy and distribute verbatim copies of the source code as received in any medium. (#) Anyone may modify your copy or copies of the L2X source code or any portion of it, and copy and distribute such modifications provided that all modifications are clearly associated with the entity that performs the modifications. NO WARRANTY : NIST PROVIDES ABSOLUTELY NO WARRANTY. THE L2X SOFTWARE IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD ANY PORTION OF THE L2X SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. IN NO EVENT WILL NIST BE LIABLE FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY NIST) THE PROGRAMS, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. SECTION: A grammar for the command table (sec:ctabgrammar) SUB-SECTION: Notation The syntactical constructs used correspond to a derivative of the Wirth Syntax Notation (WSN) [ WIRTH77]. The semantics of the enclosing braces are: o curly braces `{ }' indicate xero or more repetitions; o square brackets `[ ]' indicate an optional element; o parenthesis `( )' indicates a group; o vertical bar `|' indicates that exactly one of the terms in the expression shall be chosen. Here is the grammar for WSN defined in itself. syntax = { production } . production = identifier '=' expression '.' . expression = term { '|' term } . term = factor { factor } . factor = identifier | literal | group | option | repetition . identifier = character { character } . literal = '''' character { character } '''' . group = '(' expression ')' . option = '[' expression ']' . repetition = '{' expression '}' . We also use the following shorthand notation for particular characters: o \c --- any printable character o \n --- the end of line character(s) o eof --- the end of file character(s) SUB-SECTION: Grammar First, the keywords. Note that these are case insensitive. AudibleAlertChar = 'AUDIBLE_ALERT_CHAR=' . BackspaceChar = 'BACKSPACE_CHAR=' . BeginDocument = 'BEGIN_DOCUMENT' . BeginDollar = 'BEGIN_DOLAR' . BeginEnv = 'BEGIN_ENV' . BeginListEnv = 'BEGIN_LIST_ENV' . BeginPictureCc = 'BEGIN_PICTURE_CC' . BeginVenv = 'BEGIN_VENV' . BeginVerb = 'BEGIN_VERB' . BeginVerbatim = 'BEGIN_VERBATIM' . Buffer = 'BUFFER' . CarriageReturnChar = 'CARRIAGE_RETURN_CHAR=' . Chapter = 'CHAPTER' . CharCommand = 'CHAR_COMMAND' . Command = 'COMMAND' . CommandOop = 'COMMAND_OOP' . CommandOoopp = 'COMMAND_OOOPP' . CommandOpo = 'COMMAND_OPO' . CommandPooop = 'COMMAND_POOOP' . CommandPoop = 'COMMAND_POOP' . CommandPoopp = 'COMMAND_POOPP' . Comment = 'C=' . EndCtfile = 'END_CTFILE=' . EndDocument = 'END_DOCUMENT' . EndDollar = 'END_DOLAR' . EndEnv = 'END_ENV' . EndItem = 'END_ITEM=' . EndItemParam = 'END_ITEM_PARAM=' . EndListEnv = 'END_LIST_ENV' . EndMode = 'END_MODE' . EndOpt = 'END_OPT=' . EndPicture = 'END_PICTURE' . EndTag = 'END_TAG=' . EndTag1 = 'END_TAG_1=' . EndTag2 = 'END_TAG_2=' . EndTag3 = 'END_TAG_3=' . EndTag4 = 'END_TAG_4=' . EndTag5 = 'END_TAG_5=' . EndTag6 = 'END_TAG_6=' . EndTag7 = 'END_TAG_7=' . EndTag8 = 'END_TAG_8=' . EndTag9 = 'END_TAG_9=' . EndType = 'END_TYPE' . EndVenv = 'END_VENV' . EndVerb = 'END_VERB' . EndVerbatim = 'END_VERBATIM' . EscapeChar = 'ESCAPE_CHAR=' . File = 'FILE' . First = 'FIRST' . FormfeedChar = 'FORMFEED_CHAR=' . HexChar = 'HEX_CHAR=' . HorizontalTabChar = 'HORIZONTAL_TAB_CHAR=' . Include = 'INCLUDE=' . InMode = 'IN_MODE=' . Last = 'LAST' . Lbrace = 'LBRACE' . Name = 'NAME=' . NewlineChar = 'NEWLINE_CHAR=' . NoOp = 'NO_OP' . NoPrint = 'NO_PRINT' . OptParam = 'OPT_PARAM=' . OtherBegin = 'OTHER_BEGIN' . OtherCommand = 'OTHER_COMMAND' . OtherEnd = 'OTHER_END' . Para = 'PARA' . Paragraph = 'PARAGRAPH' . Part = 'PART' . Partm1 = 'PARTm1' . Partm2 = 'PARTm2' . PcAtEnd = 'PC_AT_END=' . PcAtStart = 'PC_AT_START=' . PictureCcpp = 'PICTURE_CCPP' . PictureCo = 'PICTURE_CO' . PictureCop = 'PICTURE_COP' . PictureCp = 'PICTURE_CP' . PictureOcc = 'PICTURE_OCC' . PictureOccc = 'PICTURE_OCCC' . PictureOco = 'PICTURE_OCO' . PicturePcop = 'PICTURE_PCOP' . PrintControl = 'PRINT_CONTROL=' . PrintP1 = 'PRINT_P1=' . PrintP2 = 'PRINT_P2=' . PrintP3 = 'PRINT_P3=' . PrintP4 = 'PRINT_P4=' . PrintP5 = 'PRINT_P5=' . PrintP6 = 'PRINT_P6=' . PrintP7 = 'PRINT_P7=' . PrintP8 = 'PRINT_P8=' . PrintP9 = 'PRINT_P9=' . PrintOpt = 'PRINT_OPT=' . Rbrace = 'RBRACE' . Reqparams = 'REQPARAMS=' . Reset = 'RESET' . ResetBuffer = 'RESET_BUFFER:' . ResetMode = 'RESET_MODE:' . Sect = 'SECT' . Sectioning = 'SECTIONING' . SectioningLevel = 'SECTIONING_LEVEL=' . SetMode = 'SET_MODE:' . SlashSpace = 'SLASH_SPACE' . Source = 'SOURCE:' . Special = 'SPECIAL' . SpecialBeginEnv = 'SPECIAL_BEGIN_ENV' . SpecialBeginList = 'SPECIAL_BEGIN_LIST' . SpecialCommand = 'SPECIAL_COMMAND' . SpecialEndEnv = 'SPECIAL_END_ENV' . SpecialEndList = 'SPECIAL_END_LIST' . SpecialSectioning = 'SPECIAL_SECTIONING' . StartItem = 'START_ITEM=' . StartItemParam = 'START_ITEM_PARAM=' . StartOpt = 'START_OPT=' . StartTag = 'START_TAG=' . StartTag1 = 'START_TAG_1=' . StartTag2 = 'START_TAG_2=' . StartTag3 = 'START_TAG_3=' . StartTag4 = 'START_TAG_4=' . StartTag5 = 'START_TAG_5=' . StartTag6 = 'START_TAG_6=' . StartTag7 = 'START_TAG_7=' . StartTag8 = 'START_TAG_8=' . StartTag9 = 'START_TAG_9=' . String = 'STRING:' . SubPara = 'SUBPARA' . SubParap1 = 'SUBPARAp1' . SubParap2 = 'SUBPARAp2' . SubSect = 'SUBSECT' . SubSubSect = 'SUBSUBSECT' . SwitchBack = 'SWITCH_BACL: ' . SwitchToBuffer = 'SWITCH_TO_BUFFER: ' . SwitchToFile = 'SWITCH_TO_FILE: ' . SwitchToSysbuf = 'SWITCH_TO_SYSBUF: ' . Sysbuf = 'SYSBUF' . TexChar = 'TEX_CHAR' . ToBuffer = 'TO_BUFFER' . ToFile = 'TO_FILE' . ToSysbuf = 'TO_SYSBUF' . Type = 'TYPE=' . Vcommand = 'VCOMMAND' . VerticalTabChar = 'VERTICAL_TAB_CHAR=' . Some utility productions. latex_id = \c { \c } . name = \c { \c } . text = '"' { \c } '"' . Eol = \n . digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' . integer = digit { digit } . ct_file_name = name . file_id = name . buffer_id = integer . mode_id = name . The starting production. table = [ special_chars ] { specification | inclusion | comment } eof . Productions for inclusion and comment and eof. inclusion = Include ct_file_name Eol . comment = Comment { \c } Eol . eof = EndCtfile { \c } Eol . Productions for special_chars. special_chars = [ escape ] [ alert ] [ backspace ] [ return ] [ feed ] [ hex ] [ htab ] [ newline ] [ vtab ] { comment } . escape = EscapeChar \c Eol Eol . alert = AudibleAlertChar \c Eol . backspace = BackspaceChar \c Eol . return = CarriageReturnChar \c Eol . feed = FormfeedChar \c Eol . hex = HexChar \c Eol . htab = HorizontalTabChar \c Eol . newline = NewlineChar \c Eol . vtab = VerticalTabChar \c Eol . Productions for specification. specification = built_in | normal | list | section | special | picture | odd . built_in = (Type built_in_type Eol) [ built_in_body ] end_type . end_type = EndType Eol . built_in_type = BeginDocument | BeginDollar | BeginVerb | BeginVerbatim | EndDocument | EndDollar | EndVerb | EndVerbatim | Lbrace | OtherBegin | OtherCommand | OtherEnd | Paragraph | Rbrace | SlashSpace . normal = (Type normal_type Eol) type_name [ normal_body ] end_type . type_name = Name latex_id Eol . normal_type = BeginEnv | BeginVenv | CharCommand | Command | EndEnv | EndVenv | TexChar | Vcommand . list = (Type list_type Eol) type_name [ list_body ] end_type . list_type = BeginListEnv | EndListEnv . section = (Type Sectioning Eol) type_name [ section_body ] end_type . special = (Type special_type Eol) type_name [ special_body ] end_type . special_type = Special | SpecialBeginEnv | SpecialBeginList | SpecialCommand | SpecialEndEnv | SpecialEndList | SpecialSectioning . picture = (Type picture_type Eol) type_name [ picture_body ] end_type . picture_type = BeginPictureCc | EndPicture | PictureCcpp | PictureCo | PictureCop | PictureCp | PictureOcc | PictureOccc | PictureOco | PicturePcop . odd = (Type odd_type Eol) type_name [ odd_body ] end_type . odd_type = CommandOop | CommandOoopp | CommandOpo | CommandPooop | CommandPoop | CommandPoopp . The X_body productions. built_in_body = [ basic_body ] { start_mode [ basic_body ] end_mode } . start_mode = InMode mode_id Eol . end_mode = EndMode Eol . normal_body = [ basic_norm_body ] { start_mode [ basic_norm_body ] end_mode } . sect_body = [ basic_sect_body ] { start_mode [ basic_sect_body ] end_mode } . list_body = [ basic_list_body ] { start_mode [ basic_list_body ] end_mode } . picture_body = [ basic_defarg_body ] { start_mode [ basic_defarg_body ] end_mode } . odd_body = [ basic_defarg_body ] { start_mode [ basic_defarg_body ] end_mode } . special_body = [ basic_special_body ] { start_mode [ basic_special_body ] end_mode } . Note: the ordering of the components of the following basic_X_body productions is immaterial. basic_body = [ start_it ] [ end_it ] . basic_norm_body = [ basic_body ] [ no_req_arg ] [ opt_arg_pos ] { arg_print } { arg_action } . basic_sect_body = sect_level [ basic_norm_body ] . sect_level = SectioningLevel div_level Eol . div_level = Chapter | Para | Part | Partm1 | Partm2 | Sect | Subpara | Subparap1 | Subparap2 | Subsect | Subsubsect . basic_defarg_body = [ basic_body ] { arg_print } { arg_action } . basic_list_body = [ basic_norm_body ] { item_action } . basic_special_body = [ sect_level ] [ basic_list_body ] . no_req_arg = Reqparams integer Eol . opt_arg_pos = OptParam ( First | Last ) Eol . The start_it and end_it productions. start_it = [ start_print ] [start_action ] . start_print = PcAtStart ( basic_pc_kind | Reset ) Eol . basic_pc_kind = NoPrint | ToSysbuf | print_to_buffer | print_to_file . print_to_buffer = ToBuffer buffer_id . print_to_file = ToFile file_id . start_action = StartTag [ text ] Eol { tag_action } . tag_action = ( String text | Source ( Sysbuf | user_buffer | user_file ) | ResetBuffer buffer_id | ResetFile file_id | ResetSysbuf | SwitchToBuffer buffer_id | SwitchToFile file_id | SwitchToSysbuf | SwitchBack | SetMode mode_id | ResetMode ) Eol . user_buffer = Buffer buffer_id . user_file = File file_id . end_it = [ end_print ] [ end_action ] . end_print = PcAtEnd (basic_pc_kind | Reset) Eol . end_action = EndTag [ text ] Eol { tag_action } . The arg_print productions. arg_print = print_arg_kind (basic_pc_kind | NoOp ) Eol . print_arg_kind = PrintOpt | PrintP1 | PrintP2 | PrintP3 | PrintP4 | PrintP5 | PrintP6 | PrintP7 | PrintP8 | PrintP9 . The arg_action productions. arg_action = arg_tag_kind [ text ] Eol { tag_action } . arg_tag_kind = EndOpt | EndTag1 | EndTag2 | EndTag3 | EndTag4 | EndTag5 | EndTag6 | EndTag7 | EndTag8 | EndTag9 | StartOpt | StartTag1 | StartTag2 | StartTag3 | StartTag4 | StartTag5 | StartTag6 | StartTag7 | StartTag8 | StartTag9 . The item_action productions. item_action = item_tag_kind [ text ] Eol { tag_action } . item_tag_kind = EndItem | EndItemParam | StartItem | StartItemParam . The parser in L2X for the command table is very simple. For each TYPE= in the command table it creates a struct to hold the specification data. If any type is multiply defined, then which one will be finally used is somewhat random because of the sorting and searching algorithms employed internally. No checks are made for multiply defined entries. Each command in the command table starts on a seperate line. The parser reads only as much of a table line as is necessary to parse that line according to the first token that it finds on the line. The data in each line after parsing is added to the current struct for the LaTeX command. If any of the command lines within an entry are multiply defined, then the latest one will overwrite any earlier ones. This line-based parsing means that effectively anything between the end of the required data on the line is ignored by the parser, and so could be treated as a comment. There is no guarantee that this behaviour will be maintained in future releases of L2X. SECTION: A grammar for EXPRESS-A (sec:expgrammar) The same WSN notation is used for the grammar for EXPRESS-A as for the command table grammar. First the keywords. Note that these are case insensitive. Also not all of the keywords have been used in this implementation of EXPRESS-A; those that have not been used are reserved for the future. ABS = 'abs' . ABSTRACT = 'abstract' . ACOS = 'acos' . AGGREGATE = 'aggregate' . ALIAS = 'alias' . AND = 'and' . ANDOR = 'andor' . ARRAY = 'array' . AS = 'as' . ASIN = 'asin' . ATAN = 'atan' . BAG = 'bag' . BEGIN = 'begin' . BINARY = 'binary' . BLENGTH = 'blength' . BOOLEAN = 'boolean' . BY = 'by' . CALL = 'call' . CASE = 'case' . CONSTANT = 'constant' . CONST_E = 'const_e' . CONTEXT = 'context' . COS = 'cos' . CRITERIA = 'criteria' . DERIVE = 'derive' . DIV = 'div' . ELSE = 'else' . END = 'end' . END_ALIAS = 'end_alias' . END_CALL = 'end_call' . END_CASE = 'end_case' . END_CODE = 'end_code' . END_CONSTANT = 'end_constant' . END_CONTEXT = 'end_context' . END_CRITERIA = 'end_criteria' . END_ENTITY = 'end_entity' . END_FUNCTION = 'end_function' . END_IF = 'end_if' . END_LOCAL = 'end_local' . END_MODEL = 'end_model' . END_NOTES = 'end_notes' . END_OBJECTIVE = 'end_objective' . END_PARAMETER = 'end_parameter' . END_PROCEDURE = 'end_procedure' . END_PURPOSE = 'end_purpose' . END_REALIZATION = 'end_realization' . END_REFERENCES = 'end_references' . END_REPEAT = 'end_repeat' . END_RULE = 'end_rule' . END_SCHEMA = 'end_schema' . END_SCHEMA_DATA = 'end_schema_data' . END_TEST_CASE = 'end_test_case' . END_TYPE = 'end_type' . ENTITY = 'entity' . ENUMERATION = 'enumeration' . EOF = 'eof' . EOLN = 'eoln' . ESCAPE = 'escape' . EXISTS = 'exists' . EXP = 'exp' . FALSE = 'false' . FIXED = 'fixed' . FOR = 'for' . FORMAT = 'format' . FROM = 'from' . FUNCTION = 'function' . GENERIC = 'generic' . HIBOUND = 'hibound' . HIINDEX = 'hiindex' . IF = 'if' . IMPORT = 'import' . IN = 'in' . INSERT = 'insert' . INTEGER = 'integer' . INVERSE = 'inverse' . LENGTH = 'length' . LIKE = 'like' . LIST = 'list' . LOBOUND = 'lobound' . LOINDEX = 'loindex' . LOCAL = 'local' . LOG = 'log' . LOG10 = 'log10' . LOG2 = 'log2' . LOGICAL = 'logical' . MOD = 'mod' . MODEL = 'model' . NOT = 'not' . NOTES = 'notes' . NUMBER = 'number' . NVL = 'nvl' . OBJECTIVE = 'objective' . ODD = 'odd' . OF = 'of' . ONEOF = 'oneof' . OPTIONAL = 'optional' . OR = 'or' . ORD = 'ord' . OTHERWISE = 'otherwise' . PARAMETERi = 'parameter' . PI = 'pi' . PRED = 'pred' . PROCEDURE = 'procedure' . PURPOSE = 'purpose' . QUERY = 'query' . READ = 'read' . READLN = 'readln' . REAL = 'real' . REALIZATION = 'realization' . REFERENCE = 'reference' . REFERENCES = 'references' . REMOVE = 'remove' . REPEAT = 'repeat' . RETURN = 'return' . REXPR = 'rexpr' . ROLESOF = 'rolesof' . ROUND = 'round' . RULE = 'rule . SCHEMA = 'schema' . SCHEMA_DATA = 'schema_data' . SELECT = 'select' . SELF = 'self' . SET = 'set' . SIN = 'sin' . SIZEOF = 'sizeof' . SKIP = 'skip' . SQRT = 'sqrt' . STRING = 'string' . SUBOF = 'subof' . SUBTYPE = 'subtype' . SUCC = 'succ' . SUPERTYPE = 'supertype' . SUPOF = 'supof' . SYSTEM = 'system' . TAN = 'tan' . TEST_CASE = 'test_case' . THE_DAY = 'the_day' . THE_MONTH = 'the_month' . THE_YEAR = 'the_year' . THEN = 'then' . TO = 'to' . TRUE = 'true' . TRUNC = 'trunc' . TYPE = 'type' . TYPEOF = 'typeof' . UNIQUE = 'unique' . UNKNOWN = 'unknown' . UNTIL = 'until' . USE = 'use' . USEDIN = 'usedin' . USING = 'using' . VALUE = 'value' . VALUE_IN = 'value_in' . VALUE_UNIQUE = 'value_unique' . VAR = 'var' . WHERE = 'where' . WHILE = 'while' . WITH = 'with' . WRITE = 'write' . WRITELN = 'writeln' . XOR = 'xor' . The following rules define various classes of characters which are used in constructing the tokens. digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' . digits = digit { digit } . letter = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' . lparen_not_star = '(' not_star . not_lparen_star = not_paren_star | ')' . not_paren_star = letter | digit | not_paren_star_special . not_paren_star_quote_special = '!' | '"' | '#' | '$' | '%' | '&' | '+' | ',' | '-' | '.' | '/' | ':' | ';' | '<' | '=' | '>' | '?' | '@' | '[' | '\' | ']' | '^' | '_' | '`' | '{' | '|' | '}' | '~' . not_paren_star_special = not_paren_star_quote_special | '''' . not_quote = not_paren_star_quote_special | letter | digit | '(' | ')' | '*' . not_rparen = not_paren_star | '*' | '(' . not_star = not_paren_star | '(' | ')' . octet = hex_digit hex_digit . special = not_paren_star_quote_special | '(' | ')' | '*' | '''' . star_not_rparen = '*' not_rparen . The following rules specify how certain combinations of characters are interpreted as lexical elements within the language. integer_literal = digits . real_literal = digits '.' [ digits ] [ 'e' [ sign ] digits ] . simple_id = letter { letter | digit | '_' } . simple_string_literal = \q { ( \q \q ) | not_quote | \s | \o } \q . The following rules specify the syntax of comments in EXPRESS-A. embedded_remark = '(*' { not_lparen_star | lparen_not_star | star_not_rparen | embedded_remark } '*)' . remark = embedded_remark | tail_remark . tail_remark = '--' { \a | \s | \o } \n . The following rules represent identifiers which are known to have a particular meaning (i.e., to be declared elsewhere as types or functions, etc.). attribute_ref = attribute_id . constant_ref = constant_id . entity_ref = entity_id . enumeration_ref = enumeration_id . function_ref = function_id . parameter_ref = parameter_id . procedure_ref = procedure_id . type_ref = type_id . variable_ref = variable_id . The following rules specify how the previous lexical elements may be combined into constructs of EXPRESS-A. White space and/or remark(s) may appear between any two tokens in these rules. The primary syntax rule for EXPRESS-A is express_a. actual_parameter_list = '(' parameter { ',' parameter } ')' . add_like_op = '+' | '-' | OR | XOR . aggregation_types = array_type | bag_type | list_type | set_type . algorithm_head = { declaration } [ local_decl ] . array_type = ARRAY bound_spec OF base_type . assignment_stmt = general_ref { qualifier } ':=' expression ';' . attribute_decl = attribute_id . attribute_id = simple_id . attribute_qualifier = '.' attribute_ref . bag_type = BAG [ bound_spec ] OF base_type . base_type = aggregation_types | simple_types | named_types . boolean_type = BOOLEAN . bound_1 = numeric_expression . bound_2 = numeric_expression . bound_spec = '[' bound_1 ':' bound_2 ']' . built_in_constant = CONST_E | PI | THE_DAY | THE_MONTH | THE_YEAR | '?' . built_in_function = ABS | COS | EOF | EOLN | EXISTS | EXP | HIBOUND | HIINDEX | LENGTH | LOBOUND | LOINDEX | LOG | LOG2 | LOG10 | NVL | ODD | ORD | PRED | REXPR | ROUND | SIN | SIZEOF | SQRT | SUCC | TAN | TRUNC . built_in_procedure = INSERT | PRINT | PRINTLN | READ | READLN | REMOVE | SYSTEM | WRITE | WRITELN . case_action = case_label { ',' case_label } ':' stmt . case_label = expression . case_stmt = CASE selector OF { case_action } [ OTHERWISE ':' stmt ] END_CASE ';' . compound_stmt = BEGIN stmt { stmt } END ';' . constant_factor = built_in_constant . constructed_types = enumeration_type . declaration = entity_decl | function_decl | procedure_decl | type_decl . entity_body = { explicit_attr } . entity_decl = entity_head entity_body END_ENTITY ';' . entity_head = ENTITY entity_id ';' . entity_id = simple_id . enum_id = simple_id . enumeration_reference = enum_id . enumeration_type = ENUMERATION OF '(' enum_id { ',' enum_id } ')' . escape_stmt = ESCAPE ';' . explicit_attr = attribute_decl { ',' attribute_decl } ':' base_type ';' . express_a = { declaration } [ local_decl ] { stmt } END_CODE . expression = simple_expression [ rel_op_extended simple_expression ] . factor = simple_factor [ '**' simple_factor ] . formal_parameter = parameter_id { ',' parameter_id } ':' parameter_type . function_call = ( built_in_function | function_ref ) [ actual_parameter_list ] . function_decl = function_head [ algorithm_head ] stmt { stmt } END_FUNCTION ';' . function_head = FUNCTION function_id [ '(' formal_parameter { ';' formal_parameter } ')' ] ':' parameter_type ';' . function_id = simple_id . generalized_types = general_aggregation_types . general_aggregation_types = general_array_type | general_bag_type | general_list_type | general_set_type . general_array_type = ARRAY [ bound_spec ] OF parameter_type . general_bag_type = BAG [ bound_spec ] OF parameter_type . general_list_type = LIST [ bound_spec ] OF parameter_type . general_ref = parameter_ref | variable_ref . general_set_type = SET [ bound_spec ] OF parameter_type . if_stmt = IF logical_expression THEN stmt { stmt } [ ELSE stmt { stmt } ] END_IF ';' . increment = numeric_expression . increment_control = variable_id ':=' bound_1 TO bound_2 [ BY increment ] . index = numeric_expression . index_1 = index . index_2 = index . index_qualifier = '[' index_1 [ ':' index_2 ] ']' . integer_type = INTEGER . interval = '{' interval_low interval_op interval_item interval_op interval_high '}' . interval_high = simple_expression . interval_item = simple_expression . interval_low = simple_expression . interval_op = '<' | '<=' . list_type = LIST [ bound_spec ] OF base_type . literal = integer_literal | logical_literal | real_literal | string_literal . local_decl = LOCAL local_variable { local_variable } END_LOCAL ';' . local_variable = variable_id { ',' variable_id } ':' parameter_type ';' . logical_expression = expression . logical_literal = FALSE | TRUE | UNKNOWN . logical_type = LOGICAL . multiplication_like_op = '*' | '/' | DIV | MOD | AND | '||' . named_types = entity_ref | type_ref . null_stmt = ';' . numeric_expression = simple_expression . parameter = expression . parameter_id = simple_id . parameter_type = generalized_types | named_types | simple_types . population = entity_ref . primary = literal | ( qualifiable_factor { qualifier } ) . procedure_call_stmt = ( built_in_procedure | procedure_ref ) [ actual_parameter_list ] ';' . procedure_decl = procedure_head [ algorithm_head ] { stmt } END_PROCEDURE ';' . procedure_head = PROCEDURE procedure_id [ '(' [ VAR ] formal_parameter { ';' [ VAR ] formal_parameter } ')' ] ';' . procedure_id = simple_id . qualifiable_factor = attribute_ref | constant_factor | function_call | general_ref | population . qualifier = attribute_qualifier | index_qualifier . real_type = REAL . referenced_attribute = attribute_ref | qualified_attribute . rel_op = '<' | '>' | '<=' | '>=' | '<>' | '=' | ':<>:' | ':=:' . rel_op_extended = rel_op | IN | LIKE . repeat_control = [ increment_control ] [ while_control ] [ until_control ] . repeat_stmt = REPEAT repeat_control ';' stmt { stmt } END_REPEAT ';' . return_stmt = RETURN [ '(' expression ')' ] ';' . selector = expression . set_type = SET [ bound_spec ] OF base_type . sign = '+' | '-' . simple_expression = term { add_like_op term } . simple_factor = enumeration_reference | interval | ( [ unary_op ] ( '(' expression ')' | primary ) ) . simple_types = integer_type | logical_type | real_type | string_type . skip_stmt = SKIP ';' . stmt = assignment_stmt | case_stmt | compound_stmt | escape_stmt | if_stmt | null_stmt | procedure_call_stmt | repeat_stmt | return_stmt | skip_stmt . string_literal = simple_string_literal . string_type = STRING . term = factor { multiplication_like_op factor } . type_decl = TYPE type_id '=' underlying_type ';' END_TYPE ';' . type_id = simple_id . unary_op = '+' | '-' | NOT . underlying_type = constructed_types | aggregation_types | simple_types | type_ref . until_control = UNTIL logical_expression . variable_id = simple_id . while_control = WHILE logical_expression . REFERENCES [LAMPORT94] Leslie Lamport. LaTeX: A Document Preparation System. Addison-Wesley Publishing Company, second edition, 1994. [KNUTH84a] Donald E. Knuth. The TeXbook. Addison-Wesley Publishing Company, 1984. [STEPIS] ISO 10303. Industrial automation systems and integration --- Product data representation and exchange, 1994. [GOLDFARB90] C. A. Goldfarb. The SGML Handbook. Oxford University Press, 1990. (Edited and with a foreword by Yuri Rubinsky). [MUSCIANO96] Chuck Musciano and Bill Kennedy. . O'Reilly & Associates, Inc., 1996. [KERNIGHAN88] Brian W. Kernighan and Dennis M. Ritchie. The C Programming Language. Prentice Hall, second edition, 1988. [EBOOK] Douglas A. Schenck and Peter R. Wilson. Information Modeling the EXPRESS Way. Oxford University Press (ISBN 0-19-308714-3), 1994. [EXPRESSIS] ISO 10303-11:1994. Industrial automation systems and integration --- Product data representation and exchange --- Part 11: Description methods: The EXPRESS language reference manual, 1994. [LEVINE92] John R. Levine, Tony Mason, and Doug Brown. lex & yacc. O'Reilly & Associates, Inc., second edition, 1992. [LESK75] M. E. Lesk and E. Schmidt. `LEX --- A Lexical Analyser Generator'. In UNIX Programmer's Manual 2. AT&T Bell Laboratories, Murray Hill, NJ, 1975. [JOHNSON75] S. C. Johnson. YACC --- Yet Another Compiler Compiler. C S Technical Report 32, Bell Telephone Laboratories, Murray Hill, NJ, 1975. [EXPRESSITR] ISO/TR 10303-12:1997. Industrial automation systems and integration --- Product data representation and exchange --- Part 12: Description method: The EXPRESS-I language reference manual, 1997. [PRW94b] Peter R. Wilson. `FLaTTeN: A Program to Flatten LaTeX Source Files'. NIST, Gaithersburg, MD 20899, December 1994. (In draft). [LIBES93] Don Libes. Obfuscated C and Other Mysteries. John Wiley & Sons, Inc., 1993. [HOLUB90] A. I. Holub. Compiler Design in C. Prentice-Hall, Inc., 1990. [ORAM91] Andrew Oram and Steve Talbott. Managing Projects with make. O'Reilly & Associates, Inc., second edition, 1991. [RINAUDOT94] Gaylen R. Rinaudot. . NISTIR 5511, NIST, Gaithersburg, MD 20899, October 1994. [WIRTH77] N. Wirth. `What Can We Do About the Unnecessary Diversity of Notation for Syntactic Definitions?'. Communications of the ACM, 20(11):822--823, November 1977. [MAKR91] Ronald Mak. Writing Compilers & Interpreters --- An Applied Approach. John Wiley & Sons, Inc., 1991.