2017-03-13 148 views
0

我創建一個程序從終端的編程語言分開終結符號沒有被指定的值。枚舉器跟蹤非終止符的標籤名稱。非終結者ID被設置爲0,並且所有其他枚舉在之後進行枚舉(因爲它應該)。然而,當程序發現非終結符,它打印的1953167781離奇值,雖然有些做出來爲0,似乎走出來爲1953年的...是是有序的,像這樣的:open int num = 7num作爲非終結。 num不是0,而是1953167781.但是,如果是像guarded class test{}這樣的聲明,那麼非終結符test是0,而不是1953167781. 這種現象是否有可能的原因?預先感謝您的反饋!下面是輸出的圖片和發生的過程的一個例子。ç枚舉不返回

enter image description here

編輯

例如,讓我們創建標題來保存我們的聲明:

#ifndef __TOK_H__ 
#define __TOK_H__ 

#define MAX (1024) 

typedef enum { 
    ID = 0,OPEN,CLOSED,GUARDED,ARTIFICIAL,STATIC,GLOBAL,CONT,SUPER,INT,FLOAT,CHAR,STRING, 
    BOOL,COLLECTION,CLASS,FUNCT,METHOD,STRUCT,ENUM,IF,ELSE,_OR_,DO,UNTIL,UNLESS,FOR, 
    FOREACH,IN,TRY,CATCH,EXCEPTION,RETURN,SKIP,BREAK,TERM,NEW,CALL,TRU,FALS,NIL, 
    INUMBER,FNUMBER,VCHAR,VSTRING,UNDEF,LT,GT,LE,GE,EQ,NE,AND,OR,ADD,ADDE,INCRE,SUB,SUBE, 
    DECRE,MULT,MULTE,DIV,DIVE,MOD,MODE,EX,EXE,INC,ASI,NOT,INHER,DOT,COM,LP,RP,LB,RB,LBR, 
    RBR,APO,QUO,SEMCO,EOFT,NAT 
} tokentype; 

typedef struct { 
    char str[MAX]; 
    tokentype type; 
} token; 

void sscan(FILE *); 
token generate(FILE *fp); 

#endif 

這一個太:

#ifndef __RESERVED_H__ 
#define __RESERVED_H__ 

char *keywords[] = { //40 keywords/reserved words 
    "open","closed","guarded","artificial","static","global","cont","super", 
    "int","float","char","string","bool","collection","class","funct","method", 
    "struct","enum","if","else","or","do","until","unless","for","foreach","in", 
    "try","catch","exception","return","skip","break","term","new","call","true", 
    "false","null", 
}; 
char *relative_operators[] = { //8 relops 
    "<",">","<=",">=","==","!=","&&","||", 
}; 
char operators[6] = { //6 operators 
    "+-*/%^", 
}; 
char delimeters[11] = { //11 delimeters 
    ".,(){}[];'\"", 
}; 
char unique_operators[] = { //5 unops 
    "#!&|=" 
}; 

#endif 

然後是(雖然不高效以任何方式)的掃描儀和分離器:

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

#include "reserved.h" 
#include "tok.h" 

int linenum = 1; 
char ch; 
token TOKEN; 

int isLangPunct(char ch); 
int isKEY(char *word); 
int isDELIM(char ch); 
int isRELOP(char ch); 
int isUNIQUE(char ch); 
int isOPERA(char ch); 
tokentype getKey(char *word); 
tokentype getDel(char ch); 

void sscan(FILE *fp) { 
    while ((ch = fgetc(fp)) != EOF) { 
     if (ch == '\n') { 
      linenum++; 
      continue; 
     } else if (isLangPunct(ch) || isalnum(ch) || isspace(ch)) { 
      continue; 
     } else { 
      fprintf(stderr, "Undefined character: %c at line %d.\n", ch, linenum); 
     } 
    } 
    rewind(fp); linenum = 1; 
    do { 
     generate(fp); 
    } while (TOKEN.type != EOFT); 
} 
int isLangPunct(char ch) { 
    int r = 0; 
    if (ch == '#' || ch == '|' || ch == '&' || ch == '=' || ch == '%' || 
     ch == '!' || ch == '+' || ch == '-' || ch == '*' || ch == '/' || 
     ch == '.' || ch == ',' || ch == '(' || ch == ')' || ch == ';' || 
     ch == '{' || ch == '}' || ch == '[' || ch == ']' || ch == '\'' || 
     ch == '"' || ch == '<' || ch == '>' || ch == '^') 
    { 
     r = 1; 
    } return r; 
} 
token generate(FILE *fp) { 
    char *word = malloc(sizeof(char) * MAX); 
    char *number = malloc(sizeof(char) * MAX); 
    int wi = 0, ni = 0; 
    while((ch = fgetc(fp)) != EOF) { 
     if (ch == '\n') { 
      linenum++; continue; 
     } else if (ch == '\t' || ch == ' ' || ch == '\r') { 
      continue; 
     } else if (isalpha(ch)) { 
      do { 
       word[wi++] = ch; 
      } while(isalpha(ch = fgetc(fp))); 
      word[wi] = '\0'; 
      wi = 0; 
      strcpy(TOKEN.str, word); 
      if (isKEY(word)) { 
       TOKEN.type = getKey(word); 
      } else { 
       TOKEN.type = ID; 
      } 
      fseek(fp, -1, SEEK_CUR); 
      printf("%d ", (int)TOKEN.type); 
      return TOKEN; 
     } else if (isdigit(ch)) { 
      do { 
       number[ni++] = ch; 
      } while(isdigit(ch = fgetc(fp))); 
      if (ch == '.') { 
       do { 
        number[ni++] = ch; 
       } while(isdigit(ch = fgetc(fp))); 
       TOKEN.type = FNUMBER; 
      } else { 
       TOKEN.type = INUMBER; 
      } 
      number[ni] = '\0'; 
      ni = 0; 
      strcpy(TOKEN.str, number); 
      printf("%s ", TOKEN.str); 
      fseek(fp, -1, SEEK_CUR); 
      return TOKEN; 
     } else if (isDELIM(ch)) { 
      TOKEN.type = getDel(ch); 
      char *str = &ch; 
      //working on getting strings and chars to have 
      //their own value types 
      strcpy(TOKEN.str, str); 
      printf("%s ", TOKEN.str); 
      return TOKEN; 
     } else if (isRELOP(ch) || isUNIQUE(ch)) { 
      switch (ch) { 
       case '<': 
        if ((ch = fgetc(fp)) == '=') { 
         TOKEN.type = LE; 
         strcpy(TOKEN.str, "<="); 
        } else { 
         TOKEN.type = LT; 
         strcpy(TOKEN.str, "<"); 
         fseek(fp, -1, SEEK_CUR); 
        } break; 
       case '>': 
        if ((ch = fgetc(fp)) == '=') { 
         TOKEN.type = GE; 
         strcpy(TOKEN.str, ">="); 
        } else { 
         TOKEN.type = GT; 
         strcpy(TOKEN.str, ">"); 
         fseek(fp, -1, SEEK_CUR); 
        } break; 
       case '=': 
        if ((ch = fgetc(fp)) == '=') { 
         TOKEN.type = EQ; 
         strcpy(TOKEN.str, "=="); 
        } else { 
         TOKEN.type = ASI; 
         strcpy(TOKEN.str, "="); 
         fseek(fp, -1, SEEK_CUR); 
        } break; 
       case '!': 
        if ((ch = fgetc(fp)) == '=') { 
         TOKEN.type = NE; 
         strcpy(TOKEN.str, "!="); 
        } else { 
         TOKEN.type = NOT; 
         strcpy(TOKEN.str, "!"); 
         fseek(fp, -1, SEEK_CUR); 
        } break; 
       case '&': 
        if ((ch = fgetc(fp)) == '&') { 
         TOKEN.type = AND; 
         strcpy(TOKEN.str, "&&"); 
        } else { 
         fprintf(stderr, "Token Error: & missing at line %d.\n", linenum); 
         fseek(fp, -1, SEEK_CUR); 
        } break; 
       case '|': 
        if ((ch = fgetc(fp)) == '|') { 
         TOKEN.type = OR; 
         strcpy(TOKEN.str, "||"); 
        } else { 
         TOKEN.type = INHER; 
         strcpy(TOKEN.str, "|"); 
         fseek(fp, -1, SEEK_CUR); 
        } break; 
       case '#': 
        TOKEN.type = INC; 
        strcpy(TOKEN.str, "#"); 
      } 
      printf("%s ", TOKEN.str); 
      return TOKEN; 
     } else if (isOPERA(ch)) { 
      switch (ch) { 
       case '+': 
        if ((ch = fgetc(fp)) == '+') { 
         TOKEN.type = INCRE; 
         strcpy(TOKEN.str, "++"); 
        } else if (ch == '=') { 
         TOKEN.type = ADDE ; 
         strcpy(TOKEN.str, "+="); 
         fseek(fp, -1, SEEK_CUR); 
        } else { 
         TOKEN.type = ADD ; 
         strcpy(TOKEN.str, "+"); 
         fseek(fp, -1, SEEK_CUR); 
        } break; 
       case '-': 
        if ((ch = fgetc(fp)) == '-') { 
         TOKEN.type = DECRE; 
         strcpy(TOKEN.str, "--"); 
        } else if (ch == '=') { 
         TOKEN.type = SUBE; 
         strcpy(TOKEN.str, "-="); 
         fseek(fp, -1, SEEK_CUR); 
        } else { 
         TOKEN.type = SUB; 
         strcpy(TOKEN.str, "-"); 
         fseek(fp, -1, SEEK_CUR); 
        } break; 
       case '*': 
        if ((ch = fgetc(fp)) == '=') { 
         TOKEN.type = MULTE; 
         strcpy(TOKEN.str, "*="); 
        } else { 
         TOKEN.type = MULT; 
         strcpy(TOKEN.str, "*"); 
         fseek(fp, -1, SEEK_CUR); 
        } break; 
       case '/': 
        if ((ch = fgetc(fp)) == '=') { 
         TOKEN.type = DIVE; 
         strcpy(TOKEN.str, "/="); 
        } else if (ch == '/') { 
         do { 
          continue; 
         } while ((ch = fgetc(fp)) != '\n'); 
        } else { 
         TOKEN.type = DIV; 
         strcpy(TOKEN.str, "/"); 
         fseek(fp, -1, SEEK_CUR); 
        } break; 
       case '%': 
        if ((ch = fgetc(fp)) == '=') { 
         TOKEN.type = MODE; 
         strcpy(TOKEN.str, "%="); 
        } else { 
         TOKEN.type = MOD; 
         strcpy(TOKEN.str, "%"); 
         fseek(fp, -1, SEEK_CUR); 
        } break; 
       case '^': 
        if ((ch = fgetc(fp)) == '=') { 
         TOKEN.type = EXE; 
         strcpy(TOKEN.str, "^="); 
        } else { 
         TOKEN.type = EX; 
         strcpy(TOKEN.str, "^"); 
         fseek(fp, -1, SEEK_CUR); 
        } break; 
      } 
      printf("%s ", TOKEN.str); 
      return TOKEN; 
     } 
    } 
    free(word); 
    free(number); 
    TOKEN.type = EOFT; 
    strcpy(TOKEN.str, "\0"); 
    printf("%s ", TOKEN.str); 
    return TOKEN; 
} 
int isKEY(char *word) { 
    int r = 0; 
    for (int i = 0; i < 40; i++) { 
     if (*word == *keywords[i]) { 
      r = 1; 
     } 
    } 
    return r; 
} 
int isDELIM(char ch) { 
    int r = 0; 
    for (int i = 0; i < 11; i++) { 
     if (ch == delimeters[i]) { 
      r = 1; 
     } 
    } 
    return r; 
} 
int isRELOP(char ch) { 
    int r = 0; 
    if (ch == '<' || ch == '>') { 
     r = 1; 
    } 
    return r; 
} 
int isUNIQUE(char ch) { 
    int r = 0; 
    for (int i = 0; i < 5; i++) { 
     if (ch == unique_operators[i]) { 
      r = 1; 
     } 
    } 
    return r; 
} 
int isOPERA(char ch) { 
    int r = 0; 
    for (int i = 0; i < 6; i++) { 
     if (ch == operators[i]) { 
      r = 1; 
     } 
    } 
    return r; 
} 
tokentype getKey(char *word) { 
    tokentype type; 
    if (!strcmp(word, "open")) { type = OPEN; } 
    else if (!strcmp(word, "closed")) { type = CLOSED; } 
    else if (!strcmp(word, "guarded")) { type = GUARDED; } 
    else if (!strcmp(word, "artificial")) { type = ARTIFICIAL; } 
    else if (!strcmp(word, "static")) { type = STATIC; } 
    else if (!strcmp(word, "global")) { type = GLOBAL; } 
    else if (!strcmp(word, "cont")) { type = CONT; } 
    else if (!strcmp(word, "super")) { type = SUPER; } 
    else if (!strcmp(word, "int")) { type = INT; } 
    else if (!strcmp(word, "float")) { type = FLOAT; } 
    else if (!strcmp(word, "char")) { type = CHAR; } 
    else if (!strcmp(word, "string")) { type = STRING; } 
    else if (!strcmp(word, "bool")) { type = BOOL; } 
    else if (!strcmp(word, "collection")) { type = COLLECTION; } 
    else if (!strcmp(word, "class")) { type = CLASS; } 
    else if (!strcmp(word, "funct")) { type = FUNCT; } 
    else if (!strcmp(word, "method")) { type = METHOD; } 
    else if (!strcmp(word, "struct")) { type = STRUCT; } 
    else if (!strcmp(word, "enum")) { type = ENUM; } 
    else if (!strcmp(word, "if")) { type = IF; } 
    else if (!strcmp(word, "else")) { type = ELSE; } 
    else if (!strcmp(word, "or")) { type = _OR_; } 
    else if (!strcmp(word, "do")) { type = DO; } 
    else if (!strcmp(word, "until")) { type = UNTIL; } 
    else if (!strcmp(word, "unless")) { type = UNLESS; } 
    else if (!strcmp(word, "for")) { type = FOR; } 
    else if (!strcmp(word, "foreach")) { type = FOREACH; } 
    else if (!strcmp(word, "in")) { type = IN; } 
    else if (!strcmp(word, "try")) { type = TRY; } 
    else if (!strcmp(word, "catch")) { type = CATCH; } 
    else if (!strcmp(word, "exception")) { type = EXCEPTION; } 
    else if (!strcmp(word, "return")) { type = RETURN; } 
    else if (!strcmp(word, "skip")) { type = SKIP; } 
    else if (!strcmp(word, "break")) { type = BREAK; } 
    else if (!strcmp(word, "term")) { type = TERM; } 
    else if (!strcmp(word, "new")) { type = NEW; } 
    else if (!strcmp(word, "call")) { type = CALL; } 
    else if (!strcmp(word, "true")) { type = TRU; } 
    else if (!strcmp(word, "false")) { type = FALS; } 
    else if (!strcmp(word, "null")) { type = NIL; } 
    return type; 
} 
tokentype getDel(char ch) { 
    tokentype type; 
    if (ch == '.') { type = DOT; } 
    if (ch == ',') { type = COM; } 
    if (ch == '(') { type = LP; } 
    if (ch == ')') { type = RP; } 
    if (ch == '{') { type = LB; } 
    if (ch == '}') { type = RB; } 
    if (ch == '[') { type = LBR; } 
    if (ch == ']') { type = RBR; } 
    if (ch == '"') { type = QUO; } 
    if (ch == '\'') { type = APO; } 
    if (ch == ';') { type = SEMCO; } 
    return type; 
} 

在單獨的或甚至在相同的文件如上述,main()能夠打開一個文件,並讀出它的文件流發送到sscan(FILE *)。對於最後一個示例文件,請閱讀:

# call Sys; 
# call SysIO; 

static int num = 7; 
cont global float fl = 12.895; 
cont char letter = 'h'; 

collection Program { 
    cont closed string aswkey = "abdcbabcdabdbcdab"; 
    open class quiz { 
     bool decision = true; 
     artificial method.study (int time) {}; 
     open quiz() { 
      //do something 
     }; 
    }; 
    class test | quiz { 
     bool descision; 
     super method.study (int time) { 
      if (decision == true) { 
       //do something 
      } or if (time == 0) { 
       //do something 
      } else { 
       //do nothing 
      }; 
      time = 50; 
     }; 
     guarded test (bool n) { 
      descision = n; 
     }; 
    }; 
    funct.Enter() { 
     quiz Quiz = new quiz(); 
     test Test = new test(false); 
     Test.study(60); 
     if (something != this) { 
      //do something 
     }; 
     term; 
    }; 
}; 
+3

請嘗試創建一個[最小,完整,可驗證的示例](http://stackoverflow.com/help/mcve)向我們展示。否則將很難不可能猜測*。 –

+1

但是,問題很可能不在您認爲的地方。你是否在某個地方複製'TOKEN',會員,並忘記複製'type'成員?或者你是否在任何地方超出了'TOKEN.str'的​​範圍?哦,'TOKEN.str' *是一個數組,不僅是一個(未初始化的)指針?使用*調試器*來遍歷代碼,同時關注變量及其值。 –

+1

如果'word'數組太小而不能容納長單詞,那麼太多的字符將被放入並覆蓋隨後的內存,可能是'type'字段。 'do'循環應該檢查最大長度。 –

回答

0

因此,要了解發生了什麼問題,我們來看看發生了什麼。在getKey(word)功能,當一個字被送到那裏對關鍵字進行比較,這將返回tokentype typeTOKEN.type聲明。但是,如果單詞不匹配任何比較,那麼它仍然只返回作爲type的變量,該變量的地址爲1953167781,特別是在我的計算機上。因此,通過添加最後的else語句getKey(word)tokentype type設置爲ID,它將所有非終結符與ID進行匹配。然而,這並不能解釋爲什麼像SysSysIO話也沒成爲1953167781.,這是一個有點混亂if(isKEY(word))怎麼可能不返回false,它看上去總是返回真。儘管它必須返回false來轉到else語句,以便將所有非終止符有效設置爲ID。但是,這仍然帶來了一個問題,我們將不討論,但應該思考:爲什麼會喜歡SysSysIO終結符號成爲ID的(注意,getKey(word)功能沒有新的最終else語句)內的總是正確的if語句,當它爲了發生這種情況必須返回假,爲什麼其他類似的詞不會有相同的過程?無論如何,它工作正常,我會讓專家來弄清楚爲什麼它在前面的陳述中做了它的工作。