📄 pure_parser.tex
字号:
\chapter{Global Objects}\label{globals_c}\section{Globals}The class \cppclass{Globals} contains all global objects, among which the symbol table and the options specifiedat the command line. Almost every class has a pointer to \cppclass{Globals}, which is set by the constructor.\section{Pure Parser}This section describes how the parser and the lexer communicate. The way it is implemented is messy, however, thisis due to bison which does not clearly separate header from source file. Neither can it generate the parser as aclass.In the file \file{hys.l}, we put the following two lines:\begin{verbatim}%option c++%option yyclass="Pure_lexer"\end{verbatim}This causes flex to generate a class \cppclass{yyFlexLexer} containing all the functionality the lexer requiresexcept the actual lexer function \function{yylex}. That function is generated as \method{Pure\_lexer}{yylex},where \cppclass{Pure\_lexer} is derived from \cppclass{yyFlexLexer}.In order to pass information to and from the lexer, the following two lines go in \file{hys.y}:\begin{verbatim}%pure_parser#define YYLEX_PARAM p_in\end{verbatim}With these two options, bison expects the following lexer declaration:\begin{verbatim}int yylex (YYSTYPE *lvalp, YYLTYPE *llocp, lexer_input *l_in);\end{verbatim}The returned value is the next token read. \code{lvalp} and \code{llocp} are used to pass the semantic value of thetoken and its line number to the parser. \code{l\_in} is used to pass information to the lexer.\code{lexer\_input} contains a pointer to \cppclass{Globals} and a pointer to the actual lexer (an instance of\cppclass{Pure\_lexer}).\cppclass{Pure\_lexer} has the following attributes:\begin{verbatim} Globals *globals; YYSTYPE *lvalp; YYLTYPE *llocp;\end{verbatim}\code{int Pure\_lexer::yylex (YYSTYPE \*lvalp, YYLTYPE \*llocp, lexer\_input \*l\_in)} sets these attributes andthen calls \function{yylex} (the lexer generated by flex), which can use these values. The global function {\ttyylex} called from within the parser is:\begin{verbatim}int yylex (YYSTYPE *lvalp, YYLTYPE *llocp, lexer_input *l_in) { return l_in->lexer->yylex(lvalp, llocp, l_in->globals);}\end{verbatim}Here is the catch: \function{yylex} needs to be declared in \file{hys.y} in the C declaration section.\code{YYSTYPE} and \code{YYLTYPE} however are declared in the grammar section of \file{hys.y} and are thereforenot yet available. It is true that bison generates a header (\file{hys.tab.h}) containing these declarations, butthis header cannot be included in \file{hys.y}, because then \code{YYSTYPE} would be defined twice resulting in acompile error. Our solution is to put the \function{yylex} declaration immediately after \code{\%union \{ \ldots\} } using \code{\%\{ \ldots \%\} }. The code put there goes unchanged into \file{hys.tab.c}, at a position where\code{YYSTYPE} is already known.In order to pass information from the main program to the parser, we did the following: In \file{hys.y}, defining{\sl \#define YYPARSE\_PARAM p\_in } causes bison to generate the parser as\begin{verbatim}int yyparse(void *p_in);\end{verbatim}The following structure is used as the argument:\begin{verbatim}typedef struct { Globals *globals; ofstream *MLD_out, *simu_out; struct lexer_input *l_in;} parser_input;\end{verbatim}Thus, the parser gets a pointer to \cppclass{Globals}, which contains the symbol table and the command lineoptions. \code{MLD\_out} is where the \MLD{} matrices are written to and \code{simu\_out} is the output stream forthe simulator, if it is requested. \code{l\_in} is the argument given to the lexer.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -