[编译原理学习]词法分析

此前一直没能系统完整地学过编译原理,只有很粗浅的理解,虽然其实对工作里的任务也没啥影响,但总觉得缺了一大块知识,加上对所谓程序员三大浪漫(编译器,操作系统,图形学)的向往,所以最近跟着网易云课堂推出的计算机专业课程来学习编译原理.无奈生性懒惰,常常下班之后觉得累了,打打游戏啊看看视频啊,拖延症就犯了.......所以在这里打算将学习的过程,心得记录下来,也算是对自己的一个督促.课程传送门http://mooc.study.163.com/learn/USTC-1000002001#/learn/announce

首先要明确一个概念,语言是设计出来的,不是写代码写出来的,编译器才是写出来的.源代码其实就是一堆字符而已,只不过些字符是按照事先规定好的规则组织起来.

编译器是一个程序,完成的功能是把源代码(c/c++,python,java。。。。)转换为目标代码.这其中又涉及到很多过程.简单的讲就是下面这个过程

 

 以if(a > 1)为例,词法分析器的任务就是要将这一句拆分出if,(,a,>,1,)并判断出他们的类型,比如if是个关键字,a是一个变量,名字叫a,>是一个大于号,1是一个整数,值为1等等...... 

下面是一个完成下列功能的简单分析器代码示例:

分析器的输入:存储在文本文件中的字符序列,字符取自ASCII字符集。文件中可能包括四种记号:关键字if、符合C语言标准的标识符、空格符、回车符\n。

分析器的输出:打印出所识别的标识符的种类、及行号、列号信息。

 

 1 #ifndef TOKENIZER_H
 2 #define TOKENIZER_H
 3 
 4 #include <iostream>
 5 #include <string>
 6 #include <vector>
 7 using namespace std;
 8 
 9 enum symbol
10 {
11     //关键字if、符合C语言标准的标识符、空格符、回车符
12     KEYWORD,
13     ID,
14     BLANK,
15     ENTER
16 };
17 
18 struct result 
19 {
20     string token; //符号名
21     int type;     //符号类型
22     int line;     //符号所在行
23     int row;      //符号所在列
24 };
25 
26 class Tokenizer
27 {
28 public:
29     Tokenizer(void);
30     ~Tokenizer(void);
31 
32 public:
33     //
34     void ReadSourceFile(const string& fileName);
35     //
36     void Parse();
37     //
38     void HandleToken(const string token,int line,int row);
39     //
40     void ShowResult();
41 private:
42     char* m_buffer;
43     vector<result> m_resultVec;
44 };
45 
46 #endif
#include "Tokenizer.h"

#include <fstream>

#define  BUFFSIZE 1024*1024

Tokenizer::Tokenizer(void)
{
    m_buffer = (char*)malloc(BUFFSIZE);
    memset(m_buffer,0,BUFFSIZE);
}


Tokenizer::~Tokenizer(void)
{
}
void Tokenizer::ReadSourceFile(const string& fileName)
{
    FILE* fp = fopen(fileName.c_str(),"r");
    if (fp != NULL)
    {
        fread(m_buffer,1,BUFFSIZE,fp);        
        fclose(fp);
    }
    else
    {
        cout<<"打开文件失败";
    }
}

void Tokenizer::Parse()
{
    std::string token;
    
    int currentLine = 1;//标记当前行数
    int pos = 1;//标记token在该行的位置

    int i = 0;
    char c = m_buffer[i];
    while(c != NULL)
    {
        if (c != ' ' && c != '\n')
        {
            token.append(1,c);
        }
        if (c == ' ')
        {
            HandleToken(token,currentLine,pos);
            token.clear();
        
            pos = (i + 1) + 1; //.下一个字符的下标为i+1.代表第(i+1)+1列.
        }
        if (c == '\n')
        {
            HandleToken(token,currentLine,pos);
            token.clear();
            pos = 1;
            currentLine += 1;
        }

        c = m_buffer[++i];
    }

    //处理最后一个token
    HandleToken(token,currentLine,pos);

}

void Tokenizer::HandleToken(const string token,int line,int row)
{
    if (token == "")
    {
        return;
    }

    result ret;
    ret.token = token;
    ret.line = line;
    ret.row = row;

    if (token == "if")
    {
        ret.type = KEYWORD;
    }
    else if(token == " ")
    {
        ret.type = BLANK;
    }
    else if(token == "\n")
    {
        ret.type = ENTER;
    }
    else
    {
        ret.type = ID;
    }

    m_resultVec.push_back(ret);
}

void Tokenizer::ShowResult()
{
    for (int i = 0;i<m_resultVec.size();i++)
    {
        switch(m_resultVec[i].type)
        {
        case KEYWORD:
            {
                cout<<m_resultVec[i].token<<"  "<<"("<<m_resultVec[i].line<<","<<m_resultVec[i].row<<")"<<endl;
                break;
            }
        case ID:
            {
                cout<<"ID("<<m_resultVec[i].token<<")"<<"  "<<"("<<m_resultVec[i].line<<","<<m_resultVec[i].row<<")"<<endl;
                break;
            }
        case BLANK:
            {
                break;
            }
        case ENTER:
            {
                break;
            }
        }
    }
}
 1 #include "Tokenizer.h"
 2 
 3 int main()
 4 {
 5     Tokenizer tokenizer;
 6     tokenizer.ReadSourceFile("./test.txt");
 7     tokenizer.Parse();
 8     tokenizer.ShowResult();
 9 
10     system("pause");
11     
12     return 0;
13 }

 

posted @ 2014-12-15 22:06  core!  阅读(972)  评论(0编辑  收藏  举报