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


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

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

     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 != '
    ')
            {
                token.append(1,c);
            }
            if (c == ' ')
            {
                HandleToken(token,currentLine,pos);
                token.clear();
            
                pos = (i + 1) + 1; //.下一个字符的下标为i+1.代表第(i+1)+1列.
            }
            if (c == '
    ')
            {
                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 == "
    ")
        {
            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 }
  • 相关阅读:
    QT多个UI文件加入一个项目
    【Go语言】学习资料
    MVC如何在Pipeline中接管请求的?
    ASP.NET MVC路由(5)
    C# dll 事件执行 js 回调函数
    初识Identity
    SpringMVC拦截器
    UrlRouting的理解
    ASP.NET MVC路由
    ASP.NET MVC Module
  • 原文地址:https://www.cnblogs.com/sdu20112013/p/4164345.html
Copyright © 2020-2023  润新知