?? scan.c
字號(hào):
/****************************************************/
/* File: scan.c */
/* The scanner implementation for the TINY compiler */
/* Compiler Construction: Principles and Practice */
/* Kenneth C. Louden */
/****************************************************/
#include "globals.h"
#include "util.h"
#include "scan.h"
/* states in scanner DFA */
typedef enum
{
START, INASSIGN, SQM,/* new add state */INCOMMENT, INNUM, INID, DONE
} StateType;
/* lexeme of identifier or reserved word */
char tokenString[MAXTOKENLEN + 1];
/* BUFLEN = length of the input buffer for
source code lines */
#define BUFLEN 256
static char lineBuf[BUFLEN]; /* holds the current line */
static int linepos = 0; /* current position in LineBuf */
static int bufsize = 0; /* current size of buffer string */
static int EOF_flag = FALSE; /* corrects ungetNextChar behavior on EOF */
/* getNextChar fetches the next non-blank character
from lineBuf, reading in a new line if lineBuf is
exhausted */
static int getNextChar(void)
{
if (!(linepos < bufsize))
{
lineno++;
if (fgets(lineBuf, BUFLEN - 1, source))
{
bufsize = strlen(lineBuf);
if (EchoSource)
{
/* new add code */
if (10 == lineBuf[bufsize - 1])
{
fprintf(listing, "%4d: %s", lineno, lineBuf);
}
else
{
fprintf(listing, "%4d: %s\n", lineno, lineBuf);
}
/* end add */
}
linepos = 0;
return lineBuf[linepos++];
}
else
{
EOF_flag = TRUE;
return EOF;
}
}
else
return lineBuf[linepos++];
}
/* ungetNextChar backtracks one character
in lineBuf */
static void ungetNextChar(void)
{
if (!EOF_flag)
linepos--;
}
/* ungetNextToken backtracks one token
in lineBuf */
void ungetNextToken(void)
{
if (!EOF_flag)
{
linepos -= strlen(tokenString);
}
}
/* lookup table of reserved words */
static struct
{
char* str;
TokenType tok;
} reservedWords[MAXRESERVED] =
{
{ "if", IF },
{ "then", THEN },
{ "else", ELSE },
{ "end", END },
{ "repeat", REPEAT },
{ "until", UNTIL },
{ "read", READ },
{ "write", WRITE },
{ "true", TINYTRUE },
{ "false", TINYFALSE },
{ "or", OR },
{ "and", AND },
{ "not", NOT },
{ "int", INT },
{ "bool", BOOL },
{ "string", STRING },
{ "while", WHILE },
{ "do", DO } };
/* lookup an identifier to see if it is a reserved word */
/* uses linear search */
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;
}
/****************************************/
/* the primary function of the scanner */
/****************************************/
/* function getToken returns the
* next token in source file
*/
TokenType getToken(void)
{ /* index for storing into tokenString */
int tokenStringIndex = 0;
/* holds current token to be returned */
TokenType currentToken;
/* current state - always begins at START */
StateType state = START;
/* flag to indicate save to 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;
/* new add code */
else if (c == '\'')
{
save = FALSE;
state = SQM;
}
/* end add */
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;
/* new add code */
case ',':
currentToken = COMMA;
break;
/* end add */
case ';':
currentToken = SEMI;
break;
default:
currentToken = ERROR;
break;
}
}
break;
/* new add code*/
case SQM:
save = TRUE;
if (c == '\n' || c == EOF)
{
state = DONE;
currentToken = ERROR;
}
else if (c == '\'')
{
save = FALSE;
state = DONE;
currentToken = STR;
}
break;
/* end add */
case INCOMMENT:
save = FALSE;
if (c == EOF)
{
state = DONE;
/* modify */
currentToken = ERROR;
}
else if (c == '}')
state = START;
break;
case INASSIGN:
state = DONE;
if (c == '=')
currentToken = ASSIGN;
else
{ /* backup in the input */
ungetNextChar();
save = FALSE;
currentToken = ERROR;
}
break;
case INNUM:
if (!isdigit(c))
{ /* backup in the input */
ungetNextChar();
save = FALSE;
state = DONE;
currentToken = NUM;
}
break;
case INID:
if (!isalpha(c))
{ /* backup in the input */
ungetNextChar();
save = FALSE;
state = DONE;
currentToken = ID;
}
break;
case DONE:
default: /* should never happen */
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;
} /* end getToken */
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -