summaryrefslogtreecommitdiff
path: root/support/splint/examples/xxpression/xymmap.sty
blob: e5576ee9cd28c50a6b2e78b209952c79a318fa49 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
% Copyright 2012-2022, Alexander Shibakov
% This file is part of SPLinT
%
% SPLinT is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% SPLinT is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with SPLinT.  If not, see <http://www.gnu.org/licenses/>.

% assigning symbolic names to production terms (this is only a demonstration)

\def\makesymbols{%
      \restorecslist{symbols}\yyunion
      \toksa{}\toksb{}\toksc{}\toksd{}%
      \the\table
      \global\newsymswitch\newsymswitch
}

% symbolic reference name parser

\newtoks\newsymswitch
\newread\symnames

\newwrite\symbolicswitch

\def\inamespace{[intermediate]}%
\let\parsernamespace\inamespace
\let\hostparsernamespace\mainnamespace % purely for testing reasons
\pinittoks{}%
\input ptab.tex % this is the enhanced expression parser
\edef\tointermediateparser{%
    \let\noexpand\parsernamespace\noexpand\inamespace % switch to the new namespace
    \the\pinittoks % restore all the tables, tokens and constants, and stacks
    \let\noexpand\getcurrentparser\noexpand\tointermediateparser
}%
\settokens % this simply assigns values to tokens where the name of each token is taken out of yytname ...
\input xxpression.tok                     % this will set up token equivalences in the namespace above ...
                                          % those are the values gleaned during the bootstrapping stage.
                                          % in the general case, one needs to run a bootsrapping (or similar)
                                          % parser to extract the token information.
                                          % this is only needed if the bison file contains a definition that
                                          % lists both the idenitifier and a string as names for a token but the grammar
                                          % uses the identifier version at least once:
                                          % (say, %token IDENTIFIER "identifier"; is used as well as
                                          %       ...
                                          %       token:
                                          %           IDENTIFIER       { ... }
                                          %       ...
                                          %  see the included xxpression.w)
\optimizeall % this is necessary for correct rule listing in the output stage:
             % otherwise \fgetelemof will use the current value of the \yy... token registers which
             % will hold the values of the full parser that is loaded next
\newsymswitch{}%
\listrules                                % ... to be used while listing the rules
% note that we do not bother to set up a lexer for this parser (even though we already have one and the
% \optimizeall macro above will create a set of associative tables for it---this is merely an unwanted
% sideffect); after the rules have been listed, the intemediate parser in no longer needed.
%\showthe\newsymswitch
\def\fullnamespace{[full]}% this is the parser that parses the bison grammar from a raw
                          % bison file; it can play a role of the bootstrap parser for
                          % the grammar above, as well, since its input is a complete
                          % bison file; note that it cannot be a bootstrap parser for itself
                          % because it will reject any input that does not form a complete
                          % bison file; this is why a special grammar was created that includes
                          % only a small subset of the full set of productions (%token rules only) to
                          % serve as a bootstrap grammar.
%\tomainparser % this will set the value of \setflexstates, so that, if the lexer initialization
               % below is omitted, the \setflexstates macro can still be used to correctly set the
               % lexer states
\let\parsernamespace\fullnamespace
\pinittoks{}% %%
\input cweb/fyytab.tex
\input cweb/ltab.tex % we reinitialize the lexer out of necessity:
                                      % \collecttokennames needs to know how to switch
                                      % between two lexer/parser environments so both states
                                      % have to be preserved; if one is sure that
                                      % grammar_declarations will not used in the productions
                                      % part of the file, this can simply be disabled
\settokens
\setflexstates % the main lexer can be reused in this case; the states still need to be set up
\input bo.tok % set up the tokens for the bison grammar parser
\newparserstate
\newlexerstate
\newlexerstateextra
%
\setnulstack{yyirulestack}%
%
\edef\tofullparser{%
    \let\noexpand\parsernamespace\noexpand\fullnamespace % switch to the new namespace
    \the\pinittoks % restore all the tables, tokens and constants, and stacks
    \let\noexpand\getcurrentparser\noexpand\tofullparser
}%
\optimizeall
\toksa{\input xxpp.y}% start building the parsing command
                   % this has to be done carefully, since all the characters input
                   % from the parser file have to be `harmless', so their categories
                   % have to be reset; in order for the parser to be able to stop,
                   % appropriate command sequences would have to be inserted at the end
\toksb{\yyeof\yyeof\endparseinput\endparse
    \let\yyinput\yyinputold
    \undoascii
    \ifyyparsefail
        \errmessage{could not process symbols}%
    \else  
        \tointermediateparser % the parsing is finished, so we have two very long strings:
                              %  o the rules of the hosted parser ([intermediate])
                              %  o the rules of the same parser just parsed
                              % these two strings are used to associate the symbolic names
                              % (which only exist in the second list) to the rule numbers and
                              % the relevant terms;
                              % switching the parse namespace above is done so that the term
                              % indices are looked up in the appropriate table
        %\showthe\table
        \makesymbols % list all the rules deriving explicit non-terminals
        %\showthe\newsymswitch
        \setexplicitinlinerules\newsymswitch % process implicit non-terminals resulting from inline actions
        %\showthe\newsymswitch
        \makesymrefs\newsymswitch % create the switch to be used by the parser (\yyparse)
    \fi
}%
% build the command to create the symbolic name switch
\toksc{\tofullparser\basicparserinit\bisonparserinit\bisonparserdatainit
    \let\yyinputold\yyinput
    \let\yyinput\yyinputtrivial % a demo of a stripped down, slightly faster input routine
    \doascii{11}\expandafter\yyparse}%
\edef\next{\the\toksc\the\toksa\relax\the\toksb}\next % \relax is to stop \TeX\ from trying to expand the file name further
                                                      % it is not flagged as a bad character  because it is part of the epilogue
\immediate\openout\symbolicswitch=\jobname.sns
%
\edef\next{\setsncommands{\def\noexpand\symswitch\hashletter1{\harmlesscomment^^J\noexpand\ifcase\hashletter1\relax
                                                                       \harmlesscomment^^J\the\setsncommands
                                                                       \noexpand\else\harmlesscomment^^J%
                                                                       \noexpand\fi\harmlesscomment^^J%
                                                                       }\harmlesscomment^^J^^J}}\next
\edef\next{\unsetsncommands{\def\noexpand\symswitchoff\hashletter1{\harmlesscomment^^J\noexpand\ifcase\hashletter1\relax
                                                                       \harmlesscomment^^J\the\unsetsncommands
                                                                       \noexpand\else\harmlesscomment^^J%
                                                                       \noexpand\fi\harmlesscomment^^J%
                                                                       }\harmlesscomment^^J^^J}}\next
{\newlinechar=`\^^J \immediate\write\symbolicswitch{\the\setsncommands\the\unsetsncommands}}%
\immediate\closeout\symbolicswitch
\tomainparser % go back to the main parser