zoukankan      html  css  js  c++  java
  • 词法分析实验报告

    实验一、词法分析实验

    专业:商业软件工程   姓名:陈蔓嘉  学号:201506110245

    一、        实验目的

         编制一个词法分析程序。

    二、        实验内容和要求

    输入:源程序字符串

    输出:二元组(种别,单词本身)

     

    内容及要求:

    1.对字符串表示的源程序;

    2.从左到右进行扫描和分解;

    3.根据词法规则;

    4.识别出一个一个具有独立意义的单词符号;

    5.以供语法分析之用;

    6.词法分析程序的功能:

    词法分析程序的主要功能是从字符流的程序中识别单词,他主要从左至右逐个字符地扫描源程序,因此他还可以完成其他任务。比如,滤掉源程序中的注释和空白(由空格/控制符或回车换行字符引起的空白);又如,为了使编译程序能将发现的错误信息与源程序的出错位置联系起来,词法分析程序负责记录新读入的字符行的行号,以便行号与出错信息相关联;再如,在支持宏处理功能的源程序中,可以由词法分析程序完成其预处理等。

    7.符号与种别码对照表:

    单词符号

    种别码

    单词符号

    种别码

    单词符号

    种别码

    auto

    1

    short

    21

    <=

    41

    break

    2

    signed

    22

    >=

    42

    case

    3

    sizeof

    23

    ==

    43

    char

    4

    static

    24

    :=

    44

    const

    5

    struct

    25

    <> 

    45

    continue

    6

    switch

    26

    46

    default

    7

    typedef

    27

    =>

    47

    do

    8

    union

    28

    =

    48

    double

    9

    unsigned

    29

    :

    49

    else

    10

    void

    33

    +

    50

    enum

    11

    include

    34

    -

    51

    extern

    12

    stdio

    35

    *

    52

    float

    13

    string

    36

    /

    53

    for

    14

    main

    37

    (

    54

    goto

    15

    stdlib

    38

    )

    55

    if

    16

    d(number)

    40

    {

    56

    int 17

    17

    l(qita)

    100

    }

    57

    long

    18

     

     

    58

    register

    19

     

     

    .

    59

    return

    20

     

     

     

     

    8.用文法描述词法规则:

    • <字母> →l
    • <数字> →d
    • <整数常数> →d|d<整数常数>
    • <标识符> →l|l〈字母数字〉
    • <关键字>→l|l〈字母数字〉
    • <运算符> →+|-|*|/|=|〈〈等号〉|〉〈等号〉……
    • <界符> →,|;|(|)|……

    其中l表示a~z中的任一英文字母,d表示0~9中的任一数字。

    三、        实验方法、步骤及结果测试

    实验方法:

     

    1. 1.      源程序名:压缩包文件(rarzip
    2. 2.      源程序名:词法分析程序.c
        1 #include<stdio.h>
        2 #include<string.h>
        3 #include<stdlib.h>
        4 char TOken[10];//分开进行比较
        5 char ch;
        6 char r1[]={"begin"};
        7 char r2[]={"if"};
        8 char r3[]={"then"};
        9 char r4[]={"while"};
       10 char r5[]={"do"};
       11 char r6[]={"end"};
       12 char r7[]={"break"};
       13 char r8[]={"case"};
       14 char r9[]={"main"};
       15 char r10[]={"l(l|d)*"};
       16 char r11[]={"dd*"};
       17 char r12[]={"="};
       18 char r13[]={"+"};
       19 char r14[]={"-"};
       20 char r15[]={"*"};
       21 char r16[]={"/"};
       22 char r17[]={":"};
       23 char r18[]={"{"};
       24 char r19[]={"}"};
       25 char r20[]={"<"};
       26 char r21[]={"!="};
       27 char r22[]={"<="};
       28 char r23[]={">"};
       29 char r24[]={">="};
       30 char r25[]={"=="};
       31 char r26[]={"("};
       32 char r27[]={")"};
       33 char r28[]={"="};
       34 char r29[]={"--"};
       35 char r30[]={"++"};
       36 char r31[]={"!"};
       37 char r32[]={":="};
       38 char r33[]={";"};
       39 char r34[]={"."};
       40 char A[10000];//输入的所有值
       41 int syn,row;
       42 int n,m,p,sum,j;
       43 static int i = 0;
       44 void scaner();
       45 int main()
       46 {
       47     row = 0 ;
       48     p = 0 ;
       49     printf("符号与种别码对照表如下:
      ");
       50     printf("        单词符号         种别码          单词符号          种别码
      ");
       51     printf("         begin             1                 :               17
      ");
       52     printf("          if               2                 {               18
      ");
       53     printf("         then              3                 }               19
      ");
       54     printf("         while             4                 <               20
      ");
       55     printf("          do               5                 !=              21
      ");
       56     printf("         end               6                 <=              22
      ");
       57     printf("         break             7                 >               23
      ");
       58     printf("         case              8                 >=              24
      ");
       59     printf("         main              9                 ==              25
      ");
       60     printf("       l(l|d)*             10                (               26
      ");
       61     printf("          dd*              11                )               27
      ");
       62     printf("          =                12                =               28
      ");
       63     printf("          +                13                --              29
      ");
       64     printf("          -                14                ++              30
      ");
       65     printf("          *                15                !               31
      ");
       66     printf("          /                16                :=              32
      ");
       67     printf("          @                0                 ;               33
      
      ");
       68     printf(" 请输入您想转换的语句(输入@结束):
      ");
       69     do{
       70         scanf("%c",&ch);
       71         A[p]=ch;
       72         p++;
       73       }while(ch!='@');/*将输入的语句分别存入数组A[]中,@出现时结束语句*/
       74       do
       75         {
       76             scaner();//进入函数进行判定
       77             switch(syn)
       78             {
       79                 case 11: printf("(%d,%d)
      ",syn,sum); break;//如果是11,那么就是数字
       80                 case -2: row=row++;break;
       81                 default: printf("(%d,%s)
      ",syn,TOken);break;//否则,就是变量名、关键词
       82                  }
       83         }while (syn!=0);
       84 
       85 }
       86 void scaner()/*分别对标示符、数字、符号进行分析*/
       87 {
       88     for(n=0;n<5;n++)
       89         TOken[n]=0;/*每次循环完就清零*/
       90     ch=A[i];
       91     while(ch==' '||ch=='
      ')/*如果字符是空格或者回车,跳过*/
       92         {
       93             i++;
       94             ch=A[i];
       95         }
       96         if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) /*如果是标示符或者变量名,循环寻找*/
       97         {
       98             m=0;
       99             while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))/*找到一个变量名或者关键字,直到遇到空格为止*/
      100             {
      101                 TOken[m]=ch;m++;
      102                 i++;ch=A[i];
      103             }
      104         TOken[m]='';/*将识别出来的字符和已定义的标示符作比较,输出其种别码*/
      105         if(strcmp(TOken,r1)==0){syn=1;}
      106             else if(strcmp(TOken,r2)==0){syn=2;}
      107             else if(strcmp(TOken,r3)==0){syn=3;}
      108             else if(strcmp(TOken,r4)==0){syn=4;}
      109             else if(strcmp(TOken,r5)==0){syn=5;}
      110             else if(strcmp(TOken,r6)==0){syn=6;}
      111             else if(strcmp(TOken,r7)==0){syn=7;}
      112             else if(strcmp(TOken,r8)==0){syn=8;}
      113             else if(strcmp(TOken,r9)==0){syn=9;}
      114 
      115         else{syn=10;}
      116         }
      117         else if((ch>='0'&&ch<='9')) //数字
      118         {
      119             sum=0;
      120             while((ch>='0'&&ch<='9'))
      121             {
      122                 sum=sum*10+ch-'0';//显示其对应数字sum
      123                 i++;
      124                 ch=A[i];
      125             }
      126             syn=11;
      127         }
      128         else switch(ch) //有两个的字符
      129             {
      130                 case'<':m=0;TOken[m]=ch;m++;
      131                 i++;ch=A[i];
      132                 if(ch=='=')
      133                 {
      134                     syn=22;//<=
      135                     TOken[m]=ch;m++;i++;
      136                 }
      137            else{syn=20;}break;//<
      138 
      139                 case'>':m=0;TOken[m]=ch;m++;
      140                 i++;ch=A[i];
      141                 if(ch=='='){
      142                     syn=24;//>=
      143                     TOken[m]=ch;m++;i++;
      144                 }
      145             else{syn=23;}break;//>
      146 
      147                 case':':m=0;TOken[m]=ch;m++;
      148                 i++;ch=A[i];
      149                 if(ch=='=')
      150                 {
      151                     syn=32;//:=
      152                     TOken[m]=ch;m++;i++;
      153                 }
      154                 else
      155                     {syn=17;}break;//:
      156 
      157                 case'@':syn=0;TOken[0]=ch;i++;break;
      158                 case'=':syn=12;TOken[0]=ch;i++;break;
      159                 case'+':syn=13;TOken[0]=ch;i++;break;
      160                 case'-':syn=14;TOken[0]=ch;i++;break;
      161                 case'*':syn=15;TOken[0]=ch;i++;break;
      162                 case'/':syn=16;TOken[0]=ch;i++;break;
      163                 case'{':syn=18;TOken[0]=ch;i++;break;
      164                 case'}':syn=19;TOken[0]=ch;i++;break;
      165                 case'(':syn=26;TOken[0]=ch;i++;break;
      166                 case')':syn=27;TOken[0]=ch;i++;break;
      167                 case';':syn=33;TOken[0]=ch;i++;break;
      168                 case'.':syn=34;TOken[0]=ch;i++;break;
      169                 case'
      ':syn=-2;break;
      170                 default: syn=-1;break;
      171             }
      172 }
      词法分析程序.c
    1. 3.      可执行程序名:词法分析程序.exe
    1. 4.      原理分析及流程图

    主要总体设计问题。(包括存储结构,主要算法,关键函数的实现等)

    主函数主要算法:

     1 do{
     2 
     3         scanf("%c",&ch);
     4 
     5         A[p]=ch;
     6 
     7         p++;
     8 
     9       }while(ch!='@');/*将输入的语句分别存入数组A[]中,@出现时结束语句*/
    10 
    11       do
    12 
    13         {
    14 
    15             scaner();//进入函数进行判定
    16 
    17             switch(syn)
    18 
    19             {
    20 
    21                 case 11: printf("(%d,%d)
    ",syn,sum); break;//如果是11,那么就是数字
    22 
    23                 case -2: row=row++;break;
    24 
    25                 default: printf("(%d,%s)
    ",syn,TOken);break;//否则,就是变量名、关键词
    26 
    27                  }
    28 
    29         }while (syn!=0);

     流程图:

    关键函数:

      1 void scaner()/*分别对标示符、数字、符号进行分析*/
      2 
      3 {
      4 
      5     for(n=0;n<5;n++)
      6 
      7         TOken[n]=0;/*每次循环完就清零*/
      8 
      9     ch=A[i];
     10 
     11     while(ch==' '||ch=='
    ')/*如果字符是空格或者回车,跳过*/
     12 
     13         {
     14 
     15             i++;
     16 
     17             ch=A[i];
     18 
     19         }
     20 
     21         if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) /*如果是标示符或者变量名,循环寻找*/
     22 
     23         {
     24 
     25             m=0;
     26 
     27             while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))/*找到一个变量名或者关键字,直到遇到空格为止*/
     28 
     29             {
     30 
     31                 TOken[m]=ch;m++;
     32 
     33                 i++;ch=A[i];
     34 
     35             }
     36 
     37         TOken[m]='';/*将识别出来的字符和已定义的标示符作比较,输出其种别码*/
     38 
     39         if(strcmp(TOken,r1)==0){syn=1;}
     40 
     41             else if(strcmp(TOken,r2)==0){syn=2;}
     42 
     43             else if(strcmp(TOken,r3)==0){syn=3;}
     44 
     45             else if(strcmp(TOken,r4)==0){syn=4;}
     46 
     47             else if(strcmp(TOken,r5)==0){syn=5;}
     48 
     49             else if(strcmp(TOken,r6)==0){syn=6;}
     50 
     51             else if(strcmp(TOken,r7)==0){syn=7;}
     52 
     53             else if(strcmp(TOken,r8)==0){syn=8;}
     54 
     55             else if(strcmp(TOken,r9)==0){syn=9;}
     56 
     57  
     58 
     59         else{syn=10;}//从for开始到这里结束,是对标示符或者变量名的识别。
     60 
     61         }
     62 
     63         else if((ch>='0'&&ch<='9')) //数字
     64 
     65         {
     66 
     67             sum=0;
     68 
     69             while((ch>='0'&&ch<='9'))
     70 
     71             {
     72 
     73                 sum=sum*10+ch-'0';//显示其对应数字sum
     74 
     75                 i++;
     76 
     77                 ch=A[i];
     78 
     79             }
     80 
     81             syn=11;
     82 
     83         }//这一段是对数字三识别。
     84 
     85         else switch(ch) //有两个的字符
     86 
     87             {
     88 
     89                 case'<':m=0;TOken[m]=ch;m++;
     90 
     91                 i++;ch=A[i];
     92 
     93                 if(ch=='=')
     94 
     95                 {
     96 
     97                     syn=22;//<=
     98 
     99                     TOken[m]=ch;m++;i++;
    100 
    101                 }
    102 
    103            else{syn=20;}break;//<
    104 
    105  
    106 
    107                 case'>':m=0;TOken[m]=ch;m++;
    108 
    109                 i++;ch=A[i];
    110 
    111                 if(ch=='='){
    112 
    113                     syn=24;//>=
    114 
    115                     TOken[m]=ch;m++;i++;
    116 
    117                 }
    118 
    119             else{syn=23;}break;//>
    120 
    121  
    122 
    123                 case':':m=0;TOken[m]=ch;m++;
    124 
    125                 i++;ch=A[i];
    126 
    127                 if(ch=='=')
    128 
    129                 {
    130 
    131                     syn=32;//:=
    132 
    133                     TOken[m]=ch;m++;i++;
    134 
    135                 }
    136 
    137                 else
    138 
    139                     {syn=17;}break;//:
    140 
    141  
    142 
    143                 case'@':syn=0;TOken[0]=ch;i++;break;
    144 
    145                 case'=':syn=12;TOken[0]=ch;i++;break;
    146 
    147                 case'+':syn=13;TOken[0]=ch;i++;break;
    148 
    149                 case'-':syn=14;TOken[0]=ch;i++;break;
    150 
    151                 case'*':syn=15;TOken[0]=ch;i++;break;
    152 
    153                 case'/':syn=16;TOken[0]=ch;i++;break;
    154 
    155                 case'{':syn=18;TOken[0]=ch;i++;break;
    156 
    157                 case'}':syn=19;TOken[0]=ch;i++;break;
    158 
    159                 case'(':syn=26;TOken[0]=ch;i++;break;
    160 
    161                 case')':syn=27;TOken[0]=ch;i++;break;
    162 
    163                 case';':syn=33;TOken[0]=ch;i++;break;
    164 
    165                 case'.':syn=34;TOken[0]=ch;i++;break;
    166 
    167                 case'
    ':syn=-2;break;
    168 
    169                 default: syn=-1;break;
    170 
    171             }//这一部分是对符号的识别。
    172 
    173 }

    关键函数流程图:

     

    1. 5.      主要程序段及其解释:

    实现主要功能的程序段,重要的是程序的注释解释。

      1 void scaner()/*分别对标示符、数字、符号进行分析*/
      2 
      3 {
      4 
      5     for(n=0;n<7;n++)
      6 
      7         TOken[n]=0;/*每次循环完就清零*/
      8 
      9     ch=A[i];
     10 
     11     while(ch==' '||ch=='
    ')/*如果字符是空格或者回车,跳过*/
     12 
     13         {
     14 
     15             i++;
     16 
     17             ch=A[i];
     18 
     19         }
     20 
     21         if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) /*如果是标示符或者变量名,循环寻找*/
     22 
     23         {
     24 
     25             m=0;
     26 
     27             while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))/*找到一个变量名或者关键字,直到遇到空格为止*/
     28 
     29             {
     30 
     31                 TOken[m]=ch;m++;
     32 
     33                 i++;ch=A[i];
     34 
     35             }
     36 
     37         TOken[m]='';/*将识别出来的字符和已定义的标示符作比较,输出其种别码*/
     38 
     39         if(strcmp(TOken,r1)==0){syn=1;}
     40 
     41             else if(strcmp(TOken,r2)==0){syn=2;}
     42 
     43             else if(strcmp(TOken,r3)==0){syn=3;}
     44 
     45             else if(strcmp(TOken,r4)==0){syn=4;}
     46 
     47             else if(strcmp(TOken,r5)==0){syn=5;}
     48 
     49             else if(strcmp(TOken,r6)==0){syn=6;}
     50 
     51             else if(strcmp(TOken,r7)==0){syn=7;}
     52 
     53             else if(strcmp(TOken,r8)==0){syn=8;}
     54 
     55             else if(strcmp(TOken,r9)==0){syn=9;}
     56 
     57  
     58 
     59         else{syn=10;}
     60 
     61         }
     62 
     63         else if((ch>='0'&&ch<='9')) //数字
     64 
     65         {
     66 
     67             sum=0;
     68 
     69             while((ch>='0'&&ch<='9'))
     70 
     71             {
     72 
     73                 sum=sum*10+ch-'0';//显示其对应数字sum
     74 
     75                 i++;
     76 
     77                 ch=A[i];
     78 
     79             }
     80 
     81             syn=11;
     82 
     83         }
     84 
     85         else switch(ch) //有两个的字符
     86 
     87             {
     88 
     89                 case'<':m=0;TOken[m]=ch;m++;
     90 
     91                 i++;ch=A[i];
     92 
     93                 if(ch=='=')
     94 
     95                 {
     96 
     97                     syn=22;//<=
     98 
     99                     TOken[m]=ch;m++;i++;
    100 
    101                 }
    102 
    103            else{syn=20;}break;//<
    104 
    105  
    106 
    107                 case'>':m=0;TOken[m]=ch;m++;
    108 
    109                 i++;ch=A[i];
    110 
    111                 if(ch=='='){
    112 
    113                     syn=24;//>=
    114 
    115                     TOken[m]=ch;m++;i++;
    116 
    117                 }
    118 
    119             else{syn=23;}break;//>
    120 
    121  
    122 
    123                 case':':m=0;TOken[m]=ch;m++;
    124 
    125                 i++;ch=A[i];
    126 
    127                 if(ch=='=')
    128 
    129                 {
    130 
    131                     syn=32;//:=
    132 
    133                     TOken[m]=ch;m++;i++;
    134 
    135                 }
    136 
    137                 else
    138 
    139                     {syn=17;}break;//:
    140 
    141  
    142 
    143                 case'@':syn=0;TOken[0]=ch;i++;break;
    144 
    145                 case'=':syn=12;TOken[0]=ch;i++;break;
    146 
    147                 case'+':syn=13;TOken[0]=ch;i++;break;
    148 
    149                 case'-':syn=14;TOken[0]=ch;i++;break;
    150 
    151                 case'*':syn=15;TOken[0]=ch;i++;break;
    152 
    153                 case'/':syn=16;TOken[0]=ch;i++;break;
    154 
    155                 case'{':syn=18;TOken[0]=ch;i++;break;
    156 
    157                 case'}':syn=19;TOken[0]=ch;i++;break;
    158 
    159                 case'(':syn=26;TOken[0]=ch;i++;break;
    160 
    161                 case')':syn=27;TOken[0]=ch;i++;break;
    162 
    163                 case';':syn=33;TOken[0]=ch;i++;break;
    164 
    165                 case'.':syn=34;TOken[0]=ch;i++;break;
    166 
    167                 case'
    ':syn=-2;break;
    168 
    169                 default: syn=-1;break;
    170 
    171             }
    172 
    173 }
    1. 6.      运行结果及分析

    一般必须配运行结果截图,结果是否符合预期及其分析。

       (截图需根据实际,截取有代表性的测试例子)

     

    四、        实验总结

    心得体会,实验过程的难点问题及其解决的方法。

    在写词法分析的过程中,难点问题主要是关键字和变量名的分辨,在循环程序中卡主了,其他问题还好。在分辨期间,我首先让这个词循环,查找,循环完就清零。如果是标示符或者变量名,找到一个变量名或者关键字,直到遇到空格为止,将识别出来的字符和已定义的标示符作比较,输出其种别码。这是我这一实验学到的最大的东西。

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    虚函数******
    C++ 中的运算符重载********
    继承
    静态成员和成员函数
    类指针
    内联函数
    k8基础架构
    cobbler自动装机
    ens33-eth0
    PXE-自动装机配置
  • 原文地址:https://www.cnblogs.com/oechen/p/5958567.html
Copyright © 2011-2022 走看看