简易词法分析器

最近开始学习编译器,希望能坚持下去,通过做编译器也把c++练好点,今天花了一天做了一个简单的词法分析器,过几天编译原理书到了后,希望能通过看书得到更好的方法。

//learn.cpp

#include <iostream>
#include "learn.h"
#include <fstream>
using namespace std;
static char *st_line;
static int st_line_pos;
int length;

typedef enum {
    INITIAL_STATUS,
    IN_INT_PART_STATUS,
    IN_FRAC_PART_STATUS,
    DOT_STATUS,
} ParseStatus;

void
get_token(Token *token) {
    int out_pos = 0;
    ParseStatus status = INITIAL_STATUS;
    char current_char;
    string temp;

    token->kind = BAD_TOKEN;
    while (st_line[st_line_pos] != ‘\0‘) {
        current_char = st_line[st_line_pos];
        if ((status == IN_INT_PART_STATUS ||
             status == IN_FRAC_PART_STATUS) && !isdigit(current_char) && current_char != ‘.‘) {
            token->kind = NUMBER_TOKEN;
            sscanf(token->str, "%lf", &token->value);
            return;
        }
        if (isalpha(current_char)) {
            while (current_char != ‘=‘ && current_char != ‘;‘ && current_char != ‘<‘ && current_char != ‘>‘ &&
                   current_char != ‘+‘ && current_char != ‘-‘ && current_char != ‘*‘ && current_char != ‘/‘ &&
                   current_char != ‘(‘ && current_char != ‘)‘) {
                temp += current_char;
                token->str[out_pos] = st_line[st_line_pos];
                ++st_line_pos;
                ++out_pos;
                current_char = st_line[st_line_pos];
                token->str[out_pos + 1] = ‘\0‘;
                if (temp == "if") {
                    token->kind = IF_OPERATOR_TOKEN;
                    return;
                } else if (temp == "while") {
                    token->kind = WHILE_OPERATOR_TOKEN;
                    return;
                } else if (temp == "for") {
                    token->kind = FOR_PAREN_TOKEN;
                    return;
                } else if (temp == "int") {
                    token->kind = INT_TOKEN;
                    return;
                } else if (temp == "double") {
                    token->kind = DOUBLE_TOKEN;
                    return;
                } else if (temp == "string") {
                    token->kind = STRING_TOKEN;
                    return;
                } else if (temp == "cout") {
                    token->kind = COUT_TOKEN;
                    return;
                } else if (temp == "return") {
                    token->kind = RETURN_TOKEN;
                    return;
                } else if (temp == "main") {
                    token->kind = MAIN_TOKEN;
                    return;
                }
            }
            token->kind = VARIABLE_NAME_TOKEN;
            token->string_value = temp;
            token->str[out_pos] = ‘\0‘;
            return;
        }
        if ((current_char == ‘"‘ || current_char == ‘\‘‘) && status == INITIAL_STATUS) {
            current_char = st_line[++st_line_pos];
            while (current_char != ‘"‘ && current_char != ‘\‘‘) {
                token->str[out_pos] = st_line[st_line_pos];
                out_pos++;
                temp += current_char;
                current_char = st_line[++st_line_pos];
            }
            token->string_value = temp;
            token->kind = STRING_VARIABLE_TOKEN;
            st_line_pos++;
            token->str[++out_pos] = ‘\0‘;
            return;
        }
        if (isspace(current_char)) {
            if (status == INITIAL_STATUS) {
                st_line_pos++;
                continue;
            }
        }

        token->str[out_pos] = st_line[st_line_pos];
        st_line_pos++;
        out_pos++;
        token->str[out_pos] = ‘\0‘;

        if (current_char == ‘+‘) {
            if (st_line[st_line_pos] == ‘+‘) {
                token->str[out_pos] = st_line[st_line_pos];
                token->str[out_pos + 1] = ‘\0‘;
                ++st_line_pos;
                token->kind = SELF_PLUS_ONE_OPERATOR_TOKEN;
                return;
            } else {
                token->kind = ADD_OPERATOR_TOKEN;
                return;
            }
        } else if (current_char == ‘-‘) {
            if (st_line[st_line_pos] == ‘-‘) {
                token->str[out_pos] = st_line[st_line_pos];
                token->str[out_pos + 1] = ‘\0‘;
                ++st_line_pos;
                token->kind = SELF_SUB_ONE_OPERATOR_TOKEN;
                return;
            } else {
                token->kind = SUB_OPERATOR_TOKEN;
                return;
            }
        } else if (current_char == ‘<‘) {
            if (st_line[st_line_pos] == ‘<‘) {
                token->str[out_pos] = st_line[st_line_pos];
                token->str[out_pos + 1] = ‘\0‘;
                ++st_line_pos;
                token->kind = OUT_OPERATER_TOKEN;
                return;
            } else {
                token->kind = LESS_OPERATER_TOKEN;
                return;
            }
        } else if (current_char == ‘>‘) {
            if (st_line[st_line_pos] == ‘>‘) {
                token->str[out_pos] = st_line[st_line_pos];
                token->str[out_pos + 1] = ‘\0‘;
                ++st_line_pos;
                token->kind = GET_OPERATER_TOKEN;
                return;
            } else {
                token->kind = GREATE_OPERATER_TOKEN;
                return;
            }
        } else if (current_char == ‘*‘) {
            token->kind = MUL_OPERATOR_TOKEN;
            return;
        } else if (current_char == ‘/‘) {
            token->kind = DIV_OPERATOR_TOKEN;
            return;
        } else if (current_char == ‘;‘) {
            token->kind = END_OF_LINE_TOKEN;
            return;
        } else if (current_char == ‘{‘) {
            token->kind = LEFT_BRACE_TOKEN;
            return;
        } else if (current_char == ‘}‘) {
            token->kind = RIGHT_BRACE_TOKEN;
            return;
        } else if (current_char == ‘(‘) {
            token->kind = LEFT_PARENTHESS_TOKEN;
            return;
        } else if (current_char == ‘)‘) {
            token->kind = RIGHT_PARENTHESE_TOKEN;
            return;
        } else if (current_char == ‘=‘) {
            if (st_line[st_line_pos] == ‘=‘) {
                token->kind = EQUAL_PAREN_TOKEN;
                return;
            } else {
                token->kind = ASSIGMENT_PAREN_TOKEN;
                return;
            }
        } else if (isdigit(current_char)) {
            if (status == INITIAL_STATUS) {
                status = IN_INT_PART_STATUS;
            } else if (status == DOT_STATUS) {
                status = IN_FRAC_PART_STATUS;
            }
        } else if (current_char == ‘.‘) {
            if (status == IN_INT_PART_STATUS) {
                status = DOT_STATUS;
            } else {
                fprintf(stderr, "syntax error.\n");
                exit(1);
            }
        }
    }
}

//void
//set_line(char *line) {
//    st_line = line;
//    st_line_pos = 0;
//}

void
parse_line(string filename) {
    Token token;
    st_line_pos = 0;
    char temp, test[1024];
    ifstream get;
    get.open(filename);
    int i = 0;
    while (!get.eof()) {
        get.read(&temp, 1);
        test[i++] = temp;
    }
    length = i;
    st_line = test;
    for (;;) {
        get_token(&token);
        if (st_line_pos == length) {
            return;
        }
        printf("kind..%d, str..%s\n", token.kind, token.str);
    }
}

int main() {
    string filename = "/home/liuyu/文档/test";
    parse_line(filename);
    return 0;
}
//learn.h

#ifndef LEARN_LEARN_H
#define LEARN_LEARN_H

#include <iostream>
using namespace std;

typedef enum {
    BAD_TOKEN,
    NUMBER_TOKEN,
    STRING_TOKEN,
    INT_TOKEN,
    DOUBLE_TOKEN,
    COUT_TOKEN,
    RETURN_TOKEN,
    MAIN_TOKEN,
    IF_OPERATOR_TOKEN,
    OUT_OPERATER_TOKEN,
    GET_OPERATER_TOKEN,
    LESS_OPERATER_TOKEN,
    GREATE_OPERATER_TOKEN,
    LEFT_BRACE_TOKEN,
    RIGHT_BRACE_TOKEN,
    LEFT_PARENTHESS_TOKEN,
    RIGHT_PARENTHESE_TOKEN,
    WHILE_OPERATOR_TOKEN,
    EQUAL_PAREN_TOKEN,
    FOR_PAREN_TOKEN,
    ASSIGMENT_PAREN_TOKEN,
    END_OF_LINE_TOKEN,
    VARIABLE_NAME_TOKEN,
    STRING_VARIABLE_TOKEN,
    ADD_OPERATOR_TOKEN,
    SUB_OPERATOR_TOKEN,
    MUL_OPERATOR_TOKEN,
    DIV_OPERATOR_TOKEN,
    SELF_PLUS_ONE_OPERATOR_TOKEN,
    SELF_SUB_ONE_OPERATOR_TOKEN,
    END_TOKEN
} TokenKind;

#define MAX_TOKEN_SIZE (100)

typedef struct {
    TokenKind kind;
    double      value;
    string      string_value;
    char        str[MAX_TOKEN_SIZE];
} Token;

void set_line(char *line);
void get_token(Token *token);

#endif

测试:

时间: 2025-01-02 09:07:37

简易词法分析器的相关文章

【词法分析器 】 编译原理作业

自己写的版本: 问题: 1:考虑到由于是嵌套接收,浮点型感觉少麻烦,因为还要判断是否两个小数点等,古没有实现 2:对于一些特殊符号,如三元运算符,格式控制符%d等分析不到位 3:类别应该分的更细,否则用唯一的symbol(sym)标识的话无法进行后续的语法分析 4:没有用文件指针,数据输入要在控制台,不利于交互 #include <iostream> #include <string.h> #include <cstdio> using namespace std; i

词法分析器

相关定义: 识别器:可以在字符流中识别特定单词的程序. 有限自动机(FA):识别器的一种形式化方法,包含一个有限状态集,一个字母表,一个转移函数,一个起始状态和一个或多个接受状态. 正则表达式:有限自动机所接受的单词的集合,形成的语言.eg:n(ew|ot) RE--NFA--DFA--最小DFA--词法分析器 RE-NFA:Thompson构造法,re的连接,选择,闭包等有一个模板,各部分的连接也有一个模板,按照模板构造 NFA--DFA:子集构造法(不动点计算,即即便计算过程中不断添加要计算

Android 开发第七弹:简易时钟(秒表)

本文承接,Android 开发第五弹:简易时钟(闹钟) 和 Android 开发第六弹:简易时钟(计时器),这一部分是关于秒表的. 布局 同样是新建一个类(StopWatchView)并扩展自LinearLayout,并将其用作布局. <myapplication.nomasp.com.clock.StopWatchView android : id = "@+id/tabStopWatch" android : layout_width = "match_parent

最简易无加密方式下的ppp拨号连接

PPP拨号连接建立虚拟网卡,并可以进行路由设置.几乎所有其他的连接服务都建立在其之上,PPPoE,PPTP,L2TP等等. 而其中一个最基本的话题可能被忽略了,PPP是如何工作的,如何使用PPP建立最简易的连接. PPP协议实际上非常简单,握手信号之后即进行数据交换,由于原来的PPP连接的使用都是基于电话MODEM的点对点通信,不考虑过于复杂的加密并保证传输效率,所以PPP的缺省设置是基于tty设备的,如果使用串口就是ttyS0-ttyS? 当然,使用pppd应用于附加服务并不必须使用tty设备

求问自制简易Android地图大概思路

============问题描述============ 我想做一个简易的Android地图,不使用Google的API.让它可以实现移动,缩放,旋转,标记的功能.我现在知道的大体思路是把整张地图图片切割成若干小块,然后让这些小块共同移动,旋转.但是不知道这个思路对不对,还有使用什么Android控件和方法实现,请各位大神指点,谢谢!! ============解决方案1============ 引用 2 楼 despotdragon 的回复: Quote: 引用 1 楼 ITbailei 的回

简易状态机

SimpleFSM 包含状态切换以及事件驱动传递参数 下面的代码是登录的状态码 1 using System; 2 using UnityEngine; 3 using System.Collections; 4 5 public class LoginState : SingletonPrivider<LoginState>, GameState 6 { 7 private delegate void LoginEventHandler(object sender, LoginEventAr

在.NET里简易实现IoC

在.NET里简易实现IoC 前言 在前面的篇幅中对依赖倒置原则和IoC框架的使用只是做了个简单的介绍,并没有很详细的去演示,可能有的朋友还是区分不了依赖倒置.依赖注入.控制反转这几个名词,或许知道的也只是知道依赖倒置是原则,依赖注入.控制反转都是实现的方式,我将在下面对这些个名词做详细的介绍,在篇幅的最后还会自己实现了IoC容器的功能. 依赖倒置原则 我们先来看一段代码,代码1-1 public class Top { public void Execution() { Underly unde

老八系统简易调用AJAX

<script src="js/jquery-1.7.2.min.js"></script> <script> $(function(){ $("#txtaccount").blur(function(){ $.post("check.asp", { name:$(this).val(), type:"tjnickname" }, function(data,status){ if(data

简易2D横版RPG游戏制作

Unity学习笔记1 简易2D横版RPG游戏制作 http://m.blog.csdn.net/article/details?id=24601905