summaryrefslogtreecommitdiff
path: root/support/splint/cweb/ssffo.w
blob: 315bffc79823ce92b0d472e10b8d9a365073c2b1 (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
@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}