编译原理:编写一个语法高亮程序

编程题目 1:语法高亮转换软件 
(1) 问题描述:在我们使用的集成化编译环境(IDE)中,C/C++语言的源代码通常使用高亮语法表示,但是如果我们将这段代码发布到网页中,它的高亮语法表示将消失。这样看起来非常不直观,我们希望在网页中代码仍然能保持原来的高亮语法表示。 
(2) 输入:C/C++源代码文件,即后缀为 c/cpp 的文件。 
(3) 输出:网页文件,即后缀为 html 的文件。 
(4) 实现功能:将 C/C++源代码转换为网页文件,在浏览器中打开网页文件时,网页
中显示 C/C++源代码并以高亮语法表示显示。 

 

(5) 涉及知识点:词法分析。

 

 

 开始拿到这个题目时,实在是一点思路都没有。后来经过查阅与思考,发现按照上课所讲,先建立一个状态转换图,枚举所有可能出现的状态就好。更详细的内容见代码。要注意部分html的转义字符

 

编译原理:编写一个语法高亮程序_第1张图片

 

//注:输入的源文件需要以Unix格式保存,因为在Windows下换行符为\r\n,会导致结果错误
#include 
using namespace std;

bool is_keyword(string str);                //关键字
bool is_operator(char ch);                  //运算符
bool is_seprator(char ch);                  //分界符
int is_notes(string str);                   //注释
int is_quotes(char ch);                     //双引号
char get_ch(ifstream &src);                 //读入一个字符
void point_back(ifstream &src);             //回退光标
void lex(ifstream &src,ofstream &dst);      //分析函数
//关键词表
string keyword[45]={"bool", "break", "case", "char",
    "cin", "const", "continue", "default", "define",
    "delete", "do", "double", "else", "enum", "endl",
    "false", "float", "for", "friend", "goto", "if", "void"
    "include", "int", "long", "namespace", "new", "while"
    "operator", "private", "cout", "printf", "public",
    "return", "string", "signed", "sizeof", "static", "struct",
	"switch", "template", "this", "true", "typedef", "using"
	};
//光标回退
void point_back(ifstream &src)
{
    src.seekg(-1,ios::cur);
}
//是否为关键字
bool is_keyword(string str)
{
    bool flag=0;
    for (int i=0;i<45;i++){
        if (str==keyword[i]){
            flag=1;
            break;
        }
    }
    return flag;
}
//是否为运算符
bool is_operator(char ch)
{
    if (strchr("+-*/%><=",ch))
        return true;
    return false;
}
//是否为分界符
bool is_seprator(char ch)
{
    if (strchr(";:{},()!&[]@?\\|~",ch))
		return true;
    return false;
}
//是否为单双引号
int is_quotes(char ch)
{
    if (ch=='\'')
        return 1;
    else if (ch=='\"')
        return 2;
    return 0;
}
//是否为注释
int is_notes(string str)
{
    if (str=="//")
        return 1;
    if (str=="/*")
        return 2;
    return 0;
}
//读入一个字符
char get_ch(ifstream &src)
{
    char res=1;
    if (src.peek()==EOF)
        return res;
    src.get(res);
    return res;
}

//词法分析
void lex(ifstream &src,ofstream &dst)
{
    char ch;
    string token;
    //读入字符
    ch=get_ch(src);
    //文件结束
    if (ch==1)
        return ;
    //换行符
    if (ch=='\n')
        dst<<"
"; //空格 else if (ch==' '||ch=='\t'){ dst<<" "; } //关键字或普通字 else if (isalpha(ch)){ while (isalpha(ch)||isdigit(ch)||ch=='_'){ token.push_back(ch); ch=get_ch(src); } if (is_keyword(token)) dst<<""<"; else dst<"<"; point_back(src); } //注释 else if (ch=='/'){ token.push_back(ch); ch=get_ch(src); token.push_back(ch); //不为注释(为除号),跳转到运算符 if (is_notes(token)==0){ point_back(src); ch='/'; token.clear(); goto a1; } //为单行注释 else if (is_notes(token)==1){ while (ch!='\n'){ ch=get_ch(src); if (ch=='\n') break; token.push_back(ch); } dst<<""<"; } //为多行注释 else { int f=0; while (1){ while (ch!='\n'){ ch=get_ch(src); if (ch=='/'&&token[token.size()-1]=='*'){ f=1; token.push_back(ch); break; } token.push_back(ch); } if (ch=='\n') dst<<""<"; else dst<<""<"; if (f) break; token.clear(); ch=get_ch(src); token.push_back(ch); } } } //运算符 else if (is_operator(ch)){ //html中无法直接显示<>,需进行转义 a1: if (ch=='<'){ token.push_back('&'); token.push_back('l'); token.push_back('t'); } else if (ch=='>'){ token.push_back('&'); token.push_back('g'); token.push_back('t'); } else token.push_back(ch); dst<<""<"; } //字符串或字符 else if (is_quotes(ch)){ token.push_back(ch); int flag=is_quotes(ch); //为单引号 if (flag==1){ ch=get_ch(src); while (ch!='\''){ token.push_back(ch); ch=get_ch(src); } token.push_back(ch); dst<<""<"; } //为双引号 else{ ch=get_ch(src); while (ch!='\"'){ token.push_back(ch); ch=get_ch(src); } token.push_back(ch); dst<<""<"; } } //分界符 else if (is_seprator(ch)){ if (ch=='&'){ token.push_back('&'); token.push_back('a'); token.push_back('m'); token.push_back('p'); } else token.push_back(ch); dst<<""<"; } //头文件 else if (ch=='#'){ while (ch!='\n'){ if (ch=='<'){ token.push_back('&'); token.push_back('l'); token.push_back('t'); } else if (ch=='>'){ token.push_back('&'); token.push_back('g'); token.push_back('t'); } else token.push_back(ch); ch=get_ch(src); } dst<<""<"; } } int main() { ifstream src("in.cpp",ios::in); ofstream dst("out.html",ios::out); if (!src.is_open()){ cerr<<"open error"<

效果如下:

编译原理:编写一个语法高亮程序_第2张图片

 

你可能感兴趣的:(编译原理:编写一个语法高亮程序)