?? scan.c
字號:
/****************************************************/
/* 文件:scan.c */
/* TINY掃描程序的執行代碼 */
/****************************************************/
#include "globals.h"
#include "util.h"
#include "scan.h"
/* 掃描程序有限自動機的狀態 */
typedef enum
{ START,INASSIGN,INCOMMENT,INNUM,INID,DONE }
StateType;
/* 用來保存當前保留字或者標識符 */
char tokenString[MAXTOKENLEN+1];
/* BUFLEN定義源文件行中的最大字符數 */
#define BUFLEN 256
static char lineBuf[BUFLEN]; /* 保留當前行 */
static int linepos = 0; /* 保存LineBuf中的當前位置 */
static int bufsize = 0; /* 當前緩存中保存的字符數 */
static int EOF_flag = FALSE; /* 當遇到EOF(文件結束符)調整ungetNextChar的操作 */
/* getNextCharlineBuf取得下一個非空格的字符。如果讀完了緩存中的全部字符,
就把新的一行讀入緩存 */
static int getNextChar(void)
{ if (!(linepos < bufsize))
{ lineno++;
if (fgets(lineBuf,BUFLEN-1,source))
{ if (EchoSource) fprintf(listing,"%4d: %s",lineno,lineBuf);
bufsize = strlen(lineBuf);
linepos = 0;
return lineBuf[linepos++];
}
else
{ EOF_flag = TRUE;
return EOF;
}
}
else return lineBuf[linepos++];
}
/* ungetNextChar把一個字符退回到lineBuf緩存中 */
static void ungetNextChar(void)
{ if (!EOF_flag) linepos-- ;}
/* 保留字表*/
static struct
{ char* str;
TokenType tok;
} reservedWords[MAXRESERVED]
= {{"if",IF},{"then",THEN},{"else",ELSE},{"end",END},
{"repeat",REPEAT},{"until",UNTIL},{"read",READ},
{"write",WRITE}};
/* T I N Y對保留字的識別是通過首先將它們看作是標識符,
* 之后再在保留字表中查找它們來完成的。
* 我們的掃描程序使用了一種非常簡便的方法—線性搜索,
* 即按順序從開頭到結尾搜索表格。這對于小型表格不成問題。
*/
static TokenType reservedLookup (char * s)
{ int i;
for (i=0;i<MAXRESERVED;i++)
if (!strcmp(s,reservedWords[i].str))
return reservedWords[i].tok;
return ID;
}
/****************************************/
/* 分析程序的主函數 */
/****************************************/
/* 耗輸入字符并根據圖8.2.1
* 中的DFA返回下一個被識別的記號
*/
TokenType getToken(void)
{ /* tokenString的引索 */
int tokenStringIndex = 0;
/* 保存當前要返回的記號 */
TokenType currentToken;
/* 當前的狀態-總是從START開始 */
StateType state = START;
/* 是否保存到tokenString的標記 */
int save;
while (state != DONE)
{ int c = getNextChar();
save = TRUE;
switch (state)
{ case START:
if (isdigit(c))
state = INNUM;
else if (isalpha(c))
state = INID;
else if (c == ':')
state = INASSIGN;
else if ((c == ' ') || (c == '\t') || (c == '\n'))
save = FALSE;
else if (c == '{')
{ save = FALSE;
state = INCOMMENT;
}
else
{ state = DONE;
switch (c)
{ case EOF:
save = FALSE;
currentToken = ENDFILE;
break;
case '=':
currentToken = EQ;
break;
case '<':
currentToken = LT;
break;
case '+':
currentToken = PLUS;
break;
case '-':
currentToken = MINUS;
break;
case '*':
currentToken = TIMES;
break;
case '/':
currentToken = OVER;
break;
case '(':
currentToken = LPAREN;
break;
case ')':
currentToken = RPAREN;
break;
case ';':
currentToken = SEMI;
break;
default:
currentToken = ERROR;
break;
}
}
break;
case INCOMMENT:
save = FALSE;
if (c == EOF)
{ state = DONE;
currentToken = ENDFILE;
}
else if (c == '}') state = START;
break;
case INASSIGN:
state = DONE;
if (c == '=')
currentToken = ASSIGN;
else
/*退回到緩存中 */
ungetNextChar();
save = FALSE;
currentToken = ERROR;
}
break;
case INNUM:
if (!isdigit(c))
{ /* 退回到緩存中 */
ungetNextChar();
save = FALSE;
state = DONE;
currentToken = NUM;
}
break;
case INID:
if (!isalpha(c))
{ /* 退回到緩存中 */
ungetNextChar();
save = FALSE;
state = DONE;
currentToken = ID;
}
break;
case DONE:
default:
fprintf(listing,"Scanner Bug: state= %d\n",state);
state = DONE;
currentToken = ERROR;
break;
}
if ((save) && (tokenStringIndex <= MAXTOKENLEN))
tokenString[tokenStringIndex++] = (char) c;
if (state == DONE)
{ tokenString[tokenStringIndex] = '\0';
if (currentToken == ID)
currentToken = reservedLookup(tokenString);
}
}
if (TraceScan) {
fprintf(listing,"\t%d: ",lineno);
printToken(currentToken,tokenString);
}
return currentToken;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -