最近在学习编译原理,用图转移算法写了一个IF的词法分析器,本来觉得原理挺简单的,没想到还鼓弄了一天才弄出来,这里把写的代码放这里记录下
通过myfile.txt输入。输入与输出如下
输入:
ifx if iif if 234
iff if
输出 第一代表行数,第二个代表开始地址
代码如下,
1 #include<stdio.h> 2 #include<memory.h> 3 #include<stdlib.h> 4 5 enum kind {IF, ID, NUM}; 6 7 typedef struct{ 8 enum kind k; 9 char lexeme[10]; 10 int line[2]; 11 }token; 12 13 typedef struct ListNode{ 14 token val; 15 struct ListNode *next; 16 }node; 17 18 void Printnode(node *head); 19 void Freenode(node *head); 20 21 // Buildtoken using link to store tokens 22 node * Buildtoken(node *cur, char *buf, int linenum) 23 { 24 int buf_index = 0; 25 int lexeme_index = 0; 26 int status = -1; 27 //node *head = cur; 28 29 cur->val.line[0] = linenum; 30 while(buf[buf_index] == ' ') 31 buf_index++; 32 cur->val.line[1] = buf_index+1; 33 34 status3: 35 if(('0' <= buf[buf_index]) && (buf[buf_index] <= '9')) 36 status = 0; 37 38 if((('A' <= buf[buf_index]) && (buf[buf_index] <= 'Z')) 39 || ('a' <= buf[buf_index] && buf[buf_index] <= 'h') 40 || ('j' <= buf[buf_index] && buf[buf_index] <= 'z') ) 41 status = 1; 42 43 if(buf[buf_index] == 'i') 44 status = 2; 45 46 switch (status) 47 { 48 case 0: 49 cur->val.k = NUM; 50 cur->val.lexeme[lexeme_index++] = buf[buf_index++]; 51 while('0' <= buf[buf_index] && buf[buf_index] <= '9') 52 { 53 cur->val.lexeme[lexeme_index++] = buf[buf_index]; 54 buf_index++; 55 } 56 57 if((('A' <= buf[buf_index]) && (buf[buf_index] <= 'Z')) 58 || ('a' <= buf[buf_index] && buf[buf_index] <= 'z')) 59 { 60 cur->val.lexeme[lexeme_index++] = buf[buf_index]; 61 buf_index++; 62 goto status1; 63 } 64 65 break; 66 case 1: 67 status1: 68 cur->val.k = ID; 69 70 while((('A' <= buf[buf_index]) && (buf[buf_index] <= 'Z')) 71 || ('a' <= buf[buf_index] && buf[buf_index] <= 'z')) 72 { 73 cur->val.lexeme[lexeme_index++] = buf[buf_index]; 74 buf_index++; 75 } 76 goto status2; 77 break; 78 case 2: 79 cur->val.k = IF; 80 cur->val.lexeme[lexeme_index++] = buf[buf_index++]; 81 if(buf[buf_index] == 'f') 82 { 83 cur->val.lexeme[lexeme_index++] = buf[buf_index++]; 84 } 85 if((('A' <= buf[buf_index]) && (buf[buf_index] <= 'Z')) 86 || ('a' <= buf[buf_index] && buf[buf_index] <= 'z')) 87 goto status1; 88 goto status2; 89 break; 90 default: 91 status2: 92 while(buf[buf_index] == ' ') 93 { 94 buf_index++; 95 } 96 if(buf[buf_index] == ' ' || buf[buf_index] == EOF) 97 { 98 return cur; 99 } 100 cur->next = malloc(sizeof(node)); 101 cur = cur->next; 102 cur->next = NULL; 103 cur->val.line[0] = linenum; 104 cur->val.line[1] = buf_index + 1; 105 lexeme_index = 0; 106 status = -1; 107 goto status3; 108 } 109 return cur; 110 } 111 112 //Print nodes 113 void Printnode(node *head) 114 { 115 node *cur = head; 116 while(cur != NULL) 117 { 118 switch (cur->val.k) 119 { 120 case IF: 121 printf("IF (%d, %d) ", cur->val.line[0], cur->val.line[1]); 122 break; 123 case ID: 124 printf("ID(%s) (%d, %d) ", cur->val.lexeme,cur->val.line[0], cur->val.line[1]); 125 break; 126 case NUM: 127 printf("NUM(%s) (%d, %d) ", cur->val.lexeme,cur->val.line[0], cur->val.line[1]); 128 break; 129 default: 130 break; 131 } 132 cur = cur->next; 133 } 134 } 135 136 // because link is used by malloc, this function free these nodes 137 void Freenode(node *head) 138 { 139 node *cur = head; 140 node *prenode = cur; 141 while(cur != NULL) 142 { 143 prenode = cur; 144 cur = cur->next; 145 free(prenode); 146 } 147 } 148 149 int main(void) 150 { 151 FILE *pFile; 152 char buf[100]; 153 int linenum = 1; 154 node *cur; 155 node* head = malloc(sizeof(node)); 156 node *prenode = NULL; 157 158 if(head == NULL) 159 { 160 printf("out of memory "); 161 exit(1); 162 } 163 cur = head; 164 cur->next = NULL; 165 pFile = fopen("myfile.txt", "r"); 166 if(pFile == NULL) 167 perror("Error opening file"); 168 169 // read one line each time 170 while(fgets(buf, 100, pFile) != NULL) 171 { 172 cur = Buildtoken(cur, buf, linenum); 173 linenum++; 174 memset(buf, '