扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
S: Statement我主要是想把它写成 C 语言的语法。
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]*
(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();
}
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者