编译原理实践:C++实现语法分析器(学习笔记)

实践说明

【题目要求】
基于已编写的C++词法分析器,分析当前目录下input.txt文件中的词法和语法,input.txt中的待分析代码必须以begin开头、以end结尾,文件最后以#结束。
词法和语法正确则输出success,词法错误则输出错误提示,如’$’ does not exist in this lexical system.,语法错误则输出错误位置和原因,如missing ‘begin’ error in line 1!。
输出结果存放到当前目录下的output.txt文件中。

【可分析语法】
<程序>:begin <语句串> end
<语句串>:<赋值语句> {;<赋值语句>};
<赋值语句>:ID = {+=,-=,=,/=,%=,>>=,<<=,&=,^=,|=} <表达式>
<表达式>:<项> {+<项> | -<项>}
<项>:<因子> {
<因子> | /<因子> | %<因子>}
<因子>:ID | NUM | (<表达式>)

【操作步骤】
1、在input.txt文件中输入或更改待分析的C源程序段(段末请以#结尾)。
2、双击程序exe文件即可完成语法分析程序的运行。
3、在output.txt文件中查看语法分析结果。

输入举例(input.txt)

int a = 20;
a = (1 + 2) * 3 / 8 % 10 
b /= 1 -;
&= 7;
int c = 4 / (5 - 6 ;#

输出举例(output.txt)

Your words(must start with 'begin', and end with 'end'):

---------------------------------
int a = 20;
a = (1 + 2) * 3 / 8 % 10 
b /= 1 -;
&= 7;
int c = 4 / (5 - 6 ;
---------------------------------

The result of syntactic analysis:

missing 'begin' error in line 1!
missing ';' error in line 2!
expression error in line 3!
statement error in line 4!
missing ')' error in line 5!
missing 'end' error in line 5!

Please correct the above syntactic errors for syntactic analysis!

编程平台

CodeBlocks 10.05

代码实现

基本思路

使用词法分析器遍历获得input.txt中每一个单词,运用上下文无关文法分析语法成分是否合乎要求。

语法分析部分预定义

void lrparser();            /*声明语法分析函数*/
void statementString();     /*声明语句串分析函数*/
void statement();           /*声明语句分析函数*/
void expression();          /*声明(等号右边的)表达式分析函数*/
void term();                /*声明项分析函数*/
void factor();              /*声明因子分析函数*/

void isLexicalError();      /*声明检测词法错误函数*/
bool isLineBreak();         /*声明检测换行符函数*/

WORD *oneWord = new WORD;    /*存放一个单词*/
int rowNumber = 1;           /*记录当前行数*/
bool lexicalError = false;   /*检测是否有词法错误*/
bool syntacticError = false; /*检测是否有语法错误*/

主函数定义

int main()
{
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);

	inputBufferIndex = 0;         // 初始化输入缓冲区下标

	scanf("%[^#]s", inputBuffer); // 读入源程序字符串到缓冲区,以#结束,允许多行输入,#会读成'\0'
	printf("Your words(must start with 'begin', and end with 'end'):\n\n");
	printf("---------------------------------\n");
    printf("%s\n", inputBuffer);
    printf("---------------------------------\n\n");
    printf("The result of syntactic analysis:\n\n");

    oneWord = scaner(); // 获得一个新单词
    lrparser();

	if(lexicalError == true && syntacticError == true)
	{
	    printf("\nPlease correct the above lexical errors and syntactic errors for syntactic analysis!\n");
	}
	else
	{
        if(lexicalError == true)
        {
            printf("\nPlease correct the above lexical errors for syntactic analysis!\n");
        }
        else if(syntacticError == true)
        {
            printf("\nPlease correct the above syntactic errors for syntactic analysis!\n");
        }
	}
	return 0;
}

语法分析主函数

void lrparser()
{
    while(isLineBreak()); // 判断是否存在换行
    if(oneWord -> categoryCode != 1) // 'begin'的种别码
    {
        cout << "missing 'begin' error in line " << rowNumber << "!" << endl;
        syntacticError = true;
    }
    else
    {
        oneWord = scaner(); // 获得一个新单词
    }
    statementString();  // 调用语句串分析函数
    if(oneWord -> categoryCode != 12)
    {
        cout << "missing 'end' error in line " << rowNumber << "!" << endl;
        syntacticError = true;
    }
    else
    {
        oneWord = scaner(); // 获得一个新单词
        while(isLineBreak()); // 判断是否存在换行
        if(oneWord -> categoryCode == 1000 && syntacticError == false && lexicalError == false) // '\0'的种别码
        {
            cout << "success!\n";
        }
        else
        {
            if(oneWord -> categoryCode != 1000)
            {
                cout << "the syntax after the first 'end' is invalid in line " << rowNumber << "!" << endl;
                syntacticError = true;
            }
            while(true)
            {
                oneWord = scaner(); // 获得一个新单词
                while(isLineBreak()); // 判断是否存在换行
                isLexicalError(); // 调用检测词法错误函数
                if(oneWord -> categoryCode == 1000)
                {
                    break;
                }
            }
        }
    }
}

语句串分析函数

void statementString()
{
    while(isLineBreak()); // 判断是否存在换行
    statement(); // 调用语句分析函数
    while(oneWord -> categoryCode == 64) // ';'的种别码
    {
        oneWord = scaner(); // 获得一个新单词
        while(isLineBreak()); // 判断是否存在换行
        isLexicalError(); // 调用检测词法错误函数
        statement(); // 调用语句分析函数
    }
}

语句分析函数

void statement()
{
    if(oneWord -> categoryCode == 1)
    {
        cout << "only the first 'begin' is valid in line " << rowNumber << "!" << endl;
        oneWord -> categoryCode = 64;
    }
    else if(oneWord -> categoryCode >= 2 && oneWord -> categoryCode <= 11
            || oneWord -> categoryCode == 13) // 关键字、单词的种别码
    {
        if(oneWord -> categoryCode >= 2 && oneWord -> categoryCode <= 11)
        {
            oneWord = scaner(); // 获得一个新单词
            isLexicalError(); // 调用检测词法错误函数
            if(oneWord -> categoryCode == 64 || oneWord -> categoryCode == 12 || oneWord -> categoryCode == 1000
               || oneWord -> categoryCode == 20) // 说明出现char;或char end或char'\0'或char'\n'的情况
            {
                if(oneWord -> categoryCode == 20)
                {
                    cout << "statement error in line " << (rowNumber - 1) << "!" << endl;
                    oneWord -> categoryCode = 64;
                }
                else
                {
                    cout << "statement error in line " << rowNumber << "!" << endl;
                }
                syntacticError = true;
                return;
            }
        }
        oneWord = scaner(); // 获得一个新单词
        isLexicalError(); // 调用检测词法错误函数
        if(oneWord -> categoryCode == 20)
        {
            cout << "missing ';' error in line "  << (rowNumber - 1) << "!" << endl;
            oneWord -> categoryCode = 64;
            syntacticError = true;
        }
        else if(oneWord -> categoryCode == 12 || oneWord -> categoryCode == 1000)
        {
            cout << "missing ';' error in line "  << rowNumber << "!" << endl;
            syntacticError = true;
        }
        else if(oneWord -> categoryCode >= 42 && oneWord -> categoryCode <= 52)
                          // '='、'+='、'-='、'*='、'/='、'%='、'>>='、'<<='、'&='、'^='、'|='的种别码
        {
            oneWord = scaner(); // 获得一个新单词
            while(isLineBreak()); // 判断是否存在换行
            isLexicalError(); // 调用检测词法错误函数
            expression(); // 调用(等号右边的)表达式分析函数
            if(oneWord -> categoryCode != 64) // 表达式一定以分号为结束
            {
                if(oneWord -> categoryCode == 20) // 说明是换行符
                {
                    cout << "missing ';' error in line "  << (rowNumber - 1) << "!" << endl;
                    oneWord -> categoryCode = 64;
                }
                else
                {
                    cout << "missing ';' error in line "  << rowNumber << "!" << endl;
                }
                syntacticError = true;
            }
        }
        else if(oneWord -> categoryCode != 64)
        {
            cout << "missing equal sign error in line "  << rowNumber << "!" << endl;
            syntacticError = true;
        }
    }
    else if(oneWord -> categoryCode != 12 && oneWord -> categoryCode != 1000) // 不是'end'或'#'
    {
        cout << "statement error in line " << rowNumber << "!" << endl;
        syntacticError = true;
        oneWord = scaner(); // 获得一个新单词
        while(isLineBreak()); // 判断是否存在换行
        isLexicalError(); // 调用检测词法错误函数
        while(oneWord -> categoryCode != 64 && oneWord -> categoryCode != 12
              && oneWord -> categoryCode != 1000)
        {
            oneWord = scaner(); // 获得一个新单词
            while(isLineBreak()); // 判断是否存在换行
            isLexicalError(); // 调用检测词法错误函数
        }
    }
}

(等号右边的)表达式分析函数

void expression()
{
    term(); // 调用项分析函数
    while(oneWord -> categoryCode == 21 || oneWord -> categoryCode == 22) // '+'或'-'的种别码
    {
        oneWord = scaner(); // 获得一个新单词
        while(isLineBreak()); // 判断是否存在换行
        isLexicalError(); // 调用检测词法错误函数
        term(); // 调用项分析函数
    }
}

项分析函数

void term()
{
    factor(); // 调用因子分析函数
    while(oneWord -> categoryCode >= 23 && oneWord -> categoryCode <= 25) // '*'、'/'、'%'的种别码
    {
        oneWord = scaner(); // 获得一个新单词
        while(isLineBreak()); // 判断是否存在换行
        isLexicalError(); // 调用检测词法错误函数
        factor(); // 调用因子分析函数
    }
}

因子分析函数

void factor()
{
    if(oneWord -> categoryCode == 13 || oneWord -> categoryCode == 14) // 单词或数字的种别码
    {
        oneWord = scaner(); // 获得一个新单词
        isLexicalError(); // 调用检测词法错误函数
    }
    else if(oneWord -> categoryCode == 56) // '('的种别码
    {
        oneWord = scaner(); // 获得一个新单词
        while(isLineBreak()); // 判断是否存在换行
        isLexicalError(); // 调用检测词法错误函数
        expression(); // 调用(等号右边的)表达式分析函数
        if(oneWord -> categoryCode == 57) // ')'的种别码
        {
            oneWord = scaner(); // 获得一个新单词
            while(isLineBreak()); // 判断是否存在换行
            isLexicalError(); // 调用检测词法错误函数
        }
        else
        {
            cout << "missing ')' error in line " << rowNumber << "!" << endl;
            syntacticError = true;
        }
    }
    else
    {
        cout << "expression error in line " << rowNumber << "!" << endl;
        syntacticError = true;
    }
}

特殊处理

/*检测词法错误函数*/
void isLexicalError()
{
    if (oneWord -> categoryCode == -1)
    {
        printf("%s\n", oneWord -> value); // 打印错误的词法
        lexicalError = true;
    }
}

/*检测换行符函数*/
bool isLineBreak()
{
    if(oneWord -> categoryCode == 20)
    {
        oneWord = scaner(); // 获得一个新单词
        return true;
    }
    return false;
}

如果文章内容出错或者您有更好的解决方法,欢迎到评论区指正和讨论!

猜你喜欢

转载自blog.csdn.net/weixin_40589192/article/details/106933125
今日推荐