用 C/C++ 编写一个 C 语言的语法分析器程序

发布时间 2023-12-09 14:37:11作者: 寒方

任务描述

本关任务:用 C/C++ 编写一个 C 语言的语法分析器程序。

相关知识

为了完成本关任务,你需要掌握:1.DFA NFA,2.C/C++ 编程语言基础。3. C 语言的基本结构知识

自动机

在编译原理课堂上已经教授了大家相关知识。在完成本实训前,一定要先设计相关自动机,再开始相关功能的实现。切勿,想到哪里,就编程到哪里,以至于代码一团糟,可维护性与可读性都很差。

C/C++

本实训涉及函数、结构体,标准流输入输出,字符串等操作

C语言基本结构

C 语言子集。 第一类:标识符 第二类:常数 第三类:保留字(32)

auto break case char const continue
default do double else enum extern
float for goto if int long
register return short signed sizeof static
struct switch typedef union unsigned void
volatile while

第四类:界符 /*// () { }[ ]" "' 等 第五类:运算符 <<=>>==+-*/^

**所有语言元素集合在 c_keys.txt **文件中。 注意,C_key.txt中缺少“//注释”的情况,请也映射到编号79!

auto    1
break    2
case    3
char    4
const    5
continue    6
default    7
do    8
double    9
else    10
enum    11
extern    12
float    13
for    14
goto    15
if    16
int    17
long    18
register    19
return    20
short    21
signed    22
sizeof    23
static    24
struct    25
switch    26
typedef    27
union    28
unsigned    29
void    30
volatile    31
while    32
-    33
--    34
-=    35
->    36
!    37
!=    38
%    39
%=    40
&    41
&&    42
&=    43
(    44
)    45
*    46
*=    47
,    48
.    49
/    50
/=    51
:    52
;    53
?    54
[    55
]    56
^    57
^=    58
{    59
|    60
||    61
|=    62
}    63
~    64
+    65
++    66
+=    67
<    68
<<    69
<<=    70
<=    71
=    72
==    73
>    74
>=    75
>>    76
>>=    77
"    78
/*注释*/    79
常数    80
标识符    81

编程要求

请仔细阅读该部分

输入

样例输入放在prog.txt文件中 样例1输入

int main()
{
  printf("HelloWorld");
  return 0;
}

 

输出

输出要满足以下要求

  1. 计数: <符号名,符号标号>

注意,冒号后边有一个空格 样例1输出

1: <int,17>
2: <main,81>
3: <(,44>
4: <),45>
5: <{,59>
6: <printf,81>
7: <(,44>
8: <",78>
9: <HelloWorld,81>
10: <",78>
11: <),45>
12: <;,53>
13: <return,20>
14: <0,80>
15: <;,53>
16: <},63>

 

注意,输出不能有多余的空格,回车等符号。请注意样例输出最后一行后是没有回车的!输出的符号都是英文的半角符号。

ERROR

本实训不考虑错误处理,我保证输入的所有代码块是合法的 C 语言代码。


开始你的任务吧,祝你成功!

 

 

// C语言词法分析器
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;
string keyword[40]={"","auto","break","case","char","const","continue",
"default","do","double","else","enum" ,"extern","float","for","goto",
"if","int","long","register","return","short","signed","sizeof",
"static","struct"," switch","typedef","union","unsigned","void",
"volatile","while"};
string mark[50]={"","-","--","-=","->","!","!=","%","%=","&","&&",
"&=","(",")","*","*=",",",".","/","/=",":",";","?","[","]","^",
"^=","{","|","||","|=","}","~","+","++","+=","<","<<","<<=","<=",
"=","==",">",">=",">>",">>=","\""};
string prog;
int cnt=1;
/* 不要修改这个标准输入函数 */
void read_prog(string& prog)
{
    char c;
    while(scanf("%c",&c)!=EOF){
        prog += c;
    }
}
/* 判断函数 */
bool isnum(char c)
{
    if(c >= '0' && c<= '9')
        return true;
    return false;
}
bool isletter(char c)
{
    if( (c>='a' && c<='z') || (c>='A' && c<='Z'))
        return true;
    return false;    
}
bool iskeyword(string s)
{
    for(int i=1;i<=32;i++)
        if(s==keyword[i])
        {
            if(cnt!=1) cout<<endl; 
            cout<<cnt<<": "<<"<"<<s<<","<<i<<">"; 
            cnt++;
            return true;
        }
            
    return false;    
}
/* 查找函数 */
int numtoken(int l)
{
    //找出整个数字 
    int r=l;
    while(isnum(prog[r]))
        r++;
    string s = prog.substr(l,r-l);
    //输出 
    if(cnt!=1) cout<<endl; 
    cout<<cnt<<": "<<"<"<<s<<","<<80<<">"; 
    cnt++;
    
    return r;
}
int lettertoken(int l)
{
    //找出整个单词 
    int r=l;
    while(isletter(prog[r]) || isnum(prog[r]))
        r++;
    string s = prog.substr(l,r-l);
    
    if(iskeyword(s))
        return r;
    //输出 
    if(cnt!=1) cout<<endl; 
    cout<<cnt<<": "<<"<"<<s<<","<<81<<">"; 
    cnt++;
    return r;
}
int note1(int l)// //注释 
{
    int r=l;
    while(prog[r]!='\n')
        r++;
    string s = prog.substr(l,r-l);
    if(cnt!=1) cout<<endl; 
    cout<<cnt<<": "<<"<"<<s<<","<<79<<">"; 
    cnt++;
    return r;
}
int note2(int l)// /*注释 
{
    int r=l;
    while(1)
    {
        if(prog[r]=='*' && prog[r+1]=='/')
            break;
        r++;
    }
    r=r+2;
    string s = prog.substr(l,r-l);
    if(cnt!=1) cout<<endl; 
    cout<<cnt<<": "<<"<"<<s<<","<<79<<">"; 
    cnt++;
    return r;
}
int operatortoken(int l)
{
    for(int j=3;j>=1;j--)
        for(int i=1;i<=46;i++)
            if(prog.substr(l,j)==mark[i])
            {
                if(cnt!=1) cout<<endl; 
                cout<<cnt<<": "<<"<"<<prog.substr(l,j)<<","<<i+32<<">"; 
                cnt++;
                return l+j;
            }
    return l+1;
}

void Analysis()
{
    read_prog(prog);
    /* 骚年们 请开始你们的表演 */
    int ptr=0,k=0;
    while(ptr<prog.length()){
        while(prog[ptr]==' ' || prog[ptr]=='\n')
            ptr++;
        if(ptr>=prog.length()) break;
        if(isnum(prog[ptr]))//常数 
            ptr=numtoken(ptr);
        else if(isletter(prog[ptr]))//关键字和变量名 
            ptr=lettertoken(ptr);
        else
        {
            //两种注释 
            if(prog[ptr]=='/' && prog[ptr+1]=='/')
                ptr=note1(ptr);
            else if(prog[ptr]=='/' && prog[ptr+1]=='*')
                ptr=note2(ptr);    
            else if(prog[ptr]=='%' && isletter(prog[ptr+1]) )
            {
                if(cnt!=1) cout<<endl; 
                cout<<cnt<<": "<<"<"<<prog.substr(ptr,2)<<","<<81<<">"; 
                cnt++;
                ptr=ptr+2;
            }
            else
                ptr=operatortoken(ptr);
        }
    }
}
int main()
{
    Analysis();
    return 0;
 }