簡體   English   中英

Lexical Analyzer C程序,用於識別令牌

[英]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編寫詞法分析器,您應該打開第一個字符並根據第一個字符的值檢查以下字符:

  • 如果您有空格,請跳過它
  • 如果有// ,則為行注釋:跳過所有字符,直到換行符。
  • 如果有/* ,則它是一個塊注釋:跳過所有字符,直到獲得對*/
  • 如果您有一個' ,則您有一個字符常量:解析字符,處理轉義序列,直到獲得結束'
  • 如果您有一個" ,則您有一個字符串文字。其作用與字符常量相同。
  • 如果您有一個數字,消耗掉所有后續數字,那么您就有一個整數。 解析整數語法需要更多代碼:將其留待以后使用。
  • 如果您有字母或下划線:使用所有后續字母,數字和下划線,然后將該單詞與一組預定義的關鍵字進行比較。 您有一個關鍵字或一個標識符。
  • 否則,您有一個運算符:檢查下一個字符是否是2或3個字符運算符的一部分,例如==>>=

這就是一個簡單的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. */
}

令牌EOINUM等應在頂部定義。 稍后,當您要編寫語法分析時,可以使用這些標記來確定代碼是否響應語言語法。 在詞法分析中,通常根本沒有定義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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM