summaryrefslogtreecommitdiff
path: root/support/splint/cweb/bo.w
diff options
context:
space:
mode:
Diffstat (limited to 'support/splint/cweb/bo.w')
-rw-r--r--support/splint/cweb/bo.w582
1 files changed, 342 insertions, 240 deletions
diff --git a/support/splint/cweb/bo.w b/support/splint/cweb/bo.w
index fe7bf59f52..630602559e 100644
--- a/support/splint/cweb/bo.w
+++ b/support/splint/cweb/bo.w
@@ -1,4 +1,4 @@
-% Copyright 2012-2020, Alexander Shibakov
+% Copyright 2012-2024, Alexander Shibakov
% Copyright 2002-2014 Free Software Foundation, Inc.
% This file is part of SPLinT
%
@@ -24,6 +24,20 @@
\fi
@**The \eatone{bison}\bison\ parser stack.
+{%
+\newdimen\halfhsize
+\newdimen\preskip
+\halfhsize=\hsize
+\divide\halfhsize by2
+\def\mypar{%
+\parshape 6
+0pt \hsize
+0pt \hsize
+0pt \hsize
+0pt \hsize
+0pt \hsize
+\halfhsize \halfhsize
+}%
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
@@ -33,8 +47,8 @@ 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.
+bootstrapping\/}@^bootstrapping@> step is discussed in more detail
+further down.
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
@@ -47,13 +61,13 @@ As was described in the
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
+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
+One should note that the productions below are not directly 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
@@ -61,7 +75,11 @@ 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.
+the boostrapping pass to typesetting the grammar rules. This allows for a
+great deal of flexibility in where and when the parsing results are
+used. A clear divide between the parsing step and the typesetting step
+provides for better debugging facilities, as well as more reliable
+macro design.
It would be impossible to completely avoid the question of the visual
presentation of the \bison\ input, however. It has already been
@@ -72,14 +90,23 @@ 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.
+placement of each fragment of the input on the page. The syntax tree
+generated by the parsers in the \bison\ stack is not fully {\em faithful\/} in
+that it does not preserve every syntactic element from the original input.
+Thus, e.g.\ optional semicolons (\prodstyle{semi.opt}) never find their way into
+the tree and their original position is lost\footnote{The opposite is true about
+the {\em whitespace\/} the parser sees (or {\em stash\/} as it is called
+in this document): all of it is carefully packaged into streams, as was described
+\locallink{parser.streams}earlier\endlink.}.
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.
-
+A number of sections are empty, since the generated \Cee\ is rather trivial.
+}%
+%\checktabletrue
@(bg.yy@>=
@G Switch to generic mode.
%{@> @<Grammar parser \Cee\ preamble@> @=%}
@@ -94,11 +121,13 @@ as \prodstyle{\%\%} below)) appear between the successive dotted lines.
%%
@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"}
+@*1 Bootstrapping.
+%\checktablefalse
+Bootstrap\namedspot{bootstrapping}@^bootstrapping@> parser is
+defined next. The purpose of the bootstrapping parser is to
+collect a minimal amount of information to `spool up' the `production'
+parsers. To understand its inner workings 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)%
@@ -119,8 +148,8 @@ 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
+and extract the equivalences between the names from it. This is
+precisely 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
@@ -145,25 +174,43 @@ 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
+up the token names. The bootstrap parser is not strictly minimal in that
+it is also capable of parsing the \prodstyle{\%nterm} declarations.
+This ability is not utilized by the parsers in \splint, however (nor
+is the accompanying bootstrap lexer designed to output the
+\prodstyle{\%nterm} tokens), and was added for the scenarios other
+than bootstrapping.
+
+The second, perhaps even more important function of the bootstrap process
+is to collect information about the scanner's states. The mechanism
+is slightly different from that for token definition gathering.
+While the token equivalences are collected purely in
+`\TeX\ mode', the bootstrap mode 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').
+the `driver' program in any data structure (the |yytname| array) and are instead defined as
+ordinary (\Cee) macros. The header file is the information the `driver' file
+needs to output the state values for the use by the lexer.
+
+Naturally, to accomplish their task, the lexer and the parser emplyed in
+state gathering need the state and token information, as well. Fortunately,
+the parser is a subset of the \flex\ input parser that does not define
+any `string' names for it tokens. Similarly, the lexer collects all the necessary
+tokens in the \flexsnstyle{INITIAL} state\footnote{An additional subtlety is
+the necessity to gracefully handle (and, in some cases, cause) the multiple
+possible {\em failures\/} for which the lexer redefines \inlineTeXx{/yyBEGIN}\
+to fail immediately when attempting to switch states. Note that the bootstrap
+mode parser looks at sections other than those where the declarations reside
+and must fail quickly and quietly in such cases.}.
+
+To reiterate a point made in the middle of this section, the bootstrapping
+process described here is necessary to `spool up' the \bison\ and \flex\ input parsers.
+A simpler procedure may be followed while designing other custom parsers where
+the programmer uses, say the full \bison\ parser to collect information about
+the token equivalences (whether such information is needed to make the parser operational
+or just to facilitate the typesetting of the token names). By adding custom
+`bootstrapping' macros to the ones defined in \.{yyunion.sty}, a number of different
+preprocessing tasks can be accomplished.
@(bb.yy@>=
@G Switch to generic mode.
%{
@@ -177,13 +224,11 @@ in \.{ssffo.w} (the somewhat cryptic name stands for `{\bf s}imple {\bf s}canner
%%
@> @<Fake start symbol for bootstrap grammar@> @=
@> @<Parser bootstrap productions@> @=
- @> @<\flex\ options parser productions@> @=
- @> @<List of symbols@> @=
- @> @<Definition of \prodstyle{symbol}@> @=
%%
@g
-@ The prologue parser is responsible for parsing various grammar
+@*1 Prologue and full parsers.
+The prologue parser is responsible for parsing various grammar
declarations as well as parser options.
@(bd.yy@>=
@G Switch to generic mode.
@@ -201,7 +246,12 @@ declarations as well as parser options.
@ 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.
+similar to the one that follows this paragraph. As a stopgap measure,
+the skeleton of a \flex\ scanner is also parsed by this parser, as they have
+an almost identical structure. This is not a perfect arrangement, however, since
+it precludes one from putting the constructs that this parser does not
+recognize into the outline. To give an example, one cannot put \flex\ specific
+options into such `skeleton'.
@(bf.yy@>=
@G Switch to generic mode.
%{@> @<Grammar parser \Cee\ preamble@> @=%}
@@ -227,7 +277,7 @@ 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
+explicitly by putting\gtextidx{\bison\ options example}{bison options example}{\bisonidxdomain}%
\medskip
\beginprod
\%define lr.type canonical-lr
@@ -259,7 +309,6 @@ 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
@<Tokens and types for the grammar parser@>=
@G
@@ -289,7 +338,6 @@ the original parser.
\iffalse
\checktrailingstashfalse
\checktablefalse
- \let\stashnext\stashnextwithnothingnx
\fi
@<Global Declarations@>=
@G
@@ -339,17 +387,6 @@ the original parser.
%token <param> 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.
-@<Tokens and...@>=
-@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
@@ -373,10 +410,15 @@ parser on the stack.
@t}\vb{\inline}{@>
input:
prologue_declarations
- "%%" grammar epilogue.opt {@> TeX_( "/getsecond{/yy(3)}/to/table" ); @=}
+ "%%" grammar epilogue.opt {@> @<Extract the grammar from a full file@> @=}
;
@g
+@ @<Extract the grammar from a full file@>=
+ @[TeX_( "/finishlist{/expandafter/yyfirstoftwo/the/yy(3)}" );@]@; /* complete the list */
+ @[TeX_( "/table/expandafter{/romannumeral0" );@]@;
+ @[TeX_( " /executelistat{/expandafter/yyfirstoftwo/the/yy(3)}{0}}" );@]@;
+
@ 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.
@@ -384,10 +426,15 @@ natural `unit' to include in a \CWEB\ file.
@G
@t}\vb{\inline}{@>
input:
- grammar epilogue.opt {@> TeX_( "/getsecond{/yy(1)}/to/table" ); @=}
+ grammar epilogue.opt {@> @<Save the grammar@> @=}
;
@g
+@ @<Save the grammar@>=
+ @[TeX_( "/finishlist{/expandafter/yyfirstoftwo/the/yy(1)}" );@]@; /* complete the list */
+ @[TeX_( "/table/expandafter{/romannumeral0" );@]@;
+ @[TeX_( " /executelistat{/expandafter/yyfirstoftwo/the/yy(1)}{0}}" );@]@;
+
@ 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
@@ -395,7 +442,7 @@ 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
+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
@@ -410,11 +457,8 @@ input:
@t}\vb{\resetf}{@>
grammar_declarations:
symbol_declaration semi.opt {@> @<Carry on@> @=}
-| flex_declaration semi.opt {@> @<Carry on@> @=}
| 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: {} | ";" {};
@@ -429,35 +473,42 @@ is undocumented so we supply an explicit action in each case.
@ 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
+these rules 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.
@<Fake start symbol for prologue grammar@>=
@G
@t}\vb{\inline}{@>
input:
- prologue_declarations epilogue.opt {@> TeX_( "/getsecond{/yy(1)}/to/table" ); @=}
+ prologue_declarations epilogue.opt {@> @<Save the declarations@> @=}
| prologue_declarations
- "%%" "%%" EPILOGUE {@> TeX_( "/getsecond{/yy(1)}/to/table" ); @=}
+ "%%" "%%" EPILOGUE {@> @<Save the declarations@> @=}
| prologue_declarations
- "%%" "%%" {@> TeX_( "/getsecond{/yy(1)}/to/table" ); @=}
+ "%%" "%%" {@> @<Save the declarations@> @=}
;
@g
+@ @<Save the declarations@>=
+ @[TeX_( "/finishlist{/expandafter/yyfirstoftwo/the/yy(1)}" );@]@; /* complete the list */
+ @[TeX_( "/table/expandafter{/romannumeral0" );@]@;
+ @[TeX_( " /executelistat{/expandafter/yyfirstoftwo/the/yy(1)}{0}}" );@]@;
+
@ {\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.
+ready to deal with the specifics of the declarations themselves.
@<Parser prologue productions@>=
@G
prologue_declarations:
- {@> TeX_( "/yy0{/nx/grammar{}{/nx/empty}}" ); @=}
+ {@> @<Start with an empty list of declarations@> @=}
| prologue_declarations
prologue_declaration {@> @<Attach a prologue declaration@> @=}
;
@g
+@ @<Start with an empty list of declarations@>=
+ @[TeX_( "/initlist{/prologuedeclarationsprefix prologue_declarations}" );@]@;
+ @[TeX_( "/yy0{{/prologuedeclarationsprefix prologue_declarations}{/nx/empty}}" );@]@;
+ @[TeX_( "/edef/prologuedeclarationsprefix{./prologuedeclarationsprefix}" );@]@;
+
@ @<Attach a prologue declaration@>=
@<Attach a productions cluster@>@;
@@ -466,6 +517,7 @@ 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.
+\eraselocalformattrue
@<Parser prologue productions@>=
@G
prologue_declaration:
@@ -474,10 +526,13 @@ prologue_declaration:
| "%<flag>" {@> 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}" );@]@+@<Prepare one parametric option@> @=}
+| "%defines" STRING {@> @t}\vb{\stashed{\Xmark prologue.decls:\Xmark}}{@> @=
+ @> @[TeX_( "/toksa{defines}" );@]@+@<Prepare one parametric option@> @=}
| "%error-verbose" {@> TeX_( "/yy0{/nx/optionflag{error verbose}{}/the/yy(1)}" ); @=}
-| "%expect" INT {@> @[TeX_( "/toksa{expect}" );@]@+@<Prepare a generic one parametric option@> @=}
-| "%expect-rr" INT {@> @[TeX_( "/toksa{expect-rr}" );@]@+@<Prepare a generic one parametric option@> @=}
+| "%expect" INT {@> @t}\vb{\stashed{\Xmark prologue.decls(g):\Xmark}}{@> @=
+ @> @[TeX_( "/toksa{expect}" );@]@+@<Prepare a generic one parametric option@> @=}
+| "%expect-rr" INT {@> @t}\vb{\stashed{\Xmark prologue.decls(g):\Xmark}}{@> @=
+ @> @[TeX_( "/toksa{expect-rr}" );@]@+@<Prepare a generic one parametric option@> @=}
| "%file-prefix" STRING {@> @[TeX_( "/toksa{file prefix}" );@]@+@<Prepare one parametric option@> @=}
| "%glr-parser" {@> TeX_( "/yy0{/nx/optionflag{glr parser}{}/the/yy(1)}" ); @=}
| "%initial-action" "{...}" {@> TeX_( "/yy0{/nx/initaction/the/yy(2)}" ); @=}
@@ -485,12 +540,14 @@ prologue_declaration:
| "%name-prefix" STRING {@> @[TeX_( "/toksa{name prefix}" );@]@+@<Prepare one parametric option@> @=}
| "%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}" );@]@+@<Prepare one parametric option@> @=}
+| "%output" STRING {@> @t}\vb{\stashed{\Xmark prologue.decls:\Xmark}}{@> @=
+ @> @[TeX_( "/toksa{output}" );@]@+@<Prepare one parametric option@> @=}
@t}\vb{\flatten}{@>
-| "%param" {}
+| "%param" {@> @t}\vb{\stashed{\rm (we simply return pointers below)}}{@> @=}
params {@> TeX_( "/yy0{/nx/paramdef{/the/yy(3)}/the/yy(1)}" ); @=}
@t}\vb{\fold}{@>
-| "%require" STRING {@> @[TeX_( "/toksa{require}" );@]@+@<Prepare one parametric option@> @=}
+| "%require" STRING {@> @t}\vb{\stashed{\Xmark prologue.decls:\Xmark}}{@> @=
+ @> @[TeX_( "/toksa{require}" );@]@+@<Prepare one parametric option@> @=}
| "%skeleton" STRING {@> @[TeX_( "/toksa{skeleton}" );@]@+@<Prepare one parametric option@> @=}
| "%token-table" {@> TeX_( "/yy0{/nx/optionflag{token table}{}/the/yy(1)}" ); @=}
| "%verbose" {@> TeX_( "/yy0{/nx/optionflag{verbose}{}/the/yy(1)}" ); @=}
@@ -507,69 +564,22 @@ params:
@ 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.
+\eraselocalformatfalse
+\smallskip
+\rulereferencex{\showlastactionfalse}{\nx\inline\nx\flatten}{prologue.decls}
+\smallskip
+\noindent The productions above are typical examples.
@<Prepare one parametric option@>=
@[TeX_( "/yy0{/nx/oneparametricoption{/the/toksa}{/nx/stringify/the/yy(2)}/the/yy(1)}" );@]@;
-@ @<Prepare a generic one parametric option@>=
+@ A variation on the theme above where the parameter is not a \prodstyle{STRING}.
+\smallskip
+\rulereferencex{\showlastactionfalse}{\nx\inline\nx\flatten}{prologue.decls(g)}
+\smallskip
+\noindent A sample of the rules to which the code below applies are given above.
+@<Prepare a generic one parametric option@>=
@[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.
-@<Parser prologue productions@>=
-@G
-prologue_declaration:
- flex_declaration {@> @<Carry on@> @=}
-;
-@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 {@> @<Define \flex\ option list@> @=}
-| flex_state symbols.1 {@> @<Define \flex\ states@> @=}
-;
-
-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 {@> @<Carry on@> @=}
-| flex_option_list flex_option {@> @<Add a \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
-
-@ @<Define \flex\ option list@>=
- @[TeX_( "/yy0{/nx/flexoptiondecls{/the/yy(2)}/the/yy(1)}" );@]@;
-
-@ @<Define \flex\ states@>=
- @[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}}" );@]@;
-
-@ @<Add a \flex\ option@>=
- @[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.
@@ -578,7 +588,8 @@ the prologue-only options.
grammar_declaration:
precedence_declaration {@> @<Carry on@> @=}
| symbol_declaration {@> @<Carry on@> @=}
-| "%start" symbol {@> @[TeX_( "/toksa{start}" );@]@+@<Prepare a generic one parametric option@> @=}
+| "%start" symbol {@> @t}\vb{\stashed{\Xmark prologue.decls(g):\Xmark}}{@> @=
+ @> @[TeX_( "/toksa{start}" );@]@+@<Prepare a generic one parametric option@> @=}
| code_props_type "{...}" generic_symlist {@> @<Assign a code fragment to symbols@> @=}
| "%default-prec" {@> TeX_( "/yy0{/nx/optionflag{default prec.}{}/the/yy(1)}" ); @=}
| "%no-default-prec" {@> TeX_( "/yy0{/nx/optionflag{no default prec.}{}/the/yy(1)}" ); @=}
@@ -617,7 +628,6 @@ union_name:
grammar_declaration:
"%union" union_name "{...}" {@> @<Prepare union definition@> @=}
;
-
symbol_declaration:
"%type" TAG symbols.1 {@> @<Define symbol types@> @=}
;
@@ -637,6 +647,7 @@ tag.opt:
{@> TeX_( "/yy0{}" ); @=}
| TAG {@> @<Prepare a \prodstyle{TAG}@> @=}
;
+@t}\vb{\insertraw{\beginfoldedsections}}{@>
@g
@ @<Prepare union definition@>=
@@ -644,6 +655,7 @@ tag.opt:
@ @<Define symbol types@>=
@[TeX_( "/yy0{/nx/typedecls{/nx/tagit/the/yy(2)}{/the/yy(3)}/the/yy(1)}" );@]@;
+@t}\endfoldedsections{@>
@ @<Define symbol precedences@>=
@[TeX_( "/getthird{/yy(1)}/to/toksa" );@]@; /* format pointer */
@@ -677,7 +689,9 @@ symbol_declaration:
@ {\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$\.{\}},
+the inserted separator (%
+\texrefx{/hspace}{other}%
+\.{\{}$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@>
@@ -700,22 +714,16 @@ symbol.prec:
;
@g
-@ {\it One or more symbols to be \prodstyle{\%type}'d}. The |@<List of
-symbols@>| rules below are reused in the boostrap parser and are put
-in a separate section for this reason.
+@ {\it One or more symbols to be \prodstyle{\%type}'d}.
@<Parser common productions@>=
- @<List of symbols@>@;
-
-@ @<List of symbols@>=
@G
+%type <intval> symbols.1 symbol;
+
symbols.1:
symbol {@> @<Carry on@> @=}
-| symbols.1 symbol {@> TeX_( "/yy0{/the/yy(1)/nx/hspace{0}{0}/the/yy(2)}" ); @=}
+| symbols.1 symbol {@> TeX_( "/yy0{/the/yy(1)/nx/hspace{0}{0}/the$[symbol]}" ); @=}
;
-@g
-@ @<Parser common productions@>=
-@G
generic_symlist:
generic_symlist_item {@> @<Carry on @> @=}
| generic_symlist generic_symlist_item {@> TeX_( "/yy0{/the/yy(1)/nx/hspace{0}{0}/the/yy(2)}" ); @=}
@@ -772,42 +780,50 @@ grammar:
;
@g
-@ {\it As a \bison\ extension, one can use the grammar declarations in the
+@*2 Rules syntax. {\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.
+side of a grammar rule. The type declarations for various non-terminals are used exclusively
+by the postprocessor whenever the `native' \bison\ term references are used (see elsewhere
+for details).
@<Parser grammar productions@>=
@G
+%type <intval> rhs id_colon named_ref.opt rhses.1 "|";
+
rules_or_grammar_declaration:
- rules {@> @<Add a productions cluster@> @=}
+ rules {@> @<Form a productions cluster@> @=}
| grammar_declaration ";" {@> @<Carry on@> @=}
| error ";" {@> TeX_( "/errmessage{parsing error!}" ); @=}
;
@t}\vb{\flatten\inline}{@>
rules:
- id_colon named_ref.opt {@> TeX_( "/relax" ); @=}
+ id_colon named_ref.opt {@> @t}\vb{\stashed{\rm (we simply return pointers below)}}{@> @=}
rhses.1 {@> @<Complete a production@> @=}
;
@t}\vb{\resetf}{@>
rhses.1[o]:
rhs {@> @<Start the right hand side@> @=}
-| rhses.1[a] "|"[b] {@> @<Insert local formatting@> @=}[c]
+| rhses.1[rhses] "|"[mid] {@> @<Insert local formatting@> @=}[c]
rhs[d] {@> @<Add a right hand side to a production@> @=}
-| rhses.1 ";" {@> @<Add an optional semicolon@> @=}
+| rhses.1 ";" {@> @<Carry on@> @=}
;
@g
@ The next few actions describe what happens when a left hand side is
attached to a rule.
@<Start with a production cluster@>=
- @[TeX_( "/getfirst{/yy(1)}/to/toksa" );@]@;
- @[TeX_( "/yy0{/nx/grammar{/the/yy(1)}{/the/toksa}}" );@]@;
+ @[TeX_( "/initlist{/grammarprefix grammar}" );@]@;
+ @[TeX_( "/getfirst{/yy(1)}/to/toksa" );@]@; /* type of the last addition */
+ @[TeX_( "/yy0{{/grammarprefix grammar}{/the/toksa}}" );@]@;
+ @[TeX_( "/appendtolistx{/grammarprefix grammar}{/the/yy(1)}" );@]@;
+ @[TeX_( "/edef/grammarprefix{./grammarprefix}" );@]@;
@ @<Attach a productions cluster@>=
- @[TeX_( "/getthird{/yy(1)}/to/toksa" );@]@; /* type of the last rule */
- @[TeX_( "/getsecond{/yy(1)}/to/toksc" );@]@; /* accumulated rules */
+ @[TeX_( "/getsecond{/yy(1)}/to/toksa" );@]@; /* type of the last rule */
+ @[TeX_( "/getfirst{/yy(1)}/to/toksc" );@]@; /* pointer to the 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 */
+ @; /* determine the spacing between sections */
@[TeX_( "/edef/next{/the/toksa}" );@]@;
@[TeX_( "/edef/default{/the/toksb}" );@]@; /* reuse \.{\\default} */
@[TeX_( "/ifx/next/default" );@]@;
@@ -818,9 +834,10 @@ attached to a rule.
@[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_( "/appendtolistx{/the/toksc}{/the/postoks/the/toksd/the/yy(2)}" );@]@;
+ @[TeX_( "/yy0{{/the/toksc}{/the/toksb}}" );@]@;
-@ @<Add a productions cluster@>=
+@ @<Form a productions cluster@>=
@[TeX_( "/getsecond{/yy(1)}/to/toksa" );@]@; /* \.{\\prodheader} */
@[TeX_( "/getsecond{/toksa}/to/toksb" );@]@; /* \.{\\idit} */
@[TeX_( "/getfourth{/toksb}/to/toksc" );@]@; /* format stream pointer */
@@ -828,90 +845,152 @@ attached to a rule.
@[TeX_( "/getthird{/yy(1)}/to/toksb" );@]@; /* \.{\\rules} */
@[TeX_( "/yy0{/nx/oneproduction{/the/toksa/the/toksb}{/the/toksc}{/the/toksd}}" );@]@;
-@ @<Complete a production@>=
- @[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)}}" );@]@;
+@ Several productions for a given nonterminal are collected in a `production cluster':
+\smallskip
+\thisrulereference{}%
+\smallskip
+\noindent The inline action does nothing at the moment and is omitted in the main text.
+@<Complete a production@>=
+ @[TeX_( "/getfourth{$[id_colon]}/to/toksa" );@]@; /* format stream pointer */
+ @[TeX_( "/getfifth{$[id_colon]}/to/toksb" );@]@; /* stash stream pointer */
+ @[TeX_( "/finishlist{/the$[rhses.1]}" );@]@; /* complete the list of rules */
+ @[TeXb_( "/yy0{/nx/pcluster{/nx/prodheader{/the$[id_colon]}{/the$[named_ref.opt]}" );@]@;
+ @[TeXfo_( " {/the/toksa}{/the/toksb}}{/nx/rules{/nx/executelist{/the$[rhses.1]}}}}" );@]@;
@ 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.
+indentation.
+\smallskip
+\thisrulereference{\nx\inline\nx\flatten}
+\smallskip
+\noindent The `layout' of the \texref{/rhs} `structure' includes
+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.
@<Start the right hand side@>=
- @[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_( "/initlist{/rhsesoneprefix rhses1}" );@]@;
+ @[TeX_( "/yy0{/rhsesoneprefix rhses1}" );@]@;
+ @[TeX_( "/edef/rhsesoneprefix{./rhsesoneprefix}" );@]@;
+ @[TeX_( "/rhsbool{$[rhs]}/to/toksa /the/toksa" );@]@;
@[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_( " /appendtolistx{/the/yyval}{/the$[rhs]}" );@]@;
+ @[TeX_( "/else" );@]@; /* right hand side does not end with an action, fake one */
+ @[TeX_( " /rhscont{$[rhs]}/to/toksa" );@]@; /* rules */
+ @[TeX_( " /yytoksempty/toksa{/toksa{/emptyterm}}{}" );@]@;
+ @[TeXb( " /appendtolistx{/the/yyval}{/nx/rhs{/the/toksa/nx/rarhssep{0}{0}" );@]@;
+ @[TeXfo( " /nx/actbraces{}{}{0}{0}/nx/bdend}{}{/nx/rhsfulltrue}}" );@]@;
@[TeX_( "/fi" );@]@;
@ Using standard notation, here is what the middle action
-does.
+does. The part of the rule this action applies to is given below for
+reference. This action may have been omitted altogether but it serves
+as a good illustration of how `inline actions' work.
+\smallskip
+\rulereference{\nx\inline\nx\flatten}{|@<Insert local formatting@>|}%
+\smallskip
+\noindent The terms are counted from left (deeper in the value stack) to right
+(on top of the value stack) although \texref{/yy(0)}
+(which is the same as \texref{/yyval}) is the {\it right\/}most term,
+i.e.\ the implicit action itself.
+
+What the parser sees at this point
+are the first two terms on the stack (i.e.\ \prodstyle{rhses.1} and
+{\toksa\expandafter{\expandafter'\vl'}\expandafter\prodtstyle\expandafter{\the\toksa}})
+and is ready to make a reduction which will push
+the value of the term corresponding to the inline action (i.e.\ |@<Insert
+local formatting@>|) on the stack.
+
+The way \bison\ does this is by
+introducing a new grammar term (named \prodstyle{bogus_inline} for some integer
+$n$) for each inline action and adding a new rule that reduces an
+empty sequence of terms to \prodstyle{bogus_inline}. The action for this rule is
+the inline action. In our case this would read as
+\begingroup
+\medskip
+\def\skipalltoks#1\par{}
+\def\preparsefallbacktext#1{%
+ \let\postparse\relax
+ \message{#1}%
+ \skipalltoks
+}
+
+\extendswitch\multicharswitch\at\stashed\by\PB\to\multicharswitchadjust
+\let\multicharswitch\multicharswitchadjust
+\def\textproductionsetup{%
+ \rulereftextproductionsetup
+ \let\acharswitch\texcharadjust
+ \let\onecharswitch\texcsadjust
+}%
+\beginprod
+\inline\flatten
+ bogus_inline:
+ \{|@<Insert local formatting@>|\}
+\endprod
+\medskip
+\endgroup
+\noindent$\ldots$except the parser knows what the state of the stack is at this
+point and thus the code inside |@<Insert local formatting@>| can now refer
+to the terms on the stack as described above.
@<Old `Insert local formatting'@>=
- @[TeX_( "/rhscont{/yy(1)}/to{/yy(0)}" );@]@;
- @[TeX_( "/yy0{/the/yy(0)/nx/midf/the/yy(2)}" );@]@;
+ @[TeX_( "/appendtolistx{/the/yy(1)}{/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.
-@<Insert local formatting@>=
+is not known to the parser in advance (as is the case for the parsers
+\splint\ generates using any version of \bison\ that is $\geq3.0$)
+a different way of accessing the stack is necessary. This notation is also more
+natural as it counts the terms from right to left, i.e.\ `into the depths
+of the stack' (for example \texref{/bb2\{\}} is the register holding the value
+of~\prodstyle{rhses1}). It is worth noting that in this case
+\texref{/yy(0)} and \texref{/yyval} are still the same
+register, the one that holds the value of the term corresponding to
+the inline action itself.
+@<Newer `Insert local formatting'@>=
@[TeX_( "/bb2{/toksa}/bb1{/toksb}" );@]@;
- @[TeX_( "/rhscont{/toksa}/to{/yy(0)}" );@]@;
- @[TeX_( "/yy0{/the/yy(0)/nx/midf/the/toksb}" );@]@;
-
-@ @<Old `Add a right hand side to a production'@>=
- @[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" );@]@;
+ @[TeX_( "/appendtolistx{/the/toksa}{/nx/midf/the/toksb}" );@]@;
-@ 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
+@ Finally, using the `native' way of referring to term values results
+in the most natural code. In this case, one can mix numeric and
+symbolic references for both implicit and explicit rules.
+@<Insert local formatting@>=
+ @[TeX_( "/appendtolistx{/the$[rhses]}{/nx/midf/the$[mid]}" );@]@;
+
+@ Productions are collected in a `productions cluster' (not an official term) by the
+following action:
+\smallskip
+\thisrulereference{\nx\inline\nx\flatten}
+\smallskip\noindent
+As can be seen in the code below, no pointers are provided for an {\it implicit\/}
+action (since there are no tokens associated with it).
+
+Processing a set of rules involves a large number of
+reexpansions. This seems to be a good place to use a list to store the nodes
+(see \.{yycommon.sty} for details on list macros). 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
+parsed table supplies very little information if the list 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.
+
+The code below relies on the inline action |@<Insert local formatting@>| above
+to store the relevant information from \texref{/yy(1)} (corresponding to
+\prodstyle{rhses1}) in \texref{/yy(3)} (which is
+the inline action `term' \inlineactionsymbol\ in the production above).
+@q Note that one cannot use \prodstyle{...} above to display \inlineactionsymbol@>
+@q since the \prodstyle{...} macro relies on the name parser. See yyunion.sty @>
+@q for further details about the special terms like this. @>
@<Add a right hand side to a production@>=
@[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_( " /appendtolistx{/the/yy(1)}{/nx/rrhssep/the/yy(2)/the/yy(4)}" );@]@;
@[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)" );@]@;
+ @[TeX_( " /yytoksempty/toksa{/toksa{/emptyterm}}{}" );@]@;
+ @[TeXb( " /appendtolistx{/the/yy(1)}{/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" );@]@;
+ @[TeXfo( " /nx/actbraces{}{}{0}{0}/nx/bdend}{}{/nx/rhsfulltrue}}" );@]@;
@[TeX_( "/fi" );@]@;
- @[TeX_( "/yy0{/nx/rules{/astarraylastcs}/the/yy(2)}" );@]@;
-
-@ @<Add an optional semicolon@>=
- @<Carry on@>@;
+ @[TeX_( "/yy0{/the/yy(1)}" );@]@;
@ @<Tokens and types...@>=
@G
@@ -942,33 +1021,46 @@ named_ref.opt:
;
@g
-@ \saveparseoutputfalse
+@ The simplest form of the right hand side is an empty rule. In this case the parser
+must make a reduction based on the lookahead only (or the current state), i.e.\ no
+tokens are consumed from the input.
+\saveparseoutputfalse
@<Make an empty right hand side@>=
@[TeX_( "/yy0{/nx/rhs{}{}{/nx/rhsfullfalse}}" );@]@;
-@ @<Add a term to the right hand side@>=
+@ Adding a \bison\ term to the right hand side involves collecting of several pieces of information.
+One of them is the (optional) symbolic named that can be used by the action code to refer to
+the place on the value stack that is allocated for this term.
+\smallskip
+\thisrulereference{\nx\inline\nx\flatten}%
+\smallskip
+\noindent The space between the term and the preceeding part of the rule may depend on the
+type of rule element that appears at the end of the rule parsed so far.
+@<Add a term to the right hand side@>=
@[TeX_( "/rhscont{/yy(1)}/to/toksa" );@]@;
@[TeX_( "/rhscnct{/yy(1)}/to/toksb" );@]@;
- @[TeX_( "/edef/next{/the/toksb}" );@]@;
- @[TeX_( "/ifx/next/empty" );@]@;
- @[TeX_( "/else" );@]@;
+ @[TeX_( "/yytoksempty/toksb{}{" );@]@;
@[TeX_( " /getfourth{/yy(2)}/to/toksc" );@]@;
@[TeX_( " /getfifth{/yy(2)}/to/toksd" );@]@;
@[TeX_( " /appendr/toksb{{/the/toksc}{/the/toksd}}" );@]@;
- @[TeX_( "/fi" );@]@;
+ @[TeX_( "}" );@]@;
@[TeXb( "/yy0{/nx/rhs{/the/toksa/the/toksb" );@]@;
@[TeXao( "/nx/termname{/the/yy(2)}{/the/yy(3)}}{/nx/hspace}{/nx/rhsfullfalse}}" );@]@;
-@ @<Add an action to the right hand side@>=
+@ Action processing is somewhat complicated since the action can be either inline or terminal,
+affecting the typesetting.
+\smallskip
+\thisrulereference{\nx\inline\nx\flatten}%
+\smallskip
+\noindent Additionally, an action may follow an empty rule in which case a special term
+must be added to aid the reader.
+@<Add an action to the right hand side@>=
@[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_( "/yytoksempty/toksa{/toksa{/emptyterm}}{}" );@]@;
@[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 */
@@ -982,10 +1074,7 @@ named_ref.opt:
@[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_( "/yytoksempty/toksa{/toksa{/emptyterm}}{}" );@]@;
@[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 */
@@ -993,16 +1082,17 @@ named_ref.opt:
@[TeXf( " /nx/bpredicate{/the/toksb}{}{/the/toksc}{/the/toksd}/nx/bdend}" );@]@;
@[TeXao( "{/nx/arhssep}{/nx/rhsfulltrue}}" );@]@;
-@ @<Add \prodstyle{\%empty} to the right hand side@>=
+@ An empty right hand side may be specified explicitly by using \prodstyle{\%empty} as
+the sole token in the production. This will increase the readability of the grammar by
+making the programmer's intentions more transparent.
+@<Add \prodstyle{\%empty} to the right hand side@>=
@[TeX_( "/rhscont{/yy(1)}/to/toksa" );@]@;
@[TeX_( "/rhscnct{/yy(1)}/to/toksb" );@]@;
- @[TeX_( "/edef/next{/the/toksb}" );@]@;
- @[TeX_( "/ifx/next/empty" );@]@;
- @[TeX_( "/else" );@]@;
+ @[TeX_( "/yytoksempty/toksb{}{" );@]@;
@[TeX_( " /getfourth{/yy(2)}/to/toksc" );@]@;
@[TeX_( " /getfifth{/yy(2)}/to/toksd" );@]@;
@[TeX_( " /appendr/toksb{{/the/toksc}{/the/toksd}}" );@]@;
- @[TeX_( "/fi" );@]@;
+ @[TeX_( "}" );@]@;
@[TeXb( "/yy0{/nx/rhs{/the/toksa/the/toksb" );@]@;
@[TeXao( "/nx/emptyterm}{/nx/hspace}{/nx/rhsfullfalse}}" );@]@;
@@ -1045,13 +1135,17 @@ named_ref.opt:
@[TeXao( "/nx/mergeop{/nx/tagit/the/yy(3)}/the/yy(2)}{/the/toksb}{/nx/rhsfullfalse}}" );@]@;
@[TeX_( "/fi" );@]@;
+ @t}\beginfoldedsections{@>
+
@ @<Create an empty named reference@>=
@[TeX_( "/yy0{}" );@]@;
@ @<Create a named reference@>=
@<Turn an identifier into a term@>@;
-@ Identifiers.
+ @t}\endfoldedsections{@>
+
+@*2 Identifiers and other symbols.
{\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.
@@ -1095,6 +1189,7 @@ string_as_id:
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).
+\beginfoldedsectionshere
@<Turn an identifier into a term@>=
@[TeX_( "/yy0{/nx/idit/the/yy(1)}" );@]@;
@@ -1113,6 +1208,8 @@ different types from the scanner).
@ @<Prepare a string for use@>=
@[TeX_( "/yy0{/nx/stringify/the/yy(1)}" );@]@;
+@t}\endfoldedsections{@>
+
@ {\it Variable and value.
The \prodstyle{STRING} form of variable is deprecated and is not \.{M4}-friendly.
For example, \.{M4} fails for \.{\%define "[" "value"}.}
@@ -1151,8 +1248,6 @@ as they have to be inserted in a place that is aware of the internal definitions
definitions are used.
@<Grammar parser \Cee\ postamble@>=
-#define YYPRINT(file, type, value) @[yyprint (file, type, value)@]
- static void yyprint (FILE *file, int type, YYSTYPE value){}
@ @<Bootstrap parser \Cee\ postamble@>=
@<Grammar parser \Cee\ postamble@>@;
@@ -1183,8 +1278,15 @@ token information from the grammar.
@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
+@*1 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.
+|union| into any data structure usable in \TeX), this section is left (nearly)
+empty. The reason for the lonely type below is the postprocessor that facilitates
+the use of \bison\ `native' term references (see elsewhere). In order to
+translate such references into appropriate \TeX\ code, the postprocessor
+must let \bison\ calculate offsets into the value stack, which requires
+assigning types to various terminals and non-terminals. The specific type
+has no significance.
@<Union of grammar parser types@>=
+ int intval; \ No newline at end of file