⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pp_scan.l

📁 一个c语言的编译器的源代码
💻 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 + -