分享
 
 
 

用C++语言手工编写的词法分析器,语法分析器

王朝c/c++·作者佚名  2006-06-27
窄屏简体版  字體: |||超大  

时间:2006-04-17更新

作者:ideawu

Document for: 用C++语言手工编写的编译器 -- 不完全功能。

这篇文章只是我学习编译原理的日记。我不是要写一个生成机器代码的编译器,我想写一个生成其它语言的编译器。可能是生成html或者c语言代码?

简介:

这是一个基于某个自定义的文法(将在下面给出)所编写的部分功能的编译器。已经实现了词法分析(Lexer.h/cpp),语法分析(Parser.h/cpp)并建立语法分析树,语法分析树数据结构(SyntaxTreeNode.h/cpp和SyntaxTree.h/cpp)。

文法定义:

S: Statement

B: Boolean

L: Block

I: Identifier

N: Number

E: Expression

Seperator: 分隔符,包括';' '\n' '\t'等,建议使用';'

S = if B then S (else S)? | while Boolean do S | I=E | '{' L '}'

L = S? D L? | <epsilon>

E = T {'+' T}

T = F {'*' F}

F = I | N

B = T2 {'|' T2}

T2 = F2 {'&' F2}

F2 = E <Relop> E

Relop = '<' | '>' | '=='

N = [0-9]+

I = [A-Za-z][0-9A-Za-z]*

我主要是想把它写成 C 语言的语法。

基本思想和功能:

词法分析器Lexer提供了nextToken()接口供语法分析器Parser使用。但是,词法分析器也可以单独使用,比如为了输出源文件的记号序列。 调用Parser的parse()方法将返回一棵源文件对应的语法分析树的指针。之后可以调用display()方法输出格式化的语法分析树。目前 Parser只能建立语法分析树和判断源文件是否存在语法错误并指出错误的地方,无法生成可执行代码。

基本模块简介:

(4.1) Lexer模块公用方法:

Lexer(char *filename); // filename: 源文件

void reset(); // 如果想再次从头分析源文件,调用此方法

bool isReady(); // Lexer是否已经准备就绪

char *getSrc(); // 得到源文件的拷贝的指针

int getIndex(); // 当前已经分析到的字符的位置

Token nextToken(); // 获取下一个记号,永远不会返回NULL

(4.2) Parser模块公用方法:

Parser(char* sourcefile); // sourcefile: 源文件

void printError(); // 打印出错误在源文件中的位置

SyntaxTree* parse(); // 得到一棵语法分析树,并返回它的指针

(4.3) SyntaxTree模块公用方法

void display(FILE *fo=stdout); // 将语法树输出到文件中,默认输出到标准输出

语法分析树输出格式

程序使用文本字符输出语法分析树,类似

'='---5

+-----ID

表示ID=5, ID表示标识符。以后将实现存储标识符的表格,从而可以显示标识符的名字。

'='---'+'---5

| '+'---b

+-----ID

表示ID=ID+5

whl---'='---'+'---5

| | +-----ID

| +-----ID

+-----'>'---3

+-----ID

表示while ID>3 then ID=ID+5

if ---blk---whl---'='---9

| | | +-----ID

| | +-----'>'---ID

| | +-----3

| +-----blk---'='---'+'---'*'---ID

| | | | +-----9

| | | +-----8

| | +-----ID

| +-----'='---3

| +-----ID

+-----'>'---8

+-----ID

对应下面的程序:

if a>8 then{

b = 3;

a = 8 + 9 * t;

}else{

while 3>a do

a=9;

}

下面的程序:

if a>8+3*d+6 | 3>4 & e<8 then{

s=2;

b=15;

if a<b then{

s = 8+te

i = 4*8

}else{

s = 0;

}

a=8+9;

rel=8*7;

}else{

while d>a do

begin

a=9+a;

b=7;

c=5+17*a;

end

}

生成树:

if ---blk---whl---blk---'='---'+'---'*'---ID

| | | | | | +-----17

| | | | | +-----5

| | | | +-----ID

| | | +-----blk---'='---7

| | | | +-----ID

| | | +-----'='---'+'---ID

| | | | +-----9

| | | +-----ID

| | +-----'>'---ID

| | +-----ID

| +-----blk---'='---'*'---7

| | | +-----8

| | +-----ID

| +-----blk---'='---'+'---9

| | | +-----8

| | +-----ID

| +-----blk---if ---blk---'='---0

| | | | +-----ID

| | | +-----blk---'='---'*'---8

| | | | | +-----4

| | | | +-----ID

| | | +-----'='---'+'---ID

| | | | +-----8

| | | +-----ID

| | +-----'<'---ID

| | +-----ID

| +-----blk---'='---15

| | +-----ID

| +-----'='---2

| +-----ID

+-----'|'---'&'---'<'---8

| | +-----ID

| +-----'>'---4

| +-----3

+-----'>'---'+'---6

| +-----'+'---'*'---ID

| | +-----3

| +-----8

+-----ID

源代码的可执行例子的使用方法:

下载源码包

代码已经在下列环境编译并测试:

Linux debian 2.6.8-2-686

gcc version 4.0.3 (Debian 4.0.3-1)

GNU Make 3.81rc2

使用相同或者相近的环境,进入源代码所在的目录,运行

./compiler

解析附带的test.txt文件。同一个目录下还附带了test_complex.txt(复杂)和test_error.txt(出错)两个文件供测试。

compiler可执行文件的使用方法为

./compiler [srcfile [outfile]]

解析srcfile源文件并输出语法分析树到outfile文件。

运行

make clean

make

将再次编译源文件。

如果在Windows下使用VC6,新建立一个工程,将所有源码文件加入工程中后就可以编译运行了。

在DOS窗口运行,进入工程所在的目录,把源代码目录下的test.txt, test_complex.txt, test_error.txt

三个测试用例复制到Debug目录下,再进入Debug目录,

使用main代替上面的compiler命令就可以测试了。

模块使用举例:

输出源文件的记号序列

Lexer lexer("source.c");

while((token = lexer.nextToken()) != ERROR){

// print token

// 已经得到一个记号

}

输出语法树到屏幕和文件中,出错则输出出错信息

FILE *fp = fopen("tree.txt", "w");

Parser parser("source.c");

SyntaxTree *tree = parser.parse();

if(tree != NULL){

tree->display();

tree->display(fp);

}else{

parser.printError();

}

代码在:http://www.ideawu.net/person/compilersrc/

Copyright©2006 idea's web. All rights reserved. | www.ideawu.net

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有