• 编译原理:词法分析程序的设计与实现


    词法分析程序(Lexical Analyzer)要求:


     

    • 从左至右扫描构成源程序的字符流
    • 识别出有词法意义的单词(Lexemes
    • 返回单词记录(单词类别,单词本身)
    • 滤掉空格
    • 跳过注释
    • 发现词法错误

    程序结构:

    输入:字符流(什么输入方式,什么数据结构保存)

    处理

    • 遍历(什么遍历方式)
    • 词法规则

    输出:单词流(什么输出形式)

    • 二元组

    单词类别:

    1. 标识符(10)
    2. 无符号数(11)
    3. 保留字(一词一码)
    4. 运算符(一词一码)
    5. 界符(一词一码)

    单词符号

    种别码

    单词符号

    种别码

    begin

    1

    :

    17

    if

    2

    :=

    18

    then

    3

    <

    20

    while

    4

    <=

    21

    do

    5

    <>

    22

    end

    6

    >

    23

    l(l|d)*

    10

    >=

    24

    dd*

    11

    =

    25

    +

    13

    ;

    26

    -

    14

    (

    27

    *

    15

    )

    28

    /

    16

    #

    0


    程序词法分析代码:

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>//关键字 
    string key[6]={"main","int","if","else","while","do"}; 
    //关键字的种别码
    int keyNum[6]={1,2,3,4,5,6}; 
    //运算符和界符 
    string symbol[17]={"<",">","!=",">=","<=","==",",",";","(",")","{","}","+","-","*","/","="};
    //char symbol[12]={'<','>','!=','>=','<=','==',',',';','(',')','{','}'};
    //运算符和界符的种别码 
    int symbolNum[17]={7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23};
    //存放文件取出的字符 
    string letter[1000];
    //将字符转换为单词
    string words[1000];
    int length; //保存程序中字符的数目 
    int num;
    
    //判断运算符和界符
    int isSymbol(string s){  
        int i;
        for(i=0;i<17;i++){
            if(s==symbol[i])
            return symbolNum[i]; 
        }
        return 0;
    } 
    //判断是否为数字 
    bool isNum(string s){
        if(s>="0" && s<="9")
        return true;
    }
    //判断是否为字母 
    bool isLetter(string s){
        if(s>="a" && s<="z")
        return true;
    }
    //判断是否为关键字,是返回种别码 
    int isKeyWord(string s){
        int i;
        for(i=0;i<6;i++){
            if(s==key[i])
            return keyNum[i];
        }
        return 0;
    }
    
    //返回单个字符的类型 
    int typeword(string str){
        if(str>="a" && str<="z") // 字母 
        return 1;
        
        if(str>="0" && str<="9") //数字 
        return 2;
        
        if(str==">"||str=="="||str=="<"||str=="!"||str==","||str==";"||str=="("||str==")"||str=="{"||str=="}"
        ||str=="+"||str=="-"||str=="*"||str=="/") //判断运算符和界符 
        return 3; 
    }
    
    string identifier(string s,int n){
        int j=n+1;
        int flag=1;
        while(flag){
            if(isNum(letter[j]) || isLetter(letter[j])){
                s=(s+letter[j]).c_str();
                if(isKeyWord(s)){
                    j++;
                    num=j;
                    return s;
                }
            j++;
            }
            else{
                flag=0;
            }
        } 
        num=j;
        return s;
    }
    
    string symbolStr(string s,int n){
        int j=n+1;
        string str=letter[j];
        if(str==">"||str=="="||str=="<"||str=="!") {
            s=(s+letter[j]).c_str();
            j++;
        }
        num=j;
        return s;
    }
    
    string Number(string s,int n){
        int j=n+1;
        int flag=1;
        while(flag){
            if(isNum(letter[j])){
                s=(s+letter[j]).c_str();
                j++;
            }
            else{
                flag=0;
            }
        }
        num=j;
        return s;
    }
    
    void print(string s,int n){
        cout<<"("<<s<<","<<n<<")"<<endl;
    }
    
    //取单词 
    void TakeWord(){ 
        int k;
        for(num=0;num<length;){
            string str1,str;
            str=letter[num];
            k=typeword(str);
            switch(k){
                case 1:
                    str1=identifier(str,num);
                    if(isKeyWord(str1))
                        print(str1,isKeyWord(str1));
                    else
                        print(str1,0);
                    break;
                case 2:
                    str1=Number(str,num);
                    print(str1,24);
                    break;
                case 3:
                    str1=symbolStr(str,num);
                    print(str1,isSymbol(str1));
                    break; 
            }
        } 
    }
    
    int main(){
        char w;
        int i,j;
        freopen("test.txt","r",stdin);//读取本地文件 
        freopen("result.txt","w",stdout); //从控制台输出,而不是文本输出
        length=0;
        while(cin>>w){
            if(w!=' '){
                letter[length]=w;
                length++;
            } //去掉程序中的空格
        }
        TakeWord();
        fclose(stdin);//关闭文件 
        fclose(stdout);//关闭文件 
        return 0;
    }

    运行程序前准备一个分析文本test.txt内容如下:

    int main()
    {
        int m,n;
        int num=0;
        n=10;
        if(n<0){
           m=-n;
        }
        else{
           m=n;
        }
        while(m!=0){
                 num=m*n;
        }
    }

    执行程序会输出如下结果:

    (int,2)
    (main,1)
    ((,15)
    (),16)
    ({,17)
    (int,2)
    (m,0)
    (,,13)
    (n,0)
    (;,14)
    (int,2)
    (num,0)
    (=,23)
    (0,24)
    (;,14)
    (n,0)
    (=,23)
    (10,24)
    (;,14)
    (if,3)
    ((,15)
    (n,0)
    (<,7)
    (0,24)
    (),16)
    ({,17)
    (m,0)
    (=,23)
    (-,20)
    (n,0)
    (;,14)
    (},18)
    (else,4)
    ({,17)
    (m,0)
    (=,23)
    (n,0)
    (;,14)
    (},18)
    (while,5)
    ((,15)
    (m,0)
    (!=,9)
    (0,24)
    (),16)
    ({,17)
    (num,0)
    (=,23)
    (m,0)
    (*,21)
    (n,0)
    (;,14)
    (},18)
    (},18)
  • 相关阅读:
    性能测试理论知识
    接口测试笔试题
    测试计划与测试报告
    java基础面试题
    软件测试人员必备的linux命令
    tomcat各目录(文件)作用
    常见的面试题
    LoadRunner中怎么设置密码参数化与用户名关联
    数据库索引总结(二)
    数据库索引总结(一)
  • 原文地址:https://www.cnblogs.com/zhif97/p/11656634.html
Copyright © 2020-2023  润新知