summaryrefslogtreecommitdiff
path: root/support/splint/cweb
diff options
context:
space:
mode:
Diffstat (limited to 'support/splint/cweb')
-rw-r--r--support/splint/cweb/Makefile131
-rw-r--r--support/splint/cweb/bo.w582
-rw-r--r--support/splint/cweb/bs.w60
-rw-r--r--support/splint/cweb/checklists.w2
-rw-r--r--support/splint/cweb/common.w38
-rw-r--r--support/splint/cweb/fk.w4
-rw-r--r--support/splint/cweb/fo.w185
-rw-r--r--support/splint/cweb/lo.w100
-rw-r--r--support/splint/cweb/mkeparser.w8
-rw-r--r--support/splint/cweb/mkscanner.w2
-rw-r--r--support/splint/cweb/np.w34
-rw-r--r--support/splint/cweb/philosophy.w37
-rw-r--r--support/splint/cweb/references.w2
-rw-r--r--support/splint/cweb/so.w133
-rw-r--r--support/splint/cweb/splint.w258
-rw-r--r--support/splint/cweb/ssffo.w123
16 files changed, 981 insertions, 718 deletions
diff --git a/support/splint/cweb/Makefile b/support/splint/cweb/Makefile
index 1c3b4d6bc3..f80b6b5886 100644
--- a/support/splint/cweb/Makefile
+++ b/support/splint/cweb/Makefile
@@ -1,4 +1,4 @@
-# Copyright 2012-2020, Alexander Shibakov
+# Copyright 2012-2024, Alexander Shibakov
# This file is part of SPLinT
#
# SPLinT is free software: you can redistribute it and/or modify
@@ -13,17 +13,30 @@
#
# You should have received a copy of the GNU General Public License
# along with SPLinT. If not, see <http://www.gnu.org/licenses/>.
+docs: splint.pdf
include ../makefile.inc
-all: ${SPLINT_PTABLES} ${SPLINT_LTABLES}
+tables: ${SPLINT_PTABLES} ${SPLINT_LTABLES}
-b%out: mkeparser.c b%.c
- ${CC} ${BISON_STATE} -DPARSER_FILE=\"$(lastword $^)\" -DYYPARSE_PARAMETERS= -o $@ $<
+bdout bbout bgout \
+bfout:b%out: mkeparser.c b%.c
+ ${CC} ${BISON_STATE} -DPARSER_FILE=\"$(lastword $^)\" -DYYPARSE_PARAMETERS= -o $@ $<
-b%.yy: bo.x
+bd.yy bg.yy \
+bb.yy bf.yy:b%.yy: bo.u bo.m
${CTANGLE} $<
+bd.yx bg.yx \
+bb.yx bf.yx:%.yx: %.yy
+ ${BRACK} --replace-only --bison-link=bo.m $*.yy $*.yx
+
+bd.y bg.y \
+bb.y bf.y:%.y: %.yx
+ cp -f $^ $@
+
+byytab.tex gyytab.tex \
+dyytab.tex fyytab.tex:\
%yytab.tex: b%out
${SPLINT_DRIVER_DIR}/$< --optimize-actions $@
@@ -33,15 +46,13 @@ ltab.tex: ltout
ltout: mkscanner.c lo_states.h lo.c
${CC} -DLEXER_FILE=\"$(lastword $^)\" -o $@ $<
-ssffo.ll lo.ll: \
-%.ll: %.x
+lo.ll: %.ll: %.x
${CTANGLE} $< && rm $(patsubst %.x, %.c, $^)
fil.ll: so.x
${CTANGLE} $< && rm $(patsubst %.x, %.c, $^)
-fip.yy rep.yy rap.yy \
-ddp.yy: fo.x
+fip.yy rep.yy rap.yy ddp.yy: fo.x
${CTANGLE} $< && rm $(patsubst %.x, %.c, $^)
# flex parser
@@ -52,19 +63,21 @@ fil.c: fil.l
fil_out: mkscanner.c fil_states.h fil.c
${CC} -DLEXER_FILE=\"$(lastword $^)\" -o $@ $<
-fil_states.h: so.tex lstab.tex byytab.tex
- ${PDFTEX} $<
-
filtab.tex: fil_out
${SPLINT_DRIVER_DIR}/$< --optimize-actions --optimize-tables $@
-fip.c rep.c rap.c \
-ddp.c:%.c: %.y
+# state parsing for the \flex\ input scanner
+
+fil_states.h: so.tex ssfstab.tex ddptab.tex ${SPLINT_ROOT}tex/grabstates.sty
+ @echo "Generating state list for the flex lexer ..."
+ @${PDFTEX} $<
+
+fip.c rep.c rap.c ddp.c:%.c: %.y
${BISON} -o $@ $<
fip_out rap_out \
-ddp_out rep_out:%_out: mkeparser.c %.c
- ${CC} ${BISON_STATE} -DPARSER_FILE=\"$(lastword $^)\" -DYYPARSE_PARAMETERS= -o $@ $<
+ddp_out rep_out:%_out: mkeparser.c %.c
+ ${CC} ${BISON_STATE} -DPARSER_FILE=\"$(lastword $^)\" -DYYPARSE_PARAMETERS= -o $@ $<
fiptab.tex raptab.tex \
ddptab.tex reptab.tex:%tab.tex: %_out
@@ -74,10 +87,11 @@ so.tex: so.x
${CWEAVE} $<
fo.tex: fo.x
- ${CWEAVE} $<
+ -${CWEAVE} $<
-fo.tok: fo.tex ltab.tex byytab.tex
- ${TEX} ${MODEBOOTSTRAP} \\input $<
+fo.tok: fo.tex ltab.tex dyytab.tex bo.tok
+ @echo "Generating token equivalences for flex input parser ..."
+ @${TEX} ${MODEBOOTSTRAP} \\input $<
lo.c: lo.l
${FLEX} -o $@ $<
@@ -86,10 +100,24 @@ mkscanner.c mkeparser.c: \
%.c: %.w
${CTANGLE} $<
+# bootstrap flex parser
+
+ssfs.ll: so.x
+ ${CTANGLE} $< && rm $(patsubst %.x, %.c, $^)
+
+ssfs.c: ssfs.l
+ ${FLEX} -o $@ $<
+
+ssfs_out: mkscanner.c ssfs.c
+ ${CC} -DLEXER_FILE=\"$(lastword $^)\" -o $@ $<
+
+ssfstab.tex: ssfs_out
+ ${SPLINT_DRIVER_DIR}/$< --optimize-actions --optimize-tables $@
+
# name parser
-smallp_out: mkeparser.c small_parser.c
- ${CC} ${BISON_STATE} -DPARSER_FILE=\"$(lastword $^)\" -DYYPARSE_PARAMETERS= -o $@ $<
+smallp_out: mkeparser.c small_parser.c
+ ${CC} ${BISON_STATE} -DPARSER_FILE=\"$(lastword $^)\" -DYYPARSE_PARAMETERS= -o $@ $<
smalll_out: mkscanner.c small_lexer.c
${CC} -DLEXER_FILE=\"$(lastword $^)\" -o $@ $<
@@ -105,71 +133,56 @@ small_lexer.ll: np.x
@${CTANGLE} $<
bo.tex: bo.x
- -${CWEAVE} -x $<
+ -${CWEAVE} -x $< 1>/dev/null
splint.tex \
splint.idx \
splint.scn: splint.x bo.x lo.x fo.x so.x np.x common.w bs.w \
fk.w philosophy.w checklists.w references.w alphas.hx
- -${CWEAVE} $<
+ -${CWEAVE} $< 1>/dev/null
alphas.hx:
- ${MISCCW} --alpha-list --alpha-length=1 $@
-
-ssffo.tex \
-ssffo.idx ssffo.scn: ssffo.x
- ${CWEAVE} $<
+ @${MISCCW} --alpha-list --alpha-length=1 $@
bo.tok: bo.tex ltab.tex byytab.tex
- ${TEX} ${MODEBOOTSTRAP} \\input $<
-
-ssffo.pdf: %.pdf: ${SPLINT_DOC_PREREQS_XREF}
- ${PDFTEX} $*.tex
-
-ssffo.dvi: %.dvi: ${SPLINT_DOC_PREREQS_XREF}
- ${TEX} $*.tex
+ @echo "Making token equivalence tables for the bison parser ..."
+ @${TEX} ${MODEBOOTSTRAP} \\input $< #1>/dev/null
-splint.gdx: %.gdx: ${SPLINT_DOC_PREREQS_XREF}
+splint.gdx splint.aux: ${SPLINT_DOC_PREREQS_XREF}
@echo "Making the bison and TeX indices ..."
- ${PDFTEX} $*.tex
+ @${PDFTEX} splint.tex #1>/dev/null
+
+# remove the implicit rule before building the main index
%.gdy: %.gdx
splint.gdy: splint.gdx
${BINDX} --fine $^ $@
-splint.xxr: %.xxr: ${SPLINT_DOC_PREREQS_XREF}
- @echo "Generating the cross references ..."
- ${PDFTEX} $*.tex
-
-splint.pdf: %.pdf: ${SPLINT_DOC_PREREQS_XREF} %.gdy %.xxr
- ${PDFTEX} \\input $*.tex && touch $*.gdy && touch $*.pdf
+splint.pdf: %.pdf: ${SPLINT_DOC_PREREQS_XREF} %.gdy %.aux
+ @echo "Generating SPLinT documentation (splint.pdf) ..."
+ while test "`diff --new-file splint.pdf /tmp/splint.pdf`"; do \
+ echo "Files differ" && mv splint.pdf /tmp/; \
+ ${PDFTEX} \\input $*.tex && touch $*.gdy && touch $*.pdf; \
+ done
splint.dvi: %.dvi: ${SPLINT_DOC_PREREQS_XREF} %.gdy
- ${TEX} $*.tex && touch $*.gdy && touch $*.dvi && rm $*.xxr && rm $*.ftn
-
-${SPLINT_ROOT}tex/btokenset.sty: # stupid make weirdness
- @
+ @${TEX} $*.tex && touch $*.gdy && touch $*.dvi && rm $*.ftn
# state parsing
-lstabout: mkscanner.c ssffo.c
- ${CC} -DLEXER_FILE=\"$(lastword $^)\" -o $@ $<
-
-lstab.tex: lstabout
- ${SPLINT_DRIVER_DIR}/$< --optimize-actions $@
-
lo.tex: lo.x
${CWEAVE} $<
-lo_states.h: lo.tex lstab.tex byytab.tex
- ${PDFTEX} $<
+lo_states.h: lo.tex ssfstab.tex ddptab.tex ${SPLINT_ROOT}tex/grabstates.sty
+ @echo "Generating state list for the bison lexer ..."
+ @${PDFTEX} $<
# clean will erase all automatically generated files in the current directory
clean: clean_core
- -rm -f ctablesout b?out ltout smallp_out \
- smalll_out lstabout fil_out fip_out rep_out rap_out ddp_out
+ -rm -f ctablesout b?out ltout smallp_out /tmp/splint.pdf \
+ smalll_out ssfs_out fil_out fip_out rep_out rap_out ddp_out
include ${SPLINT_ROOT}makefile.loc
@@ -178,9 +191,9 @@ include ${SPLINT_ROOT}makefile.loc
# of bo.tok, lo.tex, eventually leading to remaking of splint.pdf;
# the special target below tells make to treat bg.yy as if it were not an intermediate file
-.PRECIOUS: %.yy bo.tok fo.tok %.ll b%.y splint.gdx splint.xxr
+.PRECIOUS: %.yy bo.tok fo.tok %.ll b%.y splint.gdx
# the files below appear as targets but are really intermediaries for other files
-.INTERMEDIATE: smallp_out smalll_out lstabout ltout fil_out \
+.INTERMEDIATE: smallp_out smalll_out ssfs_out ltout fil_out \
fip_out rep_out rap_out ddp_out splint.gdx
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
diff --git a/support/splint/cweb/bs.w b/support/splint/cweb/bs.w
index adefd23f8b..8b32617ef3 100644
--- a/support/splint/cweb/bs.w
+++ b/support/splint/cweb/bs.w
@@ -1,4 +1,4 @@
-@q Copyright 2012-2020, Alexander Shibakov@>
+@q Copyright 2012-2024, Alexander Shibakov@>
@q This file is part of SPLinT@>
@q SPLinT is free software: you can redistribute it and/or modify@>
@@ -31,7 +31,6 @@ be done here.
_register_table_d(yypgoto)@;
_register_table_d(yytable)@;
_register_table_d(yycheck)@;
- _register_table_d(yytoknum)@;
_register_table_d(yystos)@;
_register_table_d(yytname)@;
_register_table_d(yyprhs)@;
@@ -46,8 +45,13 @@ with version~\.{3.0}) does not generate |yyprhs| and |yyrhs| or any
other arrays that contain similar information, so we fake them here if
such a crippled version of \bison\ is used.
+The |yyrimplicit| array will be used by the table output code, together with
+the postprocessor to output right hand side lengths for the term references that
+require them in the case when the `native' \bison\ references are
+used.
@<Variables and types local to the parser@>=
unsigned int yyrthree[YYNRULES + 1] = { 0 };
+ int yyrimplicit[YYNRULES + 1] = { 0 };
#ifdef BISON_IS_CRIPPLED
unsigned int yyrhs[YYNRULES + 1] = { -1 };
unsigned int yyprhs[YYNRULES + 1] = { 0 };
@@ -102,6 +106,23 @@ such a crippled version of \bison\ is used.
@<Parser table names@>=
_register_table_d(yyrthree)@;
+@ We list some macros that are used to assist the post
+processor and take advantage of the |yyrimlicit| array. As at this
+time the size of the array is unknown (the preamble is included before
+the parser file by \.{mkeparser.w} so the number of rules is unknown
+at this point), we declare the array as a pointer.
+@d BZ( term, anchor ) ( ((YYSTYPE *)&(term)) - ((YYSTYPE *)&(anchor)) + 1 )
+@d BZZ( term, anchor ) (
+ (yyrimplicit_p[yyn] = ((yyrimplicit_p[yyn] < 0) ?
+ yyrimplicit_p[yyn] : ((YYSTYPE *)&(term)) - ((YYSTYPE *)&(anchor)) + 1)),
+ ((YYSTYPE *)&(term)) - ((YYSTYPE *)&(anchor)) + 1
+)
+@<\Cee\ setup code specific to \bison@>=
+ int *yyrimplicit_p;
+
+@ @<Output parser semantic actions@>=
+ yyrimplicit_p = yyrimplicit;
+
@*2Actions. There are several ways of making |yyparse()| execute all portions of
the action code. The one chosen here makes sure that none of the
tables gets written past its last element. To see how it works, it
@@ -154,6 +175,7 @@ change affects the generated parser.
yyr1[i] = YYNTOKENS;
yydefact[0] = i;
+ yyrimplicit[i] = -yyr2[i];
yyr2[i] = 0;
yyparse(YYPARSE_PARAMETERS);
@@ -173,18 +195,32 @@ change affects the generated parser.
}
+ for ( int i = 1; i < YYNRULES + 1; i++ ) {
+
+ if ( yyrimplicit[i] > 0 ) {
+ fprintf( tables_out, "\\yyimplicitlengthset{%d}{%d}%%\n", i, yyrimplicit[i] );
+ }
+
+ }
+
@*2Constants. A generic list of constants to be used later in different contexts is defined below.
As before, the appropriate macro will be defined generically to do what is required with these
names (for example, we can turn each name into a string for reporting purposes).
@<Parser constants@>=
_register_const_d(YYEMPTY)@;
_register_const_d(YYPACT_NINF)@;
- _register_const_d(YYEOF)@;
_register_const_d(YYLAST)@;
_register_const_d(YYNTOKENS)@;
_register_const_d(YYNRULES)@;
_register_const_d(YYNSTATES)@;
_register_const_d(YYFINAL)@;
+#ifndef YYEOF
+ _register_const_d(YYSYMBOL_YYEOF)@;
+#endif
+
+@ Constants defined to maintain compatibility with the older versions of \bison.
+@<Parser virtual constants@>=
+ _register_const_d(YYSYMBOL_YYEOF, YYEOF)@;
@*2Tokens.
Similar techniques are employed in token output. Tokens are parser
@@ -582,20 +618,32 @@ rules are not output if a crippled \bison\ is used.
@ \TeX\ constant output is another place where the techniques described above are applied.
As before, the macro handles the repetitive work of initialization, declaration, etc in
-each place where the corresponding constant is mentioned. The one exception is \.{YYPACT\_NINF},
-which has to be handled separately because the underscore in its name makes it difficult to
-use it as a command sequence name.
+each place where the corresponding constant is mentioned. The exceptions are \.{YYPACT\_NINF}
+and \.{YYSYMBOL\_YYEOF} that have to be handled separately because the
+underscore in its name makes it difficult to use it as a command sequence name.
\def\YYPACTxNINFxdesc{\.{YYPACT\_NINF\_}\\{desc}}
+\def\YYSYMBOLxYYEOFxdesc{\.{YYSYMBOL\_YYEOF\_}\\{desc}}
@s YYPACT_NINF_desc TeX
+@s YYSYMBOL_YYEOF_desc TeX
@<Prepare \TeX\ format for parser constants@>=
#define _register_const_d(c_name) @[c_name##_desc.format = "\\constset{%s}{%d}%%\n"; \
c_name##_desc.name = #c_name; \
+ c_name##_desc.value = c_name; \
output_desc.output_##c_name = 1;@]
@<Parser constants@>@;
#undef _register_const_d
+#ifdef YYEOF /* other values have already been set correctly */
+#define _register_const_d(c_name,vvalue) @[c_name##_desc.format = "\\constset{%s}{%d}%%\n"; \
+ c_name##_desc.name = #c_name; \
+ c_name##_desc.value = vvalue; \
+ output_desc.output_##c_name = 1;@]
+ @<Parser virtual constants@>@;
+#undef _register_const_d
+#endif
YYPACT_NINF_desc.name = "YYPACTNINF";
+YYSYMBOL_YYEOF_desc.name = "YYSYMBOLxYYEOF";
@ Token definitions round off the \TeX\ output mode.
diff --git a/support/splint/cweb/checklists.w b/support/splint/cweb/checklists.w
index 754855d747..446bc46b96 100644
--- a/support/splint/cweb/checklists.w
+++ b/support/splint/cweb/checklists.w
@@ -1,4 +1,4 @@
-% Copyright 2012-2020, Alexander Shibakov
+% Copyright 2012-2022, Alexander Shibakov
% Copyright 2002-2014 Free Software Foundation, Inc.
% This file is part of SPLinT
%
diff --git a/support/splint/cweb/common.w b/support/splint/cweb/common.w
index 0f50fdcabd..5112fb5414 100644
--- a/support/splint/cweb/common.w
+++ b/support/splint/cweb/common.w
@@ -1,4 +1,4 @@
-@q Copyright 2012-2020, Alexander Shibakov@>
+@q Copyright 2012-2024, Alexander Shibakov@>
@q This file is part of SPLinT@>
@q SPLinT is free software: you can redistribute it and/or modify@>
@@ -454,6 +454,19 @@ code easier to look at. Further explanation is given in the grammar
file. If the parser is doing its job, this is the only place where one
would actually see these as functions (or, rather, macros).
+In case one wishes to use the `native' \bison\ way of referencing
+terms (i.e.\ something along the lines of~\.{\\the\char`\$[term]})
+these macros should be used with a trailing underscore (say, \.{TeXa\_})
+to let the postprocessor know that the code inside should be
+postprocessed. The postprocessor will then create three files: one,
+destined for \CWEAVE, will use the same macro withough the underscore
+(i.e.\ \.{TeXa} to continue our example, and have the native \bison\
+terms replaced wih the appropriate \TeX\ commands. Another file is
+intended for \CTANGLE, where the whole macro will be replaced first
+with a special identifier, which in turn, after \CTANGLE\ finishes,
+will be replaced by an appropriately constructed call to \.{TeX\_\_}. The
+third file will contain the substitutions.
+
In compliance with paragraph 6.10.8(2)\footnote{[$\ldots$] {\it Any
other predefined macro names shall begin with a leading underscore
followed by an uppercase letter or a second underscore.}} of the \ISO\
@@ -482,7 +495,7 @@ macros which produces undesirable typesetting artefacts.}.
@q \CWEB\ is not aware of variadic macros, so this has to be done the old way@>
@<\Cee\ preamble@>=
-#define TeX__( string, ... ) @[fprintf( tables_out, " " string "%s\n", __VA_ARGS__, "%" )@]
+#define TeX__( string, ... ) @[fprintf( tables_out, " " string "%%\n", __VA_ARGS__ )@]
@ If a full parser is not needed, the lexing mechanism is not required. To satisfy the compiler
and the linker, the lexer and other functions still have to be declared and defined, since these functions
@@ -524,27 +537,32 @@ values. When the names are concatenated with other tokens, however,
the \Cee\ preprocessor postpones the macro expansion until the
concatenation is complete (see clauses 6.10.3.1, 6.10.3.2, and
6.10.3.3 of the \ISO\ \Cee\ Standard, \cite[ISO/C11]). Unless the result of the
-concatenation is still expandable, the expansion will halt.
+concatenation is still expandable, the expansion will halt\footnote{Another trick
+to halt expansion is to use {\it function macros} which will expand only when
+they are followed by parentheses. Since we do not have control over how
+constants are defined by \bison, we cannot take advantage of this feature of the
+\Cee\ preprocessor.}.
@<Global variables and types@>=
struct const_d {
char *format;
char *name;
+ int value;
};
@ @<Local variable and type declarations@>=
-#define _register_const_d(c_name) @[struct const_d c_name##_desc;@]
+#define _register_const_d(c_name,...) @[struct const_d c_name##_desc;@]
@<Constant names@>@;
#undef _register_const_d
@ @<Output descriptor fields@>=
-#define _register_const_d(c_name) @[bool output_##c_name:1;@]
+#define _register_const_d(c_name,...) @[bool output_##c_name:1;@]
@<Constant names@>@;
#undef _register_const_d
@ @<Default outputs@>=
-#define _register_const_d(c_name) @[@[@].output_##c_name = 0,@[@]@]
+#define _register_const_d(c_name,...) @[@[@].output_##c_name = 0,@[@]@]
@<Constant names@>@;
#undef _register_const_d
@@ -556,10 +574,10 @@ concatenation is still expandable, the expansion will halt.
{
int any_constants = 0;
-#define _register_const_d(c_name) \
+#define _register_const_d(c_name,...) \
\
if ( output_desc.output_##c_name ) { \
- const_out( tables_out, c_name##_desc, c_name)@; \
+ const_out( tables_out, c_name##_desc)@; \
any_constants = 1; \
}
@@ -575,7 +593,7 @@ concatenation is still expandable, the expansion will halt.
@<Constant names@>=
@ A macro to help with constant output.
-@d const_out(stream, c_desc, c_name) fprintf(stream, c_desc.format, c_desc.name, c_name);
+@d const_out(stream, c_desc) fprintf(stream, c_desc.format, c_desc.name, c_desc.value);
@ Action switch output routines modify the automata tables and
therefore have to be output last. Since action output is highly
@@ -728,7 +746,7 @@ specific cases are added to in the course of adding new features.
FOREVER {
- c = getopt_long (argc, argv, ( char [] ){':'@t, @>@<Short option list@>}, long_options, &option_index);
+ c = getopt_long (argc, argv, ( char [] )@[{':'@t, @>@<Short option list@>}@], long_options, &option_index);
if (c == -1) break;
diff --git a/support/splint/cweb/fk.w b/support/splint/cweb/fk.w
index fc0c5d2e14..c25a7e8cc2 100644
--- a/support/splint/cweb/fk.w
+++ b/support/splint/cweb/fk.w
@@ -1,4 +1,4 @@
-@q Copyright 2012-2020, Alexander Shibakov@>
+@q Copyright 2012-2022, Alexander Shibakov@>
@q This file is part of SPLinT@>
@q SPLinT is free software: you can redistribute it and/or modify@>
@@ -330,6 +330,7 @@ known to the \flex\ generated scanner.
}
@*2Constants.
+The few hard coded constants needed for the lexer to work are listed here.
@<Scanner constants@>=
_register_const_d(YY_END_OF_BUFFER_CHAR)@;
_register_const_d(YY_NUM_RULES)@;
@@ -427,6 +428,7 @@ are handled separately, because they contain underscores.
@<Prepare \TeX\ format for scanner constants@>=
#define _register_const_d(c_name) @[c_name##_desc.format = "\\constset{%s}{%d}%%\n"; \
c_name##_desc.name = #c_name; \
+ c_name##_desc.value = c_name; \
output_desc.output_##c_name = 1;@]
@<Scanner constants@>@;
#undef _register_const_d
diff --git a/support/splint/cweb/fo.w b/support/splint/cweb/fo.w
index 81694024c3..d34ca57d96 100644
--- a/support/splint/cweb/fo.w
+++ b/support/splint/cweb/fo.w
@@ -30,14 +30,23 @@
@q PURPOSE. @>
@**The \ifbootstrapmode flex \else\flex\ \fi parser stack.
-\ifbootstrapmode % this is a bootstrap run to generate the tables
+\ifbootstrapmode % this is a bootstrap run to generate the token references
\input limbo.sty
\def\optimization{5}
\input yy.sty
+ \def\bstrapparser{dyytab.tex}% use the full prologue parser
+ \def\bstraptokens{bo.tok}% for which we will need token equivalences
\modebootstrap
\else % otherwise set up the pretty printing of tokens
\let\hostparsernamespace\flexnamespace
\fi
+% we can get away with the setup above because the minimal lexer
+% used for bootstrapping does not know about the \prodstyle{\%left}
+% token so in the declarations list below, the two tokens,
+% \prodstyle{CCL_OP_DIFF} and \prodstyle{CCL_OP_UNION} become
+% part of the previous \prodstyle{\%token} declaration which is a
+% legal declaration syntax; see ldman.w and ldlex.w and ldgram.w for
+% a more elaborate setup;
The scanner generator, \flex, uses \bison\ to produce a parser for its
input language. Its lexer is output by \flex\ itself so both are
reused to generate the parser and the scanner for pretty printing
@@ -69,7 +78,7 @@ any custom adjustments to the lexer state to operate correctly.
@g
@ The selection of options for \bison\ parsers suitable for \splint\
-have been discussed
+has been discussed
\ifbootstrapmode\else\locallink{bison.options}earlier \endlink\fi so we
list them here without further comments.
@<Options for \flex\ parser@>=
@@ -157,7 +166,7 @@ point of recognition, while the typesetting parser needs to be aware of them.
@G
%token TOP_OP POINTER_OP ARRAY_OP DEF_OP RE_DEF OPT_OTHER OPT_DEPRECATED
-@ {\em \POSIX\ and \.{AT\&T} \lex\ place the
+@ \namedspot{flex braces}{\em \POSIX\ and \.{AT\&T} \lex\ place the
precedence of the repeat operator, \.{\{\}}, below that of concatenation.
Thus, \.{ab\{3\}} is\/ \.{ababab}. Most other \POSIX\ utilities use an {\rm Extended
Regular Expression (ERE)} precedence that has the repeat operator
@@ -166,8 +175,8 @@ higher than concatenation. This causes \.{ab\{3\}} to yield\/ \.{abbb}.
In order to support the \POSIX\ and \.{AT\&T} precedence and the \flex\
precedence we define two token sets for the begin and end tokens of
the repeat operator, \prodstyle{BEGIN_REPEAT_POSIX} and\/ \prodstyle{END_REPEAT_POSIX}. The lexical scanner chooses
-which tokens to return based on whether {\let\it\itbold\prodstyle{posix\_compat} or \prodstyle{lex\_compat}
-are specified. Specifying either \prodstyle{posix\_compat} or \prodstyle{lex\_compat}} will
+which tokens to return based on whether {\let\it\itbold\prodstyle{posix_compat} or \prodstyle{lex_compat}
+are specified. Specifying either \prodstyle{posix_compat} or \prodstyle{lex_compat}} will
cause \flex\ to parse scanner files as per the \.{AT\&T} and \POSIX-mandated behavior.}
@<Token definitions for \flex\ input parser@>=
@G
@@ -186,6 +195,7 @@ explanation). We can nevertheless get away with an empty \Cee\ preamble.
@ @<Productions for \flex\ parser@>=
@G
+@t}\vb{\insertraw{\beginfoldedsections}}{@>
@t}\vb{\inline\flatten}{@>
goal:
initlex sect1 sect1end
@@ -202,12 +212,15 @@ initlex:
@g
@ @<Assemble a \flex\ input file@>=
- @[TeX_( "/yy0{/the/yy(2)/the/yy(4)}" );@]@;
+ @[TeX_( "/finishlist{/the/yy(4)}" );@]@;
+ @[TeX_( "/yy0{/the/yy(2)/nx/executelist{/the/yy(4)}}" );@]@;
@ @<Productions for \flex\ parser@>=
@<Productions for \flex\ section~1 parser@>@;
@<Productions for \flex\ section~2 parser@>@;
+@t}\endfoldedsections{@>
+
@ @<Exclusive productions for \flex\ section~1 parser@>=
@G
@t}\vb{\inline\flatten}{@>
@@ -220,6 +233,7 @@ goal:
@ @<Productions for \flex\ section~1 parser@>=
@G
+@t}\vb{\insertraw{\beginfoldedsections}}{@>
sect1:
sect1 startconddecl namelist1 {@> @<Add start condition declarations@> @=}
| sect1 options {@> @<Add options to section~1@> @=}
@@ -266,8 +280,11 @@ namelist1:
@ @<Report an error in \prodstylens{namelist1}{\flexnamespace} and quit@>=
@[TeX_( "/yyerror" );@]@;
+@t}\endfoldedsections{@>
+
@ @<Productions for \flex\ section~1 parser@>=
@G
+@t}\vb{\insertraw{\beginfoldedsections}}{@>
options:
OPTION_OP optionlist {@> @<Start an options list@> @=}
| POINTER_OP {@> @<Add a pointer option@> @=}
@@ -338,15 +355,19 @@ option:
@ @<Output a deprecated option@>=
@[TeX_( "/yy0{/nx/flopt{deprecated}/the/yy(1)}" );@]@;
+@t}\endfoldedsections{@>
+
@ @<Special \flex\ section~2 parser productions@>=
@G
+@t}\vb{\inline\flatten}{@>
goal:
sect2 {@> @<Output section~2@> @=}
;
@g
@ @<Output section~2@>=
- @[TeX_( "/table/yy(1)" );@]@;
+ @[TeX_( "/finishlist{/the/yy(1)}" );@]@;
+ @[TeX_( "/table/expandafter{/expandafter/executelist/expandafter{/the/yy(1)}}" );@]@;
@ This portion of the grammar was changed to make it possible to read the
action code.
@@ -364,25 +385,54 @@ initforrule:
;
@g
-@ @<Add a rule to section~2@>=
+@ The production below describes the most typical way a regular expression is
+assigned an action. The redundant term \prodstyle{initforrule} is a standard
+\bison\ trick to make sure that the appropriate initializations happen at
+the right time.
+\smallskip
+\thisrulereference{\nx\inline\nx\flatten}
+\smallskip\noindent
+The original production has been modified so that the pretty printing parser has a chance
+to consume the action code. The second \prodstyle{'\\n'} is output by the action
+processing code.
+@<Add a rule to section~2@>=
@[TeX_( "/ifflcontinued@@action" );@]@;
@[TeX_( " /toksb{/flactionc}" );@]@;
@[TeX_( "/else" );@]@;
@[TeX_( " /toksb{/flaction}" );@]@;
@[TeX_( "/fi" );@]@;
@[TeX_( "/toksa/expandafter{/astformat@@flaction}" );@]@; /* capture the formatting action */
- @[TeX_( "/yypushx{/the/yy(1)/the/toksb{/the/yy(2)}{/the/yy(4)}/the/yy(5)/the/yy(6){/the/toksa}}/on/astarray" );@]@;
- @[TeX_( "/yy0{/astarraylastcs}" );@]@;
+ @[TeX_( "/yy0{/the/yy(1)}" );@]@;
+ @[TeX_( "/appendtolistx{/the/yy(1)}{/the/toksb{/the/yy(2)}{/the/yy(4)}/the/yy(5)/the/yy(6){/the/toksa}}" );@]@;
@[TeX_( "/let/astformat@@flaction/empty" );@]@; /* reset the format */
-@ @<Add a group of rules to section~2@>=
- @[TeX_( "/yy0{/the/yy(1)/nx/flactiongroup{/the/yy(2)}/the/yy(3){/the/yy(4)}/the/yy(5)}" );@]@;
+@ For convenience, rules that are active in the same set of states may be grouped together.
+This pattern is the subject of the next production.
+\smallskip
+\thisrulereference{\nx\inline\nx\flatten}
+\smallskip\noindent
+The original parser ignores the braces while the pretty printing parser
+uses the pointers associated with the braces to collect and process the accumulated
+stash. This is how comments and \CWEB\ section references are typeset.
+@<Add a group of rules to section~2@>=
+ @[TeX_( "/yy0{/the/yy(1)}" );@]@;
+ @[TeX_( "/finishlist{/the/yy(4)}" );@]@;
+ @[TeX_( "/appendtolistx{/the/yy(1)}{/nx/flactiongroup{/the/yy(2)}/the/yy(3){/nx/executelist{/the/yy(4)}}/the/yy(5)}" );@]@;
-@ @<Start an empty section~2@>=
- @[TeX_( "/yy0{}" );@]@;
+@ Simple left recursive terms like~\prodstyle{sect2} are very suitable for being implemented as a list
+(see the macros in \.{yycommon.sty} for the details on the list implementation). The `type' of~\prodstyle{sect2}
+is a (symbolic pointer to a) list of items built up from an empty initial list. This production initializes
+the list (with the name identical to the terminal on the left hand side of the production)
+and updates the list name (rather the name's prefix) for future invocations of this action.
+
+@<Start an empty section~2@>=
+ @[TeX_( "/initlist{/secttwoprefix sect2}" );@]@;
+ @[TeX_( "/yy0{/secttwoprefix sect2}" );@]@;
+ @[TeX_( "/edef/secttwoprefix{/secttwoprefix.}" );@]@;
@ @<Add a bare action@>=
- @[TeX_( "/yy0{/the/yy(1)/nx/flbareaction/the/yy(2)}" );@]@;
+ @[TeX_( "/yy0{/the/yy(1)}" );@]@;
+ @[TeX_( "/appendtolistx{/the/yy(1)}{/nx/flbareaction/the/yy(2)}" );@]@;
@ @<Productions for \flex\ section~2 parser@>=
@G
@@ -400,14 +450,23 @@ scon:
namelist2:
namelist2 ',' sconname {@> @<Add a start condition to a list@> @=}
| sconname {@> @<Start a list with a start condition name@> @=}
- | error {@> @<Report an error compiling a start condition list@> @=}
+ | error {@> @<Report an error in a start condition list@> @=}
;
@t}\vb{\inline\flatten}{@>
sconname:
NAME {@> @<Make a \prodstylens{NAME}{\flexnamespace} into a start condition@> @=}
;
-@ @<Create a list of start conditions@>=
+@ Start conditions are just names. The data structure that is output has
+location pointers for the streams to enable interaction with \CWEB. These
+pointers are in turn the values of the angle bracket tokens that enclose the
+list of start conditions.
+
+Start condition lists may be collected in their own sections, while the list itself
+may be followed by a comment. The pointers mentioned above are used to typeset the comments
+and section references.
+\beginfoldedsectionshere
+@<Create a list of start conditions@>=
@[TeX_( "/yy0{/nx/flsconlist{/the/yy(1)}{/the/yy(3)}{/the/yy(4)}}" );@]@;
@ @<Create a universal start condition@>=
@@ -422,17 +481,24 @@ sconname:
@ @<Start a list with a start condition name@>=
@<Copy the value@>@;
-@ @<Report an error compiling a start condition list@>=
+@ @<Report an error in a start condition list@>=
@[TeX_( "/yyerror" );@]@;
@ @<Make a \prodstylens{NAME}{\flexnamespace} into a start condition@>=
@[TeX_( "/yy0{/nx/flname/the/yy(1)}" );@]@;
-@ @<Productions for \flex\ section~2 parser@>=
+@t}\endfoldedsections{@>
+
+@*1 The syntax of regular expressions. The productions in this section define the
+syntax of \flex\ regular expressions in detail. The same productions are used for
+parsing isolated regular expressions (e.g.\ to present example code). A few of these
+productions have been modified to suit the needs of the pretty printing parser.
+@<Productions for \flex\ section~2 parser@>=
@<Rules for \flex\ regular expressions@>@;
@ @<Special productions for regular expressions@>=
@G
+@t}\vb{\inline\flatten}{@>
goal:
flexrule {@> @<Output a regular expression@> @=}
;
@@ -446,33 +512,48 @@ ensures that all the changes are local to the parsing macro.
@<Output a regular expression@>=
@[TeX_( "/table/yy(1)" );@]@;
-@ @<Rules for \flex\ regular expressions@>=
+@ Regular expressions are parsed using the following productions. There are
+two major cases: rules active only at the beginning of the line, and the rest. From the
+typesetting parser's point of view, there is not much difference between the two
+(certainly not enough to justify singling out the rules at the beginning of the line into
+their own production) but it was decided to keep the original grammar rules
+for consistency.
+@<Rules for \flex\ regular expressions@>=
@G
+@t}\vb{\insertraw{\beginfoldedsections}}{@>
flexrule:
- '^' rule {@> @<Match a rule at the beginning of the line@> @=}
+ '^' rule {@> @<Match a rule at the start of the line@> @=}
| rule {@> @<Match an ordinary rule@> @=}
| EOF_OP {@> @<Match an end of file@> @=}
| error {@> @<Report an error and quit@> @=}
;
-@ @<Match a rule at the beginning of the line@>=
+@ @<Match a rule at the start of the line@>=
@[TeX_( "/toksa/expandafter{/astformat@@flrule}" );@]@;
@[TeX_( "/let/astformat@@flrule/empty" );@]@;
@[TeX_( "/yy0{/nx/flbolrule{/the/yy(2)}{/the/toksa}}" );@]@;
+@ @<Match an end of file@>=
+ @[TeX_( "/yy0{/nx/fleof/the/yy(1)}" );@]@;
+
@ @<Match an ordinary rule@>=
@[TeX_( "/toksa/expandafter{/astformat@@flrule}" );@]@;
@[TeX_( "/let/astformat@@flrule/empty" );@]@;
@[TeX_( "/yy0{/nx/flrule{/the/yy(1)}{/the/toksa}}" );@]@;
-@ @<Match an end of file@>=
- @[TeX_( "/yy0{/nx/fleof/the/yy(1)}" );@]@;
-
@ @<Report an error and quit@>=
@[TeX_( "/yyerror" );@]@;
-
-@ @<Rules for \flex\ regular expressions@>=
+
+@t}\endfoldedsections{@>
+
+@ Another broad overview of regular expression types before diving into the details
+of various operations. Note that the only trailing context that \splint\ output
+lexer can process is the end of line (\prodstyle{'\$'}) due to the way the
+scanner routine is written. It does not affect its ability to pretty print the appropriate
+rules (for a lexer that is produced by \flex\ itself, for example).
+@<Rules for \flex\ regular expressions@>=
@G
+@t}\vb{\insertraw{\beginfoldedsections}}{@>
rule:
re2 re {@> @<Match a regular expression with a trailing context@> @=}
| re2 re '$' {@> @<Disallow a repeated trailing context@> @=}
@@ -511,9 +592,22 @@ re2:
@ @<Prepare to match a trailing context@>=
@[TeX_( "/yy0{/nx/fltrail{/the/yy(1)}{/the/yy(2)}}" );@]@;
+
+ @t}\endfoldedsections{@>
-@ @<Rules for \flex\ regular expressions@>=
+@*2 Atoms. Every regular expression is assembled of atomic subexpressions, each
+of which may be modified by an repetition operator that establishes how many
+times a given pattern can repeat to stay part of the original atom. New atomic expressions
+(or \prodstyle{singleton}s as they are called below) can be formed the usual way, by
+enclosing a regular expression in parentheses.
+
+As explained \locallink{flex braces}above\endlink, braced repetition operators may
+have different binding strengths, depending on the options supplied to \flex. The pretty
+printing in both cases is identical as only the application scopes of the operator differ, and not
+its meaning.
+@<Rules for \flex\ regular expressions@>=
@G
+@t}\vb{\insertraw{\beginfoldedsections}}{@>
series:
series singleton {@> @<Extend a series by a singleton@> @=}
| singleton {@> @<Match a singleton@> @=}
@@ -540,9 +634,12 @@ series:
@ @<Match a series of exact length@>=
@<Create a series of exact length@>@;
-
+
+@t}\endfoldedsections{@>
+
@ @<Rules for \flex\ regular expressions@>=
@G
+@t}\vb{\insertraw{\beginfoldedsections}}{@>
singleton:
singleton '*' {@> @<Create a lazy series match@> @=}
| singleton '+' {@> @<Create a nonempty series match@> @=}
@@ -600,8 +697,15 @@ singleton:
@ @<Match a specific character@>=
@[TeX_( "/yy0{/nx/flchar/the/yy(1)}" );@]@;
-@ @<Rules for \flex\ regular expressions@>=
+@t}\endfoldedsections{@>
+
+@*2 Characters. Several facilities are available to specify sets of characters, including
+built-in characters classes such as {\em whitespace}, {\em printable characters},
+{\em alphanumerics}, etc. Some simple boolean operaions are also supported to make specifying
+character classes more efficient.
+@<Rules for \flex\ regular expressions@>=
@G
+@t}\vb{\insertraw{\beginfoldedsections}}{@>
fullccl:
fullccl CCL_OP_DIFF braceccl {@> @<Subtract a character class@> @=}
| fullccl CCL_OP_UNION braceccl {@> @<Create a union of character classes@> @=}
@@ -610,7 +714,7 @@ fullccl:
braceccl:
'[' ccl ']' {@> @<Create a character class@> @=}
- | '[' '^' ccl ']' {@> @<Create a complementary character class@> @=}
+ | '[' '^' ccl ']' {@> @<Complement a character class@> @=}
;
ccl:
@@ -633,11 +737,13 @@ ccl:
@ @<Create a character class@>=
@[TeX_( "/yy0{/nx/flbraceccl{/the/yy(1)}{/the/yy(2)}{/the/yy(3)}}" );@]@;
-@ @<Create a complementary character class@>=
- @[TeX_( "/yy0{/nx/flbracecclneg{/the/yy(1)}{/the/yy(3)}{/the/yy(4)}}" );@]@;
+@ @<Complement a character class@>=
+ @[TeXb( "/yy0{/nx/flbracecclneg" );@]@;
+ @[TeXfo( " {/the/yy(1)}{/the/yy(3)}{/the/yy(4)}}" );@]@;
@ @<Add a range to a character class@>=
- @[TeX_( "/yy0{/the/yy(1)/nx/flcclrnge{/nx/flchar/the/yy(2)}{/nx/flchar/the/yy(4)}}" );@]@;
+ @[TeXb( "/yy0{/the/yy(1)/nx/flcclrnge" );@]@;
+ @[TeXfo( " {/nx/flchar/the/yy(2)}{/nx/flchar/the/yy(4)}}" );@]@;
@ @<Add a character to a character class@>=
@[TeX_( "/yy0{/the/yy(1)/nx/flchar/the/yy(2)}" );@]@;
@@ -648,7 +754,12 @@ ccl:
@ @<Create an empty character class@>=
@[TeX_( "/yy0{}" );@]@;
-@ @<Rules for \flex\ regular expressions@>=
+@t}\endfoldedsections{@>
+
+@*3 Special character classes. Various character classes are predefined in \flex.
+These include alphabetic and alphanumeric characters, digits, blank characters, upper and lower
+case characters, etc.
+@<Rules for \flex\ regular expressions@>=
@G
ccl_expr:
@t}\vb{\flatten}{@>
@@ -696,7 +807,5 @@ string:
@ @<Make an empty regular expression string@>=
@[TeX_( "/yy0{}" );@]@;
-@ This is needed to get the |yytoknum| array. A trivial declaration suffices.
+@ The postamble is empty for now.
@<Postamble for \flex\ parser@>=
-#define YYPRINT(file, type, value) @[yyprint (file, type, value)@]
- static void yyprint (FILE *file, int type, YYSTYPE value){}
diff --git a/support/splint/cweb/lo.w b/support/splint/cweb/lo.w
index 68ef1b6595..c2461787a9 100644
--- a/support/splint/cweb/lo.w
+++ b/support/splint/cweb/lo.w
@@ -1,4 +1,4 @@
-@q Copyright 2012-2020 Alexander Shibakov@>
+@q Copyright 2012-2024 Alexander Shibakov@>
@q Copyright 2002-2014 Free Software Foundation, Inc.@>
@q This file is part of SPLinT@>
@@ -18,6 +18,7 @@
@**The scanner for \ifx\bison\UNDEFINED\.{bison}\else\bison\fi\ syntax.
\ifx\bison\UNDEFINED
\input limbo.sty
+ \input yystype.sty
\input grabstates.sty
\immediate\openout\stlist=lo_states.h
\fi
@@ -95,7 +96,7 @@ output it in the form of a header file for the `real' lexer output
@ {\it A \Cee-like comment in directives/rules}.
@<Grammar lexer states@>=
-@G
+@G(fs1)
%x SC_YACC_COMMENT
@g
@@ -106,22 +107,26 @@ output it in the form of a header file for the `real' lexer output
%\tracerulestrue
%\traceactionstrue
%\tracebadcharstrue
+%\traceparseresultstrue
+%\traceparserstatestrue
%\prodstyle{\%\%}%
-\traceparserstatesfalse
-\tracestacksfalse
-\tracerulesfalse
-\traceactionsfalse
-\tracebadcharsfalse
-\yyflexdebugfalse
@<Grammar lexer states@>=
-@G
+@G(fs1)
%x SC_ESCAPED_STRING SC_ESCAPED_CHARACTER
@g
@ {\it A identifier was just read in directives/rules. Special state
to capture the sequence `\.{identifier:}'}.
+\traceparserstatesfalse
+\tracestacksfalse
+\tracerulesfalse
+\traceactionsfalse
+\tracebadcharsfalse
+\yyflexdebugfalse
+\traceparseresultsfalse
+\traceparserstatesfalse
@<Grammar lexer states@>=
-@G
+@G(fs1)
%x SC_AFTER_IDENTIFIER
@g
@@ -131,7 +136,7 @@ disallow \prodstyle{NUL}, as this simplifies our implementation. We match
angle brackets in nested pairs: several languages use them for
generics/template types}.
@<Grammar lexer states@>=
-@G
+@G(fs1)
%x SC_TAG
@g
@@ -150,25 +155,25 @@ Four types of user code:
\aterm predicate (code between \.{\%?\{} and \.{\}} in middle section);
}%
@<Grammar lexer states@>=
-@G
+@G(fs1)
%x SC_PROLOGUE SC_BRACED_CODE SC_EPILOGUE SC_PREDICATE
@g
@ {\it \Cee\ and \Ceepp\ comments in code}.
@<Grammar lexer states@>=
-@G
+@G(fs1)
%x SC_COMMENT SC_LINE_COMMENT
@g
@ {\it Strings and characters in code}.
@<Grammar lexer states@>=
-@G
+@G(fs1)
%x SC_STRING SC_CHARACTER
@g
@ Bracketed identifiers support.
@<Grammar lexer states@>=
-@G
+@G(fs1)
%x SC_BRACKETED_ID SC_RETURN_BRACKETED_ID
@g
@@ -179,9 +184,9 @@ Four types of user code:
@ The code for the generated scanner is highly dependent on the options
supplied. Most of the options below are essential for the scheme
-adopted in this package to work.
+adopted in this package to work.\gtextidx{\flex\ options example}{flex options example}{\flexidxdomain}%
@<Grammar lexer options@>=
-@G
+@G(fs1)
%option bison-bridge
%option noyywrap nounput noinput reentrant
%option noyy_top_state
@@ -194,7 +199,6 @@ adopted in this package to work.
Here is a full list of regular expressions recognized by the \bison\ scanner.
@<Grammar token regular expressions@>=
@<Scan grammar white space@>@;
- @<Scan \flex\ directives and options@>@;
@<Scan \bison\ directives@>@;
@<Do not support zero characters@>@;
@<Scan after an identifier, check whether a colon is next@>@;
@@ -340,23 +344,11 @@ returns a pair of pointers as the value.
}
@g
-@ Some additional constructs needed to typeset simple \flex\
-declarations. This is not part of the original \bison\ scanner.
-@<Scan \flex\ directives and options@>=
-@G(fs2)
-<INITIAL>
-{
- "%option" {@> @[TeX_( "/yylexreturnptr{FLEX_OPTION}" );@]@=}
- "%x" {@> @[TeX_( "/yylexreturnptr{FLEX_STATE_X}" );@]@=}
- "%s" {@> @[TeX_( "/yylexreturnptr{FLEX_STATE_S}" );@]@=}
-}
-@g
-
@ We present the `bad character' code first, before going into the details
of the character matching by the rest of the lexer.
@<Process a bad character@>=
- @[TeX_( "/edef/next{/nx/csname lexspecial[/the/yytextpure]/nx/endcsname}" );@]@;
- @[TeX_( "/expandafter/expandafter/expandafter/ifx/next/relax" );@]@;
+ @[TeX_( "/expandafter/let/expandafter/next/csname lexspecial[/the/yytextpure]/endcsname" );@]@;
+ @[TeX_( "/ifx/next/relax" );@]@;
@[TeX_( " /iftracebadchars" );@]@;
@[TeX_( " /yyfatal{invalid character(s): /the/yytext}" );@]@;
@[TeX_( " /fi" );@]@;
@@ -436,13 +428,12 @@ later, after the context is known.
@ @<Process the bracketed part of an identifier@>=
@[TeX_( "/ifx/bracketedidstr/empty" );@]@;
@[TeX_( " /bracketedidcontextstate/YYSTART /yyBEGIN{SC_BRACKETED_ID}" );@]@;
- @[TeX_( " /let/next=/yylexnext" );@]@;
+ @[TeX_( " /yybreak/yylexnext" );@]@;
@[TeX_( "/else" );@]@;
@[TeX_( " /ROLLBACKCURRENTTOKEN" );@]@;
@[TeX_( " /yyBEGIN{SC_RETURN_BRACKETED_ID}" );@]@;
- @[TeX_( " /def/next{/yylexreturn{ID}}" );@]@;
- @[TeX_( "/fi" );@]@;
- @[TeX_( "/next" );@]@;
+ @[TeX_( " /yybreak{/yylexreturn{ID}}" );@]@;
+ @[TeX_( "/yycontinue" );@]@;
@ @<Process a colon after an identifier@>=
@[TeX_( "/ifx/bracketedidstr/empty" );@]@;
@@ -485,27 +476,25 @@ later, after the context is known.
@[TeX_( "/ifx/bracketedidstr/empty" );@]@;
@[TeX_( " /edef/bracketedidstr{{/the/yytextpure}{/the/yytext}" );@]@;
@[TeX_( " {/the/yyfmark}{/the/yysmark}}" );@]@;
- @[TeX_( " /let/next=/yylexnext" );@]@;
+ @[TeX_( " /yybreak/yylexnext" );@]@;
@[TeX_( "/else" );@]@;
- @[TeX_( " /def/next{/yywarn{unexpected identifier " );@]@;
+ @[TeX_( " /yybreak{/yywarn{unexpected identifier " );@]@;
@[TeX_( " in bracketed name: /the/yytext}}" );@]@;
- @[TeX_( "/fi" );@]@;
- @[TeX_( "/next" );@]@;
+ @[TeX_( "/yycontinue" );@]@;
@ @<Finish processing bracketed identifier@>=
@[TeX_( "/yyBEGINr/bracketedidcontextstate" );@]@;
@[TeX_( "/ifx/bracketedidstr/empty" );@]@;
- @[TeX_( " /def/next{/yywarn{an identifier expected}}" );@]@;
+ @[TeX_( " /yybreak{/yywarn{an identifier expected}}" );@]@;
@[TeX_( "/else" );@]@;
@[TeX_( " /ifnum/bracketedidcontextstate=/yylexstate{INITIAL}/relax" );@]@;
@[TeX_( " /expandafter/yylval/expandafter{/bracketedidstr}" );@]@;
@[TeX_( " /let/bracketedidstr=/empty" );@]@;
- @[TeX_( " /def/next{/yylexreturn{BRACKETED_ID}}" );@]@;
+ @[TeX_( " /yybreak@@{/yylexreturn{BRACKETED_ID}}" );@]@;
@[TeX_( " /else" );@]@;
- @[TeX_( " /let/next=/yylexnext" );@]@;
+ @[TeX_( " /yybreak@@/yylexnext" );@]@;
@[TeX_( " /fi" );@]@;
- @[TeX_( "/fi" );@]@;
- @[TeX_( "/next" );@]@;
+ @[TeX_( "/yycontinue" );@]@;
@ @<Complain about improper identifier characters@>=
@[TeX_( "/yyfatal{invalid character(s) in bracketed name: /the/yytext}" );@]@;
@@ -621,11 +610,10 @@ The initial quote is already eaten}.
@[TeX_( " {/the/yyfmark}{/the/yysmark}}}/next" );@]@;
@[TeX_( " /STRINGFREE" );@]@;
@[TeX_( " /yyBEGIN{INITIAL}" );@]@;
- @[TeX_( " /def/next{/yylexreturn{TAG}}" );@]@;
+ @[TeX_( " /yybreak{/yylexreturn{TAG}}" );@]@;
@[TeX_( "/else" );@]@;
- @[TeX_( " /STRINGGROW/let/next=/yylexnext" );@]@;
- @[TeX_( "/fi" );@]@;
- @[TeX_( "/next" );@]@;
+ @[TeX_( " /STRINGGROW/yybreak/yylexnext" );@]@;
+ @[TeX_( "/yycontinue" );@]@;
@ This is a slightly different rule from the original scanner. We do not perform |yyleng| computations,
so it makes sense to raise the nesting level one by one.
@@ -722,13 +710,12 @@ braced code.
@[TeX_( "/ifnum/lonesting</z@@" );@]@;
@[TeX_( " /STRINGFINISH" );@]@;
@[TeX_( " /edef/next{/yylval{{/the/laststring}{/the/yyfmark}{/the/yysmark}}}/next" );@]@;
- @[TeX_( " /def/next{/yylexreturn{BRACED_CODE}}" );@]@;
@[TeX_( " /yyBEGIN{INITIAL}" );@]@;
+ @[TeX_( " /yybreak{/yylexreturn{BRACED_CODE}}" );@]@;
@[TeX_( "/else" );@]@;
@[TeX_( " /STRINGGROW" );@]@;
- @[TeX_( " /let/next=/yylexnext" );@]@;
- @[TeX_( "/fi" );@]@;
- @[TeX_( "/next" );@]@;
+ @[TeX_( " /yybreak/yylexnext" );@]@;
+ @[TeX_( "/yycontinue" );@]@;
@ @<Add closing brace to a predicate@>=
@[TeX_( "/advance/lonesting/m@@ne" );@]@;
@@ -736,12 +723,11 @@ braced code.
@[TeX_( " /STRINGFINISH" );@]@;
@[TeX_( " /edef/next{/yylval{{/the/laststring}{/the/yyfmark}{/the/yysmark}}}/next" );@]@;
@[TeX_( " /yyBEGIN{INITIAL}" );@]@;
- @[TeX_( " /def/next{/yylexreturn{BRACED_PREDICATE}}" );@]@;
+ @[TeX_( " /yybreak{/yylexreturn{BRACED_PREDICATE}}" );@]@;
@[TeX_( "/else" );@]@;
@[TeX_( " /STRINGGROW" );@]@;
- @[TeX_( " /let/next=/yylexnext" );@]@;
- @[TeX_( "/fi" );@]@;
- @[TeX_( "/next" );@]@;
+ @[TeX_( " /yybreak/yylexnext" );@]@;
+ @[TeX_( "/yycontinue" );@]@;
@ {\it Scanning some prologue: from \.{\%\{} (already scanned) to \.{\%\}}}.
@<Scan prologue@>=
diff --git a/support/splint/cweb/mkeparser.w b/support/splint/cweb/mkeparser.w
index f60ccf5d64..79505b3be4 100644
--- a/support/splint/cweb/mkeparser.w
+++ b/support/splint/cweb/mkeparser.w
@@ -1,4 +1,4 @@
-% Copyright 2012-2020, Alexander Shibakov
+% Copyright 2012-2024, Alexander Shibakov
% This file is part of SPLinT
%
% SPLinT is free software: you can redistribute it and/or modify
@@ -24,7 +24,7 @@ Sourcer(er?) (\.{bs.w}) which will be included as soon as this paragraph is
over. Since the main function of this code is to {\it dump\/} tables
produced by \bison, and a {\it bison\/} is a large buffalo like
animal, {\it and\/} the only reason it has to be done like this is due
-to the less than optimal choices of a few developers, feel free to
+to a less than optimal choices of a few developers, feel free to
interpret the acronym as something easier to remember.
@ @<Table names@>=
@@ -32,6 +32,9 @@ interpret the acronym as something easier to remember.
@ @<Constant names@>=
@<Parser constants@>@;
+#ifdef YYEOF
+ @<Parser virtual constants@>@;
+#endif
@ @<Local variable and type declarations@>=
@<Variables and types local to the parser@>@;
@@ -83,6 +86,7 @@ interpret the acronym as something easier to remember.
@ @<\Cee\ preamble@>=
@<Common code for \Cee\ preamble@>@;
+ @<\Cee\ setup code specific to \bison@>@;
@i common.w
@i bs.w
diff --git a/support/splint/cweb/mkscanner.w b/support/splint/cweb/mkscanner.w
index e847428199..05f22bd6e3 100644
--- a/support/splint/cweb/mkscanner.w
+++ b/support/splint/cweb/mkscanner.w
@@ -1,4 +1,4 @@
-% Copyright 2012-2020, Alexander Shibakov
+% Copyright 2012-2022, Alexander Shibakov
% This file is part of SPLinT
%
% SPLinT is free software: you can redistribute it and/or modify
diff --git a/support/splint/cweb/np.w b/support/splint/cweb/np.w
index 58379649a5..a4216ee058 100644
--- a/support/splint/cweb/np.w
+++ b/support/splint/cweb/np.w
@@ -1,4 +1,4 @@
-@q Copyright 2012-2020, Alexander Shibakov@>
+@q Copyright 2012-2024, Alexander Shibakov@>
@q This file is part of SPLinT@>
@q SPLinT is free software: you can redistribute it and/or modify@>
@@ -18,7 +18,11 @@
name processing. This approach (i.e. using a `full blown' parser/scanner
combination) is probably not the best way to implement such machinery
but its main purpose is to demonstrate a way to create a separate
-parser for local purposes.
+parser for local purposes. The name parser is what allows one to
+automatically typeset term names such as \.{example1}
+and \.{\%option\_name} as \prodstyle{example1} and \prodstyle{\%option_name}.
+@q The reference to \prodstyle{example1} above serves a dual role of correcting@>
+@q an owerfull \vbox in the index.@>
% We include the macros here since this file is intended to be
% included by the documentation `aggregator' so putting bare \TeX\
% at the beginning of the file runs the risk of producing and error
@@ -61,7 +65,7 @@ parser for local purposes.
@G
full_name:
identifier_string suffixes.opt {@> @<Compose the full name@> @=}
-| META_IDENTIFIER {@> @<Turn a \prodstylens{META\_IDENTIFIER}{\smallnamespace} into a full name@> @=}
+| META_IDENTIFIER {@> @<Turn a \prodstylens{META_IDENTIFIER}{\smallnamespace} into a full name@> @=}
| quoted_name suffixes.opt {@> @<Compose the full name@> @=}
;
@@ -123,7 +127,7 @@ qualifier:
@ @<Compose the full name@>=
@[TeX_( "/yy0{/the/yy(1)/the/yy(2)}/namechars/yyval" );@]@;
-@ @<Turn a \prodstylens{META\_IDENTIFIER}{\smallnamespace} into a full name@>=
+@ @<Turn a \prodstylens{META_IDENTIFIER}{\smallnamespace} into a full name@>=
@[TeX_( "/getfirst{/yy(1)}/to/toksa" );@]@;
@[TeX_( "/getsecond{/yy(1)}/to/toksb" );@]@;
@[TeX_( "/yy0{/nx/idstr{/the/toksa}{/the/toksb}}/namechars/yyval" );@]@;
@@ -138,7 +142,9 @@ qualifier:
@[TeX_( "/getsecond{/yy(1)}/to/toksb" );@]@;
@[TeX_( "/yy0{/nx/idstr{/the/toksa}{/the/toksb}}" );@]@;
-@ @<Start with a tag@>=
+@ Tags are recognized as a separate syntax element although no special
+processing is performed by the name parser or the associated macros.
+@<Start with a tag@>=
@[TeX_( "/getfirst{/yy(2)}/to/toksa" );@]@;
@[TeX_( "/getsecond{/yy(2)}/to/toksb" );@]@;
@[TeX_( "/yy0{/nx/idstr{</the/toksa>}{</the/toksb>}}" );@]@;
@@ -193,14 +199,15 @@ qualifier:
@ An integer at the end of an identifier (such as |id1|) is
interpreted as a suffix (similar to the way \MF\ treats identifiers,
-and \mft\ typesets them\footnote{This allows, for example, names like
-|$[term0]| while leaving |$[char2int]| in its `natural' form.}) to
+and \mft\ typesets them,\footnote{This allows, for example, names like
+|$[term0]| while leaving |$[char2int]| in its `natural' form.} as \prodstyle{id1}) to
mitigate a well-intentioned but surprisingly inconvenient feature of
\CTANGLE, namely outputting something like \.{id.1} as \.{id\ .1} in an
attempt to make sure that integers do not interfere with structure
dereferences. For this to produce meaningful results, a stricter
interpretation of \prodstyle{IDENTIFIER} syntax is required,
-represented by the \.{id\_strict} syntax below.
+represented by the \flexrenstyle{id\_strict} syntax
+\locallink{id_strict definition}below\endlink.
@<Attach an integer@>=
@[TeX_( "/yy0{/the/yy(1)/nx/dotsp/nx/sfxi/the/yy(2)}" );@]@;
@@ -251,8 +258,6 @@ as they have to be inserted in a place that is aware of the internal definitions
definitions are used.
@<Name parser \Cee\ postamble@>=
-#define YYPRINT(file, type, value) @[yyprint (file, type, value)@]
- static void yyprint (FILE *file, int type, YYSTYPE value){}
@ Union of types.
@@ -281,7 +286,10 @@ void define_all_states( void ) {
@o
@g
-@ @<Lexer definitions@>=
+@ \namedspot{id_strict definition}The tokens consumed by the name parser must
+represent a relatively fine classification of various identifier substrings to be able to
+detect various suffixes.
+@<Lexer definitions@>=
@<Lexer states@>@;
@G(fs1)
letter [_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]
@@ -300,7 +308,7 @@ int [0-9]+
@ Strings and characters in directives/rules.
@<Lexer states@>=
-@G
+@G(fs1)
%x SC_ESCAPED_STRING SC_ESCAPED_CHARACTER
@g
@@ -310,7 +318,7 @@ int [0-9]+
#include <stdbool.h>
@ @<Lexer options@>=
-@G
+@G(fs1)
%option bison-bridge
%option noyywrap nounput noinput reentrant
%option noyy_top_state
diff --git a/support/splint/cweb/philosophy.w b/support/splint/cweb/philosophy.w
index 7b173f5d2f..1f5c4a3dfc 100644
--- a/support/splint/cweb/philosophy.w
+++ b/support/splint/cweb/philosophy.w
@@ -1,4 +1,4 @@
-@q Copyright 2012-2020, Alexander Shibakov@>
+@q Copyright 2012-2022, Alexander Shibakov@>
@q This file is part of SPLinT@>
@q SPLinT is free software: you can redistribute it and/or modify@>
@@ -64,6 +64,12 @@ they set a special reading rhythm, which is an added bonus in many
cases, although their presense openly violates
the `universally gray pages are a must' dogma.
+One final remark concerns the abundance of footnotes in this manual. I confess,
+there is almost no reason for it $\ldots$ except {\em I like footnotes\/}!
+They help introduce the air of mystery and adventure to an otherwise boring
+text. They are akin to the author wispering a secret in the reader's
+ear\footnote{Breaking convention by making the pages even less uniform is an added bonus.}.
+
@*1 Why GPL.
Selecting the license for this project involves more than the
availability of the source code. \TeX, by its very nature is an
@@ -191,12 +197,19 @@ the language. `Make it object-oriented' is neither a good reason nor a
clearly defined one, however.
@*1 Why not $*$\TeX.
-Simple. I never use it and have no idea of how packages, classes,
+Simple. I rarely, if ever\footnote{In some cases, a publisher would only accept
+a \LaTeX\ document, sadly. Better than most alternatives though.},
+use it and have no idea of how packages, classes,
etc., are designed. I have heard it has impressive mechanisms for
dealing with various problems commonly encountered in \TeX. Sadly, my
-knowledge of $*$\TeX\ machinery is almost nonexistent. This may change
-but right now I have tried to make the macros as generic as possible,
-hopefully making $*$\TeX\ adaptation easy.
+knowledge of $*$\TeX\ machinery is almost nonexistent\footnote{I am well familiar
+with the programming that went into \LaTeX, which is of highest quality. I do not
+share the design philosophy though and try to use only the most standard features}.
+This may change but right now I have tried to make the macros as generic as possible,
+hopefully making $*$\TeX\ adaptation easy\footnote{Unfortunately some redesign would
+be certainly necessary. Thus, \splint\ relies on the way plain \TeX\ allocates token
+registers so if the corresponding scheme in \LaTeX\ is drastically different, this
+portion of the macros would have to be rewritten.}.
The following quote from \cite[Ho] makes me feel particularly uneasy
about the current state of development of various \TeX\ variants:
@@ -205,7 +218,7 @@ and even more important is that the general impression is that of a finished boo
sometimes it seems like\/ \.{WEB} actively discourages development. This is
a subjective point, but nevertheless a quite important one.}''
-{\it Discouraging development\/} seems like a good thing to
+{\it Discouraging development\/} seems like a good feature to
me. Otherwise we are one step away from encouraging writing poor
software with inadequate tools merely `to encourage development'.
@@ -300,7 +313,7 @@ inserts \.{\\hbox\{\}}$\,$\TeX\ stuff$\,$\.{\{\}} into \CWEAVE's output. The
cost of this hack (aside from looking and feeling rather ugly on the
editor screen, not to mention disrupting the editor's brace
accounting) is a superfluous \.{\\hbox\{\}} left behind {\em before\/}
-the `\TeX\ stuff'. The programmer's provided \TeX\ code is unable to
+the `\TeX\ stuff'. The programmer provided \TeX\ code is unable to
remove this box (at the macro level, i.e.~in \TeX's `mouth' using
D.~Knuth's terminology, one may still succeed with the \.{\\lastbox}
approach unless the \.{\\hbox} was inserted in the main vertical mode)
@@ -312,6 +325,16 @@ cases such side-effects are indeed desirable, and save the programmer some
typing but it seems that the \.{@@t} facility was not well thought
out in its entirety.}.
+Continuing with the theme of inserting \TeX\ material into \CWEAVE\ output,
+another one of \CWEB's inflexibilities is the lack of means of inserting
+\TeX\ {\em between\/} sections. While inserting pure text may be arranged by
+putting a codeless section after the one with the code (appropriate macros
+can be written to suppress the generation of a reference to such a section),
+inserting command sequences that affect, say, the typesetting style
+of the consequent sections is not so easy. The trick with a `fake' section below
+will be quite visible in the final output which is almost always undesirable.
+Using the \.{@@t} mechanism is also far from ideal.
+
In general, the lack of structure in \CWEAVE's generated \TeX\ seems
to hinder even seemingly legitimate uses of \.{cwebmac.tex}
macros. Even such a natural desire as to use a different type size for
diff --git a/support/splint/cweb/references.w b/support/splint/cweb/references.w
index 83397c93bb..3824972d65 100644
--- a/support/splint/cweb/references.w
+++ b/support/splint/cweb/references.w
@@ -1,4 +1,4 @@
-@q Copyright 2012-2020, Alexander Shibakov@>
+@q Copyright 2012-2022, Alexander Shibakov@>
@q This file is part of SPLinT@>
@q SPLinT is free software: you can redistribute it and/or modify@>
diff --git a/support/splint/cweb/so.w b/support/splint/cweb/so.w
index d7a7696b8c..944f2cb82f 100644
--- a/support/splint/cweb/so.w
+++ b/support/splint/cweb/so.w
@@ -32,6 +32,7 @@
@**The lexer for \ifx\flex\UNDEFINED\.{flex}\else\flex\ \fi syntax.
\ifx\flex\UNDEFINED
\input limbo.sty
+ \input yystype.sty
\input grabstates.sty
\immediate\openout\stlist=fil_states.h
\fi
@@ -43,16 +44,31 @@ to replace them with ordinary patterns and use |yyless()| in the actions.
@G
%{@> @<Preamble for \flex\ lexer@> @=%}
@> @<Options for \flex\ input lexer@> @=
- @> @<Additional options for \flex\ input lexer@> @=
+ @> @<Output file for \flex\ input lexer@> @=
@> @<State definitions for \flex\ input lexer@> @=
@> @<Definitions for \flex\ input lexer@> @=
%%
@> @<Postamble for \flex\ input lexer@> @=
+ @> @<Common patterns for \flex\ lexer@> @=
@> @<Patterns for \flex\ lexer@> @=
%%
@> @<Auxilary code for \flex\ lexer@> @=
@g
+@ Bootstrap lexer.
+@(ssfs.ll@>=
+@G
+%{@> @<Preamble for \flex\ lexer@> @=%}
+ @> @<Options for \flex\ input lexer@> @=
+ @> @<Output file for the bootstrap \flex\ lexer@> @=
+ @> @<Definitions for \flex\ input lexer@> @=
+%%
+ @> @<Common patterns for \flex\ lexer@> @=
+ @> @<Catchall rule for the bootstrap lexer@> @=
+%%
+ @> @<Auxilary code for the bootstrap \flex\ lexer@> @=
+@g
+
@ @<Preamble for \flex\ lexer@>=
@ There are a few options that are necessary to ensure that the lexer
@@ -60,27 +76,31 @@ functions properly. Some of them (like \.{caseless}) directly
affect the behavior of the scanner, others (e.g.~\.{noyy\_top\_state})
prevent generation of unnecessary code.
@<Options for \flex\ input lexer@>=
-@G
+@G(fs1)
%option caseless nodefault stack noyy_top_state
%option nostdinit
-@g
-
-@ @<Additional options for \flex\ input lexer@>=
-@G
%option bison-bridge
%option noyywrap nounput noinput reentrant
%option debug
%option stack
+
+@ @<Output file for \flex\ input lexer@>=
+@G(fs1)
%option outfile="fil.c"
@g
+@ @<Output file for the bootstrap \flex\ lexer@>=
+@G(fs1)
+%option outfile="ssfs.c"
+@g
+
@*1 Regular expression and state definitions.
The lexer uses a large number of states to control its operation. Both
section~1 and section~2 rules rely on the scanner being in the
appropriate state. Otherwise (see \.{symbols.sty} example) the lexer
may parse the same fragment in a wrong context.
@<State definitions for \flex\ input lexer@>=
-@G
+@G(fs1)
%x SECT2 SECT2PROLOG SECT3 CODEBLOCK PICKUPDEF SC CARETISBOL NUM QUOTE
%x FIRSTCCL CCL ACTION RECOVER COMMENT ACTION_STRING PERCENT_BRACE_ACTION
%x OPTION LINEDIR CODEBLOCK_MATCH_BRACE
@@ -132,7 +152,7 @@ M4QEND "]]"
@*1 Regular expressions for \flex\ input scanner.
The code below treats \prodstyle{\%pointer} and \prodstyle{\%array} the same way it treats
\prodstyle{\%option} while typesetting.
-@<Patterns for \flex\ lexer@>=
+@<Common patterns for \flex\ lexer@>=
@G(fs2)
<INITIAL>{
^{WS} {@> @[TeX_( "/flindented@@codetrue/yyBEGIN{CODEBLOCK}/yylexnext" );@]@=}
@@ -211,7 +231,7 @@ The code below treats \prodstyle{\%pointer} and \prodstyle{\%array} the same way
<LINEDIR>{
\n {@> @[TeX_( "/yypopstate/yylexnext" );@]@=}
- [[:digit:]]+ {@> @[TeX_( "/fllinenum=/number/yytext/yylexnext" );@]@=}
+ [[:digit:]]+ {@> @[TeX_( "/fllinenum=/number/the/yytext/yylexnext" );@]@=}
\"[^"\n]*\" {@> @[TeX_( "/yylexnext" );@] /* ignore the file name in the line directives */ @=}
. {@> @[TeX_( "/yylexnext" );@] /* ignore spurious characters */ @=}
}
@@ -257,10 +277,10 @@ The code below treats \prodstyle{\%pointer} and \prodstyle{\%array} the same way
@ @<Complain if not inside a definition, continue otherwise@>=
@[TeX_( "/iffldidadef" );@]@;
@[TeX_( " /yylval/expandafter{/flnmdef}" );@]@;
- @[TeX_( " /def/next{/flinc@@linenum/yyBEGIN{INITIAL}/yylexreturn{RE_DEF}}" );@]@;
+ @[TeX_( " /yybreak{/flinc@@linenum/yyBEGIN{INITIAL}/yylexreturn{RE_DEF}}" );@]@;
@[TeX_( "/else" );@]@;
- @[TeX_( " /def/next{/yyfatal{incomplete name definition}}" );@]@;
- @[TeX_( "/fi/next" );@]@;
+ @[TeX_( " /yybreak{/yyfatal{incomplete name definition}}" );@]@;
+ @[TeX_( "/yycontinue" );@]@;
@ @<Patterns for \flex\ lexer@>=
@G(fs2)
@@ -390,7 +410,6 @@ The code below treats \prodstyle{\%pointer} and \prodstyle{\%array} the same way
<RECOVER>.*{NL} {@> @[TeX_( "/flinc@@linenum/yyBEGIN{INITIAL}/yylexnext" );@] @=}
@ Like \bison, \flex\ allows insertion of \Cee\ code in the middle of the input file.
-\saveparseoutputtrue
@<Patterns for \flex\ lexer@>=
@G(fs2)
<SECT2PROLOG>{
@@ -407,7 +426,6 @@ The code below treats \prodstyle{\%pointer} and \prodstyle{\%array} the same way
}
@ All the code inside is ignored.
-\saveparseoutputfalse
@<Consume the brace and increment the brace level@>=
@[TeX_( "/flinc/flbracelevel/yyless{2}/yylexnext" );@]@;
@@ -416,13 +434,16 @@ The code below treats \prodstyle{\%pointer} and \prodstyle{\%array} the same way
@ @<Begin section 2, prepare to reread, or ignore braced code@>=
@[TeX_( "/ifnum/flbracelevel>/z@@" );@]@;
- @[TeX_( " /let/next/yylexnext" );@]@;
+ @[TeX_( " /yybreak/yylexnext" );@]@;
@[TeX_( "/else" );@]@;
- @[TeX_( " /def/next{/yysetbol{/@@ne}/yyBEGIN{SECT2}/yyless{0}/yylexnext}" );@]@;
- @[TeX_( "/fi/next" );@]@;
+ @[TeX_( " /yybreak{/yysetbol{/@@ne}/yyBEGIN{SECT2}/yyless{0}/yylexnext}" );@]@;
+ @[TeX_( "/yycontinue" );@]@;
@ A pattern below (for the character class processing) had to be broken into two lines.
-A symbol ($\odot$@^$\odot$ separator, \flex@>) was inserted to indicate that a break had occured. The macros for \flex\
+A special symbol ($\odot$\gtextidx{$\odot$ separator, \flex}{0. separator, flex}{\flexidxdomain})
+has been inserted to indicate that a break had occured.
+
+The macros for \flex\
typesetting use a different mechanism from that of \bison\ macros and allow typographic
corrections to be applied to sections of the \flex\ code represented by various nonterminals.
These corrections can also be delayed. For the details, an interested reader may consult
@@ -477,14 +498,14 @@ These corrections can also be delayed. For the details, an interested reader may
@ @<Process a repeat pattern@>=
@[TeX_( "/yyless{1}/yyBEGIN{NUM}" );@]@;
@[TeX_( "/iffllex@@compat" );@]@;
- @[TeX_( " /def/next{/yylexreturn{BEGIN_REPEAT_POSIX}}" );@]@;
+ @[TeX_( " /yybreak{/yylexreturn{BEGIN_REPEAT_POSIX}}" );@]@;
@[TeX_( "/else" );@]@;
@[TeX_( " /ifflposix@@compat" );@]@;
- @[TeX_( " /def/next{/yylexreturn{BEGIN_REPEAT_POSIX}}" );@]@;
+ @[TeX_( " /yybreak@@{/yylexreturn{BEGIN_REPEAT_POSIX}}" );@]@;
@[TeX_( " /else" );@]@;
- @[TeX_( " /def/next{/yylexreturn{BEGIN_REPEAT_FLEX}}" );@]@;
+ @[TeX_( " /yybreak@@{/yylexreturn{BEGIN_REPEAT_FLEX}}" );@]@;
@[TeX_( " /fi" );@]@;
- @[TeX_( "/fi/next" );@]@;
+ @[TeX_( "/yycontinue" );@]@;
@ @<Process braced code in the middle of section 2@>=
@[TeX_( "/def/flbracelevel{1}" );@]@;
@@ -492,17 +513,17 @@ These corrections can also be delayed. For the details, an interested reader may
@[TeX_( "/ifflin@@rule" );@]@;
@[TeX_( " /fldoing@@rule@@actiontrue" );@]@;
@[TeX_( " /flin@@rulefalse" );@]@;
- @[TeX_( " /def/next{/yylexreturnxchar/n}" );@]@;
+ @[TeX_( " /yybreak{/yylexreturnxchar/n}" );@]@;
@[TeX_( "/else" );@]@;
- @[TeX_( " /let/next/yylexnext" );@]@;
- @[TeX_( "/fi/next" );@]@;
+ @[TeX_( " /yybreak/yylexnext" );@]@;
+ @[TeX_( "/yycontinue" );@]@;
@ This action has been changed to accomodate the new grammar. The separator (\.{\yl})
is treated as an ordinary (empty) action.
@<Process a deferred action@>=
@[TeX_( "/ifflsf@@skip@@ws" );@]@;/* whitespace ignored, still inside a pattern */
@[TeX_( " /yylessafter{|}" );@]@;
- @[TeX_( " /let/next/yylexnext" );@]@;
+ @[TeX_( " /yybreak/yylexnext" );@]@;
@[TeX_( "/else" );@]@;
@[TeX_( " /flinc@@linenum" );@]@;
@[TeX_( " /fldoing@@rule@@actiontrue" );@]@;
@@ -510,8 +531,8 @@ is treated as an ordinary (empty) action.
@[TeX_( " /flcontinued@@actiontrue" );@]@;
@[TeX_( " /unput{/n}" );@]@;
@[TeX_( " /yyBEGIN{ACTION}" );@]@;
- @[TeX_( " /edef/next{/nx/yylexreturnxchar/n}" );@]@;
- @[TeX_( "/fi/next" );@]@;
+ @[TeX_( " /yybreak{/yylexreturnxchar/n}" );@]@;
+ @[TeX_( "/yycontinue" );@]@;
@ @<Process a comment inside a pattern@>=
@[TeX_( "/ifflsf@@skip@@ws" );@]@;
@@ -525,7 +546,7 @@ is treated as an ordinary (empty) action.
@ @<Decide whether to start an action or skip whitespace inside a rule@>=
@[TeX_( "/ifflsf@@skip@@ws" );@]@;
- @[TeX_( " /let/next/yylexnext" );@]@;
+ @[TeX_( " /yybreak/yylexnext" );@]@;
@[TeX_( "/else" );@]@;
@[TeX_( " /def/flbracelevel{0}" );@]@;
@[TeX_( " /flcontinued@@actionfalse" );@]@;
@@ -533,16 +554,16 @@ is treated as an ordinary (empty) action.
@[TeX_( " /ifflin@@rule" );@]@;
@[TeX_( " /fldoing@@rule@@actiontrue" );@]@;
@[TeX_( " /flin@@rulefalse" );@]@;
- @[TeX_( " /def/next{/yylexreturnxchar/n}" );@]@;
+ @[TeX_( " /yybreak@@{/yylexreturnxchar/n}" );@]@;
@[TeX_( " /else" );@]@;
- @[TeX_( " /let/next/yylexnext" );@]@;
+ @[TeX_( " /yybreak@@/yylexnext" );@]@;
@[TeX_( " /fi" );@]@;
- @[TeX_( "/fi/next" );@]@;
+ @[TeX_( "/yycontinue" );@]@;
@ @<Finish the line and/or action@>=
@[TeX_( "/ifflsf@@skip@@ws" );@]@;
@[TeX_( " /flinc@@linenum" );@]@;
- @[TeX_( " /let/next/yylexnext" );@]@;
+ @[TeX_( " /yybreak/yylexnext" );@]@;
@[TeX_( "/else" );@]@;
@[TeX_( " /def/flbracelevel{0}" );@]@;
@[TeX_( " /flcontinued@@actionfalse" );@]@;
@@ -551,11 +572,11 @@ is treated as an ordinary (empty) action.
@[TeX_( " /ifflin@@rule" );@]@;
@[TeX_( " /fldoing@@rule@@actiontrue" );@]@;
@[TeX_( " /flin@@rulefalse" );@]@;
- @[TeX_( " /def/next{/yylexreturnxchar/n}" );@]@;
+ @[TeX_( " /yybreak@@{/yylexreturnxchar/n}" );@]@;
@[TeX_( " /else" );@]@;
- @[TeX_( " /let/next/yylexnext" );@]@;
+ @[TeX_( " /yybreak@@/yylexnext" );@]@;
@[TeX_( " /fi" );@]@;
- @[TeX_( "/fi/next" );@]@;
+ @[TeX_( "/yycontinue" );@]@;
@ @<Start section 3@>=
@[TeX_( "/def/flsectnum{3}" );@]@;
@@ -596,26 +617,26 @@ The braces and the possible trailing whitespace will be dealt with by the typese
@ @<Determine if this is extended syntax or return a parenthesis@>=
@[TeX_( "/iffllex@@compat" );@]@;
- @[TeX_( " /def/next{/yyless{1}/flsf@@push/yylexreturnraw(}" );@]@;
+ @[TeX_( " /yybreak{/yyless{1}/flsf@@push/yylexreturnraw(}" );@]@;
@[TeX_( "/else" );@]@;
@[TeX_( " /ifflposix@@compat" );@]@;
- @[TeX_( " /def/next{/yyless{1}/flsf@@push/yylexreturnraw(}" );@]@;
+ @[TeX_( " /yybreak@@{/yyless{1}/flsf@@push/yylexreturnraw(}" );@]@;
@[TeX_( " /else" );@]@;
- @[TeX_( " /def/next{/yypushstate{EXTENDED_COMMENT}}" );@]@;
+ @[TeX_( " /yybreak@@{/yypushstate{EXTENDED_COMMENT}}" );@]@;
@[TeX_( " /fi" );@]@;
- @[TeX_( "/fi/next" );@]@;
+ @[TeX_( "/yycontinue" );@]@;
@ @<Determine if this is a parametric group or return a parenthesis@>=
@[TeX_( "/flsf@@push" );@]@;
@[TeX_( "/iffllex@@compat" );@]@;
- @[TeX_( " /def/next{/yyless{1}}" );@]@;
+ @[TeX_( " /yybreak{/yyless{1}}" );@]@;
@[TeX_( "/else" );@]@;
@[TeX_( " /ifflposix@@compat" );@]@;
- @[TeX_( " /def/next{/yyless{1}}" );@]@;
+ @[TeX_( " /yybreak@@{/yyless{1}}" );@]@;
@[TeX_( " /else" );@]@;
- @[TeX_( " /def/next{/yyBEGIN{GROUP_WITH_PARAMS}}" );@]@;
+ @[TeX_( " /yybreak@@{/yyBEGIN{GROUP_WITH_PARAMS}}" );@]@;
@[TeX_( " /fi" );@]@;
- @[TeX_( "/fi/next" );@]@;
+ @[TeX_( "/yycontinue" );@]@;
@[TeX_( "/yylexreturnraw(" );@]@;
@ @<Patterns for \flex\ lexer@>=
@@ -708,14 +729,14 @@ The braces and the possible trailing whitespace will be dealt with by the typese
@ @<Finish the repeat pattern@>=
@[TeX_( "/yyBEGIN{SECT2}" );@]@;
@[TeX_( "/iffllex@@compat" );@]@;
- @[TeX_( " /def/next{/yylexreturn{END_REPEAT_POSIX}}" );@]@;
+ @[TeX_( " /yybreak{/yylexreturn{END_REPEAT_POSIX}}" );@]@;
@[TeX_( "/else" );@]@;
@[TeX_( " /ifflposix@@compat" );@]@;
- @[TeX_( " /def/next{/yylexreturn{END_REPEAT_POSIX}}" );@]@;
+ @[TeX_( " /yybreak@@{/yylexreturn{END_REPEAT_POSIX}}" );@]@;
@[TeX_( " /else" );@]@;
- @[TeX_( " /def/next{/yylexreturn{END_REPEAT_FLEX}}" );@]@;
+ @[TeX_( " /yybreak@@{/yylexreturn{END_REPEAT_FLEX}}" );@]@;
@[TeX_( " /fi" );@]@;
- @[TeX_( "/fi/next" );@]@;
+ @[TeX_( "/yycontinue" );@]@;
@ @<Patterns for \flex\ lexer@>=
@@ -833,3 +854,19 @@ void define_all_states( void ) {
#include "fil_states.h"
#undef _register_name
+@ @<Catchall rule for the bootstrap lexer@>=
+@G(fs2)
+<*>. {@> @[TeX_( "/yyerrterminate" );@] @=}
+
+@ The drive expects this function to be defined but the bootstrap
+lexer has no need for it. We leave it in to appease the compiler.
+@<Auxilary code for the bootstrap \flex\ lexer@>=
+void define_all_states( void ) {
+ @<Collect state definitions for the bootstrap \flex\ lexer@>@;
+}
+
+@ @<Collect state definitions for the bootstrap \flex\ lexer@>=
+#define _register_name( name ) @[Define_State( #name, name )@]
+ /* The \flexsnstyle{INITIAL} state is generated automatically */
+#undef _register_name
+
diff --git a/support/splint/cweb/splint.w b/support/splint/cweb/splint.w
index e50e090c32..4bf32953ff 100644
--- a/support/splint/cweb/splint.w
+++ b/support/splint/cweb/splint.w
@@ -1,4 +1,4 @@
-% Copyright 2012-2020, Alexander Shibakov
+% Copyright 2012-2024, Alexander Shibakov
% This file is part of SPLinT
%
% SPLinT is free software: you can redistribute it and/or modify
@@ -13,19 +13,12 @@
%
% You should have received a copy of the GNU General Public License
% along with SPLinT. If not, see <http://www.gnu.org/licenses/>.
-%
-\newwrite\gindex % index entries generated by the various parsers, \prodstyle{...} commands, etc.
-%
+
\input limbo.sty
\input frontmatter.sty
\def\optimization{5}
\input yy.sty
\modenormal
-\input noweb.sty
- \xreflocaltrue
- \readlxrefs % read the reference file if exists before any sections appear
- \newwrite\xrefstream % references for noweb like style of sectioning.
- \immediate\openout\xrefstream=\jobname.xxr
% multi-column output
\input dcols.sty
\topskip=9pt % this is a purely aesthetic choice, also negating the \raggedbottom
@@ -71,9 +64,9 @@
\defreserved{Y}{\.{Y}}
\showlastactiontrue
+\initauxstream
@**Introduction.
-\setupfootnotes
\splint\footnote{I was tempted to call the package {\tt ParLALRgram}
which stands for Parsing {\sc LALR} Grammars or {\tt PinT} for
`Parsing in \TeX' but both sounded too generic.} (Simple Parsing and
@@ -117,9 +110,9 @@ output is some very rudimentary post- and pre-processing.
Our main concern is thus \CWEAVE\ that not only pretty prints the
program but also creates an index, cross-references all the
sections, etc. Getting \CWEAVE\ to pretty print a language other than
-\Cee\ requires some additional attention. A true digital warrior would
+\Cee\ requires some additional effort. A true digital warrior would
probably try to decipher \CWEAVE's output `in the raw' but, alas, my
-WebFu is not that strong. The loophole comes in the form of a rarely
+(C)WebFu is not that strong. The loophole comes in the form of a rarely
(for a good reason) used \CWEB\ command: the verbatim (\.{@@=...@@>})
output. The material to be output by this construct undergoes minimal
processing and is put inside \.{\\vb\{}$\ldots$\.{\}}. All that is
@@ -134,9 +127,9 @@ merely a brief overview of the approach.
Every \CWEB\ document is split into {\em sections}, each divided into
three parts (any one of which can be empty): the \TeX\ part, the middle part, and
-the \Cee\ part (which should more appropriately be called the {\em code
-part\/}). The code part of each\footnote{With the exception of the nameless \.{@@c}
-sections.} section carries a name for cross referencing
+the \Cee\ part (which should more appropriately be called the {\em code\/} or
+the {\em program\/} part). The \Cee\ part of each\footnote{With the exception of the
+nameless \.{@@c} (or \.{@@p}) sections.} section carries a name for cross referencing
purposes. The sections themselves are automatically numbered by \CWEAVE\ and
their code parts may be referenced from other sections, as well
as included in other sections' code parts using \CWEB's cross referencing
@@ -151,7 +144,7 @@ The original \CWEB\ macros (from \.{cwebmac.tex}) used the numbers
generated by \CWEAVE\ to refer to specific sections. This was true
for the table of contents, as well as the index entries. The macros
used by \splint\ adopt a different convention, proposed by N.~Ramsey
-for his literate programming software, \noweb. In the new system
+for his literate programming software \noweb. In the new system
(which will be referred to as the \noweb\ style of cross referencing),
each section is labelled by the page number where it starts and an
alphabetic character that indicates the order of appearance of the
@@ -163,10 +156,13 @@ section.
The top level (\.{@@**}) sections, introducing
major portions of the code have also been given more prominent
-appearance and carry a chapter number in addition to the the \noweb\
-style section number (the latter is used for cross references, as the
-chapter number gives no indication as to where the said chapter is
-located).
+appearance. They display the chapter number using a large typeface
+and omit the marginal section reference. References to such sections
+are typeset as {\it cnnn\/} where {\it nnn\/} represents the chapter
+number. While such references obscure the page number, hopefully one keeps
+the number of chapters, as well as such references, small. This
+modification improves the appearance of the first chapter pages.
+
\CWEB\ also generates an {\em index\/} of all the identifiers (with
some exceptions, such as single letter names) appearing in the
@@ -247,7 +243,7 @@ important application.
@*1 Parsing and parsers.
At an abstract level, a {\em parser@^parser@>\/} is just a routine
-that transforms text. Naturally, not every possible tranformation is
+that transforms text. Naturally, not every possible transformation is
beneficial, so, informally, the value of a parser lies in its ability
to expose some {\em meaning\/} in the text. If valid texts are reduced
to a small finite set (while each text can be arbitrarily long) one
@@ -342,7 +338,7 @@ longer strings.
Computing $m$ and $n$ above now reduces to incrementing an appropriate
variable upon exiting the corresponding function. More important,
-however, is the observation that this parsing algorithm can be
+however, is the observation that this parser specification can be
extracted from the grammar in a very straightforward fashion. To
better illustrate the r\^ole of the grammar in the choice of the
parsing algorithm, consider the following syntax for the same
@@ -364,10 +360,10 @@ astring:
\noindent While the language is unchanged, so the algorithm
above still works, the lookahead tokens are not {\em immediately\/}
apparent upon looking at the productions. Some preprocessing must take
-place before one can decide on the choice of parser states and the
-appropriate lookahead tokens. Such algorithms indeed exist and result
-in what is known as an {\sc LR} parser for the fragment above
-(actually, a simpler {\sc LALR} parser may be built for this
+place before one can decide on the choice of the parser states and the
+appropriate lookahead tokens. Such parser generating algorithms
+indeed exist and will produce what is known as an {\sc LR} parser
+for the fragment above (actually, a simpler {\sc LALR} parser may be built for this
grammar\footnote{Both of these algorithms will use the parser stack
more efficiently, effectively resolving the `call stack depth' issue
mentioned earlier.}). One can see that some grammar types may make
@@ -411,11 +407,12 @@ non_terminal:
@g
@ $\ldots$ if the syntax is correct.
-In case it is a bit off (note the missing colon after \.{whoops}), the parser will give up and
+In case it is a bit off (note the missing colon after \.{whoops} below), the parser will give up and
you will see a different result. The code in the fragment below is easily
recognizable, and some parts of it (all of \Cee\ code, in fact) are
still pretty printed by \CWEAVE. Only the verbatim portion is left
-unprocessed.
+unprocessed. The layout of the original code is reproduced unchanged, including the braces and production separators (i.e.\
+\.{\yl}) normally removed by the parser for presentation purposes.
@<A silly example@>=
@G
whoops
@@ -478,7 +475,7 @@ automatically from the \CWEB\ source file by the
\CWEAVE\ processing stage. All of these definitions can be
overwritten to get the desired output (say, one might want to typeset
\.{ID} in a roman font, as `identifier'; all that needs to be done to
-make this possible is a macro that says \.{\\prettywordpair\{ID\}\{\{\\rm
+make this possible is to provide a macro that says \.{\\prettywordpair\{ID\}\{\{\\rm
identifier\}\}} in an appropriate namespace (usually
\.{\\hostparternamespace})). The file \.{btokenset.sty} input above
contains a number of such definitions.
@@ -567,11 +564,11 @@ the file below.
@*1 On debugging. This concludes a short introduction to the \bison\
grammar pretty printing using this macro collection. It would be
-incomplete, however, without a short reference to debugging\footnote{Here
-we are talking about debugging the output produced by \CWEAVE\ when
+incomplete, however, without a short reference to debugging\footnote{At
+the moment we are discussing debugging the output produced by \CWEAVE\ when
the included \bison\ parser is used, {\it not\/} debugging parsers
written with the help of this software: the latter topic is covered in more
-detail later on}. There is a
+detail later on.}. There is a
fair amount of debugging information that the macros can output,
unfortunately, very little of it is tailored to the {\em use\/} of the
macros in the \bison\ parser. Most of it is designed to help build a
@@ -653,7 +650,7 @@ identifier determines its association with the appropriate set.}.
a collection of parsers, usually derived from a common set of
productions, and sharing a common lexer. As the name suggests, the
parsers in the collection are tried in order until the input is parsed
-successfully or every parser has been tried. This terminology may be the
+successfully or every parser has been tried. This terminology may become a
source of some confusion, since each parsing algorithm used by \bison\
maintains several stacks. We will always refer to them by naming a specific
task the stack is used for (such as the {\em value stack\/} or the
@@ -687,7 +684,7 @@ productions.
\aterm{term} in a narrow sense, an `element' of a grammar. Instead of
a long winded definition, an example, such as \prodstyle{ID} should
suffice. Terms are further classified into {\it terminals\/} (tokens)
-and {\it nonterminals\/} (which can be intuitively thought of as
+and {\it nonterminals\/} (which may be intuitively thought of as
composite terms).
\aterm{token} in short, an element of a set. Usually encoded as an
@@ -734,7 +731,7 @@ some attention, as well. There are a number of excellent programs
written to automate this step in much the same fashion as \bison\
automates the generation of parsers. One such tool, \flex, though
(in the opinion of this author) slightly lacking in the simplicity and
-elegance as compared to \bison, was used to implement the lexer for
+elegance when compared to \bison, was used to implement the lexer for
this software suite. Lexing in \TeX\ will be discussed in considerable
detail later in this manual.
@@ -750,7 +747,7 @@ syntax-directed translation} (which requires an appropriate
abstraction to represent \bison's actions inside \TeX). We shall
begin by discussing the parsing process itself.
-@*1 Arrays, stacks and the parser.
+@*1 Arrays, stacks, and the parser.
Let us briefly examine the programming environment offered by \TeX.
Designed for typesetting, \TeX's remarkable language
provides a layer of macro processing atop of a set of commands that
@@ -826,7 +823,9 @@ implementation). Since stacks pop up and disappear frequently (what
else are stacks to do?), list macros are usually used to store
them. The optimized parser uses a separate \.{\\count} register to
keep track of the top of the stack in the corresponding associative
-array.
+array\footnote{Which means, unfortunately, that making such fully optimized
+parser {\em reentrant\/} would take an extraordinary amount of effort. Hence,
+if reentrancy is a requirement, stacks are better kept inside list macros.}.
Let us now switch our attention
to the code that implements the parser and scanner {\it functions\/}.
@@ -1175,8 +1174,10 @@ token and move on but what if this was a control sequence? After all,
just as easily as \.{\\string} makes a sequence into characters,
\.{\\csname}$\,\ldots\,$\.{\\endcsname} pair will make any sequence of
characters into a control sequence so determining the end the character
-sequence produced by \.{\\string} may prove impossible. Huh~$\ldots$
-
+sequence produced by \.{\\string} may prove impossible.
+$$
+\hbox{Huh~$\ldots$}
+$$
What we need is a backup mechanism: keeping a copy of the
token sequence ahead, one can use \.{\\string} to see whether
the next token is a real
@@ -1233,7 +1234,7 @@ or even {\it tokener}), discussed in the next section.
@*1 Lexing in \TeX. In a typical system that uses a parser to process
text, the parsing pass is usually split into several stages: the raw
input, the lexical analysis (or simply {\it lexing}), and the parsing
-proper. The {\it lexing\/} (also called {\it scanning}, we use these
+proper. The {\it lexing\/} pass (also called {\it scanning}, we use these
terms interchangeably) clumps various sequences of characters into
{\it tokens\/} to facilitate the parsing stage. The reasons for this
particular hierarchy are largely pragmatic and are partially historic
@@ -1242,7 +1243,7 @@ phases, as well, although it usually isn't).
If one recalls a few basic facts from the formal language theory, it
becomes obvious that a lexer, that parses {\it regular\/} languages,
-can (theoretically) be replaced by an {\sc LALR} parser, that parses {\it
+can be (in theory) replaced by an {\sc LALR} parser, that parses {\it
context-free\/} ones (or some subset thereof, which is
still a super set of all regular languages). A common justification given for
creating specialized lexers is efficiency and speed. The
@@ -1266,7 +1267,10 @@ matching input is accepted. The only straightforward way to do this
with a traditional parser is to parse longer and longer inputs again
and again. While this process can be optimized to a certain degree,
the fact that a parser has a {\it stack\/} to maintain limits its
-ability to back up.
+ability to back up\footnote{It should be also mentioned that the fact that
+the lexing pass takes place prior to the parser consuming the resulting tokens
+allows one to process some grammars that are not context free. See, for example
+the {\em parser hack\/} used to process |typedef|s in \Cee.}.
As an aside, the mechanism by which \CWEB\ assembles its `scraps'
into chunks of recognized code is essentially iterative lexing,
@@ -1450,7 +1454,7 @@ altering the grammar mentioned above apply in this case, as well, only
at the `lexical analysis level'. At a minimum, the set of tokens
matched by the scanner would have to be altered.
-A much more satisfying approach involves inserting the hints at the input stage and
+A much more satisfying approach, however, involves inserting the hints at the input stage and
passing this information to the scanner and the parser as part of the token
`values'. The hints themselves can masquerade as characters ignored by the scanner
(white space\footnote{Or even the `intercharacter space', to make the
@@ -1482,7 +1486,8 @@ This is exactly what the scanner produced by the tools in this package
does: along with the main stream of tokens meant for the parser, it
produces two\footnote{There would be no difficulty in splitting either
of these streams into multiple `substreams' by modifying the stream
-extraction macros accordingly.} hidden streams (called the \.{\\yyformat} stream and
+extraction macros accordingly.} hidden streams\namedspot{parser.streams}
+(called the \.{\\yyformat} stream and
the \.{\\yystash} stream) and provides the parser with two
strings (currently only strings of digits are used although arbitrary
sequences of \TeX\ tokens can be used as pointers) with the promise
@@ -1490,10 +1495,13 @@ that {\it all the `hints' between the beginning of the corresponding
stream and the point labeled by the current stream pointer appeared
among the characters up to and, possibly, including the ones matched
as the current token}. The macros to extract the relevant parts of the
-streams (\.{\\yyreadfifo} and its cousins) are provided for the
+streams (\.{\\consumelistupto} and its cousins) are provided for the
convenience of the parser designer.
-The \.{\\yystash} stream collects all the typesetting commands inserted by
+What the parser does with these pointers and the information they provide, is
+up to the parser designer (the parsers for \flex\ and \bison\ syntax
+in this package use somewhat different strategies).
+The \.{\\yystash} stream currently collects all the typesetting commands inserted by
\CWEB\ to be possibly used in displaying the action code in \bison\
productions, for example. Because of this, it may appear in somewhat
unexpected places, introducing spaces where the programmer did not
@@ -1505,10 +1513,10 @@ The interested reader can consult the input routine macros in
\.{yyinput.sty} for the
details of the internal representation of the streams.
-In the interest of full disclosure, let me point out that this simple
+In the interest of full disclosure, it should be pointed out that this simple
technique introduces a significant strain on \TeX's
computational resources: the lowest level macros, the ones that handle
-character input and are thus executed (sometimes multiple times), for
+character input and are thus executed (in some cases multiple times), for
{\it every\/} character in the input stream are rather complicated and
therefore, slow. Whenever the use of such streams is not desired a simpler
input routine can be written to speed up the process (see
@@ -1517,9 +1525,13 @@ input routine can be written to speed up the process (see
Finally, while probably not directly related to the present
discussion, this approach has one more interesting feature: after the
parser is finished, the parser output and the streams exist
-`statically', fully available for any last minute preprocessing or for
+`statically', fully available for any last minute postprocessing or for
debugging purposes, if necessary\footnote{One may think of the parser output
-as an {\it executable abstract syntax tree (AST)}.}. Under most circumstances, the parser
+as an {\it executable abstract syntax tree\/} (\AST\ or \EAST\ if one
+likes cute abbreviations, or even e\AST\ for an extra touch of modernity).
+This parser feature is used to implement the facility that allows easy referencing of
+productions in the section that implements the action code for one. See \.{yyunion.sty}
+and the source of this file (\.{splint.w}) for details.}. Under most circumstances, the parser
output is `executed' and the macros in the output are the ones reading
the various streams using the pointers supplied at the parsing stage
(at least, this is the case for all the parsers supplied with the
@@ -1532,7 +1544,9 @@ how the tables produced by \bison\ get converted into \TeX\ {\it macros\/}
that drive the parser in {\it \TeX}.
The tables that drive the \bison\ input parsers
-are collected in \.{\{b,d,f,g,n\}yytab.tex} and \.{small\_tab.tex}. Each
+are collected in \.{\{b,d,f,g,n\}yytab.tex}, \.{small\_tab.tex} and other similarly named
+files\footnote{Incidentally, one of the names above is not used anymore. See the \.{cweb}
+directory after a successful build to find out which. Aren't footnotes great?!}. Each
one of these files contains the tables that implement a specific parser
used during different stages of processing.
Their exact function is well explained
@@ -1584,30 +1598,34 @@ it after \.{\\classexpand} (such sequences are usually prepared by the
\bison\ from your grammar).
You can give a case a readable label (say, \.{brackets}) and enclose
-this label in \.{\\raw}$\ldots$\.{\\raw}. A word of caution: an `\.{a}'
-inside of \.{\\raw}$\ldots$\.{\\raw} (which is most likely an
-\.{a}$_{11}$ unless you played with the category codes before loading the
-\.{\\switchon} macros) and the one outside it are two different
+this label in \.{\\raw}$\ldots$\.{\\raw}. A word of caution: an
+`\.{a}' inside of \.{\\raw}$\ldots$\.{\\raw} (which is most likely an
+\.{a}$_{11}$ unless you played with the category codes before loading
+the \.{\\switchon} macros) and the one outside it are two different
characters, as one is no longer a letter (category 11) in the eyes of
\TeX\ whereas the other one still is. For this reason one should not
-use characters other than letters in h\.{\{}is\.{,}er\.{\}} state
-{\em names}: the way a state picks an action does not distinguish between,
+use characters other than letters in h\.{\{}is\.{,}er\.{\}} state {\em
+names\/} if such characters can form tokens by themselves:
+the way a state picks an action does not distinguish between,
say, a `\.{(}' in `\.{(letter)}' and a stand alone `\.{(}' and may
pick an action that you did not intend\footnote{One way to mitigate
this is by putting such named states at the end of the switch, {\em
-after\/} the actions labelled by the standalone characters.}.
-This applies even if `\.{(}'
-is not among the characters explicitly inserted in the state macro: if
-an action for a given character is not found in the state macro, the
-\.{\\switchon} macro will insert a current \.{\\default} action
-instead, which most often you would want to be \.{\\yylex} or
-\.{\\yyinput} (i.e.\ skip this token). If a single `\.{(}' or `\.{)}' matches
-the braced group that follows `\.{(letter)}' chaos may ensue (most
-likely \TeX\ will keep reading past the \.{\\end} or \.{\\yyeof} that
-should have terminated the input). Make the names of character
-categories as unique as possible: the \.{\\switchon} is simply a
-string matching mechanism, with the added differentiation between
-characters of different categories.
+after\/} the actions labelled by the standalone characters. There is nothing
+special about non-letter characters, of course. To continue the \.{letter}
+example, placing a state named \.{let} {\em after\/} the \.{letter} one
+will make it essentially invisible to the switch macros for the reasons
+explained before this footnote.}. This applies even if `\.{(}' is not among
+the characters explicitly
+inserted in the state macro: if an action for a given character is not
+found in the state macro, the \.{\\switchon} macro will insert a
+current \.{\\default} action instead, which most often you would want
+to be \.{\\yylex} or \.{\\yyinput} (i.e.\ skip this token). If a
+single `\.{(}' or `\.{)}' matches the braced group that follows
+`\.{(letter)}' chaos may ensue (most likely \TeX\ will keep reading
+past the \.{\\end} or \.{\\yyeof} that should have terminated the
+input). Make the names of character categories as unique as possible:
+the \.{\\switchon} is simply a string matching mechanism, with the
+added differentiation between characters of different categories.
Finally, the construct \.{\\statecomment}{\it
anything\/}\.{\\statecomment} allows you to insert comments in the
@@ -1620,15 +1638,14 @@ makes the debugging information difficult to decipher). The debugging
mode for the lexer implemented with these macros is activated by
\.{\\tracedfatrue}.
-The functionality of the \.{\\switchon} (as well as the \.{\\switchonwithtype}, which
-is capable of some rudimentary type checking) macros (for `historical'
-reasons, one can also use \.{\\action} as a synonym for the latter) has been
-implemented in a number of other macro packages (see \cite[Fi] that
-discusses the well-known and widely used \.{\\CASE} and \.{\\FIND}
-macros). The macros in this collection have the additional property
-that the only assignments that persist after the \.{\\switchon}
-completes are the ones performed by the user code inside the selected
-case.
+The functionality of the \.{\\switchon} (as well as the
+\.{\\switchonwithtype}, which is capable of some rudimentary type
+checking) macros has been implemented in a number of other macro
+packages (see \cite[Fi] that discusses the well-known and widely used
+\.{\\CASE} and \.{\\FIND} macros). The macros in this collection have
+the additional property that the only assignments that persist after
+the \.{\\switchon} completes are the ones performed by the user code
+inside the selected case.
This last property of the switch macros is implemented using another
mechanism that is part of this macro suite: the `subroutine-like'
@@ -1662,7 +1679,10 @@ be able to write parsers of arbitrary sophistication:
value of the $n$-th term of the rule's right hand side, $n>0$. The left
hand side of a production is accessed through \.{\\yyval}. A
convenient shortcut is \.{\\yy0\{{\rm \TeX\space material}\}} which
-will expand (as in \.{\\edef}) the `\TeX\ material' inside the braces. Thus, a simple way
+will expand (as in \.{\\edef}) the `\TeX\ material' inside the braces and store the result
+in \.{\\yyval} (note that this only works if a sequence of \.{0}s, possibly followed or preceeded
+by spaces are the only tokens between \.{\\yy} and the opening braces; see the discussion of
+\.{\\bb} macros below for a description of what happens in other cases). Thus, a simple way
to concatenate the values of the first two production terms is
\.{\\yy0\{\\the\\yy(1)\\the\\yy(2)\}}. The included \bison\
parser can also be used to provide support for `symbolic names',
@@ -1673,8 +1693,9 @@ however.
There is also a \.{\\bb$\,n$} macro, that has no analogue in the
`real' \bison\ parsers, and provides access to the term
-values in the `natural order' (e.g.~\.{\\bb1} is the last term read). Its
-intended use is with the `inline' rules (see the main parser for
+values in the `natural order' (e.g.~\.{\\bb1} is the last term in the part of
+the production preceeding the action). Its intended use is with the `inline'
+rules (see the main parser for
such examples). As of version \.{3.0} \bison\ no longer outputs
|yyrhs| and |yyprhs|, which makes it impossible to produce the
|yyrthree| array necessary for processing such rules in the `left to right'
@@ -1682,13 +1703,41 @@ order. One might also note that the new notation is better suited for
the inline rules since the value that is pushed on the stack is that
of \.{\\bb0}, i.e.~the term implicitly inserted by \bison. Be aware
that there are no \.{\\bb[$\cdot$]} or \.{\\bb($\cdot$)} versions of
-these macros, for obvious reasons. A less obvious feature of this
+these macros, for obvious reasons\footnote{The obvious reason is the mechanism
+used by \.{\\yy[$\cdot$]} and \.{\\yy($\cdot$)} to make them expandable.
+These macros are basically references to the appropriate token registers. Since
+the \.{\\bb} macros were designed for the environment where \.{\\yylen} is unknown,
+establishing such references before the action is executed is not possible. A
+less obvious reason is the author's lazy approach.}. A less obvious feature of this
macro is its `nonexpandable' nature. This means they cannot be used
-inside \.{\\edef}. Thus, the most common use pattern is
-\.{\\bb$\,n$\{\\toks$\,m$\}} with a subsequent expansion of
-\.{\\toks$\,m$}. Making these macros expandable is certainly possible
+inside \.{\\edef} (just like its \.{\\yy$\,n$} counterpart, it makes several
+assignments which will not be executed by \.{\\edef}).
+Thus, the most common use pattern is \.{\\bb$\,n$\{\\toks$\,m$\}} (where $n>0$)
+with a subsequent expansion of \.{\\toks$\,m$}\footnote{Similar to how \.{\\yy$\,n$} macros
+work, whenever $n>0$, this pattern simply puts the contents of the braced group
+that follows in front of a (braced) single expansion of the appropriate
+value on the stack. If, as in the example above, the contents of the
+braced group are \.{\\toks$\,m$}, this effectively stores the value of the braced group in
+the token register. In the case $n=0$ the meaning is different:
+the stack value {\em corresponding to the implicit term\/} becomes the expanded (by \.{\\edef})
+contents of the braced group following \.{\\bb$\,n$}.}.
+Making these macros expandable is certainly possible
but does not seem crucial for the intended limited use pattern.
+Finally, the scripts included with \splint\ include a postprocessor
+(see the appropriate~\.{Makefile} for further details) that allows the
+use of the `native' \bison\ term references (i.e.\ of the form
+\.{\char`\$}$\ldots$) to access the value stack\footnote{Incidentally,
+\bison\ itself uses a preprocessor (\.{M4}) to turn its term references
+into valid \Cee.}. Utilizing the postprocessor allows any syntax for
+term references used by \bison\ to be used inside \.{TeX}$\ldots$ \Cee\ macros.
+In this case a typical
+idiom is \.{\\the\char`\$[term\_name]} to get the value of
+\prodstyle{term_name}. While storing a new value for the term (i.e.\
+modifying the value stack) is also possible, it is not very
+straightforward and thus not recommended. This applies to all forms of
+term references discussed above.
+
Naturally, a parser writer may need a number of other data
abstractions to complete the task. Since these are highly dependent on
the nature of the processing the parser is supposed to provide, we
@@ -1703,7 +1752,8 @@ most importantly, to create `reentrant' parsers that can, e.g.\ call
{\it themselves\/} recursively.
@*1 `Optimization'.
-\namedspot{optimization}By default, the generated parser and scanner keep all of their tables
+\namedspot{optimization}By default, the generated parser and scanner
+keep all of their tables
in separate token registers. Each stack is kept in a single macro (this
description is further complicated by the support for parser {\it
namespaces\/} that exists even for unoptimized parsers but this
@@ -1806,7 +1856,8 @@ appropriate terms in a production. If mathematics pays your bills, use
\let\hostparsernamespace\mainnamespace % to typeset examples in the text
% properly
-@**Index. This section is, perhaps, the most valuable product of
+@**Index. \global\let\secrangedisplay\empty% do not show the current section range anymore
+This section is, perhaps, the most valuable product of
\CWEB's labors. It lists references to definitions (set in {\it
italic}) as well as uses for each \Cee\ identifier used in the
source. Special facilities have been added to extend the indexing to
@@ -1845,7 +1896,7 @@ appeared on the left hand side of a production. A production:
}%
\beginmprod
left_hand_side:
- term.1 term.2 term.3 \{\stashed{|TeX_("/do/something/yy(1)");|}\}
+ term.1 term.2 term.3 \{\stashed{|TeX_("/do/something/with/yy(1)");|}\}
\endmprod
inside the \TeX\ part of a \CWEB\ section will generate several
index entries, as well, including the entries for any
@@ -1865,20 +1916,18 @@ available, thus avoiding referencing the same token twice).
\TeX\ control sequences are listed following the index of all \bison\ and \flex\
entries. The different sections of the index are separated by a {\it dinkus\/}
-(\dinkus). Since it is nearly impossible to determine at what point a
+(\dinkus)@^dinkus (\dinkus)@>. Since it is nearly impossible to determine at what point a
\TeX\ macro is defined (and most of them are defined outside of the
\CWEB\ sources), only their uses are listed (to be more precise, {\it
every\/} appearance of a macro is assumed to be its use). In a few cases, a
`graphic' representation for a control sequence appears in the index (for
-example, {\let\writetexidxentry\writetextxtidxentry
-\def\texnspace{texline}\def\texispace{index}\inlineTeXx{/getfirst}} represents
+example, \texref{/getfirst} represents
{\let\writetexidxentry\writetextxtidxentry
\def\texnspace{other}\def\texispace{other}\inlineTeXx{/getfirst}$\!$}).
The index entries are ordered alphabetically. The
latter may not be entirely obvious in the cases when the `graphical
representation' of the corresponding token manifests a significant
-departure from its string version (such as
-{\let\writetexidxentry\writetextxtidxentry|TeX_("/yy(1)");|}
+departure from its string version (such as \texref{/yy(1)}
instead of {\def\texnspace{other}\def\texispace{other}%
\let\writetexidxentry\writetextxtidxentry
|TeX_("/yy(1)");|$\!$}). Incidentally, for the examples on this page
@@ -1886,11 +1935,8 @@ instead of {\def\texnspace{other}\def\texispace{other}%
the `graphic' as well as `text' versions of the control sequence are
indexed. It is instructive to verify that their location in the index
corresponds to the `spelling' of their visual representation (thus,
-{\let\writetexidxentry\writetextxtidxentry
-\def\texnspace{texline}\def\texispace{index}\inlineTeXx{/getfirst}}
-appears under `p'). One should also be aware that the indexing of some terms has
-been suppressed, since they appear too often.
-\unsetfootnotes % this way the footnote stream is not affected by the extra index pages
+\texref{/getfirst} appears under `p'). One should also be aware that
+the indexing of some terms has been suppressed, since they appear too often.
% TODO: explain the visibility system. Note the anomalous order of \prodstyle{term.1}
% vs.~\prodstyle{term0} due to the dot in \.{term.1}, which is otherwise invisible. Underscore the
% importance of following a consistent naming scheme, including the `stringized' versions
@@ -1899,15 +1945,5 @@ been suppressed, since they appear too often.
@q the lack of control over the generation of \CWEB's index; the correct order @>
@q of index entries depends on the placement of this inclusion @>
@i alphas.hx
-
-\closeout\gindex
-\termindexfalse % do not attach indexing entries to the terms in the index, or the section list
-\def\next{\expandafter\eatone\string}
-\edef\unindexable{{\next\the}{\next\nx}{\next\yy}{\next\yylexnext}{\next\else}{\next\fi}{\next\yyBEGIN}{\next\next}}
-\input gindex.sty
-%\indexverbosetrue
-\let\inx\inxmod
-\let\fin\finmod
-\lxrefseparator % start generating section lists
-%\displaytokenrawtrue % so that the `nonstringified' version of the token is displayed as well
-\def\topofcontents{\null\vskip-3\baselineskip\centerline{C{\sc ONTENTS} (\sc\uppercase\expandafter{\title})}\medskip}
+\makeunindexablex{{\csstring\the}{\csstring\nx}{\csstring\yy}{\csstring\yylexnext}%
+ {\csstring\else}{\csstring\fi}{\csstring\yyBEGIN}{\csstring\next}}
diff --git a/support/splint/cweb/ssffo.w b/support/splint/cweb/ssffo.w
deleted file mode 100644
index 315bffc798..0000000000
--- a/support/splint/cweb/ssffo.w
+++ /dev/null
@@ -1,123 +0,0 @@
-@q Copyright 2012-2020, Alexander Shibakov@>
-@q This file is part of SPLinT@>
-
-@q SPLinT is free software: you can redistribute it and/or modify@>
-@q it under the terms of the GNU General Public License as published by@>
-@q the Free Software Foundation, either version 3 of the License, or@>
-@q (at your option) any later version.@>
-
-@q SPLinT is distributed in the hope that it will be useful,@>
-@q but WITHOUT ANY WARRANTY; without even the implied warranty of@>
-@q MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the@>
-@q GNU General Public License for more details.@>
-
-@q You should have received a copy of the GNU General Public License@>
-@q along with SPLinT. If not, see <http://www.gnu.org/licenses/>.@>
-\input limbo.sty
-\def\optimization{5}
-\input yy.sty
-\modenormal
-\let\oldN\N
-\let\N\textN
-\let\M\textM
-% uncomment the next line to leave the typesetting of tokens in its raw state.
-%\def\hostparsernamespace{[unreacheable]}
-\let\hostparsernamespace\mainnamespace
-\input btokenset.sty
-
-@** A simple scanner for \flex\ options.
-This is a `bare-bones' scanner for a subset of the `extended' \bison\
-grammar that parses some of the `extensions', namely, the
-\flex\ state declarations. It does not use the state mechanism
-itself, and is supposed to be used with the bootstrapping parser, even
-though this is not strictly necessary. It parses state declarations as
-long as they are separated into their own \CWEB\ sections and extracts
-the {\it names\/} of the states. The \flex\ scanner output `driver'
-does the rest after including the produced header file.
-
-If reusing the existing scanner for \bison\ were not a priority a
-proper way to design a scanner like this is to make it a subset of the
-existing scanner code. This way portions of the program would be made
-more reusable and the overall design made more consistent.
-@s TeX_ TeX
-@(ssffo.ll@>=
-@G
- @> @<Lexer definitions@> @=
-%{@> @<Lexer \Cee\ preamble@> @=%}
- @> @<Lexer options@> @=
-%%
- @> @<Regular expressions@> @=
-%%
-@g
-
-@ A couple of handy abbreviations to get started. Note that the
-definition of a letter is more restrictive in this case since we only
-need to grab the states of an existing \bison\ lexer. For a
-bootstrapping scanner like this it is beneficial to fail early while
-scanning something that is not in its attention domain: it results in
-faster bootstrapping and lower chance of accidentally parsing
-something that should not have been. Making the syntax and the grammar
-more restrictive helps to acheive this, as well as makes the overall
-design simpler.
-@<Lexer definitions@>=
-@G(fs1)
-letter [_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]
-id {letter}({letter}|[-0-9])*
-@g
-
-@ @<Lexer \Cee\ preamble@>=
-
-#include <stdint.h>
-#include <stdbool.h>
-
- void define_all_states( void ){}
-
-@ A standard combination of options to match the \TeX\ code that
-drives the scanner.
-@<Lexer options@>=
-@G
-%option bison-bridge
-%option noyywrap nounput noinput reentrant
-%option noyy_top_state
-%option debug
-%option stack
-%option outfile="ssffo.c"
-@g
-
-@ There are not that many regular expressions to list, since the range
-of tokens recognized by this routine is not very wide.
-@<Regular expressions@>=
- @<Scan white space@>@;
- @<Scan identifiers@>@;
-
-@ White space skipping.
-@<Scan white space@>=
-@G(fs2)
-[ \f\n\t\v] {@> @[TeX_( "/yylexnext" );@]@=}
-@g
-
-@ The rest of it are either identifiers or \.{\%}-options. The typesetting of
-the appropriate \bison\ tokens below was arranged by inputting \.{btokenset.sty} and
-relying on the pretty-printing macros for {\it \TeX} to do their job.
-@<Scan identifiers@>=
-@G(fs2)
-{id} {@> @<Return an identifier@> @=}
-"%x" {@> @[TeX_( "/yylexreturnptr{FLEX_STATE_X}" );@] @=}
-"%s" {@> @[TeX_( "/yylexreturnptr{FLEX_STATE_S}" );@] @=}
-. {@> @<React to a bad character@> @=}
-@g
-
-@ @<React to a bad character@>=
- @[TeX_( "/iftracebadchars" );@]@;
- @[TeX_( " /yycomplain{invalid character(s): /the/yytext}" );@]@;
- @[TeX_( "/fi" );@]@;
- @[TeX_( "/yylexreturn{$undefined}" );@]@;
-
-@ The lexer returns standard \.{\\yyunion} types.
-@<Return an identifier@>=
- @[TeX_( "/edef/next{/yylval{{/the/yytextpure}{/the/yytext}" );@]@;
- @[TeX_( " {/the/yyfmark}{/the/yysmark}}}/next" );@]@;
- @[TeX_( "/yylexreturn{ID}" );@]@;
-
-@** Index.
-\def\TeXx{\TeX\ material} \ No newline at end of file