📄 pp_scan.l
字号:
%{
// This file does the preprocess of the source,
// mainly about #include and simple #define
// Syntax:
// _line_header #include "file_to_include" _line_end
// _line_header #define ID _anything _line_end
//
// However, the error handling here is really poor now...
// Use `flex -opp_scan.cpp pp_scan.l` to generate the cpp source
//
// Written by bood, boodweb@163.com, http://boodweb.126.com
// 2005-03-13
#pragma warning(disable:4786)
#include <iostream>
#include <string>
#include <stack>
#include <list>
#include <map>
#include "pp_scan.h"
#define MAX_INCLUDE_DEPTH 10
#define YY_DECL int yylex(ostream &preproc_out)
using namespace std;
// Used for restore the lex process of up-level file
typedef struct {
string filename; // name of the up-level file
YY_BUFFER_STATE buffer; // buffer of up-level file
int file_lineno; // break line of up-level file
} FILE_UNIT;
static stack<FILE_UNIT> include_stack; // for restore the lex context
static map<string,string> define_map; // for definition replacement
static string define_id;
static int lineno = 1; // lineno of generated code
static int file_lineno = 1; // lineno in source files
static string filename; // file we're dealing with
// typedef struct {
// int lineno;
// string filename;
// int file_lineno;
// } INCLUDE_NODE;
//
// Here I'd like to explain the error location mechanism I use
// When an include is found, this scanner adds the corresponding
// lineno and include filename into the include_list, then do the
// expanding
//
// And when an include is ended, scanner also adds a INCLUDE_NODE
// into the list, whose filename is the up-level one and file_lineno
// follows the one before doing the include expanding
//
// So... just imagine the location procedure yourself :)
list<INCLUDE_NODE> include_list;
list<INCLUDE_NODE>::iterator include_it;
%}
%x INCLUDE DEFINE REPLACEMENT COMMENT
%option noyywrap
%%
^[\t ]*#define[\t ]+ { //Define
BEGIN DEFINE;
}
<DEFINE>[[:alpha:]]+[\t ]+ {
define_id = yytext;
define_id = define_id.substr(0,
define_id.find_last_not_of(" \t")+1 );
BEGIN REPLACEMENT;
}
<DEFINE>. {}
<REPLACEMENT>.* {
define_map[define_id] = yytext;
BEGIN INITIAL;
}
^[\t ]*#include[\t ]*\"[^\"\n]*\"[\t ]*\n { //Inlcude
int a, b;
string incl_line;
FILE_UNIT fileunit;
// Test whether beyond the MAX_INCLUDE_DEPTH, we don't go deeper
// Probably an endless include nesting is met
if ( include_stack.size() >= MAX_INCLUDE_DEPTH ) {
cout<<"Includes nested too deeply\n";
exit( 1 );
}
// Save the context
fileunit.file_lineno = file_lineno;
fileunit.buffer = YY_CURRENT_BUFFER;
fileunit.filename = filename;
include_stack.push(fileunit);
// Switch to the include file
incl_line = yytext;
a = incl_line.find('"');
b = incl_line.find('"', a+1);
filename = incl_line.substr(a+1, b-a-1);
file_lineno = 1;
yyin = fopen(filename.c_str(),"r");
if(yyin==NULL) {
cout<<"Preprocessor: include file "<<filename
<<" not found in "<<include_stack.top().filename
<<" line "<<include_stack.top().file_lineno<<endl;
exit(0);
}
yy_switch_to_buffer(
yy_create_buffer( yyin, YY_BUF_SIZE ) );
// Save the location infomation
INCLUDE_NODE incl_node;
incl_node.lineno = lineno;
incl_node.filename = filename;
incl_node.file_lineno = file_lineno;
include_list.push_back(incl_node);
}
"/*" { // Recogonize the comment
// We do not do the definition replacement in an comment
preproc_out<<yytext;
BEGIN COMMENT;
}
<COMMENT>"*/" { preproc_out<<yytext; BEGIN INITIAL; }
[[:alpha:]]+ {
if(define_map.find(yytext)!=define_map.end())
preproc_out<<define_map[yytext];
else
preproc_out<<yytext;
}
<COMMENT,INITIAL>. {
preproc_out<<yytext;
}
<*>\n {
preproc_out<<'\n';
lineno++;
file_lineno++;
}
<*><<EOF>> {
if ( include_stack.empty() ) {
yyterminate();
}
else {
// Switch back
FILE_UNIT& fileunit = include_stack.top();
filename = fileunit.filename;
file_lineno = fileunit.file_lineno+2;
yy_delete_buffer( YY_CURRENT_BUFFER );
yy_switch_to_buffer(
fileunit.buffer );
include_stack.pop();
// Save the location infomation
INCLUDE_NODE incl_node;
incl_node.lineno = lineno;
incl_node.filename = filename;
incl_node.file_lineno = file_lineno;
include_list.push_back(incl_node);
}
}
%%
void preprocess(char* src, ostream& os=cout)
{
filename = src;
// This initial node is necessary
INCLUDE_NODE incl_node;
incl_node.lineno = lineno;
incl_node.filename = filename;
incl_node.file_lineno = file_lineno;
include_list.push_back(incl_node);
yyin = fopen(src,"r");
if(yyin==NULL) {
cout<<"Preprocessor: source file "<<src<<" not found."<<endl;
exit(0);
}
yylex(os);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -