编译原理,例:词法分析器

编译原理课作业要求自己写一个词法分析器,我尝试写了一下。
词法分析:计算机科学中将字符序列转换为单词(Token)序列的过程。进行词法分析的程序或者函数叫作词法分析器(Lexical analyzer),也叫扫描器(Scanner)。词法分析器一般以函数的形式存在,供语法分析器调用。 完成词法分析任务的程序称为词法分析程序或词法分析器或扫描器。完成词法分析任务的程序称为词法分析程序或词法分析器或扫描器。从左至右地对源程序进行扫描,按照语言的词法规则识别各类单词,并产生相应单词的属性字。
 
词法分析是编译器对源代码进行编译处理的第一步。编写指定程序语言的词法分析器需要构造相应的有限自动机,然后根据其编写。
目标:对下面的一段程序进行语法分析,输出分词。
var n, f;
begin
     n := 0;
     f := 1;
     while n # 10 do
     begin
          n := n + 1;
          f := f * n;
     end;
     call print;
end.

有限自动机在纸上手画的,这个语言的词法比较简单,算符界符表,保留字表比较少,我直接写到代码里了(*^▽^*)

#include<iostream>
#include <fstream>
#include <cassert>

using namespace std;

bool IsDigit(char ch);
bool IsLetter(char ch);
int Reserve(string s);

int main(){
    ifstream infile;    //文件输入流
    string file;    //文件路径
    int code;    //
    char ch;    //
    string strToken ;    //字符串
    cout<<"源程序路径:"<<endl;
    cin>>file;

    infile.open(file.data());    //将文件流对象与文件连接起来
    assert(infile.is_open());   //若失败,则输出错误消息,并终止程序运行

    infile >> noskipws    ;//noskipws:no skip whitespace 不跳过空格回车

    infile>>ch;

    while(!infile.eof()){
        strToken = "";
        while(ch==' '||ch=='
'||ch=='
'){
            if(infile.eof())    break;
            infile>>ch;//若是空白字符跳过
        }
        if(IsLetter(ch))//进入字母状态
        {
            while((IsLetter(ch)||IsDigit(ch)))
            {
                strToken.append(1,ch);
                infile>>ch;
            }
            code = Reserve(strToken);//查询保留字
            if(code==0) //不是保留字
            {
                cout<<"< "<<strToken<<" , 标识符 >"<<endl;
            }
            else
            {
                cout<<"< "<<strToken<<" , 保留字 >"<<endl;
            }
            continue;
        }
        else if(IsDigit(ch))//进入数字状态
        {
            while(IsDigit(ch)){
                strToken.append(1,ch);
                infile>>ch;
            }
            cout<<"< "<<strToken<<" , 常量 >"<<endl;
            continue;
        }
        else
        if(ch == '+') cout<<"< + , 算符 >"<<endl;
        else if(ch == '-') cout<<"< - , 算符 >"<<endl;
        else if(ch == '*') cout<<"< * , 算符 >"<<endl;
        else if(ch == '/') cout<<"< / , 算符 >"<<endl;
        else if(ch == '<') cout<<"< < , 算符 >"<<endl;
        else if(ch == '>') cout<<"< > , 算符 >"<<endl;
        else if(ch == ':')
        {
            infile>>ch;
            if(ch == '=')
                cout<<"< := , 算符 >"<<endl;
            else
                cout<<"Error :"<<ch<<endl;
        }
        else if(ch == 0x23) cout<<"<# ; , 界符 >"<<endl;
        else if(ch == 0x28) cout<<"< ( , 界符 >"<<endl;
        else if(ch == 0x29) cout<<"< ) , 界符 >"<<endl;
        else if(ch == 0x2c) cout<<"< , , 界符 >"<<endl;
        else if(ch == 0x2e) cout<<"< . , 界符 >"<<endl;
        else if(ch == 0x3b) cout<<"< ; , 界符 >"<<endl;

        else if(ch==' '||ch=='
'||ch=='
')    continue;
        else cout<<"Error :"<<ch<<endl;

        infile>>ch;

        if(infile.eof())    break;
    }

    infile.close();//关闭文件输入流
    return 0;
}

bool IsDigit(char ch)
{
    if(ch>='0'&&ch<='9') return true;
    else return false;
}
bool IsLetter(char ch)
{
    if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))    return true;
    else return false;
}
int Reserve(string s)
{
        if(s == "begin")    return 1;
        else if(s == "call")    return 2;
        else if(s == "const")    return 3;
        else if(s == "do")        return 4;
        else if(s == "end")        return 5;
        else if(s == "if")        return 6;
        else if(s == "odd")        return 7;
        else if(s == "procedure")    return 8;
        else if(s == "then")    return 9;
        else if(s == "var")        return 10;
        else if(s == "while")    return 11;
        else    return 0;
}

最后的输出:



 
原文地址:https://www.cnblogs.com/mydrizzle/p/12565176.html