[英]Lexical Analyzer C program for identifying tokens
我寫了一個用於lex分析器的C程序(一個小代碼),它將識別關鍵字,標識符和常量。 我正在獲取一個字符串(C源代碼為字符串),然后將其拆分為單詞。
#include <stdio.h>
#include <conio.h>
#include <string.h>
char symTable[5][7] = { "int", "void", "float", "char", "string" };
int main() {
int i, j, k = 0, flag = 0;
char string[7];
char str[] = "int main(){printf(\"Hello\");return 0;}";
char *ptr;
printf("Splitting string \"%s\" into tokens:\n", str);
ptr = strtok(str, " (){};""");
printf("\n\n");
while (ptr != NULL) {
printf ("%s\n", ptr);
for (i = k; i < 5; i++) {
memset(&string[0], 0, sizeof(string));
for (j = 0; j < 7; j++) {
string[j] = symTable[i][j];
}
if (strcmp(ptr, string) == 0) {
printf("Keyword\n\n");
break;
} else
if (string[j] == 0 || string[j] == 1 || string[j] == 2 ||
string[j] == 3 || string[j] == 4 || string[j] == 5 ||
string[j] == 6 || string[j] == 7 || string[j] == 8 ||
string[j] == 9) {
printf("Constant\n\n");
break;
} else {
printf("Identifier\n\n");
break;
}
}
ptr = strtok(NULL, " (){};""");
k++;
}
_getch();
return 0;
}
使用上面的代碼,我可以識別關鍵字和標識符,但無法獲得數字的結果。 我試過使用strspn()
但無濟於事。 我什至將0,1,2...,9
替換為'0','1',....,'9'
。
任何幫助,將不勝感激。
這是您的解析器中的一些問題:
測試string[j] == 0
不會測試string[j]
是否為數字0
。 數字字符寫為'0'
至'9'
,其值在ASCII和UTF-8中為48至57。 此外,您應該比較*p
而不是string[j]
以測試string[j]
是否有數字表示數字的開頭。
用strtok()
分割字符串不是一個好主意:它修改字符串並用'\\0'
覆蓋第一個分隔符:這將防止匹配運算符,例如(
, )
...
字符串" (){};"""
與" (){};"
完全相同 。 為了轉義"
內部字符串,您必須使用\\"
。
要為C編寫詞法分析器,您應該打開第一個字符並根據第一個字符的值檢查以下字符:
//
,則為行注釋:跳過所有字符,直到換行符。 /*
,則它是一個塊注釋:跳過所有字符,直到獲得對*/
。 '
,則您有一個字符常量:解析字符,處理轉義序列,直到獲得結束'
。 "
,則您有一個字符串文字。其作用與字符常量相同。 ==
和>>=
。 這就是一個簡單的C解析器。 完整的語法需要更多的工作,但是您一次只能到達一個步驟。
在編寫lexer時,請始終創建用於查找令牌的特定函數(名稱yylex
用於工具System Lex ,這就是我使用該名稱的原因)。 用main編寫詞法分析器不是一個聰明的主意,尤其是如果您以后要進行語法和語義分析。
從您的問題尚不清楚,您是否只想弄清楚數字令牌是什么,還是要令牌+獲取數字值。 我將假設第一個。
這是示例代碼 ,可以找到整數:
int yylex(){
/* We read one char from standard input */
char c = getchar();
/* If we read new line, we will return end of input token */
if(c == '\n')
return EOI;
/* If we see digit on input, we can not return number token at the moment.
For example input could be 123a and that is lexical error */
if(isdigit(c)){
while(isdigit(c = getchar()))
;
ungetc(c,stdin);
return NUM;
}
/* Additional code for keywords, identifiers, errors, etc. */
}
令牌EOI
, NUM
等應在頂部定義。 稍后,當您要編寫語法分析時,可以使用這些標記來確定代碼是否響應語言語法。 在詞法分析中,通常根本沒有定義ASCII值,例如,您的詞法分析器函數將僅返回')'
。 知道這一點,令牌應定義為255值以上。 例如:
#define EOI 256
#define NUM 257
如果您還有其他疑問,請隨時提問。
string[j]==1
該測試是錯誤的 (1) (在我聽說過的所有C實現中),因為string[j]
是一些char
例如使用ASCII (或UTF-8 ,甚至是IBM大型機上使用的舊EBCDIC )編碼和char
digit 1不是數字1。在我的Linux / x86-64機器上(以及在大多數使用ASCII或UTF-8的機器上,例如幾乎所有機器),使用UTF-8, 字符 1
被編碼為代碼48(即(char)48 == '1'
)
你可能想要
string[j]=='1'
並且您應該考慮使用標准的isdigit
(和相關)功能。
請注意,UTF-8實際上在任何地方都可以使用,但是它是一種多字節編碼(可顯示字符)。 看到這個答案 。
注意(1): string[j]==1
測試可能也放錯了位置! 也許您可以在更好的地方測試isdigit(*ptr)
。
PS。 請養成使用所有警告和調試信息進行編譯的習慣(例如,如果使用GCC,則使用gcc -Wall -Wextra -g
),並使用調試器 (例如gdb
)。 您應該比在這里得到答案所花費的時間要短。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.