简单词法分析器的实现


title: 简单词法分析器的实现
date: 2018-10-08 23:15:26
updated: 2018-10-08 23:15:26
description: 简单词法分析器的实现_编译原理实现
categories: 必修
photo:
tags:

  • 编译原理
    music-id: 415793869
    password:
    math:

一.实验题目

用C或C++语言编写一个简单的词法分析程序,扫描C语言小子集的源程序,根据给定的词法规则,识别单词,填写相应的表。如果产生词法错误,则显示错误信息、位置,并试图从错误中恢复。简单的恢复方法是忽略该字符(或单词)重新开始扫描。

二.词法分析规则:

<标识符>::=<字母>
<标识符>::=<标识符><字母>
<标识符>::=<标识符><数字>
<无符号整数>::=<数字>
<无符号整数>::=<数字序列><数字>
<数字序列>::=<数字序列><数字>
<数字序列>::=<数字>
<字母>::=a|b|c|……|x|y|z
<数字>::=0|1|2|3|4|5|6|7|8|9

<加法运算符>::=+|-
<乘法运算符>::=*|/
<关系运算符>::=<|>|!=|>=|<=|==
<分界符>::=,|;|(|)|{|}
<保留字>::=main|int|if|else|while|do

三.实现任务

1.根据给定的词法规则,识别单词,填写相应的表。
2.忽略空白字符,注释
3.产生词法错误时,显示错误信息、位置,并试图从错误中恢复。

四.实现流程

1.读到空格则略过,读下一个字符;若读到的是字母,就再接着读,直到读到的既不是字母也不是数字也不是下划线,并将读到的写入到token数组;
2.若读到的是数字,直到读到的不是数字或小数点,将读到的写入到token数组;
3.若读到的是<|>|=,则再读入下一位,若为=,则该运算符为<=|>=|==,若为其他字符,则返回<|>|=的种别码;若读到的是/,则读下一位,若为*,则说明之后为注释内容,一直读入直到读入*,并判断下一位是否为/,若是则注释结束,不是继续往下一位读入;若读入\n,则行数加一,若读入的字符与以上都不匹配,则报错,并输出出错行数。
https://i-blog.csdnimg.cn/blog_migrate/9bbad76fcad94e1776743f7646f4638b.png

五.种别码:

单词符号种别码单词符号种别码
#0+18
Num1-19
Letter2*20
main3/21
if4=22
else5>23
do6>=24
while7<25
for8<=26
swtich9;27
case10"28
int11++29
double1230
float13/*31
long14*/32
void15{33
(16}34
)17

六.代码实现

#include<bits/stdc++.h>
using namespace std;

const int max_word = 505;
char token[12];
char in[105];
FILE *fin,*fout;
int cnt = 0,token_num = 0;
int row = 1;
int flag = 0;
char ch;
//关键字 
const char keyWord[13][20] = {"main","if","else","do","while","for","switch",
"case","int","double","float","long","void"};


void init_token(){
	int i;
	for(i = 0;i < 12;i++){
		token[i] = NULL;
	}
}

int judge_token(){
	init_token();
	if(flag == 0){
		ch = getc(fin);
	}
	flag = 1;
	while(ch == ' ' || ch == '\t' || ch == '\n'){
		if(ch == '\n'){
			row++;
		}
		ch=getc(fin);
	}
	token_num = 0;
	if((ch>='a' && ch <= 'z') || (ch >= 'A' &&ch <= 'Z')){
		//可能为标识符或者变量名 
		while((ch>='a' && ch <= 'z') || (ch >= 'A' &&ch <= 'Z') || (ch >= '0' && ch <= '9')){
			token[token_num++] = ch;
			ch = getc(fin);
		}
		token[token_num++] = '\0';
		for(int i = 0;i <13;i++){
			if(strcmp(token,keyWord[i]) == 0){
				//3为关键词 
				return 3;
			}
		}
		//2为标识符 
		return 2;
	}
	//是数字 
	else if(ch >= '0' && ch <= '9'){
		while((ch >= '0'&& ch <= '9') || ch == '.'){
			token[token_num++] = ch;
			ch = getc(fin);
		}
		return 1;
	}
	else{
		token[token_num++] = ch;
		switch(ch){
			case '(': ch = getc(fin); return 16;
			case ')': ch = getc(fin); return 17;
			case '{': ch = getc(fin); return 33;
			case '}': ch = getc(fin); return 34;
			case '+':
				ch = getc(fin);
				if(ch == '+'){
					token[token_num++] = ch;
					ch = getc(fin); 
					return 29;
				}
				else{
					return 18;
				}
			case '-':
				ch = getc(fin);
				if(ch == '-'){
					token[token_num++] = ch;
					ch = getc(fin); 
					return 30;
				}
				else{
					return 19;
				}
			case '*':
				ch = getc(fin);
				if(ch == '/'){
					token[token_num++] = ch;
					ch = getc(fin); 
					return 32;
				}
				else{
					return 20;
				}
			case '/':
				ch = getc(fin);
				if(ch == '*'){
					token[token_num++] = ch;
					ch = getc(fin); 
					return 31;
				}
				else{ 
					return 21;
				}
			//这里要重新编码 
			case '=':
				ch = getc(fin);
				if(ch == '='){
					token[token_num++] = ch;
					ch = getc(fin); 
					return 23;
				}
				else{
					return 22;
				}
			case '>':
				ch = getc(fin);
				if(ch == '='){
					token[token_num++] = ch;
					ch = getc(fin); 
					return 24;
				}
				else{
					return 23;
				}
			case '<':
				ch = getc(fin);
				if(ch == '='){
					token[token_num++] = ch;
					ch = getc(fin); 
					return 26;
				}
				else{
					return 25;
				}
			case ';': ch = getc(fin); return 27;
			case '"': ch = getc(fin); return 28;
			case '!':
				ch = getc(fin);
				if(ch == '='){
					token[token_num++] = ch;
					ch = getc(fin); 
					return 37;
				}
				else{
					return 36;
				}
			case '#': ch = getc(fin); return -2;
			case ',': ch = getc(fin); return 35;
			case EOF: return -1;
			default: ch = getc(fin); return -10;
		}
	}
}

void getWord(){
	int temp;
	while(1){
		temp = judge_token();
		if(temp==-1){
			break;
		}
		switch(temp){
			case -10:
				cout<<"第 "<<row<<" 行出现错误."<<endl;
				break;
			default:
				cout<<"<"<<temp<<","<<token<<">"<<endl;
				break;
		}
	}
}

int main(){
	fin = fopen("compiler.txt","r");
	getWord();
	return 0;
}

七.样例结果

样例:

在这里插入图片描述

结果:

在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值