Mercurial > ~dholland > hg > ag > index.cgi
view doc/manual/sf.tex @ 23:cac4c76600eb
Update lint ok file for recent change.
author | David A. Holland |
---|---|
date | Mon, 13 Jun 2022 00:17:10 -0400 |
parents | 13d2b8934445 |
children |
line wrap: on
line source
\chapter{Syntax Files} \index{Syntax file}\index{File} Input files to AnaGram are called \agterm{syntax files}. A syntax file comprises a grammar and associated C or C++ code. The grammar consists of a number of productions along with supportng information such as configuration sections and definitions of character sets. The associated code consists of reduction procedures (see \S 8.2.13) and embedded C or C++ code (\S 8.2.17). This chapter explains the rules for writing syntax files acceptable to AnaGram. The rules for interfacing your parser to the balance of your program are given in Chapter 9. \section{Lexical Conventions} \index{Lexical conventions} \subsection{Statements} \index{Statements} For purposes of this manual, AnaGram statements are considered to be productions, definition statements, configuration sections, and blocks of embedded C or C++ code, all discussed individually below. Each statement must begin on a new line. It is a good idea to separate statements visually in your file by using blank lines freely. There are generally no restrictions on the \index{Statements}\index{Order of statements}order of statements in a syntax file. Good programming practice, however, suggests that definitions and configuration sections should precede the grammar itself. \subsection{Spaces and Tabs} \index{Spaces}\index{Tabs} AnaGram allows spaces and tabs to be used freely to improve the readability of grammars. Spaces and tabs are ignored, except when embedded in a token name, in a character set definition, or in a keyword. Within a token name, any sequence of spaces and tabs counts as a single space. \subsection{Continuation Lines} \index{Continuation lines} AnaGram statements normally end with a newline character or the end of file. If AnaGram encounters the end of a line and the statement it is reading appears to be complete, it will not look for a continuation. To continue a statement to another line, just make sure that what you have on the first line is clearly incomplete. For example, \begin{indentingcode}{0.4in} prep phrase -> preposition, "the", noun \end{indentingcode} looks complete to AnaGram, whereas \begin{indentingcode}{0.4in} prep phrase -> preposition, "the", noun, \end{indentingcode} looks incomplete because of the dangling comma at the end. \subsection{Comments} \index{Comments} AnaGram accepts comments in accordance with the rules of C and C++, that is, normal C comments bracketed with \agcode{/*} and \agcode{*/}, as well as comments which begin with \agcode{//} and continue to the end of line. AnaGram also observes these conventions when skipping over embedded C code. Since the ANSI standard for C insists that normal C comments do not nest, AnaGram, by default, disallows nested comments. You may, however, set a configuration parameter, \index{Nest comments}\index{Configuration switches}\index{Comments} \agparam{nest comments}, to allow nested comments. See Appendix A. In any case, AnaGram will use the same convention for embedded C as it uses for AnaGram proper. You can change the convention in the middle of the file if necessary. AnaGram treats each comment delimited with \agcode{/*} and \agcode{*/} as though it were a single space. You can even put such comments in the middle of token names if you should want to. A comment that begins with \agcode{//} is treated as though the end of line occurred at the \agcode{//}. \subsection{Blank Lines and Form Feeds} \index{Blank lines} Because blank lines and form feeds are visual separators, AnaGram will not skip either looking for a continuation line. Therefore blank lines and form feeds can occur only between AnaGram statements, not in the middle of a statement. It is a good idea to separate groups of productions with a blank line or two, lest an accidental dangling comma make AnaGram think the beginning of the next production is a continuation of the present one. \section{Elements of Grammars} \subsection{Names} \index{Name}\index{Token} You may use names to represent tokens, character sets, keywords and \index{Virtual productions}\index{Production}virtual productions. Names follow the same general rules as for any programming language, with the notable exception that they may have embedded white space. Names are made up of letters, digits, or underscores. They may not begin with a digit. Any sequence of embedded spaces, tabs or comments counts as a single space. AnaGram distinguishes between upper and lower case\index{Case sensitivity}, so that \agcode{Word} and \agcode{word} are different names. There is no particular limit to the length of a name. There are no reserved words as such, although \agcode{grammar}, \agcode{eof}, and \agcode{error} will be treated as reserved words unless you take special action by setting appropriate configuration parameters. The names AnaGram uses for \index{Configuration parameters}configuration parameters follow the same rules as for other names, except that \index{Case sensitivity}case is ignored. \subsection{Reserved Words} \index{Reserved words}\index{Words} % XXX shouldn't that be \index{Grammar token}? AnaGram treats tokens with the names \index{Grammar}\agcode{grammar}, \index{Eof token}\index{Token}\agcode{eof}, and \index{Error token}\index{Token}\agcode{error} in a special manner unless certain measures are taken. Since you can override AnaGram's use of these names, they are not reserved words in the true sense. If your grammar has a token named \agcode{grammar}, AnaGram will take that token to be the grammar token for your grammar unless you set the \index{Token}\index{Grammar token}\index{Configuration parameters} \agparam{grammar token} configuration parameter or mark some other token as the grammar token using ``\index{ \_dol}\$''.% See below ???. If your grammar has a token named \agcode{error} and you take no further steps, AnaGram will assume you wish to use error token resynchronization in case of \index{Syntax error}\index{Errors}syntax error. See Chapter 9. If you wish to use some other token as an error token you may select it using the \index{Configuration parameters}\index{Token}\index{Error token} \agparam{error token} configuration parameter. If you wish to use \agcode{error} as a token name, but do not want error token resynchronization, you may set the \agparam{error token} configuration parameter to any name that is not used in your grammar. You may then use \agcode{error} as a token name without causing AnaGram to include error token resynchronization in your parser. \index{Resynchronization} If you select automatic resynchronization or error token resynchronization (see Chapter 9), AnaGram will look for a token called \agcode{eof} to use as an end of file indicator. You may either name your end of file token \agcode{eof} or you may set the \agparam{eof token} configuration parameter with the name of your end of file token. \subsection{Variable Names} \index{Name}\index{C variable names} With AnaGram you can associate C/C++ variable names with the \index{Semantic value}\index{Token}\index{Value}semantic values of tokens for use in your \index{Reduction procedure}reduction procedures. Each name follows the corresponding token in the grammar rule on the right of the production, separated from the token by a colon. AnaGram allows variable names made up of letters, digits, and underscores. They may not begin with a digit. Embedded spaces, tabs or comments, are not allowed, of course. AnaGram imposes no restriction on length, but uses your variable names just as you have written them in the code it generates to call reduction procedures. Remember that your compiler may have a limit on the length of variable names. Also, AnaGram itself uses C variable names beginning with \agcode{ag{\us}}. It is therefore wise to avoid using names of this form. \subsection{Terminal Tokens} \index{Terminal token}\index{Token} A \agterm{terminal token} is a token which does not appear on the left side of a production. It represents, therefore, a basic unit of input to your parser. You have several options with respect to terminal tokens. If the input to your parser consists of ASCII characters, you may define terminal tokens explicitly as ASCII characters or as sets of ASCII characters. If you have an input procedure which produces numeric codes, you may define the terminal tokens directly in terms of these numeric codes. On the other hand, you may leave the terminal tokens completely undefined. In this case, you must provide an input procedure which can determine the appropriate \index{Token}\index{Token number}\index{Number}token numbers. It is an all or none situation. If you provide any explicit definitions, you must provide them for all terminal tokens. Input procedures and token input are discussed in Chapter 9. Examples of non-character input may be found in the Macro Preprocessor example in the \agfile{examples/mpp} directory on your AnaGram distribution disk.% Further examples are given in Chapter ???. % XXX change ``on ...distribution disk'' to ``in ...distribution''. \subsection{Character Representations} \index{Character representations} In specifying admissible input characters you may use \index{Character constants}character constants following the normal C conventions. Remember that a character constant may specify only a single character. Although some C compilers will allow constructs such as \agcode{'mv'}, AnaGram doesn't allow this. AnaGram recognizes the same escape sequences as C, including octal and hex sequences, even though this is, strictly speaking, unnecessary. The escape sequences AnaGram recognizes are: % % It would be nice to be able to just write this and tell latex to set % it in three columns. but no... that would be too easy. % % %\begin{tabular}{ll} %\agcode{{\bs}a}&alert (bell) character\\ %\agcode{{\bs}b}&backspace\\ %\agcode{{\bs}f}&formfeed\\ %\agcode{{\bs}n}&newline\\ %\agcode{{\bs}r}&carriage return\\ %\agcode{{\bs}t}&horizontal tab\\ %\agcode{{\bs}v}&vertical tab\\ %\agcode{{\bs\bs}}&backslash\\ %\agcode{{\bs}?}&question mark\\ %\agcode{{\bs}'}&single quote\\ %\agcode{{\bs}"}&double quote\\ %\agcode{{\bs}ooo}&octal number\\ %\agcode{{\bs}xhh}&hexadecimal number\\ %\end{tabular} \begin{indenting}{0.4in} \begin{tabular}{llllll} \agcode{{\bs}a}&alert (bell) character& \agcode{{\bs}t}&horizontal tab& \agcode{{\bs}'}&single quote\\ \agcode{{\bs}b}&backspace& \agcode{{\bs}v}&vertical tab& \agcode{{\bs}"}&double quote\\ \agcode{{\bs}f}&formfeed& \agcode{{\bs\bs}}&backslash& \agcode{{\bs}\textit{ooo}}&octal number\\ \agcode{{\bs}n}&newline& \agcode{{\bs}?}&question mark& \agcode{{\bs}x\textit{hh}}&hexadecimal number\\ \agcode{{\bs}r}&carriage return\\ \end{tabular} \end{indenting} \bigskip The octal escape sequence allows up to three octal digits, in accordance with ANSI specifications for C. The hexadecimal numbers may contain an arbitrary number of digits; however AnaGram will truncate the result to sixteen bits. A backslash followed by any character other than those listed above will cause a syntax error. You may also represent characters by writing the numeric code explicitly, in decimal, octal, or hexadecimal representations. AnaGram follows the C conventions for integer constants: a leading \agcode{0} means the number is octal, a leading \agcode{0x} or \agcode{0X} means it is hexadecimal. The hex digits \agcode{a-f} may be either upper or lower case\index{Case sensitivity}. Numbers may be preceded by an optional minus sign. If your parser uses a pre-existing \index{Lexical scanner}lexical scanner and you wish to use the code numbers it generates to identify tokens, you may simply treat those code numbers as character numbers. You may use the numbers directly in your productions, or you may use definition statements to name them. You may also use an \agparam{enum} statement within a configuration section to attach names to the code numbers. % XXX shouldn't this use of enum be indexed? AnaGram also allows a special notation for control characters. You may represent a control character by using the ``\^{}'' character preceding any printing ascii character. Thus you can write \agcode{\^{}z} or \agcode{\^{}Z} to represent the DOS end-of-file character. Notice that quotation marks are not necessary. Examples of character representations: \begin{indenting}{0.4in} \begin{tabular}{cccc} \agcode{'K'}&\agcode{-1}&\agcode{0}&\agcode{'{\bs}t'}\\ \agcode{\^{}J}&\agcode{'{\bs}xff'}&\agcode{077}&\agcode{0XF3}\\ \end{tabular} \end{indenting} \subsection{Character Ranges} \index{Character range}\index{Range} It is convenient to be able to specify ranges of characters when writing a grammar. AnaGram supports several ways of representing ranges of characters. The first is an extension of the notation for character constants: \agcode{'a-z'} is the set of lower case characters. You can even use escape sequences such as \agcode{'{\bs}n-{\bs}r'} if you like. The order of characters used to specify the range is immaterial: \agcode{'z-a'} is the same as \agcode{'a-z'}. AnaGram will, however, issue a warning just in case the unusual order results from a clerical error. The second way to specify a range is by using two arbitrary character representations, as described above, separated by two dots. For example, \agcode{\^{}C..\^{}Z}, \agcode{3..26}, \agcode{3..032}, \agcode{3..0x1a}, and \agcode{\^{}C..0x1a}, all represent the same range of characters. Similarly, \agcode{'A-F'}, \agcode{'A'..'F'}, \agcode{0101..0106}, \agcode{0x41..0x46}, \agcode{65..70}, and \agcode{65..'F'} all represent the same range of characters. \subsection{Character Sets} \index{Character sets} If you provide explicit definitions for terminal tokens, the basic input unit for your parser will be considered a character set, even if your input procedure provides numeric codes that are not actually characters. As a terminal token, a character set will be matched by any input character that is a member of the set. Character sets may be named in definition statements, but they may also appear on the right sides of productions without being named. A character set may consist of one or more characters. You can specify a character set that consists of a single character by using any of the character representation methods described above. You can specify a set consisting of a range of characters by using any of the representations of character ranges described above. \index{Character sets} To specify more complicated sets, you can write \index{Expressions}\index{Set expressions}expressions using conventional set theoretic operations. In AnaGram input, these operations are specified as follows: \index{Union}\index{Difference}\index{Intersection}\index{Complement} \begin{indenting}{0.4in} \begin{tabular}{cl} \agcode{A + B}&(union)\\ \agcode{A - B}&(difference)\\ \agcode{A \& B}&(intersection)\\ \agcode{\~{}A}&(complement)\\ \end{tabular} \end{indenting} where \agcode{A} and \agcode{B} are arbitrary sets. Union and difference have the same precedence. Intersection has higher precedence and complement has the highest precedence. Thus in the expression \begin{indentingcode}{0.4in} A + \~{}B\&C \end{indentingcode} the complement operation is performed first, then the intersection, and finally the union. Watch out! In an AnaGram syntax file \agcode{65 + 97} represents the character set which consists of lower case \agcode{a} and upper case \agcode{A}. It does not represent 162, the sum of 65 and 97. Parentheses may be used to force the order of evaluation: \begin{indentingcode}{0.4in} \~{}(A \& (B+C)) \end{indentingcode} In this example the union of \agcode{B} and \agcode{C} is calculated, then the intersection of this set with \agcode{A} is calculated, and finally the complement is evaluated. The computation of the \index{Complement}complement of a \index{Character sets}set requires a definition of the \index{Universe}universe of set elements. AnaGram will define the universe to be the set of unsigned 8-bit characters, unless one or more characters outside that range have been specified. In that case, the universe will consist of all characters on the interval defined by the lesser of zero and the lowest character code used and the greater of 255 and the highest character code used. The complement of a character set is everything in this universe except the characters in the set. Characters which make up part of the character universe, but are not legitimate input according to your grammar, are lumped together into a special token which will cause an error if it occurs in your input. When your parser reads an input character, it uses that character to index a conversion table in order to determine the appropriate \index{Token number}\index{Token}\index{Number}token number. If the \index{Range}\index{Test range}\index{Configuration switches} \agparam{test range} configuration switch is on, its default setting, your parser will include code to verify that the character is in bounds before it indexes the conversion table. If you are satisfied that checking bounds is unnecessary, you may turn the \agparam{test range} switch off and get a slightly higher level of performance from your parser. For efficient processing, it is well to keep the number of tokens to a minimum. Therefore if you have a choice between defining a construct as a token, with a production, or a set, with a definition, the set is to be preferred. Some useful character sets are: \begin{indenting}{0.4in} \begin{tabular}{ll} \agcode{'a-z' + 'A-Z'}&Alphabetic characters\\ \agcode{'a-f' + 'A-F'}&Hex digits\\ \agcode{'0-9'}&Decimal digits\\ \agcode{0..127}&ASCII character set\\ \agcode{32..126}&Printing ASCII characters\\ \agcode{\~{}'{\bs}n'}&Anything but newline\\ \agcode{\^{}Z}&Windows/DOS end of file indicator\\ \agcode{-1}&Stream I/O end of file indicator\\ \agcode{0}&String terminator\\ \agcode{32..126 - 'a-z' - 'A-Z' - '0-9'}&Punctuation\\ \end{tabular} \end{indenting} \bigskip % XXX ``punctuation'' is wrong; it should subtract off space too Note that \agcode{'a-z'} is a range of characters but \agcode{32..126 - 'a-z'} is a set difference. When AnaGram encounters a character set in a grammar rule, it assigns a token number to the character set. If it has previously seen the same character set it will assign the same token number; however, it assigns the same token number only if the set expressions are obviously the same. Thus, AnaGram will assign the same token number every time it sees \agcode{A + B}, but will assign a different token number if it sees \agcode{B + A}. Only when AnaGram has finished scanning the entire syntax file can it actually evaluate the character sets. If it finds that several different tokens all refer to the same character set, it will create a single token that represents the true character set and create \index{Shell productions}\index{Production}``shell productions'' for the others. \index{Character sets}If the character sets you use in your grammar overlap, they do not properly represent \index{Terminal token}\index{Token}terminal tokens. To deal with this situation, AnaGram identifies all overlaps among character sets and extends your grammar by adding a number of extra productions. For instance, suppose your grammar uses the following character sets as though they were terminal tokens: \begin{indentingcode}{0.4in} 'a-z' + 'A-Z' '0-9' '0-7' 'a-f' + 'A-F' \end{indentingcode} AnaGram will then modify your grammar by adding the following productions: \begin{indentingcode}{0.4in} 'a-z' + 'A-Z' -> 'a-f' + 'A-F' | 'g-z' + 'G-Z' '0-9' -> '0-7' + '8-9' \end{indentingcode} Although the tokens \agcode{'a-z' + 'A-Z'} and \agcode{'0-9'} are technically now \index{Nonterminal token}\index{Token}nonterminal tokens, for purposes of determining the \index{Token}\index{Data type}data type of their \index{Semantic value}\index{token}\index{Value}semantic values, AnaGram continues to regard them as terminal tokens. This \index{Partition}\index{Universe}\index{Character universe} ``partitioning'' of the character universe is described in Chapter 6. \subsection{Keyword Strings} \index{Keywords} In your grammar, AnaGram recognizes character strings within double quotes (e.g., \agcode{"IF"}) as keywords. The strings follow the same syntactic rules as strings in C. The same escape sequences are honored. AnaGram does not, however, allow for the concatenation of adjacent strings. Note that AnaGram strings are used only for the definition of keywords in your grammar, not for messages to be displayed or printed. Keyword strings may not include null characters and must be at least one character long. You may have any number of keywords. Each is treated as a single terminal token. A keyword may be given a name by means of a definition statement. Keywords may appear in virtual productions. AnaGram's keyword recognition works in the following way. First, for each state in your parser, AnaGram prepares a list of all the keywords that are admissible in that state. Your parser will recognize a keyword \emph{only} if it is in an appropriate state; otherwise it will appear to be an anonymous sequence of characters. Your parser, in any state, checks for keywords it expects before it checks for acceptable characters. That is, \emph{keywords take precedence} over simple characters. It does not look for keywords that would not be acceptable input. The parser will do whatever lookahead is necessary in order to pick up the entire keyword. Thus if the character \agcode{I} and the keyword \agcode{IF} are both legitimate input at some point, \agcode{IF} will be recognized, if present, in preference to \agcode{I}. If several admissible keywords match the input, such as \agcode{IF} and \agcode{IFF}, the parser will select the longest match, \agcode{IFF} in this example. AnaGram does not incorporate keywords into its character sets. Keywords stand apart and should not appear in definitions of character sets. In particular, they are not considered as belonging to the complement of a character set. Thus for the production \begin{indentingcode}{0.4in} next char -> \~{}('{\bs}n' + \^{}Z) \end{indentingcode} a keyword would not be considered legitimate input. Note also that a keyword consisting of a single character does not belong to the character universe. Because of this fact, AnaGram's treatment of \agcode{'X'} and \agcode{"X"} is very different. If this seems confusing at first, try using only keywords which are at least two characters long until you have some experience with them. AnaGram's keyword recognition logic normally does not make any assumptions about what precedes or follows a keyword. Thus if \agcode{int} is a keyword, your parser will be capable of plucking it out of a string of characters such as \agcode{disintegrate} if, according to your grammar, it could follow \agcode{dis}. The \agparam{sticky} declaration and the \agparam{distinguish keywords} statement, described below, can prevent such unwanted recognition of keywords. A keyword following a \agparam{sticky} token will not be recognized if the first character of the keyword can be shifted in as part of the \agparam{sticky} token. The \agparam{distinguish keywords} statement prevents recognition of a keyword if it is followed immediately by a character of the sort that makes up the keyword. \subsection{Type Specifications For Tokens} \index{Token}\index{Token type}\index{Type declarations} When you write productions or token declarations (see below), AnaGram allows you to specify the data type\index{Token}\index{Data type} of the \index{Semantic value}\index{Token}\index{Value}semantic value of a token by using a C or C++ data type specification. The restrictions are that AnaGram does not allow specification of array or function types, nor explicit structure types. Types that are defined with typedef statements, structure definitions, or class definitions, including template classes, in your embedded C or C++ are acceptable. Thus the following specifications, for example, are acceptable: \begin{indentingcode}{0.4in} void int char * unsigned long *near static float *far my{\us}type double * struct descriptor struct widget * vector <double> * \end{indentingcode} On the other hand, the following specifications are \emph{not} valid: \begin{indentingcode}{0.4in} int[20] int *(int, unsigned char) \bra int x,y; float z; \ket struct \bra int k; float z; \ket \end{indentingcode} Note that AnaGram itself does nothing with the type specifications. It simply passes them on to your compiler as appropriate. \subsection{Productions} \index{Production} Productions are the basic units of a grammar. A production consists of a left side and a right side. \index{Left side}The left side of a production consists of one or more token names, joined by commas, optionally preceded by a type specification enclosed in parentheses. \index{Right side}The right side begins with an arrow and may either begin on the same line as the left side or on a new line. For example: \begin{indentingcode}{0.4in} program -> statement list, eof expression -> expression, plus, term (int) variable name, function name -> name:n = look{\us}up(n); \end{indentingcode} The part of the right side of a production following the arrow is called a \index{Grammar rule}\index{Rule}\agterm{grammar rule}, discussed below. A production need not have a right side at all. In this case, it is simply called a \index{Declaration}\index{Token}\agterm{token declaration}. AnaGram assigns \index{Token number}\index{Token}\index{Number}token numbers to the token names on the left side, and, if there is a type specification, records the data type for each of the tokens declared. Declarations of this sort are most useful when using input from a \index{Lexical scanner}lexical scanner. See Chapter 9 for a discussion of techniques for interfacing a lexical scanner to your parser. If you do not intend to use a lexical scanner you will have no need for token declarations. If you do not explicitly specify the type for the \index{Semantic value}\index{Token}\index{Value}semantic value of a token, it will be determined by the configuration parameter \index{Default token type}\index{Configuration parameters}\index{Token} \agparam{default token type} if it is a \index{Nonterminal token}\index{Token}nonterminal token or by the \index{Configuration parameters}configuration parameter \index{Input token type}\index{Default input type}\agparam{default input type} if it is a \index{Token}terminal token. \agparam{Default token type} defaults to \agcode{void}. \agparam{Default input type} defaults to \agcode{int}. If a production has more than one token on the left side, as in the third example above, it is called a \index{Semantically determined production}\index{Production} \agterm{semantically determined production}. Semantically determined productions are a useful tool for exerting semantic control over syntactic analysis. A semantically determined production should have a reduction procedure which determines on a case by case basis which of the tokens on the left side should be taken as the reduction token. If there is no reduction procedure, or if the reduction procedure does not make a choice, the reduction token will be the first syntactically correct token on the left side of the production. In the example above, \agcode{variable name} will be the reduction token unless \agcode{look{\us}up} changes it to \agcode{function name}. Semantically determined productions are discussed more fully in Chapter 9. If several productions have the same left side, it does not need to be repeated. Subsequent right hand sides must each start on a new line. For example: \begin{indentingcode}{0.4in} integer -> digit -> integer, digit name -> letter -> name, letter -> name, digit \end{indentingcode} On the other hand, you do not have to group productions with the same left side. You could write the above productions as follows, although it would certainly not be good programming practice: \begin{indentingcode}{0.4in} name -> name, digit integer -> integer, digit name -> name, letter integer -> digit name -> letter \end{indentingcode} Nevertheless, there are a few occasions involving complex cross recursions and semantically determined productions where it is not possible to group productions neatly. The right side of a production can be empty. Such a production is called a \index{Null productions}\index{Production}\agterm{null production}. Null productions are useful to denote an optional element in a grammar, or a list that may be empty. For example: \begin{indentingcode}{0.4in} optional widget -> -> widget optional qualifiers -> -> optional qualifiers, qualifier \end{indentingcode} A second way to write multiple productions with the same left side uses the \index{Vertical bar}\index{|}vertical bar character, ``$|$'', to separate the grammar rules. The productions given above for \agcode{name}, \agcode{optional widget}, and \agcode{optional qualifiers} can also be written: \begin{indentingcode}{0.4in} name -> letter | name, letter | name, digit optional widget -> | widget optional qualifiers -> | optional qualifiers, qualifier \end{indentingcode} Note that a null production cannot \emph{follow} a vertical bar. A token that has a null production is called a \index{Zero length token}\index{Token}\agterm{zero length token}, since it can be represented by an empty sequence of input characters, that is to say, by nothing at all. Furthermore, even if a token doesn't have any null productions, if it has at least one rule consisting entirely of zero length tokens it is also a zero length token. In the Token Table window, AnaGram notes which tokens are zero length, because they can be a source of conflicts. \subsection{Grammar Token} Every grammar must have a single token which produces the entire grammar. This token is variously called the \index{Token}\index{Grammar token}\agterm{grammar token}, the \index{Goal token}\agterm{goal token} or the \index{Start token}\agterm{start token}. AnaGram provides several methods you may use to specify which token in your grammar is the grammar token. You may simply use the name \agcode{grammar} for the grammar token. If you wish to use some other more descriptive name for your grammar token, you may mark it with a following dollar sign when it appears on the left side of a production. Alternatively, you may set the \index{Grammar token}\index{Configuration parameters}\agparam{grammar token} configuration parameter to specify the grammar token. Here are examples of the methods: \begin{indentingcode}{0.4in} grammar -> [statement | newline]/... program \$ -> [statement | newline]/... {}[ grammar token = program ] program -> [statement | newline]/... \end{indentingcode} If you should use more than one of these techniques, AnaGram resolves the issue in the following manner: A marked token or a configuration parameter setting always takes precedence over simply naming a token \agcode{grammar}. If you mark more than one token or set the configuration parameter more than once, the last setting or mark wins. \subsection{Grammar Rules} \index{Rule}\index{Grammar rule} The part of a production to the right of the arrow is more often called a \agterm{grammar rule}, or simply \agterm{rule}. A grammar rule is a sequence of \index{Rule elements}\agterm{rule elements}, joined by commas, as in the examples of productions given above. Rule elements are token names, character set expressions, virtual productions, or immediate actions (see below). Each rule element may be optionally followed by a parameter assignment. The entire rule may be followed by an optional reduction procedure. A \index{Parameter assignment}parameter assignment is a colon followed by a C variable name. Here are some examples of rule elements with parameter assignments: \begin{indentingcode}{0.4in} '0-9':d integer:n expression:x declaration:declaration{\us}descriptor \end{indentingcode} The parameters you assign to tokens in your grammar rule become the formal parameters for your \index{Reduction procedure}reduction procedure. The data type\index{Data type}\index{Reduction procedure arguments} of the parameter is determined by the data type for the semantic value of the token to which it is assigned. If your grammar rule has parameter assignments, but does not have a reduction procedure, AnaGram will give you a warning in case the lack of a reduction procedure is an oversight. If you don't need a reduction procedure you may safely ignore the warning. On the other hand, AnaGram has no way to determine whether you have failed to make necessary parameter assignments. You won't find out until you compile your parser, when your compiler will give you error messages for undefined symbols. AnaGram assigns a unique rule number to each rule in your grammar. Rules are numbered sequentially as they are encountered in the syntax file. AnaGram constructs rule zero itself. Rule zero normally has a single element, the grammar token, unless you have a \agparam{disregard} statement in your grammar. In this case there will be two elements. \subsection{Reduction Procedures} \index{Reduction procedure} % XXX somewhere in here it ought to say something like % ``in the parsing literature reduction procedures are often known as % \agterm{semantic actions}.'' % Note that R. says there's some subtle difference between the usual % concept of semantic action and AG's concept of reduction procedure. % I don't know what this difference is and I hope she can recall it. % % D. thinks this note ought to be at the end; R. wants it at the top. A \agterm{reduction procedure} is a piece of C code which optionally follows a production. The code is executed when your parser identifies the production in its input. There are two forms for reduction procedures, a short form and a long form. The short form consists of a single C expression. The long form consists of an arbitrary block of C code. When AnaGram builds a parser, it inspects the grammar rule to which the procedure is attached and identifies the parameters for the procedure. It uses these parameters as the formal parameters for the procedure. If the \index{Macros}\index{Allow macros}\index{Configuration switches} \agparam{allow macros} configuration switch has not been turned off, AnaGram codes the reduction procedure as a macro definition whenever possible. Otherwise AnaGram codes it as a function definition. AnaGram builds the name for a reduction procedure by appending its internal procedure number to the string \agcode{ag{\us}rp{\us}}. Thus reduction procedures are numbered in the order in which they are encountered in the syntax file. Both long and short form reduction procedures are preceded by an equal sign which follows the production. The short form consists of a C or C++ expression terminated by a semicolon. When the grammar rule is reduced, the expression will be evaluated and its value will become the value of the reduction token. The expression and the terminating semicolon must be entirely on a single line. Note that, if you really need to make the expression longer than will fit on one line, you can embed a newline in a comment. Some examples of short form reduction procedures are: % XXX is there anything we can do about the ugly underscores? \begin{indentingcode}{0.4in} =0; =1; =10*n + d-'0'; = special{\us}processor(first{\us}parameter, second{\us}parameter); =word{\us}count++; =widget(constant{\us}1*parameter{\us}1 + constant{\us}2*parameter{\us}2 /* {} */ + constant{\us}3*parameter{\us}3); \end{indentingcode} A long form reduction procedure consists of an arbitrary block of C or C++ code, enclosed in braces (\bra \ket). AnaGram will code the reduction procedure as a function. To return a value for the reduction token, simply use the \agcode{return} statement. There are effectively no restrictions on the content or length of a reduction procedure. Of course, if there are unbalanced braces, unterminated comments or unterminated string literals, AnaGram will not be able to determine where the reduction procedure ends. AnaGram treats \index{Comments}nested comments within a reduction procedure according to the value of the \index{Nest comments}\index{Configuration switches}\agparam{nest comments} configuration switch at the point where it encounters the reduction procedure. From a practical point of view it is not usually good practice to have a reduction procedure that is more than a few lines long since a long procedure will hamper your overall view of your grammar. Long reduction procedures should be written as separate named functions, and should either be included in the embedded C portion of your syntax file or should be included in a wholly separate module. Here is an example of a long form reduction procedure: \begin{indentingcode}{0.4in} =\bra if (flag) \bra total += x; return identify(x); \ket else \bra total = 0; flag = 1; return init{\us}table(x); \ket \ket \end{indentingcode} If a rule does not have a reduction procedure, the semantic value of the reduction token will be set to the \index{Semantic value}\index{Token}\index{Value}semantic value of the first token in the rule, unless the rule is a \index{Null productions}null production. In the latter case, the value of the reduction token will be set to zero. % XXX and what if zero isn't a valid value for the type? a compiler % error will occur. % XXX add something like % % Variables appearing in reduction procedures which do not have a % parameter assignment in the corresponding grammar rule can be % declared globally or (file)-statically in your embedded C, or % alternatively could be added to the parser control block using % the \agparam{extend pcb} statement (q.v. | See Section ....). % (Reword this.) % % Should also discuss the sequencing of reduction procedure calls % so that people understand what happens if you use such variables. % % also ``A reduction procedure can be used to terminate parsing for % semantic reasons''. % \subsection{Immediate Actions} \index{Immediate action}\index{Action} An immediate action is a rule element that consists of executable C or C++ code embedded within a grammar rule to be executed when it is encountered. An immediate action is denoted by the use of an exclamation point, \index{!}``!''. The content of an immediate action may be written following the rules for either long form or short form reduction procedures. As with any other rule element, it must be separated from preceding and following rule elements by commas. In the grammar for a simple desk calculator, one might write \begin{indentingcode}{0.4in} transaction -> !printf('\#');, expression:x = printf("\%d{\bs}n", x); \end{indentingcode} % XXX s/apparent/visible/ Notice that the only apparent difference between an immediate action and a reduction procedure is that the immediate action is preceded by ``!'' instead of ``=''. The immediate action must be followed by a comma to separate it from the following rule element. Immediate actions may also be used in definitions: \begin{indentingcode}{0.4in} prompt = !printf('\#'); \end{indentingcode} AnaGram implements an immediate action by creating a special token for it. AnaGram then creates a single null production for the token. Finally, the immediate action is implemented as the reduction procedure for the null production. For example, you could implement \agcode{prompt} by writing a null production with a reduction procedure: \begin{indentingcode}{0.4in} prompt -> = printf('\#'); \end{indentingcode} This production would be equivalent to the definition above. There are two ways, however, in which immediate actions differ from the equivalent null production. Immediate actions may access any parameter assignments which precede them in the rule in which they occur. On the other hand, there is no way to assign a data type to the semantic value, if any, returned by the immediate action. Therefore, the type is determined by your setting of the \index{Default token type}\index{Configuration parameters} \agparam{default token type} configuration parameter. \subsection{Virtual Productions} \index{Virtual productions}\index{Production} Virtual productions are a convenient short form notation for common grammatical constructs involving choice and repetition. The notation represents an extension of notation commonly used in programming manuals. A virtual production may be written in a grammar rule at any place where you could write a token name, even within another virtual production. Note that use of virtual productions is never \emph{required}, since the equivalent productions can always be written out explicitly instead. When AnaGram encounters a virtual production, it replaces the virtual production with a new token and writes appropriate productions for the new token. When you look at your syntax tables using AnaGram windows, you will see the productions that AnaGram generates. AnaGram keeps a record of virtual productions, so that generally if you use the same virtual production a second time, you get the same set of tokens and productions that were generated the first time it was used. This is not the case if the virtual productions contain reduction procedures or immediate actions, since AnaGram is not equipped to determine whether two pieces of C code are equivalent. Thus, a virtual production that contains a reduction procedure will be unique and will not be reused. One disadvantage of virtual productions is that there is no way to specify the data type of the \index{Semantic value}\index{Virtual production}semantic value of a virtual production. Therefore, if you have a reduction procedure within a virtual production, its return value must be consistent with the type defined by the \index{Default token type}\index{Configuration parameters}\agparam{default token type} configuration parameter. The simplest virtual production is the \index{Token}\index{Optional token}\agterm{optional token}. If \agcode{x} is an arbitrary token name or set expression, you can indicate an optional \agcode{x} by writing \index{?}\agcode{x?}. You may also indicate a repetition of \agcode{x} by using the ellipsis with either \agcode{x} or \agcode{x?}. \index{...}\index{Ellipsis}Thus \agcode{x...} represents one or more instances of \agcode{x} and \index{?...}\agcode{x?...} represents zero or more instances of \agcode{x}. For example: \begin{indentingcode}{0.4in} '+'? \end{indentingcode} can be used to represent an optional plus sign, that is, a choice between a plus sign and nothing at all. Similarly, \begin{indentingcode}{0.4in} '{\bs}n'?... \end{indentingcode} represents an optional sequence of newline characters. \index{Brackets}\index{Braces}\index{\_opb\_clb}\index{[]} The next category of virtual productions uses brackets or braces to indicate a choice among a number of enclosed grammar rules separated by vertical bars. A single rule may also be enclosed. Note that \emph{rules}, with following reduction procedures, are allowed, not simply tokens. Braces are used to indicate that one option must be chosen. Brackets are used to indicate the choice is optional, i.e. may be omitted altogether. The ellipsis following a set of options within brackets or braces indicates the option may be repeated an indefinite number of times. You can use braces to indicate a simple choice among a number of options. A Cobol grammar offers the following choice of equivalent keywords: \begin{indentingcode}{0.4in} \bra "RECORD", "IS"? | "RECORDS", "ARE"? \ket \end{indentingcode} \index{\_opb\_clb...}\index{ []...} You may use the ellipsis with braces to indicate an arbitrary positive number of repetitions of the choice: \begin{indentingcode}{0.4in} {\bra}type specifier | storage class specifier{\ket}... \end{indentingcode} This expression requires at least one type specifier or storage class specifier, but will accept any number. \index{[]} To make a choice optional, use brackets instead of braces. An example, again drawn from a Cobol grammar, is: \begin{indentingcode}{0.4in} {}["LIMIT", "IS"? | "LIMITS", "ARE"?] \end{indentingcode} \index{[]...} Ellipses may be used with brackets to indicate an arbitrary number of choices that may be omitted altogether: \begin{indentingcode}{0.4in} {}[argument, [',', argument]...] \end{indentingcode} This expression describes an optional argument list with arguments separated by commas. If you use a null production within braces, it must be the first option: \begin{indentingcode}{0.4in} \bra | '+' | '-' \ket \end{indentingcode} Normally, you would do this only if you wanted to attach a reduction procedure to the null production. Note that if you include a null production within braces, and add an ellipsis after the closing brace for repetition, your grammar will be ambiguous. Just exactly how many times does the null production occur? Use brackets instead, and omit the null production. Null productions are not allowed with brackets, since they would be intrinsically ambiguous. The options within braces or brackets may be grammar rules of any length or complexity and may themselves contain virtual productions of arbitrary complexity. Nevertheless, in practice, clarity suffers as soon as the options get very complex. Virtual productions are most important and useful when used in simple situations. In those situations they will enhance the clarity of your grammar. Here is an example that is moderately complex, even though each rule consists of a single token: \begin{indentingcode}{0.4in} \bra{\bra}"on" | "true"\ket = 1; | {\bra}"off" | "false"\ket = 0; | integer\ket \end{indentingcode} This example can be used to allow as input either an integer or, for special cases, keywords. You could write this option out in the following way: \begin{indentingcode}{0.4in} p1 -> p2 = 1; -> p3 = 0; -> integer p2 -> "on" -> "true" p3 -> "off" -> "false" \end{indentingcode} The final category of virtual production provides a notation for \index{Alternating sequence}\agterm{alternating sequences}. An alternating sequence is a set of choices which may be repeated arbitrarily subject to the side condition that no choice may follow itself, in other words, that the choices must alternate. Alternating sequences are written with either brackets or braces depending on whether the sequence is optional or not, followed by \index{/...}``\agcode{/...}''. Note that the choices themselves may allow sequences. For example: \begin{indentingcode}{0.4in} program -> [statement | newline...]/..., eof \end{indentingcode} represents a sequence of statements separated by one or more newlines. Any two statements must be separated by one or more newline characters, and newlines may also appear at the beginning and the end of the program. Null productions are not allowed within alternating sequences, since they are intrinsically ambiguous in all cases. \subsection{Definition Statements} \index{Definitions}\index{Definition statement}\index{Statement} A definition statement is simply a shorthand way of naming a character set, a \index{Virtual productions}\index{Production}virtual production, a keyword string, or an immediate action. It can also be used for providing an alternate name for a token. Definitions have the form: \begin{indentingcode}{0.4in} name = \codemeta{character set} name = \codemeta{virtual production} name = \codemeta{keyword} name = \codemeta{immediate action} name = \codemeta{token name} \end{indentingcode} The name may be any name acceptable to AnaGram. The name can then be used anywhere you might have used the expression on the right side. \index{!}For example: \begin{indentingcode}{0.4in} upper case letter = 'A-Z' lower case letter = 'a-z' letter = upper case letter + lower case letter statement list = statement?... while keyword = "WHILE" prompt = !printf("Please enter name:"); \end{indentingcode} It is important to recognize that a definition statement that names a set does not define a token. A token is defined only when the set is used in a grammar rule, and then only if the set is used directly, not in combination with some other set. Furthermore, if you use a character set directly in a grammar rule, and in some other rule you use a name that refers to the same set of characters, you will get two different tokens. For example, if you have defined \agcode{upper case letter} as in the above example and use both \agcode{upper case letter} and \agcode{'A-Z'} in grammar rules, AnaGram will assign different \index{Token number}\index{Token}\index{Number}token numbers to accommodate any differences in attributes you may assign to the tokens. Renaming tokens is a convenient way to connect two independently written portions of a grammar. % See the C grammar in the EXAMPLES directory of your distribution % disk for an example. \subsection{Embedded C} \index{Embedded C} You may encapsulate C or C++ code in your syntax file by enclosing it in braces (\bra \ket). Such pieces of code are copied to the parser file untouched, in the order they are found in the syntax file. There may be any number of such pieces of embedded C. The only restriction is that they must not start on the same line as some other AnaGram statement, and following AnaGram statements must also start on fresh lines. Normally, the blocks of embedded C in your syntax file are copied to the parser file \emph{following} a set of definitions and declarations AnaGram needs for the code it generates. However, if the \emph{first} statement in your \index{Syntax file}syntax file is a block of embedded C, it will \emph{precede} AnaGram's definitions and declarations. This block of embedded C is called the \index{Prologue}\index{C prologue}``C prologue''. There are two main reasons for this special treatment. First, you may want to have a title and \index{Copyright notice}copyright notice in your parser. If you include them in an initial block of embedded C they will be right at the beginning of both your syntax file and your parser file. Second, if some of your tokens have data type\index{Token}\index{Data type}s other than those predefined in C or C++, you may include the definitions here, so they will be available to the code AnaGram generates. AnaGram scans embedded C only insofar as is necessary to find the closing right brace. Therefore any braces used within embedded C must balance properly. AnaGram skips braces enclosed in character constants and string literals, as well as braces enclosed in comments. It also recognizes C++ style comments that begin with \agcode{//}. \index{Comments}Treatment of nested versus non-nested comments is controlled by the \index{Nest comments}\index{Configuration switches}\agparam{nest comments} configuration parameter. AnaGram will use the status of this parameter in effect at the beginning of the section of embedded C. AnaGram, of course, can be confused by unterminated strings, unbalanced brackets, and unterminated comments. The most likely outcome, in such a situation, is that AnaGram will encounter the end of file looking for the end of the embedded C. Should this happen, AnaGram will identify the beginning of the piece of embedded C which caused the problem. The code you include as embedded C, of course, has to coexist with the code AnaGram generates. In order to keep the potential for conflicts to a minimum, all variables and functions which AnaGram defines begin either with the name of your parser or with the letters \agcode{ag{\us}}. You should avoid variable names which begin with these letters. Reduction procedures are copied to the \index{Parser file}\index{File}parser file in the order in which they are defined \emph{following} all of the embedded C. Thus your reduction procedures may freely use variables and macros defined anywhere in your embedded C. \subsection{Configuration Sections} \index{Configuration section} A configuration section is a special section of your syntax file enclosed in brackets. Within a configuration section you may set the values of configuration parameters or switches, or you may use one or more of several available attribute statements to specify special treatment for certain tokens. There can be as many or as few configuration sections in your syntax file as you wish. Each configuration section must begin on a new line. Any AnaGram statement which follows a configuration section must also begin on a new line. Within a configuration section, each parameter setting and each attribute statement must begin on a new line. The rules for using comments and continuation lines are the same as for the rest of AnaGram. Configuration parameters control the way AnaGram interprets your syntax file and the way it builds your parser. A full discussion of the use of configuration parameters, including a complete discussion of each parameter and its default value, is given in Appendix A. \index{Attribute statements}\index{Statement} Attribute statements comprise the \index{Precedence declarations}precedence declarations \agparam{left}, \agparam{right}, and \agparam{nonassoc}; the \agparam{sticky} declaration; the \agparam{distinguish keywords} statement; the \agparam{hidden} declaration; the \agparam{disregard} and \agparam{lexeme} statements; the \agparam{enum} statement; the \index{Reserve keywords}\agparam{reserve keywords} declaration; and the \index{Rename macro}\agparam{rename macro} statement. The precedence declarations and the \index{Sticky declaration}\index{Declaration}\agparam{sticky} declaration may be used to resolve conflicts in your grammar. The \agparam{distinguish keywords} statement may be used to control keyword recognition. The \index{Hidden declaration}\index{Declaration}\agparam{hidden} declaration causes certain token names not to be used when your parser produces \index{Syntax error}\index{Errors}\index{Error messages}syntax error messages. You may use the \agparam{disregard} and \agparam{lexeme} statements to cause your parser to skip automatically over certain tokens in its input. The \agparam{enum} statement is almost identical to the enum statement in C. It can be used to assign names to input codes in grammars which are taking input from a \index{Lexical scanner}lexical scanner or another parser. The \index{Reserve keywords}\agparam{reserve keywords} declaration allows you to specify certain keywords as reserved words. The \index{Rename macro}\agparam{rename macro} statement allows you to override the names AnaGram uses for various macro definitions it creates in the code it generates. Attribute statements are discussed below. Except for \agparam{disregard} and \agparam{rename macro} statements, attribute statements accept lists of operands enclosed in braces (\bra \ket) and separated by commas. A dangling comma following the last item in a list will be ignored. \subsection{Setting Configuration Parameters} \index{Configuration parameters}\index{Parameters} Each configuration parameter has a name that follows the AnaGram conventions for symbol names, except that AnaGram ignores case\index{Case sensitivity} when looking up configuration parameter names. There are a number of varieties of configuration parameters. The simplest, \index{Configuration switches}\index{Switches}configuration switches, simply turn some feature of AnaGram on or off. These parameters need simply be stated to turn the feature on, or negated with the tilde (\agcode{\~{}}) to turn the feature off: \begin{indentingcode}{0.4in} nest comments \end{indentingcode} causes AnaGram to allow nested comments, and \begin{indentingcode}{0.4in} \~{}nest comments \end{indentingcode} causes AnaGram to disallow nested comments. You may also set or reset configuration switches with explicit on or off values: \begin{indentingcode}{0.4in} nest comments = on nest comments = off \end{indentingcode} The remaining configuration parameters are assigned values using a simple assignment statement. Depending on the parameter, the value it takes may be the name of a token, a C variable name, a C or C++ data type, a string constant or an integer. String constants are written using the same rules as keyword strings, described above. \begin{indentingcode}{0.4in} grammar token = program parser name = widget default token type = void * header file name = "widget.h" parser stack size = 50 \end{indentingcode} A number of string-valued \index{Configuration parameters}configuration parameters are used to determine file names and variable names. In these parameters, the \index{\#}``\#'', \index{\_dol}``\$'', and ``\index{ \_prc}\%'' characters are used as wild cards. In file name specifications and the specification of the name of your parser, ``\#'' will be replaced by the name of your syntax file. In other function and variable names AnaGram creates while building your parser, ``\$'' will be replaced by the name of your parser. When building enumeration constants for the names of the tokens in your grammar, ``\%'' will be replaced by the name of the token. Note that when entering a Windows/DOS path name as a value for a file name parameter you must quote any backslashes in the path name. For example, \begin{indentingcode}{0.4in} coverage file name = "f:{\bs\bs}sna{\bs\bs}foo.nrc" \end{indentingcode} \subsection{Precedence Declarations} \index{Precedence declarations} AnaGram allows you to resolve shift-reduce conflicts by assigning precedence levels to operators. There are three precedence declarations available, beginning with the keywords \index{Left}\agparam{left}, \index{Right}\agparam{right}, and \index{Nonassoc}\agparam{nonassoc} respectively. Each such declaration consists of the appropriate keyword and a list of tokens enclosed in braces (\bra \ket). All the tokens in the list have the same precedence, higher than tokens in any previous declaration and lower than in any subsequent declaration. If the keyword is \agparam{left}, the tokens will group to the left. If it is \agparam{right}, they will group to the right. If it is \agparam{nonassoc} (for non-associative) no grouping will be assumed. Precedence declarations must be included in a configuration section. Here are precedence declarations appropriate to a simple desk calculator program: \begin{indentingcode}{0.4in} {}[ left \bra '+', '-' \ket left \bra star, '/', '\%' \ket right \bra unary minus \ket ] unary minus = '-' \end{indentingcode} Note that \agcode{unary minus} and \agcode{'-'} can have different precedence. Precedence declarations are one of the few instances in AnaGram where the \index{Statements}\index{Order of statements}order of statements is significant. The use of precedence declarations is discussed in Chapter 9. \subsection{``Sticky'' Declarations} \index{Sticky declaration}\index{Declaration} AnaGram provides another means for resolving shift-reduce conflicts. You may characterize any token as ``sticky''. Then, in the case of a \index{Shift-reduce conflict}\index{Conflicts}shift-reduce conflict where a ``sticky'' token is the last token in the input buffer, the conflict will be resolved by selecting the shift operation. Intuitively, you may think of this as though the ``sticky'' token adheres to and draws in any subsequent input that it can. ``Sticky'' declarations are included in configuration sections. They begin with the keyword \agcode{sticky} followed by a list of tokens, separated by commas inside braces (\bra \ket). Suppose, for instance, you wished to pick up a line of text, skipping any leading space or tab characters. You might write the following syntax: \begin{indentingcode}{0.4in} white space = ' ' + '{\bs}t' text char -> \~{}'{\bs}n':c = do{\us}something(c); line -> leading white space, text char?..., '{\bs}n' leading white space -> -> leading white space, white space \end{indentingcode} Unfortunately, this syntax is ambiguous, since space and tab are legitimate instances of both leading white space and text char. What you really want to do is to skip white space until you find a non-blank character and then you want to accept all characters to the end of the line. There are two ways to address the problem. The first is to define a special token for the first non-blank character and, using it, to write an unambiguous grammar. This approach, while laudable, is tedious and prolix. Instead, use \agparam{sticky} to resolve the problem: \begin{indentingcode}{0.4in} {}[ sticky \bra leading white space \ket ] \end{indentingcode} Now when AnaGram analyzes your grammar, and encounters the ambiguity, it will understand that a blank or tab that could be treated either as leading white space or the as the first text character should be treated as white space. Since \agcode{leading white space} is ``sticky'', any subsequent white space adheres to it. As with conflicts resolved with precedence levels, AnaGram lists all conflicts that it resolves using \agcode{sticky} in the \index{Resolved Conflicts}\index{Window}\agwindow{Resolved Conflicts Table}, so you can verify that the conflicts have been correctly resolved. An important use of sticky tokens is to inhibit the recognition of following \index{Keywords}keywords. Following a sticky token, a keyword, which, according to your grammar, would otherwise be legitimate input, will not be recognized if a shift action is possible for the first character of the keyword. For example, imagine that \agcode{name} has been defined in the conventional way, and there exists a production with name followed immediately by the keyword \agcode{int}. Then if, in your input, the word \agcode{print} were to occur, your grammar would parse it as a name, \agcode{pr}, followed by the keyword \agcode{int}. If you make \agcode{name} sticky, however, the first letter of \agcode{int} will be seen to be an acceptable character for \agcode{name} and the keyword will not be recognized. Your parser will then recognize the \agcode{name} as \agcode{print}. \subsection{Distinguish Keywords Statement} \index{Distinguish keywords}\index{Keywords} Distinguish keywords statements are occasionally needed to prevent keyword recognition. You may, for example, wish to prevent the recognition of the keyword \agcode{int} when it occurs embedded in a word such as \agcode{interval}. Of course, you need to do this only if both the keyword and the other word are both legitimate input at the same point in your grammar. A distinguish keywords statement can prevent recognition of a keyword which is embedded in another word provided at least one character of the other word follows the keyword. The distinguish keywords statement has the form: \begin{indentingcode}{0.4in} distinguish keywords \bra \codemeta{list of character sets} \ket \end{indentingcode} AnaGram compares all the characters in each keyword to the characters included in each character set in turn. If it finds that all the characters in a keyword are members of a particular set, it tells the keyword recognition logic to try to match the keyword only against the longest sequence of characters drawn from the specified set. In other words, in order for a keyword to be recognized, the keyword \emph{must} be followed by a character \emph{not} in the set. The set associated with a keyword is the first one in the list which contains all the characters found in the keyword. If you have more than one \agparam{distinguish keywords} statement in your grammar, the lists are tried in the order in which they appear in the grammar. The purpose of the \agparam{distinguish keywords} statement is to enable your parser to distinguish a keyword from the same sequence of characters embedded within another sequence. Thus suppose that \agcode{int} is a keyword, and, according to your grammar, could appear in the same place as the word \agcode{integral}. If you don't want it to be recognized as a keyword in these circumstances, you would write the following distinguish statement: \begin{indentingcode}{0.4in} distinguish keywords \bra 'a-z'+'A-Z' \ket \end{indentingcode} To also inhibit recognition of \agcode{int} within \agcode{print}, you would combine the use of the distinguish keywords statement with the \agparam{sticky} declaration. \subsection{``Hidden'' Declarations} \index{Hidden declaration}\index{Declaration} AnaGram provides an optional \index{Error diagnosis}error diagnosis feature for your parser (see Chapter 9). The \agparam{hidden} declaration allows you to identify tokens that you do not wish to be used in making up \index{Diagnostic messages}diagnostic messages. These tokens are tokens whose names would not mean anything to your users. The format of a ``hidden'' declaration is the same as that of precedence and ``sticky'' declarations. Within a configuration section, the keyword ``hidden'' is followed by a list of tokens. For example: \begin{indentingcode}{0.4in} {}[ hidden \bra comment head \ket ] comment -> comment head, "*/" comment head -> "/*" -> comment head, \~{}eof \end{indentingcode} This is an AnaGram representation of ANSI standard C comments (non-nested). In this example the token \agcode{comment head} exists only for convenience in writing the grammar and has no particular meaning to an end user. On the other hand, he knows what the word \agcode{comment} refers to. The ``hidden'' attribute will cause AnaGram's diagnostic builder, by backing up the stack until it finds a non-hidden token, to eschew \agcode{comment head} in favor of \agcode{comment}. % XXX eschew obfuscation. how about ``avoid''? \subsection{Disregard Statement} The purpose of the \index{Disregard statement}\index{Statement}\agparam{disregard} statement is to skip over uninteresting \index{White space}white space and comments in your input files. The disregard statement allows you to specify a token that should be passed over in the input to your parser. The statement takes the form: \begin{indentingcode}{0.4in} disregard ws \end{indentingcode} where \agcode{ws} is a token name or character set. Disregard statements may be placed in any configuration section. You may have more than one disregard statement in your grammar. If you do, AnaGram will create a shell production. For example, suppose you write: \begin{indentingcode}{0.4in} {}[ disregard alpha disregard beta ] \end{indentingcode} AnaGram will proceed as though you had written: \begin{indentingcode}{0.4in} gamma -> alpha | beta {}[ disregard gamma ] \end{indentingcode} It frequently happens that you wish your parser to disregard blanks or comments, except that white space within names, numbers, strings, and other elementary constructs is subject to special rules and thus should not be disregarded blindly. In this case, you can use the \agparam{lexeme} statement to declare these constructs off limits for the disregard statement. Within these constructs, the disregard statement will be inoperative and the admissibility of white space will be determined solely by the productions which define these constructs. Outside those productions which define lexemes, you should not generally use a token which is supposed to be disregarded. If you do, your grammar will have conflicts, since the token could satisfy both the explicit usage and the implicit rules set up by the disregard statement. Such conflicts, however, are resolved automatically in favor of your explicit use of the token. The conflicts will appear in the \agwindow{Resolved Conflicts} window. % XXX I'm not sure that's still true. In order to implement the disregard statement AnaGram will redefine some tokens in your grammar. For example, \agcode{+} may be redefined to consist of a simple plus sign followed by optional white space: \begin{indentingcode}{0.4in} '+' -> '+'\%, white space?... \end{indentingcode} The percent sign is used to indicate the original, simple plus sign without the optional white space attached. You will probably notice the percent sign appearing in some windows and traces. In earlier versions of AnaGram, the degree sign, ``\agcode{\degrees}'', was used rather than ``\agcode{\%}''. \subsection{Lexeme Statement} The ``lexeme'' \index{Statement}\index{Lexeme statement}statement is used to fine-tune the disregard statement. The lexeme statement takes the form: \begin{indentingcode}{0.4in} {}[ lexeme \bra \codemeta{nonterminal token list} \ket ] \end{indentingcode} where \textit{nonterminal token list} is a list of nonterminal tokens separated by commas. Lexeme statements may be placed in any configuration section, and there may be any number of them. When you specify that a token is to be disregarded, AnaGram rewrites your grammar so that the token will be passed over whenever it occurs at the beginning of a file or following a lexical unit, or \agterm{lexeme}. If you have no \agparam{lexeme} statement, then the lexemes in your grammar are just the terminal tokens. The \agparam{lexeme} statement allows you to specify that certain nonterminal tokens are also to be treated as lexemes. This means that the disregard token will be skipped following the lexeme, but not between the characters that constitute the lexeme. Lexemes correspond to the tokens that a lexical scanner, if you were using one, would commonly identify and pass to a parser as single tokens. You don't usually wish to disregard white space within these tokens. For example, in a grammar for a conventional programming language where blank characters are to be disregarded, you might include: \begin{indentingcode}{0.4in} {}[ lexeme \bra string, character constant, name, number \ket ] \end{indentingcode} since blank characters must not be overlooked within strings and character constants and should not be permitted within names or numbers. Normally, AnaGram considers the disregard token to be optional; however there are circumstances where treating the disregard token as optional would lead to conflicts: two successive names, or two successive numbers, for example. In this case, you would like to require that the lexemes be separated by instances of the disregard token. To do this, simply set the \index{Distinguish lexemes}\index{Configuration switches} \agparam{distinguish lexemes} configuration switch. When this switch is set, AnaGram will ensure that disregard tokens will be required in those situations where making them optional would lead to conflicts. White space may be used explicitly within definitions of lexeme tokens in your grammar if desired, without causing conflicts. Thus, if you wish to allow embedded space in variable names, you might write: \begin{indentingcode}{0.4in} {}[ disregard space lexeme \bra variable name \ket ] space = ' ' + '{\bs}t' letter = 'a-z' + 'A-Z' digit = '0-9' variable name -> letter -> variable name, letter + digit -> variable name, space..., letter + digit \end{indentingcode} \subsection{Enum Statement} \index{Enum statement}\index{Enumeration}\index{Token} The \agparam{enum} statement follows rules nearly identical to those for C and C++. This makes it possible to copy an enum statement from your syntax file to a program file written in either C or C++, without any need for editing. The only differences are that AnaGram makes no provision for blank lines within the enumeration list, nor does it accept a type name. The \agparam{enum} statement is equivalent to a corresponding set of definition statements. It is especially useful when a parser is accepting token input from another program, a \index{Lexical scanner}lexical scanner, for example. Using the enum statement you may conveniently define all the identification codes for the input tokens. Each entry in an enum statement may be either a name, or a name followed by an ``='' sign and a character representation. If there is a character representation the name is assigned the value of the specified character. Otherwise it is assigned a value one more than that assigned to the previous name. If the first name in the list is not given an explicit value, it will be given the value zero. For example: \begin{indentingcode}{0.4in} {}[ enum \bra eof, a,b,c, blank = '\ ', x, y \ket ] \end{indentingcode} is equivalent to the following definition statements \begin{indentingcode}{0.4in} eof = 0 a = 1 b = 2 c = 3 blank = '\ ' x = 33 y = 34 \end{indentingcode} \subsection{Subgrammar Declarations} \index{Subgrammar declaration}\index{Declaration} A \agparam{subgrammar} declaration can be a useful way to deal with conflicts in certain situations. It tells AnaGram to treat the tokens listed in the declaration as though they were each grammar tokens, each specifying a complete subgrammar in itself, and, in determining shift and reduction actions, to ignore the usage of the tokens in the larger grammar. In some cases it is perfectly reasonable to ignore usage. The most common example occurs when building a lexical scanner for a language such as C as in the example in Section 7.4.4. In this case, you can write a complete grammar for a C token with no difficulty. But if you try to extend it to a sequence of tokens, you get scores of conflicts. This situation arises because you specify that any C token can follow another, when in actual practice, an identifier, for example, cannot follow another identifier without some intervening space or punctuation. It is theoretically possible, but in practice quite awkward, to write a grammar for a sequence of tokens so that there are no conflicts. The subgrammar declaration provides a way around this problem by telling AnaGram that when it is looking for reducing tokens for any rule produced directly or indirectly by a subgrammar token, it should disregard the usage of the token and only consider usage internal to the definition of the subgrammar token, as though the subgrammar token were the start token of the grammar. The subgrammar declaration is made in a configuration section and consists of the keyword \agcode{subgrammar} followed by a list of one or more nonterminal token names, separated by commas and enclosed in braces (\bra \ket). For example: \begin{indentingcode}{0.4in} {}[ subgrammar \bra C token, word \ket ] \end{indentingcode} Since the subgrammar statement changes the way AnaGram determines reducing tokens, it should be used with caution. You should be sure that the conflicts you are eliminating are really inconsequential. \subsection{Reserve Keywords Declaration} \index{Reserve keywords}\index{Keywords}\index{Keyword anomalies} The \agparam{reserve keywords} declaration can be used to specify a list of keywords that are reserved and cannot be used except as explicitly specified in the grammar. This enables AnaGram to avoid issuing meaningless keyword anomaly diagnostics (see \S 7.5). AnaGram does not automatically presume that keywords are also reserved words, since in many grammars there is no need to specify reserved words. The reserve keywords declaration is made in a configuration section and consists of the words \agcode{reserve keywords} followed by a list of one or more keyword strings, separated by commas and enclosed in braces (\bra \ket). For example: \begin{indentingcode}{0.4in} {}[ reserve keywords \bra "int", "char", "float", "double" \ket ] \end{indentingcode} \subsection{Rename Macro Statement} \index{Rename macro}\index{Macros} AnaGram uses a number of macros in its generated code. It is possible, therefore, to run into naming collisions with other components of your program. The \agparam{rename macro} statement allows you to change the name AnaGram uses for a particular macro to avoid these problems. For example, the Windows NT operating system uses \agcode{CONTEXT} structures to perform various internal operations. If you use the context tracking option (see \S 9.5.4) your parser will have a macro called \agcode{CONTEXT}. To avoid the name collision, add the following statement to any configuration section in your grammar: \begin{indentingcode}{0.4in} rename macro CONTEXT AG{\us}CONTEXT \end{indentingcode} Then, simply use \agcode{AG{\us}CONTEXT} where you would otherwise have used \agcode{CONTEXT}.