📄 scan.cpp
字号:
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include "scan.h"
Scan::Scan();
void Scan::Init(FILE *source) //初始化
{
this->source=source;
listing=stdout;
linepos = 0;
bufsize = 0;
lineno = 0;
EOF_flag = FALSE;
}
int Scan::getNextChar() //读取一个字符
{
if (!(linepos < bufsize))
{
lineno++;
if(fgets(lineBuf,BUFLEN-1,source))
{
bufsize = strlen(lineBuf);
linepos = 0;
return lineBuf[linepos++];
}
else
{
EOF_flag = TRUE;
return EOF;
}
}
else return lineBuf[linepos++];
}
void Scan::ungetNextChar(void)
{
if (!EOF_flag) linepos-- ;
}
Token Scan::getToken() //取得一个单词符号
{
int isSecond=FALSE;
int tokenStringIndex = 0;
TokenType currentToken;
StateType state = START;
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;
isSecond=TRUE;
}
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;
}
} //end else
break;
case INCOMMENT:
if(c!='/' && isSecond)
{
currentToken=OVER;
ungetNextChar();
state = DONE;
}else{
save = FALSE;
isSecond=FALSE;
}
if (c == EOF)
{ state = DONE;
currentToken = ENDFILE;
}
else if (c == '\n') 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) && !isdigit(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;
} //End switch
if ((save) && (tokenStringIndex <= MAXTOKENLEN))
token.string[tokenStringIndex++] = (char) c;
if (state == DONE)
{
token.string[tokenStringIndex] = '\0';
if (currentToken == ID)
currentToken = reservedLookup(token.string);
}
}
token.type=currentToken;
fprintf(listing,"\t%d: ",lineno);
printToken();
return token;
}
TokenType Scan::reservedLookup (char * s)
{
int i;
for (i=0;i<MAXRESERVED;i++)
if (!strcmp(s,reservedWords[i].str))
return reservedWords[i].tok;
return ID;
}
void Scan::printToken()
{
switch (token.type)
{
case IF:
case THEN:
case ELSE:
case END:
case REPEAT:
case UNTIL:
case READ:
case WRITE:
fprintf(listing,"reserved word: %s\n",token.string);
break;
case ASSIGN:
case LT:
case EQ:
case LPAREN:
case RPAREN:
case SEMI:
case PLUS:
case MINUS:
case TIMES:
case OVER: fprintf(listing,"%s\n",token.string);break;
case ENDFILE:fprintf(listing,"EOF\n"); break;
case NUM:
fprintf(listing,"NUM, val= %s\n",token.string);
break;
case ID:
fprintf(listing,"ID, name= %s\n",token.string);
break;
case ERROR:
fprintf(listing,"ERROR: %s\n",token.string);
break;
default:
fprintf(listing,"Unknown token: %d\n",token.type);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -