码迷,mamicode.com
首页 > 其他好文 > 详细

简单词法分析器的实现

时间:2015-04-05 18:39:36      阅读:200      评论:0      收藏:0      [点我收藏+]

标签:

这是我们的一次编程作业,要求用C编写一个简单的词法分析器。要求如下:

编制一个单词获取程序,从文件输入的源程序中,识别出各个具有独立意义的单词,即关键字、标识符、整数、小数、字符串、分隔符、运算符等七大类。并依次输出各个单词的内部编码及单词符号自身文本串(遇到错误时可显示“Error”,然后跳过错误部分继续显示)。

注意:单词类型大小写不敏感(即不区分大小写)

 

1、词法规则

关键字: program、const、var、integer、decimal、string、procedure、begin、end 、if、then、else、while、do、call、read、write、not

单词类别:1

标识符: 字母或“_”打头的由字母、数字串或“_”组成的任意长度的符号串。

单词类别:2

整数:   数字串。

单词类别:3

小数:   数字串·数字串

单词类别:4

字符串: 由一对“”括起来的任意长度的符号串。注意:可以多行。

单词类别:5

分隔符: {、}、(、)、;、空格

单词类别:6

运算符: :=、=、<、<=、>、>=、+、-、*、/

单词类别:7

2、设计词法分析函数getToken( ),完成以下功能:

1)getToken( )每调用一次就分析出一个单词;

2)返回单词类别、单词自身文本串、单词在源文件中的行列号;

3、编写测试程序,反复调用函数getToken ( ),输出单词信息。


 

以下是代码实现:

 

注意的事项:

  1,">="这一类操作符要进行判断。

  2,小数的识别。为了简便,我把小数当成字符串进行处理,后续可以加上一个字符串转数字的程序,或者直接直接识别成小数。

  3,输入的源程序如何判断结束,我使用的是"#"字符进行判断,应该可以通过使用EOF进行识别吧。

  4,超前搜索指针要回退。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

#define KW 1 //关键字
#define ID 2 //标识符
#define INT 3 //整数
#define FLT 4 //小数
#define STR 5 //字符串
#define BRK 6 //分隔符
#define OP 7 //操作符

#define WordLen 100
char prog[80],token[WordLen];
char ch;
int p,j,syn;
int rowNum,lineNum;
char *keyword[18] = {"program","const","var","integer","decimal","string","procedure",
                "begin","end","if","then","else","while","do","call","read","write","not"};

void getToken(){
    for(int i = 0;i < WordLen;i++)
        token[i] = NULL;
    ch = prog[p++];
    /*识别标识符或者变量名*/
    if(ch >= a&&ch <= z||ch == _){
        int i = 0;
        while((ch >= 0&&ch <= 9)||(ch >= a&&ch <= z)||ch == _){
            token[i++] = ch;
            ch = prog[p++];
        }
        token [i++] = \0;
        p--;
        syn = ID;
        for(int n = 0;n < 18 ;n++){
            if(strcmp(token,keyword[n]) == 0){
                syn = KW;
                break;
            }
        }
    }
    /*识别实数*/
    else if(ch >= 0 && ch <= 9){
        bool isDouble = false; //是否是小数
        j = 0;
        while(ch>=0&&ch<=9){
            token[j++] = ch;
            ch = prog[p++];
        }
        if(ch==.){
            isDouble = true;
            token[j++] = ch;
            ch = prog[p++];
            while((ch>=0 && ch<=9)){
                token[j++] = ch;
                ch = prog[p++];
            }
        }
        if(isDouble){
            syn = FLT;
        }
        if(!isDouble){
            syn = INT;
        }
        p--;
    }
    /*以下代码用于判断字符串*/
    else if(ch == \"){
        j = 0;
        token[j++] = ch;
        while(prog[p] != \"){
            token[j ++] = prog[p++];
        }
        token[j] = \";
        p--;
        syn = STR;
    }
    /*以下代码用于判断运算符*/
    else switch(ch){//其他字符
        case<:
            j = 0;
            token[j++] = ch;
            ch = prog[p++];
            if(ch == =){
                token[j++] = ch;
                syn = OP;
            }
            else{
                p--;
                syn = OP;
            }
            break;
        case>:
            j = 0;
            token[j++] = ch;
            ch = prog[p++];
            if(ch == =){
                token[j] = ch;
                syn = OP;
            }
            else{
                p--;
                syn = OP;
            }
            break;
        case::
            j = 0;
            token[j++] = ch;
            ch = prog[p++];
            if(ch == =){
                syn = OP;
                token[j++] = ch;
            }
            else
            {
                syn = -1;
                p--;
            }
            break;
        case =:syn = OP;token[0] = ch;break;
        case +:syn = OP;token[0] = ch;break;
        case *:syn = OP;token[0] = ch;break;
        case /:syn = OP;token[0] = ch;break;
        case {:syn = BRK;token[0] = ch;break;
        case }:syn = BRK;token[0] = ch;break;
        case (:syn = BRK;token[0] = ch;break;
        case ):syn = BRK;token[0] = ch;break;
        case ;:syn = BRK;token[0] = ch;break;
        case  :syn = BRK;token[0] = ch;break;
        case \n:syn = -2;rowNum = 0;break;
        case #:syn = 0;break;
        default :syn = -1;break;
    }
}
int main()
{
    //freopen("D:\\compiler.txt","r",stdin);
    p = 0;
    lineNum = 1;
    gets(prog);
    for(int m = 0;m < sizeof(prog);m++){
        if(prog[m] >= A&&prog[m] <= Z){
            prog[m] = prog[m] - A + a;
        }
    }
    do {
        getToken();
        rowNum++;
        switch(syn)
        {
            case 1: cout<<lineNum<<" "<<rowNum<<" "<<"("<<syn<<","<<token<<")"<<endl;break;
            case 2: cout<<lineNum<<" "<<rowNum<<" "<<"("<<syn<<","<<token<<")"<<endl; break;
            case 5: cout<<lineNum<<" "<<rowNum<<" "<<"("<<syn<<","<<token<<")"<<endl; break;
            case 6: cout<<lineNum<<" "<<rowNum<<" "<<"("<<syn<<","<<token[0]<<")"<<endl; break;
            case 3: cout<<lineNum<<" "<<rowNum<<" "<<"("<<syn<<","<<token<<")"<<endl; break;
            case 4: cout<<lineNum<<" "<<rowNum<<" "<<"("<<syn<<","<<token<<")"<<endl; break;
            case -1: cout<<"Error !"<<endl; break;
            case -2: lineNum = lineNum++;break;
            case 0:break;
        }
    }while(syn != 0);
    return 0;
}

 

简单词法分析器的实现

标签:

原文地址:http://www.cnblogs.com/ohxiaobai/p/4394384.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!