首页
社区
课程
招聘
我写的pl0词法分析代码,大家给点意见
发表于: 2005-6-29 10:37 5228

我写的pl0词法分析代码,大家给点意见

2005-6-29 10:37
5228
正准备继续写符号表和语法分析:
有志同道合的朋友不妨好好交流

/*
Name: Scanner.h
version: 0.2
Copyright: 版权所有
Author: 刘奇
Date: 28-06-05 01:35
Description: pl0词法分析程序
*/

#ifndef SCANNER_H
#define SCANNER_H

#include <set>
#include <string>
#include <iostream>

using namespace std;

typedef enum token_type
{
        //End of file
        ENDFILE = 200,   // '.'
        
        //**** identifier *********************************
        ID = 0,
               
        //**** keyword ************************************
                KEYWORD = 1,
               
                //**** delimiter **********************************
                SEMICOLON = 2, // ';'
                COMMA = 3, // ','
                ASSIGNOP = 4, // ":="
                PLUSOP = 5, // '+'
                SUBOP = 6, // '-'
                MULOP = 7, // *
                DIVOP = 8, // '/'
                LPAREN = 9, // '('
                RPAREN = 10, // ')'
               
                //**** Operation *********************************
                GT = 12, // '>'
                LT = 13, // '<'
                GE = 14, // '>='
                LE = 15, // '<='
                COLON = 16, // ':'
                EQ = 17, // '='
                SEMI = 18, // ';'
                SHARP = 19,
               
                //**** NUM **********************************
                NUM = 20
};

class Scanner
{
public:
        Scanner(string src_file_name);
        ~Scanner();
       
public:
        void SetReserved(); //设置保留字表
        token_type CheckReserved();   //检测token_string是否为保留字
        void ShowReserved();   //显示所有的保留字,用于测试保留字表是否正确
        void ShowAllTokens(); //显示所有的token_string及其类型
        token_type GetToken(); //返回token 类型
       
private:
        char GetNextChar();                //返回下一个字符
        void UngetNextChar(char in_char);        //回退一个字符
       
private:
        set<string> set_of_reserved_words; //存放保留字的集合
        string token_string;
        token_type token;
       
private:
        FILE *src_file;                //保存pl0源代码的文件指针
        FILE *listing;      //输出文件
};

Scanner::Scanner(string src_file_name)
{
        src_file = fopen(src_file_name.c_str(), "r"); //打开存放源代码的文件
        if (!src_file) //打开文件失败
        {
                cout << "Open file " << "source file: " << src_file_name << " faild!!" << endl;
                exit(-1);
        }
       
        listing = fopen("listing.txt", "w");
        if (!listing) //打开文件失败
        {
                cout << "Open file " << "listing file: " << " faild!!" << endl;
                exit(-1);
        }
}

Scanner::~Scanner()
{
        fclose(src_file);
        fclose(listing);
}

token_type Scanner::CheckReserved()
{        //查找token
        set<string>::iterator iter = set_of_reserved_words.find(token_string);
        //找到token, 说明token是保留字
        if (iter != set_of_reserved_words.end())
        {
                return KEYWORD;
        }
        else //没有找到,返回ID
        {
                return ID;
        }
}

void Scanner::SetReserved()
{
        set_of_reserved_words.insert("var");
        set_of_reserved_words.insert("procedure");
        set_of_reserved_words.insert("begin");
        set_of_reserved_words.insert("end");
        set_of_reserved_words.insert("read");
        set_of_reserved_words.insert("write");
        set_of_reserved_words.insert("if");
        set_of_reserved_words.insert("then");
        set_of_reserved_words.insert("call");
        set_of_reserved_words.insert("while");
        set_of_reserved_words.insert("do");
        set_of_reserved_words.insert("const");
}

void Scanner::ShowAllTokens()
{
        token_type tmp_token;
        while ((tmp_token = GetToken()) != ENDFILE)
        {
                fprintf(listing, "type: %d, ", tmp_token);
                if (tmp_token != NUM)
                {
                        fprintf(listing, "%s\n", token_string.c_str());
                }
                else
                {
                        fprintf(listing, "%d\n", atoi(token_string.c_str()));
                }
        }
}

char Scanner::GetNextChar()
{
        char in_char = EOF;
       
        if (!feof(src_file))
        {
                in_char = fgetc(src_file);
        }
       
        return in_char;
}

void Scanner::UngetNextChar(char in_char)
{
        ungetc(in_char, src_file);
}

void Scanner::ShowReserved()
{
        set<string>::iterator iter_end = set_of_reserved_words.end();
       
        cout << endl << "All reserved words: " <<endl;
        set<string>::const_iterator iter = set_of_reserved_words.begin();
        for (; iter != iter_end; iter++)
        {
                cout << *iter << "\t";
        }
        cout << endl << endl;
}

token_type Scanner::GetToken()
{
        int token_length = 0;
        char in_char;
        const max_token_length = 10;
       
        token_string.resize(0);
       
    while ((in_char = GetNextChar()) != EOF)
        {       
                while (in_char == '\t' || in_char == '\n' || in_char == ' ')
                {
                        in_char = GetNextChar();
                }
                //数字
                if (isdigit(in_char))
                {
                        do
                        {
                                token_string += in_char;
                                in_char = GetNextChar();
                        }while (isdigit(in_char));
                        UngetNextChar(in_char);
                        token = NUM;
                }
                //ID OR reserved word
                else if (isalpha(in_char))
                {
                        do
                        {
                                token_string += in_char;;
                                token_length ++;
                                in_char = GetNextChar();
                        }while (isalpha(in_char) && (token_length < max_token_length));
                        UngetNextChar(in_char);
                        token = CheckReserved();
                }
                //是否是赋值符号
                else if (in_char == ':')
                {
                        token_string += in_char;
                        in_char = GetNextChar();
                        if (in_char == '=')
                        {
                                token = ASSIGNOP;
                        }
                        else
                        {
                                UngetNextChar(in_char);
                                token = COLON;
                        }
                }
                //其它符号
                else
                {
                        switch (in_char)
                        {
                        case EOF:
                                token = ENDFILE;
                                break;
                        case '=':
                                token = EQ;
                                break;
                                /////////////////////////////////////////////////////////
                                //未支持  >= <=
                        case '<':
                                token = LT;
                                break;
                        case '>':
                                token = GT;
                                break;
                                ////////////////////////////////////////////////////////
                        case '+':
                                token = PLUSOP;
                                break;
                        case '-':
                                token = SUBOP;
                                break;
                        case '*':
                                token = MULOP;
                                break;
                        case '/':
                                token = DIVOP;
                                break;
                        case '(':
                                token = LPAREN;
                                break;
                        case ')':
                                token = RPAREN;
                                break;
                        case ';':
                                token = SEMI;
                                break;       
                        case ',':
                                token = COMMA;
                                break;
                        case '#':
                                token = SHARP;
                                break;                               
                        case '.':
                                token = ENDFILE;///////////////////////
                                break;       
                        default:       
                                fprintf(listing, "Unknown : %d\n", in_char);
                                token = ENDFILE;
                                break;
                        }
                }
                break;
        }

        return token;
}
       
#endif

测试程序:
#include "Scanner.h"

int main()
{
        Scanner scan("testPas.txt");
        scan.SetReserved();
        scan.ShowReserved();
        scan.ShowAllTokens();

        return 0;
}

测试文件:
        const a=10;
        var b,c;
        procedure p;
                var d;
                begin
                        d:=20;
                        c:=d/a;
                        c:=c+b;
                end;
        begin
                read (b);
                while b#0 do
                        begin
                                call p;
                                write(2*c);
                                read(b);
                        end
        end.

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 390
活跃值: (707)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
2
不错

不过在
      case '<':
        token = LT;
        break;
      case '>':
        token = GT;
        break;
里再分析一到二个字符就可以支持<=了

为什么不继续呢?
2005-6-29 16:15
0
雪    币: 267
活跃值: (235)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
3
最初由 firstrose 发布
不错

不过在
case '<':
token = LT;
........


使用>, <, =  也可以完成>=, <=的功能,这次为了简单就不写了,第一次写编译器,打算先搞清楚基本原理,放假想写个相对比较完善的Minus c 编译器,欢迎多交流
2005-6-29 19:25
0
雪    币: 255
活跃值: (175)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
4
编译原理的课程设计不就是做的这个吗???
2005-6-29 19:40
0
游客
登录 | 注册 方可回帖
返回
//