今天早了个起,想要写完昨天的代码,万幸,刚才写完了,初步测试了一下,基本功能是有,不知道有什么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;
}