结合课程实验和课程设计,时间跨度为一个月,完成预处理,词法分析器。(词法分析器已作为JavaSwing项目上传至GitHub。)
预处理程序
#include<cstdio>
#include<iostream>
#include<fstream>
using namespace std;
void processSpace(ifstream &fin, const char); // 处理空格
void processMargin(ifstream &fin, const char); // 处理注释
void processCrLf(ifstream &fin, const char); // 处理回车换行
int main()
{
ifstream fin("F:\\CompilerPrinciple\\Test1\\demo.cpp", ios::in); // 预处理源代码文件
freopen("F:\\CompilerPrinciple\\Test1\\out.cpp","w",stdout); // 输出结果文件
char now, last;
fin.get(last);
while(!fin.eof() && isspace(last)) // 一个字符测试空文件
fin.get(last);
fin.unget();
while(!fin.eof())
{
fin.get(now);
switch(now)
{
case ' ':
processSpace(fin, last);
fin.unget(); // 超前搜索回退
break;
case '/':
processMargin(fin, last);
break;
case '\n': // 只存在Mac和windows下\r\n,\r
processCrLf(fin, last);
last = '\n';
break;
case '\t': break;
default:
putchar(now);
}
last = now;
}
return 0;
}
void processSpace(ifstream &fin, const char st)
{
/* 一.去多余空格:
* 1.判定当前字符,是空格则转第二步;否则输出
* 2.判定记录的上一个字符,如果是换行符,则是行首空格,不输出;
* 如果是赋值号,则是多余空格,不输出
* 继续判定下一个字符,如果是斜线,则是行末与注释间的空格,不输出
* 如果是分号,则是行末多余字符,不输出。
* 如果是空格,则是多余空格,不输出
*/
char next;
fin.get(next);
while(!fin.eof() && isspace(next)) // 去多个连续空格
fin.get(next);
if(st != '\n' && st != '='
&& next != '/' && next != ';' && next != '=')
putchar(' ');
}
void processCrLf(ifstream &fin, const char st)
{
/* 二. 去回车换行
* 1.超前搜索:如果下一个字符不是换行符,为Mac下源文件,回退文件指针,输出一个空格。否则
* 不回退,输出一个空格
* 考虑到兼容性,windows下\r\n,unix下 \n ,Mac下是 \r,过滤
*/
char next;
if(!fin.eof())
{
fin.get(next);
if(next != '\n')
fin.unget();
putchar(' ');
}
}
void processMargin(ifstream &fin, const char st)
{
/* 三. 去注释
* 1.判定当前字符是否为 / ,是则进入第2步;否则输出
* 2.超前搜索下一个字符是否为 / ,是则为单行注释,直接结束本行;否则转第3步
* 3.超前搜索下一个字符是否为 * ,进入下一次循环,转第4步
* 4.判定当前字符是否为 * ,是则进入第5步;否则放弃当前字符,进入下一次循环
* 5.超前搜索下一个字符是否为 '/',是则结束循环退出子程序;
* 否则进入下一次循环,转第4步
*/
char next, now;
fin.get(next);
if(!fin.eof())
{
if(next == '/') // 单行注释
{
while(!fin.eof())
{
fin.get(now);
if(now == '\r' || now == '\n')
break;
}
if(now == '\n') // 不是回车换行符,回退
fin.unget();
}
else if(next == '*') //多行注释
{
while(!fin.eof())
{
fin.get(next);
if(next == '*')
{
fin.get(next);
if(next == '/')
break;
}
}
}
}
}