• 词法分析器的设计与实现--编译原理操作步骤,1、你的算法工作流程图; 2、你的函数流程图;3,具体代码


    实验原理:

    词法分析是编译程序进行编译时第一个要进行的任务,主要是对源程序进行编译预处理之后,对整个源程序进行分解,分解成一个个单词,这些单词有且只有五类,分别时标识符、关键字(保留字)、常数、 运算符 、界符。

    词法分析器读取有字符串组成的输入流,并产生包含单词的输出流,每个单词都标记了其语法范畴(syntactic category)或类型,等效于英文单词的词类。为了完成这种聚集和分类操作,词法分析器会应用一组描述输入程序设计语言的词法结构(也称微语法,microsyntax)的规则。程序设计语言的微语法规定了如何将字符组合为单词,以及反过来如何分开混合在一起的各个单词。

    操作步骤:

    算法工作流程图:

    35db928612934abea2216bcbd7b61f36.png

    函数流程图:

    1713585c0cd54b76bef633166e1bbc70.png

    各单词符号对应的种别码2c5f14d14caf45ceb05b5e7803021679.png

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. //关键字
    7. string key[11]={"int","float","double","char","main","if","else","while","do","for","return"};
    8. //种别码
    9. int keyNum[11]={27,28,29,30,1,2,3,4,5,6,7};
    10. //运算符和界符
    11. string symbol[17]={"+","-","*","/","%",">",">=","<","<=","==","!=","=",";","(",")","{","}"};
    12. //运算符和界符种别码
    13. int symbolNum[17]={10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26};
    14. //从文件取出的字符
    15. string letter[1000];
    16. //将字符转换为单词
    17. string words[1000];
    18. int length; //保存程序中字符的长度
    19. int num;
    20. //判断是否为关键字,是返回种别码
    21. int isKeyWord(string s){
    22. int i;
    23. for(i=0;i<11;i++){
    24. if(s==key[i])
    25. return keyNum[i];
    26. }
    27. return 0;
    28. }
    29. int isSymbol(string s){ //判断运算符和界符
    30. int i;
    31. for(i=0;i<17;i++){
    32. if(s==symbol[i])
    33. return symbolNum[i];
    34. }
    35. return 0;
    36. }
    37. //判断是否为数字
    38. bool isNumber(string s){
    39. if(s>="0" && s<="9")
    40. return true;
    41. return false;
    42. }
    43. //判断是否为字母
    44. bool isLetter(string s)
    45. {
    46. if(s>="a" && s<="z")
    47. return true;
    48. return false;
    49. }
    50. //返回单个字符的类型
    51. int typeword(string str){
    52. if(str>="a" && str<="z") // 字母
    53. return 1;
    54. if(str>="0" && str<="9") //数字
    55. return 2;
    56. if(str==">"||str=="="||str=="<"||str=="!"||str==","||str==";"||str=="("||str==")"||str=="{"||str=="}"
    57. ||str=="+"||str=="-"||str=="*"||str=="/") //判断运算符和界符
    58. return 3;
    59. }
    60. string identifier(string s,int n){
    61. int j=n+1;
    62. int flag=1;
    63. while(flag){
    64. if(isNumber(letter[j]) || isLetter(letter[j])){
    65. s=(s+letter[j]).c_str();
    66. if(isKeyWord(s)){
    67. j++;
    68. num=j;
    69. return s;
    70. }
    71. j++;
    72. }
    73. else{
    74. flag=0;
    75. }
    76. }
    77. num=j;
    78. return s;
    79. }
    80. string symbolStr(string s,int n){
    81. int j=n+1;
    82. string str=letter[j];
    83. if(str==">"||str=="="||str=="<"||str=="!") {
    84. s=(s+letter[j]).c_str();
    85. j++;
    86. }
    87. num=j;
    88. return s;
    89. }
    90. string Number(string s,int n){
    91. int j=n+1;
    92. int flag=1;
    93. while(flag){
    94. if(isNumber(letter[j])){
    95. s=(s+letter[j]).c_str();
    96. j++;
    97. }
    98. else{
    99. flag=0;
    100. }
    101. }
    102. num=j;
    103. return s;
    104. }
    105. void print(string s,int n){
    106. cout<<"<"<","<">"<
    107. }
    108. void recognizeWord(){ //识别单词
    109. int k;
    110. for(num=0;num
    111. string str,ss;
    112. str=letter[num];
    113. k=typeword(str);
    114. switch(k){
    115. case 1:
    116. {
    117. ss=identifier(str,num);
    118. if(isKeyWord(ss))
    119. print(ss,isKeyWord(ss));
    120. else
    121. print(ss,8);
    122. break;
    123. }
    124. case 2:
    125. {
    126. ss=Number(str,num);
    127. print(ss,9);
    128. break;
    129. }
    130. case 3:
    131. {
    132. ss=symbolStr(str,num);
    133. print(ss,isSymbol(ss));
    134. break;
    135. }
    136. }
    137. }
    138. }
    139. int main(){
    140. char w;
    141. freopen("e:\\11.txt","r",stdin); //控制台输入
    142. freopen("e:\\result.txt","w",stdout); //控制台输出
    143. length=0;
    144. while(cin>>w){
    145. if(w!=' '){
    146. letter[length]=w;
    147. length++;
    148. } //去掉程序中的空格
    149. }
    150. recognizeWord();
    151. fclose(stdin);//关闭文件
    152. fclose(stdout);//关闭文件
    153. return 0;
    154. }

     输入文件

    90cd65647fed4136b00f88777a72c0bc.png输出文件

    bd893b09790b430f80783af567dab68b.png

     

     1、实验中出现过的问题或错误分析

    1)自己在书写地址过程中总是忘记绝对路径的书写格式;

    2)忘记将无用的成分如注释,空格,回车等单独仔细的考虑;

    3)开始在多位运算符号的判定出现问题,字符串数组的下标的值未能及时修改;

    2、保证实验成功(或程序运行正确)的关键问题

    1)在程序编写时,用到了C自带的库函数可以将字符串按照给定的多个一位分割符进行分割,将界符,运算符和其他区分开,便于遍历;

    2)在调试程序过程中,调用修改下标函数专门对下标进行修改;

    3)对于普通标识符和常量,分别建立标识符表和常量表,当遇到一个标识符或常量时,查找标识符表或常量表,若存在,则返回位置,否则返回0并且填写符号表或常量表。

    收获及体会

    在进行实验之前要先通过自己画出的程序的流程图,一步一步的优化自己的编程流程,可以在自己脑海中形成清晰的框架,确保不会出现一些大的方向上的判断错误,更有利于后续代码的书写以及实验的进行。在程序编写时,学会使用众多C自带的头文件,可以很好地处理输入串并对串进行分割,将界符、运算符和其他区分开,便于遍历。在调试程序过程中,一开始出现空格和换行无法识别的情况,于是就把这种情况单独编写了一个函数进行识别,便于串的后续识别。同时通过这次实验让我对于之前学到的词法分析有了进一步的了解,加深了对于词法分析的步骤的理解与领悟。对于我今后对编译原理的学习有很大的帮助。

    (注:代码是之前粘的别的博主的,因为我也不会写,流程图等是自己写的,互相借鉴)

     

  • 相关阅读:
    Qt数据库之QSqlQueryModel
    数据库命名规范
    【论文笔记】SDCL: Self-Distillation Contrastive Learning for Chinese Spell Checking
    济南某类国企单位面试复盘
    【Gradle自动化构建编程框架】一、介绍
    质量小议14 -- DevOps
    C语言-判断上三角矩阵
    React + TypeScript + Taro前端开发小结
    Rycky9.0安装k8s1.25.0+containerd
    井字棋游戏
  • 原文地址:https://blog.csdn.net/weixin_69491512/article/details/139162309