简单词法分析器实现

编写分析器有两种方法,一种是通过DFA对单词进行识别,二是通过直接编敲代码进行识别。

本程序採用DFA对单词进行识别。

DFA的实现方法。大概思想和书上一致,在程序中,则是用二维数组代表状态转换矩阵,用一维数组表示终态。

一个词法编辑要实现的功能主要包含下面几点:

可以识别标识符、keyword、数字和运算符,对凝视进行过滤。同一时候还能识别出程序错误。

使用说明:

本程序的输入由当前文件夹下的in.txt文件读取输入,输出为一系列二元式

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//用指针而不是二维数组表示。这样就不用指定字符串长度,仅仅是不能改动指针所指向字符串的内容
char *key[]={"int","char","float","double","void","const","for","if","else","then","while","switch","break","main","return"};
char buffer[20];//存储当前识别出的单词
char *identifier[50];
char *num[50];
int ident_num;//标志符数
int number;//数字数
int judgement_num(char c) {
	if (c >= ‘0‘ && c <= ‘9‘) return 0;
	else if (c == ‘.‘) return 1;
	return -1;
}
int judge(char c){
	if(c==‘_‘) return 2;
	else if(c>=‘0‘&&c<=‘9‘) return 1;
	else if(c>=‘a‘&&c<=‘z‘||c>=‘A‘&&c<=‘Z‘) return 0;
	return -1;
}
//next_i,next_j分别代表着状态转换表move的当前状态与接收到的字符
//width代表每一状态可能遇到的状态数,length代表终态集大小
int DFA(int begin,int move[],int width,int final[],int length,int(*judge)(char)){
    int len=0,next_i,next_j,tmp;
    char next_char;
    memset(buffer,0,sizeof(buffer));
    next_char=getchar();
    next_i=begin;
    while((next_j=judge(next_char))!=-1){
		tmp=next_i;
		next_i=move[next_i*width+next_j];
		if(next_i==-1){
            printf("move[%d][%d]has not next state\n",tmp,next_j);
            return -1;
		}
		buffer[len++]=next_char;
        next_char=getchar();

    }
    ungetc(next_char,stdin);
    buffer[len]=‘\0‘;
    for(int i=0;i<length;i++){
		if(next_i==final[i])  return 0;
    }
    return -1;
}

void is_comment(){
    char next_char;
    char tmp[5];
    memset(tmp,0,sizeof(tmp));
    tmp[0]=getchar();
    next_char=getchar();
    if(next_char==‘*‘){
		while((next_char=getchar())!=EOF){
            if(next_char==‘*‘&&getchar()==‘/‘) return;
		}
		printf("The comment is error\n");
    }
    else if(next_char==‘/‘){
        while((next_char=getchar())!=‘\n‘);
    }
    else if(next_char==‘=‘){
        printf("(/=,_)\n");
    }
    else{
		printf("(/,_)\n");
		ungetc(next_char,stdin);
    }
}
void is_other(){
    char next_char,c=getchar();
    if(c==‘+‘||c==‘-‘||c==‘*‘||c==‘%‘){
        next_char=getchar();
        if(next_char==‘=‘) printf("(%c=,_)\n",c);
        else {
			printf("(%c,_)\n",c);
			ungetc(next_char,stdin);
        }
    }
    else if(c==‘>‘||c==‘<‘){
		next_char=getchar();
        if(next_char==‘=‘) printf("(rlop,%c=)\n",c);
        else {
			printf("(rlop,%c)\n",c);
			ungetc(next_char,stdin);
        }
    }
    else if(c==‘!‘){
		next_char=getchar();
        if(next_char==‘=‘) printf("(!=,_)\n");
        else {
			printf("(not,_)\n");
			ungetc(next_char,stdin);
        }
    }
    else if(c==‘|‘){
		next_char=getchar();
        if (next_char == ‘|‘)
			printf("(or,||)\n");
		else {
			ungetc(next_char, stdin);
		}
    }
    else if(c==‘&‘){
		next_char=getchar();
        if (next_char == ‘&‘)
			printf("(and,&&)\n");
		else {
			ungetc(next_char, stdin);
		}
    }
    else if(c==‘=‘||c==‘(‘||c==‘)‘||c==‘[‘||c==‘]‘||c==‘;‘||c==‘,‘||c==‘{‘||c==‘}‘){
        printf("(%c,_)\n",c);
    }
}
void is_digit(){
    int begin=0;
    int move[]={1,-1,1,2,2,-1};
	int final[]={1,2};
	int result=-1;
	result=DFA(begin,move,2,final,2,judgement_num);
	if(result==-1){
		printf("digit DFA error\n");
		exit(-1);
	}
	else if(result==0){
        //printf("%s\n",buffer);
        for(int i=0;i<number;i++){
			if(strcmp(buffer,num[i])==0){
                printf("(num,%s)\n",buffer);
				return;
			}
        }
        num[number]=(char*)malloc(sizeof(buffer));
        strcpy(num[number++],buffer);
        printf("(num,%s)\n",buffer);
        return;
	}
}
void is_letter(){
	int i;
	int begin=0;
	int move[] ={1,-1,1,1,1,1};
	int final[]={1,2};
	int result=-1;
	result=DFA(begin,move,3,final,1,judge);
    if(result==-1){
		printf("letter DFA error\n");
		exit(-1);
    }
    else if(result==0){
		int len=sizeof(key)/sizeof(char *);
		//如为keyword
        for(i=0;i<len;i++){
			if(strcmp(buffer,key[i])==0){
                printf("(key,%s)\n",key[i]);
                return;
			}
        }
        //如为标志符
        for(i=0;i<ident_num;i++){
			//在当前标志符表中已经存在
			if(strcmp(buffer,identifier[i])==0){
				printf("(%id,%s)\n",identifier[i]);
				return;
			}
        }
        //如不存在,则写入
        identifier[ident_num]=(char*)malloc(sizeof(buffer));
        strcmp(identifier[ident_num++],buffer);
        printf("(id,%s)\n",buffer);
        return;
    }
}

void init() {
	ident_num=0;
    number=0;
}
void work() {
	char c;
    while((c=getchar())!=EOF){
		ungetc(c,stdin);
		if(judge(c)==2||judge(c)==0) is_letter();
		else if(judge(c)==1) is_digit();
		else if(c==‘/‘) is_comment();
		else is_other();
    }
}

int main() {
    freopen("in.txt","r",stdin);
    init();
    work();
    return 0;
}
时间: 2024-10-29 19:12:41

简单词法分析器实现的相关文章

编译原理简单词法分析器(first,follow,分析表)源码下载

编译原理(简单词法分析器下载) http://files.cnblogs.com/files/hujunzheng/%E7%AE%80%E5%8D%95%E8%AF%AD%E6%B3%95%E5%88%86%E6%9E%90%E5%99%A8.zip

java实现的简单词法分析器

一个简单的词法分析器 词法分析(Lexical Analysis) 是编译的第一阶段.词法分析器的主要任务是读入源程序的输入字符.将他们组成词素,生成并输出一个词法单元序列,每个词法单元对应一个词素.这个词法单元序列被输出到语法分析器进行语法分析. 有关原理的介绍参考http://www.cnblogs.com/yanlingyin/archive/2012/04/17/2451717.html 这里就不多说了. 下面直接代码,相关注释在代码中均已经给出,对字符串的处理完全按照自己的思路编写的.

简单词法分析器的实现

用c语言对一个简单的语言的子集编制一个一遍扫描的编译程序 #include <iostream> #include <string.h> #include <ctype.h> char prog[80],token[8]; char ch; int syn,p,m,n,sum=0; char *rwtab[6]={"begin","if","then","while","do&qu

表达式求值:从“加减”到“带括号的加减乘除”的实践过程

本文乃Siliphen原创,转载请注明出处:http://blog.csdn.net/stevenkylelee ● 为什么想做一个表达式求值的程序 最近有一个需求,策划想设置游戏关卡的某些数值,这个数值不是一个常量,而是根据关卡的某些环境数据套上一个计算表达式算出来的.这个需求无法用excel拖表预计算出,因为关卡的环境数据只有在游戏中才能产生,在excel制表时,这些都是未知的.作为程序员,我可以把计算表达式硬编码在代码中,但这个做法有缺陷,如果策划要修改计算表达式的话,只能通过我修改程序并

编译原理(简单自动词法分析器LEX)

编译原理(简单自动词法分析器LEX)源程序下载地址:  http://files.cnblogs.com/files/hujunzheng/%E6%B1%87%E7%BC%96%E5%8E%9F%E7%90%86%E7%AE%80%E5%8D%95LEX%EF%BC%88%E8%AF%8D%E6%B3%95%E8%87%AA%E5%8A%A8%E5%88%86%E6%9E%90%E5%99%A8%EF%BC%89.zip

C词法分析器的Python简单实现

原文引用https://www.dazhuanlan.com/2019/08/25/5d62598fd13ee/ 在学习编译原理的课程设计中,需要设计一个词法分许进程.于是尝试用Python来简单实现C语言词法分析器.其中其实并没有什么具体需要克服的难处,只要将部分的词法分析DFA设计好,实现起来思路便更清晰. ? 1.前言 C语言中我们需要提取出关键字,标识符,分隔符,运算符,不同数据类型的常量.其中标识符.标识符及分隔符的提取更简单,而运算符因为各运算符组合具有不同意义需详细分解,例如:>>

自己动手实现简单编译器之(二)词法分析器和有穷自动机

一:实验指导书 对下述单词表定义的语言设计编制一个词法分析器.单词符号及种别表和词法分析器功能及基本要求如下: (1)单词符号及种别表 单词符号 种别编码 单词值 main 1   int 2   float 3   double 4   char 5   if 6   else 7   do 8   while 9   l(l|d)* 10 内部字符串 ( +|-|ε ) dd*(.dd* | ε)( e ( +|-|ε ) dd*|ε) 20 二进制数值表示 = 21   + 22   -

简易词法分析器

最近开始学习编译器,希望能坚持下去,通过做编译器也把c++练好点,今天花了一天做了一个简单的词法分析器,过几天编译原理书到了后,希望能通过看书得到更好的方法. //learn.cpp #include <iostream> #include "learn.h" #include <fstream> using namespace std; static char *st_line; static int st_line_pos; int length; type

Luence简单实现1

初步认识Luence,简单按照官方文档做了个例子,大牛绕开,仅供小白路过参考.如有错误,欢迎指正批评. 建一个简单工程,并且加入这几个小奶瓶,如下图: 注:版本不同,可能对jdk的需求是不同的,这个需要注意,我在尝试的6.1.0的时候,在jdk1.7下会报错,在java8下就没问题.5.x的在1.7下应该没问题,具体需要自行百度. 然后根据官网例子,稍加修改,如下:本例子基于内存存储 //创建词法分析器 Analyzer analyzer = new StandardAnalyzer(); //