% Copyright 2012-2020, Alexander Shibakov
% Copyright 2002-2014 Free Software Foundation, Inc.
% This file is part of SPLinT
%
% SPLinT is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% SPLinT is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with SPLinT. If not, see .
\ifbootstrapmode % this is a bootstrap run to extract the states
\message{bootstrapping \jobname.tex ...}%
\input limbo.sty
\def\optimization{5}
\input yy.sty
\modebootstrap
\fi
@**The \eatone{bison}\bison\ parser stack.
The input language for \bison\ loosely follows the {\sc BNF} notation, with
a few enhancements, such as the syntax for {\em actions}, to implement
the syntax-directed translation@^syntax-directed translation@>, as
well as various declarations for tokens, nonterminals, etc.
On the one hand, the language is relatively easy to handle, is
nearly whitespace agnostic, on the other, a primitive parser is
required for some basic setup even at a very early stage, so the
design must be carefully thought out. This {\em
bootstrapping\/}@^bootstrapping@> step is discussed in more details
later on.
The path chosen here is by no means optimal. What it lacks in
efficiency, though, it may amply gain in practicality, as we reuse the
original grammar used by \bison\ to produce the parser(s) for both
pretty printing and bootstrapping. Some minor subtleties arising from
this approach are explained in later sections.
As was described in the
\ifbootstrapmode\else\locallink{parser.stacks} discussion of parser
stacks \endlink\fi@^parser stack@> above, to pretty print a variety
of grammar fragments, one may employ
a {\em parser stack\/} derived from the original grammar. The most
natural and common unit of a \bison\ grammar is a set of
productions. It is thus natural to begin our discussion of the parsers
in the \bison\ stack with the parser responsible for processing
individual rules.
One should note that the productions below are not concerned with the
typesetting of the grammar. Instead this task is delegated to the
macros in \.{yyunion.sty} and its companions. The first pass of the
parser merely constructs an `executable abstract syntax tree' (or
\EAST\footnote{One may argue that \EAST\ is still merely a syntactic
construct requiring a proper macro framework for its execution and
should be called a `weak executable syntax tree' or \WEST. This
acronym extravagnza is heading south so we shall stop here.}) which
can serve very diverse purposes: from collecting token declarations in
the boostrapping pass to typesetting the grammar rules.
It would be impossible to completely avoid the question of the visual
presentation of the \bison\ input, however. It has already been
pointed out that the syntax adopted by \bison\ is nearly insensitive
to whitespace. This makes {\em writing\/} \bison\ grammars easier. On
the other hand, {\em presenting\/} a grammar is best done using a
variety of typographic devices that take advantage of the meaningful
positioning of text on the page: skips, indents, etc. Therefore, the
macros for \bison\ pretty printing trade a number of \bison\ syntax
elements (such as \.{\yl}, \.{;}, action braces, etc.) for the careful
placement of each fragment of the input on the page.
Let's take a short break for a broad overview of the input file.
The basic structure is that of an ordinary \bison\ file that produces
plain \Cee\ output. The \Cee\ actions, however, are programmed to output \TeX.
The \bison\ sections (separated by \.{\%\%} (shown (pretty printed)
as \prodstyle{\%\%} below)) appear between the successive dotted lines.
@(bg.yy@>=
@G Switch to generic mode.
%{@> @ @=%}
@> @ @=
%union {@> @ @=}
%{@> @ @=%}
@> @ @=
%%
@> @ @=
@> @ @=
@> @ @=
%%
@g
@ Bootstrap\namedspot{bootstrapping}@^bootstrapping@> mode is next.
The reason for a separate bootstrap parser is to
collect the minimal amount of information to `spool up' the `production'
parsers. To understand the mechanics and the reasons behind it, consider what happens
following a declaration such as \.{\%token TOKEN "token"}
(or, as it would be typeset by the macros in this package
`\prodstyle{\%token} \.{TOKEN} \.{token}'; see the index entries for
more details)%
\idxinline{TOKEN}\idxinline{token}.
The two names for the same token are treated very differently. \.{TOKEN} becomes
an |enum| constant in the \Cee\ parser generated by \bison. Even when
that parser becomes part of the `driver' program that outputs the \TeX\
version of the parser tables, there is no easy way to output the {\it
names\/} of the appropriate |enum| constants. The other name
(\.{"token"}) becomes an entry in the |yytname| array. These names
can be output by either the `driver' or \TeX\ itself after the
\.{\\yytname} table has been input. The scanner, on the other hand,
will use the first version (\.{TOKEN}). Therefore, it is important to
establish an equivalence between the two versions of the name. In the
`real' parser, the token values are output in a special header
file. Hence, one has to either parse the header file to establish the
equivalences or find some other means to find out the numerical values
of the tokens.
One approach is to parse the file containing the {\it declarations\/}
and extract the equivalences between the names from it. This is the
function of the bootstrap parser. Since the lexer is reused, some
token values need to be known in advance (and the rest either ignored
or replaced by some `made up' values). These tokens are `hard coded'
into the parser file generated by \bison\ and output using a special
function. The switch `|@[#define@]@; BISON_BOOTSTRAP_MODE|' tells the
`driver' program to output the hard coded token values.
@q Bizarre looking way of typing #define is due to the awkward way@>
@q \CWEB\ treats switching in and out of $-mode in inline \Cee@>
Note that the equivalence of the two versions of token names would
have to be established every time a `string version' of a token is
declared in the \bison\ file and the `macro name version' of the token
is used by the corresponding scanner. To establish this equivalence,
however, the bootstrapping parser below is not always necessary (see
the \.{xxpression} example, specifically, the file \.{xxpression.w} in
the \.{examples} directory for an example of using a different parser
for this purpose). The reason it is necessary here is that a parser
for an appropriate subset of the \bison\ syntax is not yet available
(indeed, {\it any\/} functional parser for a \bison\ syntax subset
would have to use the same scanner (unless you want to write a custom
scanner for it), which would need to know how to output tokens, for
which it would need a parser for a subset of \bison\ syntax $\ldots$
it is a genuine `chicken and egg' problem). Hence the need for
`bootstrap'. Once a functional parser for a large enough subset of the
\bison\ input grammar is operational, {\it it\/} can be used to pair
up the token names.
The second function of the bootstrap parser is to collect information
about the scanner's states. The mechanism is slightly different for
states. While the token equivalences are collected purely in
`\TeX\ mode', the bootstrap parser collects all the state names into a
special \Cee\ header file. The reason is simple: unlike the token
values, the numerical values of the scanner states are not passed to
the `driver' program in any data structure and are instead defined as
ordinary macros. The header file is the information the `driver' file
needs to output the state values.
An additional subtlety in the case of the state value output is that the
main lexer for the \bison\ grammar utilizes states extensively and thus
cannot be easily used with the bootstrap parser before the state
values are known. The solution is to substitute a very simple scanner barely
capable of lexing state declarations. Such a scanner is implemented
in \.{ssffo.w} (the somewhat cryptic name stands for `{\bf s}imple {\bf s}canner
{\bf f}or {\bf f}lex {\bf o}ptions').
@(bb.yy@>=
@G Switch to generic mode.
%{
@> @ @=
@> @/#define BISON_BOOTSTRAP_MODE @=
%}
@> @ @=
%union {@> @ @=}
%{@> @ @=%}
@> @ @=
%%
@> @ @=
@> @ @=
@> @<\flex\ options parser productions@> @=
@> @ @=
@> @ @=
%%
@g
@ The prologue parser is responsible for parsing various grammar
declarations as well as parser options.
@(bd.yy@>=
@G Switch to generic mode.
%{@> @ @=%}
@> @ @=
%union {@> @ @=}
%{@> @ @=%}
@> @ @=
%%
@> @ @=
@> @ @=
@> @ @=
%%
@g
@ The full \bison\ input parser is used when a complete \bison\ file is
expected. It is also capable of parsing a `skeleton' of such a file,
similar to the one that follows this paragraph.
@(bf.yy@>=
@G Switch to generic mode.
%{@> @ @=%}
@> @ @=
%union {@> @ @=}
%{@> @ @=%}
@> @ @=
%%
@> @ @=
@> @ @=
@> @ @=
@> @ @=
%%
@g
@ \namedspot{bison.options}The first two options below are essential
for the parser operation
as each of them makes \bison\ produce additional tables (arrays) used
in the operation (or bootstrapping) of \bison\ parsers. The
start symbol can be set implicitly by listing the appropriate
production first. Modern \bison\ also allows specifying the kind of
parsing algorithm to be used (provided the supplied grammar is in the
appropriate class): {\sc LALR}($n$), {\sc LR}($n$), {\sc GLR}, etc.
The default is to use the {\sc LALR}($1$) algorithm (with the
corresponding assumption about the grammar) which can also be set
explicitly by putting
\medskip
\beginprod
\%define lr.type canonical-lr
\endprod
\medskip
\noindent
in with the rest of the options.
Using other types of grammars will wreak havoc
on the parsing algorithm hardcoded into \splint\ (see \.{yyparse.sty})
as well as on the production of \.{\\stashed} and \.{\\format} streams.
@=
@G
%token-table
%debug
%start input
@g
@*1 Token declarations. Most of the original comments present in
the grammar file used by \bison\ itself have been preserved and appear in
{\it italics\/} at the beginning of the appropriate section.
To facilitate the {\it bootstrapping\/} of the parser (see above), some
declarations have been separated into their own sections. Also, a
number of new rules have been introduced to create a hierarchy of
`subparsers' that parse subsets of the grammar. We begin by listing
most of the tokens used by the grammar. Only the string versions are
kept in the |yytname| array, which, in part is the reason for a
special bootstrapping parser as explained earlier.
\iffalse
\checktrailingstashtrue % see what is left at the end
\checktabletrue % display the table
\let\stashnext\stashnextwithnothing % collect the stash expanded
\fi
@=
@G
%token GRAM_EOF 0 "end of file"
%token STRING "string"
%token PERCENT_TOKEN "%token"
%token PERCENT_NTERM "%nterm"
%token PERCENT_TYPE "%type"
%token PERCENT_DESTRUCTOR "%destructor"
%token PERCENT_PRINTER "%printer"
%token PERCENT_LEFT "%left"
%token PERCENT_RIGHT "%right"
%token PERCENT_NONASSOC "%nonassoc"
%token PERCENT_PRECEDENCE "%precedence"
%token PERCENT_PREC "%prec"
%token PERCENT_DPREC "%dprec"
%token PERCENT_MERGE "%merge"
@g
@@;
@ We continue with the list of tokens below, following the layout of
the original parser.
\iffalse
\checktrailingstashfalse
\checktablefalse
\let\stashnext\stashnextwithnothingnx
\fi
@=
@G
%token
PERCENT_CODE "%code"
PERCENT_DEFAULT_PREC "%default-prec"
PERCENT_DEFINE "%define"
PERCENT_DEFINES "%defines"
PERCENT_ERROR_VERBOSE "%error-verbose"
PERCENT_EXPECT "%expect"
PERCENT_EXPECT_RR "%expect-rr"
PERCENT_FLAG "%"
PERCENT_FILE_PREFIX "%file-prefix"
PERCENT_GLR_PARSER "%glr-parser"
PERCENT_INITIAL_ACTION "%initial-action"
PERCENT_LANGUAGE "%language"
PERCENT_NAME_PREFIX "%name-prefix"
PERCENT_NO_DEFAULT_PREC "%no-default-prec"
PERCENT_NO_LINES "%no-lines"
PERCENT_NONDETERMINISTIC_PARSER
"%nondeterministic-parser"
PERCENT_OUTPUT "%output"
PERCENT_REQUIRE "%require"
PERCENT_SKELETON "%skeleton"
PERCENT_START "%start"
PERCENT_TOKEN_TABLE "%token-table"
PERCENT_VERBOSE "%verbose"
PERCENT_YACC "%yacc"
;
%token BRACED_CODE "{...}"
%token BRACED_PREDICATE "%?{...}"
%token BRACKETED_ID "[identifier]"
%token CHAR "char"
%token EPILOGUE "epilogue"
%token EQUAL "="
%token ID "identifier"
%token ID_COLON "identifier:"
%token PERCENT_PERCENT "%%"
%token PIPE "|"
%token PROLOGUE "%{...%}"
%token SEMICOLON ";"
%token TAG ""
%token TAG_ANY "<*>"
%token TAG_NONE "<>"
%token INT "integer"
%token PERCENT_PARAM "%param";
@g
@ \namedspot{flex.options}Extra tokens for typesetting \flex\ state
declarations and options are declared in addition to the ones that a
standard \bison\ parser recognizes. This extension of the original
grammar has become unnecessary with the addition of the \flex\ input
parser(s) but is left as part of the extended grammar for convenience and
`historical' reasons.
@=
@G
%token FLEX_OPTION FLEX_STATE_X FLEX_STATE_S
@g
@*1 Grammar productions.
We are ready to describe the top levels of the parse tree. The first
`sub parser' we consider is a `full' parser, that is the parser that
expects a full grammar file, complete with the prologue, declarations,
etc. This parser can be used to extract information from the grammar
that is otherwise absent from the executable code generated by
\bison. This includes, for example, the `name' part of
\.{\$}\.{[}{\rm name}\.{]}.
This parser is therefore used to generate the `symbolic
switch' to provide support for symbolic term names similar to
the `genuine' \bison's \.{\$}\.{[}$\ldots$\.{]} syntax.
The action of the parser in this case is simply to separate the
accumulated `parse tree' from the auxiliary information carried by the
parser on the stack.
\saveparseoutputfalse
\checktablefalse
\tracenamesfalse
@=
@G
@t}\vb{\inline}{@>
input:
prologue_declarations
"%%" grammar epilogue.opt {@> TeX_( "/getsecond{/yy(3)}/to/table" ); @=}
;
@g
@ Another subgrammar deals with the syntax of isolated \bison\ rules. This is
the most commonly used `subparser' since a rules cluster is the most
natural `unit' to include in a \CWEB\ file.
@=
@G
@t}\vb{\inline}{@>
input:
grammar epilogue.opt {@> TeX_( "/getsecond{/yy(1)}/to/table" ); @=}
;
@g
@ The bootstrap parser has a very narrow set of goals: it is concerned
with \prodstyle{\%token} declarations only in
order to supply the token information to the lexer (since, as noted
above, such information is not kept in the |yytname| array).
The parser can also parse \prodstyle{\%nterm} declarations but the
bootstrap lexer ignores the \prodstyle{\%nterm} token, since the
\bison\ grammar does not use one.
It also extends the syntax of a \prodstyle{grammar\_declaration} by allowing a
declaration with or without a semicolon at the end (the latter is only
allowed in the prologue). This works since the token declarations have
been carefully separated from the rest of the grammar in different
\CWEB\ sections. The range of tokens output by the bootstrap
lexer is limited, hence most of the other rules are ignored.
@=
@G
@t}\vb{\inline}{@>
input:
grammar_declarations {@> TeX_( "/table=/yy(1)" ); @=}
;
@t}\vb{\resetf}{@>
grammar_declarations:
symbol_declaration semi.opt {@> @ @=}
| flex_declaration semi.opt {@> @ @=}
| grammar_declarations
symbol_declaration semi.opt {@> TeX_( "/yy0{/the/yy(1)/the/yy(2)}" ); @=}
| grammar_declarations
flex_declaration semi.opt {@> TeX_( "/yy0{/the/yy(1)/the/yy(2)}" ); @=}
;
@t}\vb{\inline\flatten}{@>
semi.opt: {} | ";" {};
@g
@ The following is perhaps the most common action performed by the
parser. It is done automatically by the parser code but this feature
is undocumented so we supply an explicit action in each case.
@=
@[TeX_( "/yy0{/the/yy(1)}" );@]@;
@ Next comes a subgrammar for processing prologue declarations. Finer
differentiation is possible but the `subparsers' described here work
pretty well and impose a mild style on the grammar writer. Note that
these roles are not part of the official \bison\ input grammar and are
added to make the typesetting of `file outlines' (e.g.~|@(bb.yy@>|
above) possible.
@=
@G
@t}\vb{\inline}{@>
input:
prologue_declarations epilogue.opt {@> TeX_( "/getsecond{/yy(1)}/to/table" ); @=}
| prologue_declarations
"%%" "%%" EPILOGUE {@> TeX_( "/getsecond{/yy(1)}/to/table" ); @=}
| prologue_declarations
"%%" "%%" {@> TeX_( "/getsecond{/yy(1)}/to/table" ); @=}
;
@g
@ {\it Declarations: before the first \prodstyle{\%\%}}. We are now
ready to deal with the specifics of the declarations themselves. The
\.{\\grammar} macro is a `structure', whose first `field' is the
grammar itself, whereas the second carries the type of the last
declaration added to the grammar.
@=
@G
prologue_declarations:
{@> TeX_( "/yy0{/nx/grammar{}{/nx/empty}}" ); @=}
| prologue_declarations
prologue_declaration {@> @ @=}
;
@g
@ @=
@@;
@ Here is a list of most kinds of declarations that can appear in the
prologue. The scanner returns the `stream pointers' for all the
keywords so the declaration `structures' pass on those pointers to the
grammar list. The original syntax has been left intact even though for
the purposes of this parser some of the inline rules are unnecessary.
@=
@G
prologue_declaration:
grammar_declaration {@> @ @=}
| "%{...%}" {@> TeX_( "/yy0{/nx/prologuecode/the/yy(1)}" ); @=}
| "%" {@> TeX_( "/yy0{/nx/optionflag/the/yy(1)}" ); @=}
| "%define" variable value {@> TeX_( "/yy0{/nx/vardef{/the/yy(2)}{/the/yy(3)}/the/yy(1)}" ); @=}
| "%defines" {@> TeX_( "/yy0{/nx/optionflag{defines}{}/the/yy(1)}" ); @=}
| "%defines" STRING {@> @[TeX_( "/toksa{defines}" );@]@+@ @=}
| "%error-verbose" {@> TeX_( "/yy0{/nx/optionflag{error verbose}{}/the/yy(1)}" ); @=}
| "%expect" INT {@> @[TeX_( "/toksa{expect}" );@]@+@ @=}
| "%expect-rr" INT {@> @[TeX_( "/toksa{expect-rr}" );@]@+@ @=}
| "%file-prefix" STRING {@> @[TeX_( "/toksa{file prefix}" );@]@+@ @=}
| "%glr-parser" {@> TeX_( "/yy0{/nx/optionflag{glr parser}{}/the/yy(1)}" ); @=}
| "%initial-action" "{...}" {@> TeX_( "/yy0{/nx/initaction/the/yy(2)}" ); @=}
| "%language" STRING {@> @[TeX_( "/toksa{language}" );@]@+@ @=}
| "%name-prefix" STRING {@> @[TeX_( "/toksa{name prefix}" );@]@+@ @=}
| "%no-lines" {@> TeX_( "/yy0{/nx/optionflag{no lines}{}/the/yy(1)}" ); @=}
| "%nondeterministic-parser" {@> TeX_( "/yy0{/nx/optionflag{nondet. parser}{}/the/yy(1)}" ); @=}
| "%output" STRING {@> @[TeX_( "/toksa{output}" );@]@+@ @=}
@t}\vb{\flatten}{@>
| "%param" {}
params {@> TeX_( "/yy0{/nx/paramdef{/the/yy(3)}/the/yy(1)}" ); @=}
@t}\vb{\fold}{@>
| "%require" STRING {@> @[TeX_( "/toksa{require}" );@]@+@ @=}
| "%skeleton" STRING {@> @[TeX_( "/toksa{skeleton}" );@]@+@ @=}
| "%token-table" {@> TeX_( "/yy0{/nx/optionflag{token table}{}/the/yy(1)}" ); @=}
| "%verbose" {@> TeX_( "/yy0{/nx/optionflag{verbose}{}/the/yy(1)}" ); @=}
| "%yacc" {@> TeX_( "/yy0{/nx/optionflag{yacc}{}/the/yy(1)}" ); @=}
| ";" {@> TeX_( "/yy0{/nx/empty}" ); @=}
;
params:
params "{...}" {@> TeX_( "/yy0{/the/yy(1)/nx/braceit/the/yy(2)}" ); @=}
| "{...}" {@> TeX_( "/yy0{/nx/braceit/the/yy(1)}" ); @=}
;
@g
@ This is a typical parser action: encapsulate the `type' of the
construct just parsed and attach some auxiliary info, in this case the
stream pointers.
@=
@[TeX_( "/yy0{/nx/oneparametricoption{/the/toksa}{/nx/stringify/the/yy(2)}/the/yy(1)}" );@]@;
@ @=
@[TeX_( "/yy0{/nx/oneparametricoption{/the/toksa}{/the/yy(2)}/the/yy(1)}" );@]@;
@ These rules handle extra declarations to typeset \flex\ options and
declarations. These are not part of the \bison\ syntax but their
structure is similar enough that they can be included in the
grammar. As was pointed out \locallink{flex.options}earlier \endlink
the addition of the \flex\ input parser to \splint\ made this
extension of the original \bison\ grammar obsolete but it was kept as
part of the extended grammar for convenience and `historical'
reasons. The convenience results from simplifying the bootstrap
procedure by using a single parser.
@=
@G
prologue_declaration:
flex_declaration {@> @ @=}
;
@g
@<\flex\ options parser productions@>@;
@ The syntax of \flex\ options was extracted from \flex\ documentation
so it is not guaranteed to be correct.
@<\flex\ options parser productions@>=
@G
flex_declaration:
FLEX_OPTION flex_option_list {@> @ @=}
| flex_state symbols.1 {@> @ @=}
;
flex_state:
FLEX_STATE_X {@> TeX_( "/yy0{/nx/flexxstatedecls/the/yy(1)}" ); @=}
| FLEX_STATE_S {@> TeX_( "/yy0{/nx/flexsstatedecls/the/yy(1)}" ); @=}
;
flex_option_list:
flex_option {@> @ @=}
| flex_option_list flex_option {@> @ @=}
;
flex_option:
ID {@> TeX_( "/yy0{/nx/flexoptionpair{/nx/idit/the/yy(1)}{}}" ); @=}
| ID "=" symbol {@> TeX_( "/yy0{/nx/flexoptionpair{/nx/idit/the/yy(1)}{/the/yy(3)}}" ); @=}
;
@g
@ @=
@[TeX_( "/yy0{/nx/flexoptiondecls{/the/yy(2)}/the/yy(1)}" );@]@;
@ @=
@[TeX_( "/getfirst{/yy(1)}/to/toksa" );@]@;
@[TeX_( "/getsecond{/yy(1)}/to/toksb" );@]@;
@[TeX_( "/getthird{/yy(1)}/to/toksc" );@]@;
@[TeX_( "/yy0{/the/toksa{/the/yy(2)}{/the/toksb}{/the/toksc}}" );@]@;
@ @=
@[TeX_( "/getsecond{/yy(2)}/to/toksa" );@]@; /* the identifier */
@[TeX_( "/getfourth{/toksa}/to/toksb" );@]@; /* the format pointer */
@[TeX_( "/getfifth{/toksa}/to/toksc" );@]@; /* the stash pointer */
@[TeX_( "/yy0{/the/yy(1)/nx/hspace{/the/toksb}{/the/toksc}/the/yy(2)}" );@]@;
@ {\it Grammar declarations}. These declarations can appear in both
the prologue and the rules sections. Their treatment is very similar to
the prologue-only options.
@=
@G
grammar_declaration:
precedence_declaration {@> @ @=}
| symbol_declaration {@> @ @=}
| "%start" symbol {@> @[TeX_( "/toksa{start}" );@]@+@ @=}
| code_props_type "{...}" generic_symlist {@> @ @=}
| "%default-prec" {@> TeX_( "/yy0{/nx/optionflag{default prec.}{}/the/yy(1)}" ); @=}
| "%no-default-prec" {@> TeX_( "/yy0{/nx/optionflag{no default prec.}{}/the/yy(1)}" ); @=}
| "%code" "{...}" {@> TeX_( "/yy0{/nx/codeassoc{code}{}/the/yy(2)/the/yy(1)}" ); @=}
| "%code" ID "{...}" {@> TeX_( "/yy0{/nx/codeassoc{code}{/nx/idit/the/yy(2)}/the/yy(3)/the/yy(1)}" ); @=}
;
code_props_type:
"%destructor" {@> TeX_( "/yy0{{destructor}/the/yy(1)}" ); @=}
| "%printer" {@> TeX_( "/yy0{{printer}/the/yy(1)}" ); @=}
;
@g
@ @=
@[TeX_( "/getfirst{/yy(1)}/to/toksa" );@]@; /* name of the property */
@[TeX_( "/getfirst{/yy(2)}/to/toksb" );@]@; /* contents of the braced code */
@[TeX_( "/getsecond{/yy(2)}/to/toksc" );@]@; /* braced code format pointer */
@[TeX_( "/getthird{/yy(2)}/to/toksd" );@]@; /* braced code stash pointer */
@[TeX_( "/getsecond{/yy(1)}/to/tokse" );@]@; /* code format pointer */
@[TeX_( "/getthird{/yy(1)}/to/toksf" );@]@; /* code stash pointer */
@[TeX_( "/yy0{/nx/codepropstype{/the/toksa}{/the/toksb}{/the/yy(3)}{/the/toksc}{/the/toksd}{/the/tokse}{/the/toksf}}" );@]@;
@ @=
@G
%token PERCENT_UNION "%union";
@g
@ @=
@G
@t}\vb{\inline\flatten}{@>
union_name:
{@> TeX_( "/yy0{}" ); @=}
| ID {@> @ @=}
;
grammar_declaration:
"%union" union_name "{...}" {@> @ @=}
;
symbol_declaration:
"%type" TAG symbols.1 {@> @ @=}
;
@t}\vb{\resetf\flatten}{@>
precedence_declaration:
precedence_declarator tag.opt symbols.prec {@> @ @=}
;
precedence_declarator:
"%left" {@> TeX_( "/yy0{/nx/preckind{left}/the/yy(1)}" ); @=}
| "%right" {@> TeX_( "/yy0{/nx/preckind{right}/the/yy(1)}" ); @=}
| "%nonassoc" {@> TeX_( "/yy0{/nx/preckind{nonassoc}/the/yy(1)}" ); @=}
| "%precedence" {@> TeX_( "/yy0{/nx/preckind{precedence}/the/yy(1)}" ); @=}
;
@t}\vb{\inline}{@>
tag.opt:
{@> TeX_( "/yy0{}" ); @=}
| TAG {@> @ @=}
;
@g
@ @=
@[TeX_( "/yy0{/nx/codeassoc{union}{/the/yy(2)}/the/yy(3)/the/yy(1)}" );@]@;
@ @=
@[TeX_( "/yy0{/nx/typedecls{/nx/tagit/the/yy(2)}{/the/yy(3)}/the/yy(1)}" );@]@;
@ @=
@[TeX_( "/getthird{/yy(1)}/to/toksa" );@]@; /* format pointer */
@[TeX_( "/getfourth{/yy(1)}/to/toksb" );@]@; /* stash pointer */
@[TeX_( "/getsecond{/yy(1)}/to/toksc" );@]@; /* kind of precedence */
@[TeX_( "/yy0{/nx/precdecls{/the/toksc}{/the/yy(2)}{/the/yy(3)}{/the/toksa}{/the/toksb}}" );@]@;
@ The bootstrap grammar forms the smallest subset of the full grammar.
@=
@@;
@ @=
@[TeX_( "/yy0{/nx/tagit/the/yy(1)}" );@]@;
@ These are the two most important rules for the bootstrap parser. The reasons for
the~\prodstyle{\%token} declarations to be collected during the bootstrap pass are
outlined in the \locallink{bootstrapping}section on bootstrapping\endlink.
The~\prodstyle{\%nterm} declarations are not strictly necessary for
boostrapping the parsers included in \splint\ but they are added for
the cases when the bootstrap mode is used for purposes other than
bootstrapping \splint.
@=
@G
@t}\vb{\flatten}{@>
symbol_declaration:
"%nterm" {} symbol_defs.1 {@> TeX_( "/yy0{/nx/ntermdecls{/the/yy(3)}/the/yy(1)}" ); @=}
@t}\vb{\fold\flatten}{@>
| "%token" {} symbol_defs.1 {@> TeX_( "/yy0{/nx/tokendecls{/the/yy(3)}/the/yy(1)}" ); @=}
;
@g
@ {\it Just like \prodstyle{symbols.1} but accept \prodstyle{INT} for
the sake of \POSIX}. Perhaps the only point worth mentioning here is
the inserted separator (\.{\\hspace\{}$p_0$\.{\}\{}$p_1$\.{\}},
typeset as
|TeXa("/hspace"); TeXao(@t\TeXlit"\{\hbox{$p_0$}\}\{\hbox{$p_1$}\}\hbox{$\!$}"@>);|).
@q A string "..." is a syntactic unit in \CWEB\ so it is impossible@>
@q to insert \TeX\ material in the middle of the string directly@>
Like any other separator, it takes
two parameters, the stream pointers $p_0$ and~$p_1$. In this case, however, both pointers are null
since there seems to be no other meaningful assignment. If any
formatting or stash information is needed, it can be extracted by the
symbols themselves.
@=
@G
symbols.prec:
symbol.prec {@> @ @=}
| symbols.prec symbol.prec {@> TeX_( "/yy0{/the/yy(1)/nx/hspace{0}{0}/the/yy(2)}" ); @=}
;
symbol.prec:
symbol {@> TeX_( "/yy0{/nx/symbolprec{/the/yy(1)}{}}" ); @=}
| symbol INT {@> TeX_( "/yy0{/nx/symbolprec{/the/yy(1)}{/the/yy(2)}}" ); @=}
;
@g
@ {\it One or more symbols to be \prodstyle{\%type}'d}. The |@| rules below are reused in the boostrap parser and are put
in a separate section for this reason.
@=
@@;
@ @=
@G
symbols.1:
symbol {@> @ @=}
| symbols.1 symbol {@> TeX_( "/yy0{/the/yy(1)/nx/hspace{0}{0}/the/yy(2)}" ); @=}
;
@g
@ @=
@G
generic_symlist:
generic_symlist_item {@> @ @=}
| generic_symlist generic_symlist_item {@> TeX_( "/yy0{/the/yy(1)/nx/hspace{0}{0}/the/yy(2)}" ); @=}
;
@t}\vb{\flatten\inline}{@>
generic_symlist_item:
symbol {@> @ @=}
| tag {@> @ @=}
;
tag:
TAG {@> @ @=}
| "<*>" {@> @ @=}
| "<>" {@> @ @=}
;
@g
@ {\it One token definition}.
@=
@G
symbol_def:
TAG {@> @ @=}
@t}\vb{\flatten}{@>
| id {@> TeX_( "/yy0{/nx/onesymbol{/the/yy(1)}{}{}}" ); @=}
| id INT {@> TeX_( "/yy0{/nx/onesymbol{/the/yy(1)}{/the/yy(2)}{}}" ); @=}
| id string_as_id {@> TeX_( "/yy0{/nx/onesymbol{/the/yy(1)}{}{/the/yy(2)}}" ); @=}
| id INT string_as_id {@> TeX_( "/yy0{/nx/onesymbol{/the/yy(1)}{/the/yy(2)}{/the/yy(3)}}" ); @=}
;
@g
@ {\it One or more symbol definitions}.
@=
@G
symbol_defs.1:
symbol_def {@> @ @=}
| symbol_defs.1 symbol_def {@> @ @=}
;
@g
@ @=
@[TeX_( "/getsecond{/yy(2)}/to/toksa" );@]@; /* the identifier */
@[TeX_( "/getfourth{/toksa}/to/toksb" );@]@; /* the format pointer */
@[TeX_( "/getfifth{/toksa}/to/toksc" );@]@; /* the stash pointer */
@[TeX_( "/yy0{/the/yy(1)/nx/hspace{/the/toksb}{/the/toksc}/the/yy(2)}" );@]@;
@ {\it The grammar section: between the two
\prodstyle{\%\%}'s}. Finally, the following few short sections define
the syntax of \bison's rules.
@=
@G
grammar:
rules_or_grammar_declaration {@> @ @=}
| grammar rules_or_grammar_declaration {@> @ @=}
;
@g
@ {\it As a \bison\ extension, one can use the grammar declarations in the
body of the grammar}. What follows is the syntax of the right hand
side of a grammar rule.
@=
@G
rules_or_grammar_declaration:
rules {@> @ @=}
| grammar_declaration ";" {@> @ @=}
| error ";" {@> TeX_( "/errmessage{parsing error!}" ); @=}
;
@t}\vb{\flatten\inline}{@>
rules:
id_colon named_ref.opt {@> TeX_( "/relax" ); @=}
rhses.1 {@> @ @=}
;
@t}\vb{\resetf}{@>
rhses.1[o]:
rhs {@> @ @=}
| rhses.1[a] "|"[b] {@> @ @=}[c]
rhs[d] {@> @ @=}
| rhses.1 ";" {@> @ @=}
;
@g
@ The next few actions describe what happens when a left hand side is
attached to a rule.
@=
@[TeX_( "/getfirst{/yy(1)}/to/toksa" );@]@;
@[TeX_( "/yy0{/nx/grammar{/the/yy(1)}{/the/toksa}}" );@]@;
@ @=
@[TeX_( "/getthird{/yy(1)}/to/toksa" );@]@; /* type of the last rule */
@[TeX_( "/getsecond{/yy(1)}/to/toksc" );@]@; /* accumulated rules */
@[TeX_( "/getfirst{/yy(2)}/to/toksb" );@]@; /* type of the new rule */
@[TeX_( "/let/default/positionswitchdefault" );@]@;
@[TeX_( "/switchon{/the/toksb}/in/positionswitch" );@]@; /* determine the position of the first token in the group */
@[TeX_( "/edef/next{/the/toksa}" );@]@;
@[TeX_( "/edef/default{/the/toksb}" );@]@; /* reuse \.{\\default} */
@[TeX_( "/ifx/next/default" );@]@;
@[TeX_( " /let/default/separatorswitchdefaulteq" );@]@;
@[TeX_( " /switchon{/the/toksa}/in/separatorswitcheq" );@]@;
@[TeX_( "/else" );@]@;
@[TeX_( " /concat/toksa/toksb" );@]@;
@[TeX_( " /let/default/separatorswitchdefaultneq" );@]@;
@[TeX_( " /switchon{/the/toksa}/in/separatorswitchneq" );@]@;
@[TeX_( "/fi" );@]@;
@[TeX_( "/yy0{/nx/grammar{/the/toksc/the/postoks/the/toksd/the/yy(2)}{/the/toksb}}" );@]@;
@ @=
@[TeX_( "/getsecond{/yy(1)}/to/toksa" );@]@; /* \.{\\prodheader} */
@[TeX_( "/getsecond{/toksa}/to/toksb" );@]@; /* \.{\\idit} */
@[TeX_( "/getfourth{/toksb}/to/toksc" );@]@; /* format stream pointer */
@[TeX_( "/getfifth{/toksb}/to/toksd" );@]@; /* stash stream pointer */
@[TeX_( "/getthird{/yy(1)}/to/toksb" );@]@; /* \.{\\rules} */
@[TeX_( "/yy0{/nx/oneproduction{/the/toksa/the/toksb}{/the/toksc}{/the/toksd}}" );@]@;
@ @=
@[TeX_( "/getfourth{/yy(1)}/to/toksa" );@]@; /* format stream pointer */
@[TeX_( "/getfifth{/yy(1)}/to/toksb" );@]@; /* stash stream pointer */
@[TeXb( "/yy0{/nx/pcluster{/nx/prodheader{/the/yy(1)}{/the/yy(2)}" );@]@;
@[TeXao( "{/the/toksa}{/the/toksb}}{/the/yy(4)}}" );@]@;
@ It is important to format the right hand side properly, since we
would like to indicate that an action is inlined by an
indentation. The `format' of the \.{\\rhs} `structure' includes the
stash pointers and a `boolean' to indicate whether the right hand side ends
with an action. Since the action can be implicit, this decision has to
be postponed until, say, a semicolon is seen.
No formatting or stash pointers are added for implicit actions.
@=
@[TeX_( "/rhsbool{/yy(1)}/to/toksa /the/toksa" );@]@;
@[TeX_( "/getthird{/yy(1)}/to/toksb" );@]@; /* the format pointer */
@[TeX_( "/getfourth{/yy(1)}/to/toksc" );@]@; /* the stash pointer */
@[TeX_( "/ifrhsfull" );@]@;
@[TeX_( " /yy0{/nx/rules{/the/yy(1)}{/the/toksb}{/the/toksc}}" );@]@;
@[TeX_( "/else" );@]@; /* it does not end with an action, fake one */
@[TeX_( " /rhscont{/yy(1)}/to/toksa" );@]@; /* rules */
@[TeX_( " /edef/next{/the/toksa}" );@]@;
@[TeX_( " /ifx/next/empty" );@]@;
@[TeX_( " /toksa{/emptyterm}" );@]@;
@[TeX_( " /fi" );@]@;
@[TeXb( " /yy0{/nx/rules{/nx/rhs{/the/toksa/nx/rarhssep{0}{0}" );@]@;
@[TeXfo( " /nx/actbraces{}{}{0}{0}/nx/bdend}{}{/nx/rhsfulltrue}}{/the/toksb}{/the/toksc}}" );@]@;
@[TeX_( "/fi" );@]@;
@ Using standard notation, here is what the middle action
does.
@=
@[TeX_( "/rhscont{/yy(1)}/to{/yy(0)}" );@]@;
@[TeX_( "/yy0{/the/yy(0)/nx/midf/the/yy(2)}" );@]@;
@ However, if the length of the rule preceding the inline action
is not known a different way of accessing the stack is necessary.
@=
@[TeX_( "/bb2{/toksa}/bb1{/toksb}" );@]@;
@[TeX_( "/rhscont{/toksa}/to{/yy(0)}" );@]@;
@[TeX_( "/yy0{/the/yy(0)/nx/midf/the/toksb}" );@]@;
@ @=
@[TeX_( "/rhsbool{/yy(4)}/to/toksa /the/toksa" );@]@;
@[TeX_( "/ifrhsfull" );@]@;
@[TeX_( " /yy0{/nx/rules{/the/yy(3)/nx/rrhssep/the/yy(2)/the/yy(4)}/the/yy(2)}" );@]@;
@[TeX_( "/else" );@]@;
@[TeX_( " /rhscont{/yy(4)}/to/toksa" );@]@;
@[TeX_( " /edef/next{/the/toksa}" );@]@;
@[TeX_( " /ifx/next/empty" );@]@;
@[TeX_( " /toksa{/emptyterm}" );@]@;
@[TeX_( " /fi" );@]@;
@[TeXb( " /yy0{/nx/rules{/the/yy(3)/nx/rrhssep/the/yy(2)" );@]@;
@[TeXf( " /nx/rhs{/the/toksa/nx/rarhssep{0}{0}" );@]@; /* streams have already been grabbed */
@[TeXfo( " /nx/actbraces{}{}{0}{0}/nx/bdend}{}{/nx/rhsfulltrue}}/the/yy(2)}" );@]@;
@[TeX_( "/fi" );@]@;
@ No pointers are provided for an {\it implicit\/} action. Processing a set of rules involves a large number of
reexpansions. This seems to be a good place to use an array to store {\sc AST} nodes ({\let\writetexidxentry\writetextxtidxentry
\def\texnspace{texline}\def\texispace{index}\inlineTeXx{/astarray}}). While
providing a noticeable speed up, this technique significantly
complicates the debugging of the grammar. In particular, inspecting a
parsed table supplies very little information if the {\sc AST} nodes are not
expanded. The macros in \.{yyunion.sty} provide a special debugging
namespace where the expansion of the parser produced control sequences
may be modified to safely expand the generated table.
@=
@[TeX_( "/rhsbool{/yy(4)}/to/toksa /the/toksa" );@]@;
@[TeX_( "/ifrhsfull" );@]@;
@[TeX_( " /yypushx{/the/yy(3)/nx/rrhssep/the/yy(2)/the/yy(4)}/on/astarray" );@]@;
@[TeX_( "/else" );@]@;
@[TeX_( " /rhscont{/yy(4)}/to/toksa" );@]@;
@[TeX_( " /edef/next{/the/toksa}" );@]@;
@[TeX_( " /ifx/next/empty" );@]@;
@[TeX_( " /toksa{/emptyterm}" );@]@;
@[TeX_( " /fi" );@]@;
@[TeXb( " /yypushx{/the/yy(3)/nx/rrhssep/the/yy(2)" );@]@;
@[TeXf( " /nx/rhs{/the/toksa/nx/rarhssep{0}{0}" );@]@; /* streams have already been grabbed */
@[TeXfo( " /nx/actbraces{}{}{0}{0}/nx/bdend}{}{/nx/rhsfulltrue}}/on/astarray" );@]@;
@[TeX_( "/fi" );@]@;
@[TeX_( "/yy0{/nx/rules{/astarraylastcs}/the/yy(2)}" );@]@;
@ @=
@@;
@ @=
@G
%token PERCENT_EMPTY "%empty";
@g
@ The centerpiece of the grammar is the syntax of the right hand side
of a production. Various `precedence hints' must be attached to an
appropriate portion of the rule, just before an action (which can
be inline, implicit or both in this case).
\saveparseoutputtrue
@=
@G(b)
rhs:
{@> @ @=}
| rhs symbol named_ref.opt {@> @ @=}
| rhs "{...}" named_ref.opt {@> @ @=}
| rhs "%?{...}" {@> @ @=}
| rhs "%empty" {@> @ @=}
| rhs "%prec" symbol {@> @ @=}
| rhs "%dprec" INT {@> @ @=}
| rhs "%merge" TAG {@> @ @=}
;
named_ref.opt:
{@> @ @=}
| BRACKETED_ID {@> @ @=}
;
@g
@ \saveparseoutputfalse
@=
@[TeX_( "/yy0{/nx/rhs{}{}{/nx/rhsfullfalse}}" );@]@;
@ @=
@[TeX_( "/rhscont{/yy(1)}/to/toksa" );@]@;
@[TeX_( "/rhscnct{/yy(1)}/to/toksb" );@]@;
@[TeX_( "/edef/next{/the/toksb}" );@]@;
@[TeX_( "/ifx/next/empty" );@]@;
@[TeX_( "/else" );@]@;
@[TeX_( " /getfourth{/yy(2)}/to/toksc" );@]@;
@[TeX_( " /getfifth{/yy(2)}/to/toksd" );@]@;
@[TeX_( " /appendr/toksb{{/the/toksc}{/the/toksd}}" );@]@;
@[TeX_( "/fi" );@]@;
@[TeXb( "/yy0{/nx/rhs{/the/toksa/the/toksb" );@]@;
@[TeXao( "/nx/termname{/the/yy(2)}{/the/yy(3)}}{/nx/hspace}{/nx/rhsfullfalse}}" );@]@;
@ @=
@[TeX_( "/rhscont{/yy(1)}/to/toksa" );@]@;
@[TeX_( "/rhsbool{/yy(1)}/to/toksb /the/toksb" );@]@;
@[TeX_( "/ifrhsfull" );@]@; /* the first half ends with an action */
@[TeX_( " /appendr/toksa{/nx/arhssep{0}{0}/nx/emptyterm}" );@]@; /* no pointers to streams */
@[TeX_( "/fi" );@]@;
@[TeX_( "/edef/next{/the/toksa}" );@]@;
@[TeX_( "/ifx/next/empty" );@]@;
@[TeX_( " /toksa{/emptyterm}" );@]@;
@[TeX_( "/fi" );@]@;
@[TeX_( "/getfirst{/yy(2)}/to/toksb" );@]@; /* the contents of the braced code */
@[TeX_( "/getsecond{/yy(2)}/to/toksc" );@]@; /* the format stream pointer */
@[TeX_( "/getthird{/yy(2)}/to/toksd" );@]@; /* the stash stream pointer */
@[TeXb( "/yy0{/nx/rhs{/the/toksa/nx/rarhssep{/the/toksc}{/the/toksd}" );@]@;
@[TeXf( " /nx/actbraces{/the/toksb}{/the/yy(3)}{/the/toksc}{/the/toksd}/nx/bdend}" );@]@;
@[TeXfo( " {/nx/arhssep}{/nx/rhsfulltrue}}" );@]@;
@ @=
@[TeX_( "/rhscont{/yy(1)}/to/toksa" );@]@;
@[TeX_( "/rhsbool{/yy(1)}/to/toksb /the/toksb" );@]@;
@[TeX_( "/ifrhsfull" );@]@; /* the first half ends with an action */
@[TeX_( " /appendr/toksa{/nx/arhssep{0}{0}/nx/emptyterm}" );@]@; /* no pointers to streams */
@[TeX_( "/fi" );@]@;
@[TeX_( "/edef/next{/the/toksa}" );@]@;
@[TeX_( "/ifx/next/empty" );@]@;
@[TeX_( " /toksa{/emptyterm}" );@]@;
@[TeX_( "/fi" );@]@;
@[TeX_( "/getfirst{/yy(2)}/to/toksb" );@]@; /* the contents of the braced code */
@[TeX_( "/getsecond{/yy(2)}/to/toksc" );@]@; /* the format stream pointer */
@[TeX_( "/getthird{/yy(2)}/to/toksd" );@]@; /* the stash stream pointer */
@[TeXb( "/yy0{/nx/rhs{/the/toksa/nx/rarhssep{/the/toksc}{/the/toksd}" );@]@;
@[TeXf( " /nx/bpredicate{/the/toksb}{}{/the/toksc}{/the/toksd}/nx/bdend}" );@]@;
@[TeXao( "{/nx/arhssep}{/nx/rhsfulltrue}}" );@]@;
@ @=
@[TeX_( "/rhscont{/yy(1)}/to/toksa" );@]@;
@[TeX_( "/rhscnct{/yy(1)}/to/toksb" );@]@;
@[TeX_( "/edef/next{/the/toksb}" );@]@;
@[TeX_( "/ifx/next/empty" );@]@;
@[TeX_( "/else" );@]@;
@[TeX_( " /getfourth{/yy(2)}/to/toksc" );@]@;
@[TeX_( " /getfifth{/yy(2)}/to/toksd" );@]@;
@[TeX_( " /appendr/toksb{{/the/toksc}{/the/toksd}}" );@]@;
@[TeX_( "/fi" );@]@;
@[TeXb( "/yy0{/nx/rhs{/the/toksa/the/toksb" );@]@;
@[TeXao( "/nx/emptyterm}{/nx/hspace}{/nx/rhsfullfalse}}" );@]@;
@ @=
@[TeX_( "/rhscont{/yy(1)}/to/toksa" );@]@;
@[TeX_( "/rhscnct{/yy(1)}/to/toksb" );@]@;
@[TeX_( "/rhsbool{/yy(1)}/to/toksc /the/toksc" );@]@;
@[TeX_( "/ifrhsfull" );@]@;
@[TeX_( " /yy0{/nx/sprecop{/the/yy(3)}/the/yy(2)}" );@]@; /* reuse \.{\\yyval} */
@[TeX_( " /supplybdirective/toksa/yyval" );@]@; /* the directive is `absorbed' by the action */
@[TeX_( " /yy0{/nx/rhs{/the/toksa}{/the/toksb}{/nx/rhsfulltrue}}" );@]@;
@[TeX_( "/else" );@]@;
@[TeXb( " /yy0{/nx/rhs{/the/toksa" );@]@;
@[TeXao( "/nx/sprecop{/the/yy(3)}/the/yy(2)}{/the/toksb}{/nx/rhsfullfalse}}" );@]@;
@[TeX_( "/fi" );@]@;
@ @=
@[TeX_( "/rhscont{/yy(1)}/to/toksa" );@]@;
@[TeX_( "/rhscnct{/yy(1)}/to/toksb" );@]@;
@[TeX_( "/rhsbool{/yy(1)}/to/toksc /the/toksc" );@]@;
@[TeX_( "/ifrhsfull" );@]@;
@[TeX_( " /yy0{/nx/dprecop{/the/yy(3)}/the/yy(2)}" );@]@; /* reuse \.{\\yyval} */
@[TeX_( " /supplybdirective/toksa/yyval" );@]@; /* the directive is `absorbed' by the action */
@[TeX_( " /yy0{/nx/rhs{/the/toksa}{/the/toksb}{/nx/rhsfulltrue}}" );@]@;
@[TeX_( "/else" );@]@;
@[TeXb( " /yy0{/nx/rhs{/the/toksa" );@]@;
@[TeXao( "/nx/dprecop{/the/yy(3)}/the/yy(2)}{/the/toksb}{/nx/rhsfullfalse}}" );@]@;
@[TeX_( "/fi" );@]@;
@ @=
@[TeX_( "/rhscont{/yy(1)}/to/toksa" );@]@;
@[TeX_( "/rhscnct{/yy(1)}/to/toksb" );@]@;
@[TeX_( "/rhsbool{/yy(1)}/to/toksc /the/toksc" );@]@;
@[TeX_( "/ifrhsfull" );@]@;
@[TeX_( " /yy0{/nx/mergeop{/nx/tagit/the/yy(3)}/the/yy(2)}" );@]@; /* reuse \.{\\yyval} */
@[TeX_( " /supplybdirective/toksa/yyval" );@]@; /* the directive is `absorbed' by the action */
@[TeX_( " /yy0{/nx/rhs{/the/toksa}{/the/toksb}{/nx/rhsfulltrue}}" );@]@;
@[TeX_( "/else" );@]@;
@[TeXb( " /yy0{/nx/rhs{/the/toksa" );@]@;
@[TeXao( "/nx/mergeop{/nx/tagit/the/yy(3)}/the/yy(2)}{/the/toksb}{/nx/rhsfullfalse}}" );@]@;
@[TeX_( "/fi" );@]@;
@ @=
@[TeX_( "/yy0{}" );@]@;
@ @=
@@;
@ Identifiers.
{\it Identifiers are returned as |uniqstr| values by the scanner.
Depending on their use, we may need to make them genuine symbols}. We,
on the other hand, simply copy the values returned by the scanner.
@=
@G
id:
ID {@> @ @=}
| CHAR {@> @ @=}
;
@g
@ @=
@@;
@ @=
@G
symbol:
id {@> @ @=}
| string_as_id {@> @ @=}
;
@g
@ @=
@G
@t}\vb{\inline}{@>
id_colon:
ID_COLON {@> @ @=}
;
@g
@ A string used as an \prodstyle{ID}.
@=
@G
@t}\vb{\inline}{@>
string_as_id:
STRING {@> @ @=}
;
@g
@ The remainder of the action code is trivial but we reserved the
placeholders for the appropriate actions in case the parser gains some
sophistication in processing low level types (or starts expecting
different types from the scanner).
@=
@[TeX_( "/yy0{/nx/idit/the/yy(1)}" );@]@;
@ @=
@[TeX_( "/yy0{/nx/charit/the/yy(1)}" );@]@;
@ @=
@@;
@ @=
@@;
@ @=
@@;
@ @=
@[TeX_( "/yy0{/nx/stringify/the/yy(1)}" );@]@;
@ {\it Variable and value.
The \prodstyle{STRING} form of variable is deprecated and is not \.{M4}-friendly.
For example, \.{M4} fails for \.{\%define "[" "value"}.}
@=
@G
@t}\vb{\flatten\inline}{@>
variable:
ID {@> @ @=}
| STRING {@> @ @=}
;
value:
{@> TeX_( "/yy0{}" ); @=}
| ID {@> @ @=}
| STRING {@> @ @=}
| "{...}" {@> TeX_( "/yy0{/nx/bracedvalue/the/yy(1)}" ); @=}
;
@g
@ @=
@G
@t}\vb{\flatten\inline}{@>
epilogue.opt:
{@> TeX_( "/yy0{}" ); @=}
| "%%" EPILOGUE {}
;
@g
@ \Cee\ preamble for the grammar parser. In this case, there are no `real' actions that our
grammar performs, only \TeX\ output, so this section is empty.
@=
@ \Cee\ postamble for the grammar parser. It is tricky to insert function definitions that use \bison's internal types,
as they have to be inserted in a place that is aware of the internal definitions but before said
definitions are used.
@=
#define YYPRINT(file, type, value) @[yyprint (file, type, value)@]
static void yyprint (FILE *file, int type, YYSTYPE value){}
@ @=
@@;
@@;
@ @=
void bootstrap_tokens( char *bootstrap_token_format ) {
#define _register_token_d(name) @[fprintf( tables_out, bootstrap_token_format, #name, name, #name );@;
@@;
#undef _register_token_d@;
}
@ \namedspot{bootstraptokens}Here is the minimal list of tokens needed
to make the lexer operational just enough to extract the rest of the
token information from the grammar.
@=
_register_token_d(ID)@;
_register_token_d(PERCENT_TOKEN)@;
_register_token_d(STRING)@;
@q The tokens below are not required to make a minimal bootstrapping parser work @>
@q but they do appear in the rules the parser will encounter while extracting @>
@q token information. @>
@q _register_token_d(INT) /* only encountered in GRAM_EOF definition which is never used */ @>
@q _register_token_d(CHAR) /* \bison\ never declares character tokens */ @>
@q _register_token_d(SEMICOLON) /* can be omitted in prologue */ @>
@q _register_token_d(TAG) /* only encountered in the definition of PERCENT_PARAM */ @>
@ Union of types. This section of the \bison\ input lists the types
that may appear on the value stack. Since \TeX\ does not provide any
mechanism for type checking (nor is it clear how to translate a \Cee\
|union| into any data structure usable in \TeX), this section is left empty.
@=