@q Copyright (c) 1990 The Regents of the University of California. @> @q All rights reserved. @> @q This code is derived from software contributed to Berkeley by @> @q Vern Paxson. @> @q The United States Government has rights in this work pursuant @> @q to contract no. DE-AC03-76SF00098 between the United States @> @q Department of Energy and the University of California. @> @q This file is part of SPLinT. @> @q Redistribution and use in source and binary forms, with or without @> @q modification, are permitted provided that the following conditions @> @q are met: @> @q 1. Redistributions of source code must retain the above copyright @> @q notice, this list of conditions and the following disclaimer. @> @q 2. Redistributions in binary form must reproduce the above copyright @> @q notice, this list of conditions and the following disclaimer in the @> @q documentation and/or other materials provided with the distribution. @> @q Neither the name of the University nor the names of its contributors @> @q may be used to endorse or promote products derived from this software @> @q without specific prior written permission. @> @q THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR @> @q IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED @> @q WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @> @q PURPOSE. @> @**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 The original lexer for \flex\ grammar relies on a few rules that use `trailing context'. The lexing mechanism implemented by \splint\ cannot process such rules properly in general. The rules used by \flex\ match fixed-length trailing context only, which makes it possible to replace them with ordinary patterns and use |yyless()| in the actions. @(fil.ll@>= @G %{@> @ @=%} @> @ @= @> @ @= @> @ @= @> @ @= %% @> @ @= @> @ @= @> @ @= %% @> @ @= @g @ Bootstrap lexer. @(ssfs.ll@>= @G %{@> @ @=%} @> @ @= @> @ @= @> @ @= %% @> @ @= @> @ @= %% @> @ @= @g @ @= @ There are a few options that are necessary to ensure that the lexer 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. @= @G(fs1) %option caseless nodefault stack noyy_top_state %option nostdinit %option bison-bridge %option noyywrap nounput noinput reentrant %option debug %option stack @ @= @G(fs1) %option outfile="fil.c" @g @ @= @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. @= @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 %x GROUP_WITH_PARAMS %x GROUP_MINUS_PARAMS %x EXTENDED_COMMENT %x COMMENT_DISCARD @ Somewhat counterintuitively, \flex\ definitions do not {\it always\/} have to be fully formed regular expressions. For example, after $$ \hbox to 3in{\flexrenstyle{BOGUS}\hfil\.{\^[a-}} $$ one can form the following action: $$ \hbox to 3in{\flexrenstyle{BOGUS}\.{t]}\hfil\.{;}} $$ although without the `\.{\^}' in the definition of `\flexrenstyle{BOGUS}' \flex\ would have put a `\.{)}' inside the character class. We will assume such (rather counterproductive) tricks are not used. If the definition is not a well-formed regular expression the pretty printing will be suspended. @= @G(fs1) WS [[:blank:]]+ OPTWS [[:blank:]]* NOT_WS [^[:blank:]\r\n] NL \r?\n NAME ([[:alpha:]_][[:alnum:]_-]*) NOT_NAME [^[:alpha:]_*\n]+ SCNAME {NAME} ESCSEQ (\\([^\n]|[0-7]{1,3}|x[[:xdigit:]]{1,2})) FIRST_CCL_CHAR ([^\\\n]|{ESCSEQ}) CCL_CHAR ([^\\\n\]]|{ESCSEQ}) CCL_EXPR ("[:"^?[[:alpha:]]+":]") LEXOPT [porkacne] M4QSTART "[[" 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. @= @G(fs2) { ^{WS} {@> @[TeX_( "/flindented@@codetrue/yyBEGIN{CODEBLOCK}/yylexnext" );@]@=} ^"/*" {@> @[TeX_( "/yypushstate{COMMENT}/yylexnext" );@]@=} ^#{OPTWS}line{WS} {@> @[TeX_( "/yypushstate{LINEDIR}/yylexnext" );@]@=} ^"%s"{NAME}? {@> @[TeX_( "/yylexreturnptr{SCDECL}" );@]@=} ^"%x"{NAME}? {@> @[TeX_( "/yylexreturnptr{XSCDECL}" );@]@=} ^"%{".*{NL} {@> @ @=} ^"%top"[[:blank:]]*"{"[[:blank:]]*{NL} {@> @ @=} ^"%top".* {@> @[TeX_( "/yyfatal{malformed '/harmlesscomment top' directive}" );@] @=} {WS} {@> @[;@]/* discard */ @=} ^"%%".* {@> @ @=} ^"%pointer".*{NL} {@> @[TeX_( "/flinc@@linenum/yylexreturn{POINTER_OP}" );@]@=} ^"%array".*{NL} {@> @[TeX_( "/flinc@@linenum/yylexreturn{ARRAY_OP}" );@]@=} ^"%option" {@> @[TeX_( "/yyBEGIN{OPTION}/yylexreturn{OPTION_OP}" );@]@=} ^"%"{LEXOPT}{OPTWS}[[:digit:]]*{OPTWS}{NL} {@> @[TeX_( "/flinc@@linenum/yyflexoptreturn{OPT_DEPRECATED}" );@]@=} ^"%"{LEXOPT}{WS}.*{NL} {@> @[TeX_( "/flinc@@linenum/yyflexoptreturn{OPT_DEPRECATED}" );@]@=} ^"%"[^porksexcan{}].* {@> @[TeX_( "/yyfatal{unrecognized '/harmlesscomment' directive: /the/yytext}" );@] @=} ^{NAME} {@> @ @=} {SCNAME} @> @[TeX_( "/RETURNNAME" );@] @= ^{OPTWS}{NL} {@> @[TeX_( "/flinc@@linenum/yylexnext" );@]/* allows blank lines in section 1 */@=} {OPTWS}{NL} {@> @[TeX_( "/flinc@@linenum/yylexnext" );@]/* maybe end of comment line */@=} } @ @= @[TeX_( "/flinc@@linenum" );@]@; @[TeX_( "/flindented@@codefalse/yyBEGIN{CODEBLOCK}" );@]@; @[TeX_( "/yylexnext" );@]@; @ Ignore setting |brace_start_line| as it is only used internally to report errors. @= @[TeX_( "/flinc@@linenum" );@]@; @[TeX_( "/def/flbrace@@depth{1}" );@]@; @[TeX_( "/yypushstate{CODEBLOCK_MATCH_BRACE}/yylexnext" );@]@; @ @= @[TeX_( "/def/flsectnum{2}/def/flbracelevel{0}" );@]@; @[TeX_( "/yyBEGIN{SECT2PROLOG}/yylexreturnptr{SECTEND}" );@]@; @ @= @[TeX_( "/fldidadeffalse/yyBEGIN{PICKUPDEF}" );@]@; @[TeX_( "/yylexreturnsym{DEF_OP}" );@]@; @ @= @G(fs2) { "*/" {@> @[TeX_( "/yypopstate/yylexnext" );@]@=} "*" {@> @[TeX_( "/yylexnext" );@]@=} {M4QSTART} {@> @[TeX_( "/yylexnext" );@]@=} {M4QEND} {@> @[TeX_( "/yylexnext" );@]@=} [^*\n] {@> @[TeX_( "/yylexnext" );@]@=} {NL} {@> @[TeX_( "/flinc@@linenum/yylexnext" );@]@=} } /* This is the same as \flexsnstyle{COMMENT}, but is discarded rather than output. */ { "*/" {@> @[TeX_( "/yypopstate/yylexnext" );@]@=} "*" {@> @[TeX_( "/yylexnext" );@]@=} [^*\n] {@> @[TeX_( "/yylexnext" );@]@=} {NL} {@> @[TeX_( "/flinc@@linenum/yylexnext" );@]@=} } { ")" {@> @[TeX_( "/yypopstate/yylexnext" );@]@=} [^\n\)]+ {@> @[TeX_( "/yylexnext" );@]@=} {NL} {@> @[TeX_( "/flinc@@linenum/yylexnext" );@]@=} } { \n {@> @[TeX_( "/yypopstate/yylexnext" );@]@=} [[:digit:]]+ {@> @[TeX_( "/fllinenum=/number/the/yytext/yylexnext" );@]@=} \"[^"\n]*\" {@> @[TeX_( "/yylexnext" );@] /* ignore the file name in the line directives */ @=} . {@> @[TeX_( "/yylexnext" );@] /* ignore spurious characters */ @=} } { ^"%}".*{NL} {@> @[TeX_( "/flinc@@linenum/yyBEGIN{INITIAL}/yylexnext" );@]@=} {M4QSTART} {@> @[TeX_( "/yylexnext" );@]@=} {M4QEND} {@> @[TeX_( "/yylexnext" );@]@=} . {@> @[TeX_( "/yylexnext" );@]@=} {NL} {@> @[TeX_( "/flinc@@linenum/ifflindented@@code/yyBEGIN{INITIAL}/fi/yylexnext" );@]@=} } { "}" {@> @ @=} "{" {@> @[TeX_( "/flinc/flbrace@@depth/yylexnext" );@] @=} {NL} {@> @[TeX_( "/flinc@@linenum/yylexnext" );@]@=} {M4QSTART} {@> @[TeX_( "/yylexnext" );@]@=} {M4QEND} {@> @[TeX_( "/yylexnext" );@]@=} [^{}\r\n] {@> @[TeX_( "/yylexnext" );@]@=} <> {@> @[TeX_( "/yyfatal{Unmatched '/lbchar'}" );@] @=} } @ @= @[TeX_( "/fldec/flbrace@@depth" );@]@; @[TeX_( "/ifnum/flbrace@@depth=/z@@/relax" );@]@; @[TeX_( " /yypopstate/yylexreturnxchar/n" );@]@; @[TeX_( "/else" );@]@; @[TeX_( " /yylexnext" );@]@; @[TeX_( "/fi" );@]@; @ @= @G(fs2) { {WS} {@> @[TeX_( "/yylexnext" );@]@=} {NOT_WS}[^\r\n]* {@> @ @=} {NL} {@> @ @=} } @ @= @[TeX_( "/edef/flnmdef{{/the/yytext}{/the/yytextpure}{/the/yyfmark}{/the/yysmark}}" );@]@; @[TeX_( "/fldidadeftrue/yylexnext" );@]@; @ @= @[TeX_( "/iffldidadef" );@]@; @[TeX_( " /yylval/expandafter{/flnmdef}" );@]@; @[TeX_( " /yybreak{/flinc@@linenum/yyBEGIN{INITIAL}/yylexreturn{RE_DEF}}" );@]@; @[TeX_( "/else" );@]@; @[TeX_( " /yybreak{/yyfatal{incomplete name definition}}" );@]@; @[TeX_( "/yycontinue" );@]@; @ @= @G(fs2)