summaryrefslogtreecommitdiff
path: root/support/splint/examples/symbols/symmap.sty
blob: 0a4afbc50a1bcf5eb52b7ed71b40f88cfdac0dec (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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
% 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)
% no attempt is made to make this code modular or namespace safe;
% the approach is not very elegant and can stand a lot of improvement;
% it was decided against such optimization to present a more explicit demonstration
% of the procedures

\def\makesymbols{%
  \ifsymdemo
      \restorecslist{symbols}\yyunion
      \toksa{}\toksb{}\toksc{}\toksd{}%
      %\showthe\newsymswitch
      \the\table
      \global\newsymswitch\newsymswitch
  \else
      \newsymswitch{}% otherwise \yysymswitch is trying to expand the wrong names (\namepair is not present to do \csname ... )
  \fi
}

% symbolic reference name parser

\newtoks\newsymswitch
\newread\symnames

\newwrite\symbolicswitch
\newif\ifsymdemo

\symdemotrue

\ifbootstrapmode
    \symdemofalse
\fi

\ifsymdemo
    \def\inamespace{[intermediate]}%
    \let\parsernamespace\inamespace
    \let\hostparsernamespace\mainnamespace % purely for testing reasons
    \pinittoks{}%
    \input cweb/gyytab.tex % this should be the parser that will be used later
                                            % in this case it is just an example
    \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 bo.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.
    \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 is 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 bg.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
%
%   \flex\ parser test
%    
    {%
        \toflexreparser
        \basicparserinit
        \flexreparserinit
        \flexreparserdatainit
        \yyBEGIN{SECT2}%
        \flin@ruletrue
        % special status of `\yl' in \CWEB\ makes the following workaround necessary
        % if the code is unsed inside a \CWEB\ file
        %|@t}\expandafter\yyparse\space [a-b]*(c|d|e)?\yyeof\yyeof\endparseinput\endparse{@>|
        \expandafter\yyparse\space [a-b]*(c|d|e)?\yyeof\yyeof\endparseinput\endparse
        \ifyyparsefail\else
            \ferrmessage{done processing flex}%
        \fi
    }%    
%
    {%
        \def\flnamespace{[flex]}
        \let\parsernamespace\flnamespace
        \toflexparser
        \basicparserinit
        %\flexparserinit
        \flexparserdatainit
        \yylessusedtrue % TODO: put it in the \genericparser command
        \let\f@nishparse\finishparse
        \def\finishparse{\endinput\message{end of input}\relax\let\cleanupcs\f@nishparse}%
        \def\next{%
            \catcode`\\=12
            \catcode`\^^J=12
            \catcode`\%=12
            \catcode`\^^M=12
            \catcode`\{=12
            \catcode`\}=12
            \catcode`\#=12
            \catcode`\_=12
            %\yydebugmost
            \expandafter\yyparse\input cweb/lo.l \cleanupcs\yyeof\yyeof\endparseinput\endparse % note that the space after the file name is necessary
            \ifyyparsefail
                \errmessage{stopped}%
            \fi
            \yydebugnone
            \basicparserinit
            \expandafter\yyparse\input cweb/fil.l \cleanupcs\yyeof\yyeof\endparseinput\endparse 
            % note that the space after the file name is necessary
        }\expandafter\next % to lock the \catcode of the brace
    }%
\fi