2014-03-17续昨天的代码

本文介绍了一个简单的词法分析器的实现过程,该分析器能够处理特定格式的伪代码,并将其转换为词法记号序列。文章详细展示了如何通过C语言编程来识别关键字、标识符、数字以及各种符号。

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

今天早了个起,想要写完昨天的代码,万幸,刚才写完了,初步测试了一下,基本功能是有,不知道有什么bug,等会要提交,现在再从头分析一遍,找找问题

要求:对以'#'结束的标准输入进行词法分析

例如,对源程序   x:=5;  if (x>0)  then  x:=2*x+1/3;  else  x:=2/x;  #
                          经词法分析后输出如下序列:
                  (10,’x’)(18, :=) (11,5) (26, ;) (2, if )  (27,( )……                                   ( 注:前面为词法记号,后面是词法单元)

详细的表在下面,这是题目的要求,换了其他的表也是一样的

词法单元 词法记号 词法单元 词法记号
for                     1                          :                     17
if                     2                        :=               18
then             3                         <               20
else                     4                        <>               21
while             5                        <=               22
do                     6                         >               23
letter(letter+digit)*10                >=               24
digit digit*    11                     =               25
+                    13                   ;               26
-                    14                   (               27
*                    15                     )               28
/                    16                   #                0
下面是源代码,前面的函数都是很简单的,主要看看主函数的逻辑,有没有错,我等一会要发给老师了!

#include <stdio.h>
#include <string.h>

char *keyword[6] = {"for", "if", "then", "else", "while", "do"};//keywords array
int kwlength[6] = {3, 2, 4, 4, 5, 2};                           //keywords' length array
int pos = 0; 			                                //position pointer
char s[256];  			                                // input string saved in s[]
char new[32];			                                //buffer to produce substring

char *substring(char *src, int pos, int length){		//get substring
    for(int i = 0; i < length; i++){
	new[i] = s[pos + i];		
    }
    new[length] = '\0';
    return new;
}

int isLetter(char c){		                                //is a letter or not
    if(c < 'A' || c > 'z' || (c > 'Z' && c < 'a'))
	return 0;	
    return 1;
}

int isNumber(char c){		                                //is a number or not
    if(c > '9' || c < '0')
	return 0;
    return 1;
}
int readKeyword(){		                                //read keyword
    for(int i = 0; i<6; i++){
	int eq = strcmp(keyword[i], substring(s, pos, kwlength[i]));
	if(eq == 0){
	    if(isLetter(s[pos + kwlength[i]]) || isNumber(s[pos + kwlength[i]]))
		return 0;
	    printf("(%d, %s)\n", i, keyword[i]);
	    pos += kwlength[i];
	    return 1;
	}
    }
    return 0;
}

int readID(){				                       //read identifier
    if(!isLetter(s[pos]))	
	return 0;
    int old_pos = pos;
    pos++;
    while(isLetter(s[pos]) || isNumber(s[pos])){
	pos ++;
    }
    printf("(10, %s)\n", substring(s, old_pos, pos - old_pos));
    return 1;
}

int readNum(){                                                //read number
    if(!isNumber(s[pos]))
	return 0;
    int old_pos = pos;
    pos ++;
    while(isNumber(s[pos])){
	pos ++; 
    }
    if(s[pos] == '.'){
	pos ++;
	while(isNumber(s[pos])){
	    pos ++;	
	}
    }
    printf("(11, %s)\n", substring(s, old_pos, pos - old_pos));
}

int readSymbol(){                                              //read symbol
    switch(s[pos]){
	case '+':
	    pos ++;
	    printf("(13, +)\n");
	    return 1;
	case '-':
	    pos ++;
	    printf("(14, -)\n");
	    return 1;
	case '*':
	    pos ++;
	    printf("(15, *)\n");
	    return 1;
	case '/':
	    pos ++;
	    printf("(16, /)\n");
	    return 1;
	case ':':
	    pos ++;
	    printf("(17, :)\n");
	    return 1;
	case '<':
	    pos ++;
	    printf("(20, <)\n");
	    return 1;
	case '>':
	    pos ++;
	    printf("(23, >)\n");
	    return 1;
	case '=':
	    pos ++;
	    printf("(25, =)\n");
	    return 1;
	case ';':
	    pos ++;
	    printf("(26, ;)\n");
	    return 1;
	case '(':
	    pos ++;
	    printf("(27, ()\n");
	    return 1;
	case ')':
	    pos ++;
	    printf("(28, ))\n");
	    return 1;
	case '#':
	    pos ++;
	    printf("(0, #)\n");
	    return 1;
	default:
	    return 0;
    }
}

int readSymbol2(){                                          //read 2-char symbol
    if(s[pos] == '<' && s[pos + 1] == '>'){
	pos += 2;
	printf("(21, <>)\n");
	return 1;
    }
    if(s[pos] == '<' && s[pos + 1] == '='){
	pos += 2;
	printf("(22, <=)\n");
	return 1;
    }
    if(s[pos] == '>' && s[pos + 1] == '='){
	pos += 2;
	printf("(24, >=)\n");
	return 1;
    }
	return 0;
}

int isBlank(char c){                                        //is blank or not
    if(c == ' ' || c == '\t')
	return 1;
    return 0;
}

int readBlank(){                                            //read blanks
    if(isBlank(s[pos])){
	pos ++;
	while(isBlank(s[pos])){
	    pos ++;	
	}
	return 1;
    }
    return 0;
}

/*主函数的工作比较简单,将s[]中的字符一个一个拿出来判断
判断前,先将空格和制表符吞了,先判断关键字,再判断id,再判断数字,再判断二目运算法,最后是一目运算符,
如果,都判断了一遍,没有得到肯定的答案,说明这个字符不是规范输入,则提示用户并退出;
当判断到结束符'#'后,将它也分析,然后程序结束
*/
int main(){
    printf("INFORM:This is a simple program,please do not input unsupported chars.\n");
    printf("so input your source code really carefully:\n");
    gets(s);
    printf("here is the analyzation result:\n");
    while(s[pos] != '#'){
	readBlank();
	if(s[pos] != '#')
	    if(readKeyword())
		continue;
	if(s[pos] != '#')
	    if(readID())
		continue;	
	if(s[pos] != '#')
	    if(readNum())
		continue;
	if(s[pos] != '#')
	    if(readSymbol2())
		continue;
	if(s[pos] != '#')
	    if(readSymbol())
		continue;
	if(s[pos] != '#'){
	    printf("sorry, you break the rule, program exit!\n");
	    return -1;
	}
    }
    printf("(0, #)\n");
    return 1;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值