自制编译器---c++实现词法分析器

本文介绍了一个使用C++实现的简单编译器词法分析器,该词法分析器能将输入的源代码转换成一系列词法单元,便于后续的语法分析。文章详细展示了如何定义词法单元,并在主程序中进行单词的分割。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一直想写一个编译器,在csdn上看到tyler_download网友用Java写的编译器,自己也有所启发,非常感谢他的分享,但是,感觉他的词法分析函数的调用过多,感觉很是不习惯,同时还很复杂,自己是学c/c++的,因此想用c++编写一个编译器。
在这个过程中,其中对我帮助最大的是一个外国的网友,虽然不知道他的名字,但是还是要感谢他。。。。

词法单元词法解析器在编译器中的作用,是将输入流解析为一种能够被语法解析器使用和管理的格式。他将输入文本分割,打标签,也就是用一些数值来指代一系列相应的字符串。
例如:

int a,b,c;
a=34;
b=56;
int c=a*b;

经过词法单元会生成如下的形式这里写图片描述
首先定义一组词法单元

#include <iostream>
#include <string>
using namespace std;
#define NTOKEN 1000
//定义词法单元值
enum TokenValue {
    TOK_COMMA,          //逗号
    TOK_DIV,
    TOK_END,
    TOK_EQUAL,
    TOK_FOR,
    TOK_ID,
    TOK_IF,
    TOK_INTEGER,
    TOK_MINUS,
    TOK_MULT,
    TOK_PLUS,
    TOK_SEMICOLON,
    TOK_UNDEFINED,
    TOK_WHILE,
};
string TOKEN_VALUE_DESCRIPTION[] =
{
    "TOK_COMMA",
    "TOK_DIV",
    "TOK_END",
    "TOK_EQUAL",
    "TOK_FOR",
    "TOK_ID",
    "TOK_IF",
    "TOK_INTEGER",
    "TOK_MINUS",
    "TOK_MULT",
    "TOK_PLUS",
    "TOK_SEMICOLON",
    "TOK_UNDEFINED",
    "TOK_WHILE",
};
//标签和标签的值
typedef struct _Token {
    int  type;
    string str;
} Token;

然后在主程序中进行单词的分割

#include <stdio.h>
#include <ctype.h>
#include "lexer.h"
Token token[NTOKEN];
//输入参数为路径
int lexer(char *path) {
    FILE *fin;
    int  ch;
    char buf[256], *p;
    int n = 0;

    if ((fin = fopen(path, "r")) == NULL) {
        fprintf(stderr, "Cant' open the file... :(\n");
    }
    while ((ch = fgetc(fin)) != EOF) {
        if (ch <= ' ') continue;                  // [\n\t ]
        p = buf;
        switch (ch)     
        {
        case '+':
            token[n].type = TOK_PLUS;
            token[n++].str = '+';
            break;
        case '-':
            token[n].type = TOK_MINUS;
            token[n++].str = '-';
            break;
        case '*':
            token[n].type = TOK_MINUS;
            token[n++].str = '*';
            break;
        case ';':
            token[n].type = TOK_SEMICOLON;
            token[n++].str = ';';
            break;
        case '=':
            token[n].type = TOK_EQUAL;
            token[n++].str = '=';
            break;  
        case ',':
            token[n].type = TOK_COMMA;
            token[n++].str = ',';
            break;
        default:
            break;
        }
        if (isalpha(ch)) {                        // [A-Za-z][A-Za-z0-9],以字母开头为真
            token[n].type = TOK_ID;               //是一个标识符
            *p++ = ch;
            while (isalnum(ch = fgetc(fin))) *p++ = ch;  //是否为字母或数字
            ungetc(ch, fin);
            *p++ = '\0';
            token[n++].str = buf;
        }
        if (isdigit(ch)) {                 // [0-9]+
            token[n].type = TOK_INTEGER;
            *p++ = ch;
            while (isdigit(ch = fgetc(fin))) *p++ = ch;
            ungetc(ch, fin);
            *p++ = '\0';
            token[n++].str = buf;
        }
    }
    fclose(fin);
    return n;
}
/*************************************************************************************
CMD下运行的结果。
void main(int argc, char* argv[]) {
    int n;
    int nToken = lexer(argv[1]);
    for (n = 0; n < nToken; n++) {
        //printf("%s: %s\n", TOKEN_VALUE_DESCRIPTION[token[n].type], token[n].str);
        cout << TOKEN_VALUE_DESCRIPTION[token[n].type] << ": " << token[n].str << endl;
    }
}
***************************************************************************************/
//vs上调试结果
void main(int argc, char* argv[]) {
    int n;
    char* input = "aa.txt";
    int nToken = lexer(input);
    for (n = 0; n < nToken; n++) {
        cout << TOKEN_VALUE_DESCRIPTION[token[n].type] << ": " << token[n].str << endl;
    }
}
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值