?? word_analysis.c
字號(hào):
/*++
module name: word_analysis.c
kernel module of linear scan
--*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h> /* strtol(,,) */
#include "symbol_table.h"
#include "error_.h"
/* the maximum file size */
#define MAX_FILE_SIZE (1024*100)
/**********************************************************/
char *p_char = NULL;
int pre_type = TYPE_UNDEF;
char str_tem[MAX_LENGTH] = "";
char file_buffer[MAX_FILE_SIZE] = "";
/**********************************************************/
/* copy certain file to buffer and attach our global pointer to file buffer */
int file_to_buffer(char *filename)
{
FILE *pfile;
int i = 0;
pfile = fopen(filename, "r" );
if( pfile == NULL ) /* bad file name */
return FALSE;
do
{
file_buffer[i++] = fgetc(pfile );
}while( file_buffer[i-1] != EOF );
/* 將文件內(nèi)容寫入緩沖區(qū) 并寫入字符串結(jié)尾符 */
file_buffer[i-1] = '\0';
/* we don't need pfile any more */
fclose(pfile );
/* attach our char_pointer to file buffer */
p_char = file_buffer;
return TRUE;
}
/* if we've got to the end of file */
int is_end (void)
{
return (*p_char == EOF || *p_char == '\0') ? TRUE : FALSE;
}
/* 當(dāng)前字符指針p_char自加 如果當(dāng)前字符為文件結(jié)尾 返回錯(cuò)誤 */
int pop_char(void)
{
if( *p_char == EOF || *p_char == '\0' )
return FALSE;
p_char++;
return TRUE;
}
/* need more testing... */
/* 當(dāng)前字符若不屬于合法Token的一部分 則將當(dāng)前字符指針指向下一個(gè)合法Tolen首符 */
/* 如果到達(dá)源文件字串的結(jié)尾 返回FALSE */
int goto_token(void)
{
do
{
switch( *p_char )
{/* fgetc func cannot get '\r', it only get '\n' */
case '\n':
line++; /* fall through */
case ' ' :
case '\t' : /* 處理空格 制表符 回車 換行符 */
if( !pop_char() ) /* 到達(dá)串結(jié)尾 */
return FALSE;
else /* 繼續(xù) 處理下一字符 */
break;
case '/' : /* 處理注釋 */
if( *(p_char+1) == '*' ) /* C style comment */
{
p_char += 2;
while( !(*p_char == '*' && *(p_char+1) == '/') )
{
if( *(p_char+1) == '\n' /* && *p_char == '\r' */ )
line++; /* fgetc func cannot get '\r', it only get '\n' */
if( !pop_char() )
return FALSE;
}
p_char += 2; /* skip '*' and '/' */
break;
}
else if( *(p_char+1) == '/' ) /* C++ style comment */
{
p_char += 2; /* skip "//" */
/* fgetc func cannot get '\r', it only get '\n' */
while( !(*p_char == '\n') ) /* stop at the end of each line */
if( !pop_char() )
return FALSE;
/* p_char += 2; */ /* go to next line */
pop_char(); /* we only need to skip '\n', there's no '\r' any more */
line++;
break;
}
else /* 不是注釋 退出 */
return TRUE;
default: /* 當(dāng)前字符屬于某個(gè)Token */
return TRUE;
}
}while(TRUE);
}
/**********************************************************************/
/* some functions for certain char *p_char judging */
/* 是否為空格 */
int is_blank(void) /* is *p_char a blank */
{
return *p_char == ' ' ;
}
/* 是否為制表符 */
int is_tab (void)
{
return *p_char == '\t' ;
}
/* 是否為數(shù)字 */
int is_digit (void)
{
if( *p_char >=48 && *p_char <=57 ) /* 0-9 */
return TRUE;
else
return FALSE;
}
/* 是否為字母 或許該將下劃線作為字母 */
int is_letter(void)
{
if( *p_char >= 65 && *p_char <= 90 ) /* A-Z */
return TRUE;
else if( *p_char >= 97 && *p_char <= 122 ) /* a-z */
return TRUE;
else if( *p_char == '_' )
return TRUE;
else
return FALSE;
}
/* 是否為保留字 */
int is_reserve(char *str)
{
ENTRY entry = { TYPE_UNDEF, NULL };
entry = query_reserve_table(str );
return entry.p_item == NULL ? FALSE : TRUE ;
}
/* 是否為界符 包括運(yùn)算符 */
int is_specifier(void) /* 界符 */
{
char str[2] = { *p_char, '\0' };
ENTRY entry = { TYPE_UNDEF, NULL };
entry = query_specifier_table(str );
return entry.p_item == NULL ? FALSE : TRUE ;
}
/* 判斷是否為合法轉(zhuǎn)義字符 從'\\'后面第一個(gè)字符開始分析 若不合法 返回FALSE */
/* 合法則返回TRUE,并將轉(zhuǎn)義字符的值寫入p_c指向的字符 將字符指針指向后一個(gè)字符 */
/* 但不檢查該字符是否為 '\'' 此工作交給Deal_single來做 */
int is_tranmean (char *p_c)
{
char tem[4] = "";
int i = 0 ;
switch( *p_char )
{
case 'n':
*p_c = '\n';
pop_char(); /* skip to ' */
return TRUE;
case 't':
*p_c = '\t';
pop_char(); /* skip to ' */
return TRUE;
case 'b':
*p_c = '\b';
pop_char(); /* skip to ' */
return TRUE;
case 'r':
*p_c = '\r';
pop_char(); /* skip to ' */
return TRUE;
case 'f':
*p_c = '\f';
pop_char(); /* skip to ' */
return TRUE;
case '\\': /* fall through */
case '\'':
case '\"':
*p_c = *p_char;
pop_char(); /* skip to ' */
return TRUE;
case 'x':
{/* \xdd */
pop_char();
/* 0-9 a-f A-F */
if( ! (is_digit() || (*p_char >= 65 && *p_char <= 70)
|| (*p_char >= 97 && *p_char <= 102)) )
return FALSE;
for( i = 0; is_digit() || (*p_char >= 65 && *p_char <= 70)
|| (*p_char >= 97 && *p_char <= 102); i++ )
{/* 0-9 a-f A-F \xdd */
if( i > 1 )
return FALSE;
tem[i] = *p_char;
pop_char();
}
*p_c =(char) strtol(tem, NULL, 16 );
return TRUE;
}
default:
{
if( !is_digit() ) /* !(0-9) */
return FALSE;
/* 0-9 \ddd */
for( i = 0; is_digit() ; i++ )
{
if( i > 2 )
return FALSE;
tem[i] = *p_char;
pop_char();
}
*p_c =(char) strtol(tem, NULL, 10 );
return TRUE;
}/* default */
}/* switch */
}
/****************************************************************/
/* some functions deal with certain type */
ENTRY deal_specifier (void) /* 處理界符 */
{
ENTRY entry = { TYPE_UNDEF, NULL };
/* 假設(shè)界符和運(yùn)算符最多兩個(gè)字符 */
char str_tem[3] = { *p_char, *(p_char+1), '\0' };
entry = query_specifier_table(str_tem );
if( entry.type == TYPE_UNDEF )
{
str_tem[1] = '\0';
entry = query_specifier_table(str_tem );
}
else
pop_char();
pop_char();
strcpy(str_tem, "" ); /* clear the str_tem array for next call */
pre_type = entry.type; /* 為判斷+ 和- 的意義做準(zhǔn)備 */
return entry;
}
/* 處理字符串常量 將其添加入字符串常量表 */
ENTRY deal_double_ (void) /* " */
{
int i;
ENTRY entry;
pop_char(); /* skip the first " */
/* stop when meet another " except \" */
for(i=0; !(*p_char == '\"' && *(p_char-1) != '\\'); i++ )
{/* 可能的錯(cuò)誤 缺少配對(duì)的 " */
/* fgetc func cannot get '\r', it only get '\n' */
if( *p_char == '\\' )
{
pop_char();
if( is_tranmean(str_tem +i ) )
continue;
else
p_char--; /* back to pre char */
}
if( /* *p_char == '\r' && */ *(p_char+1) == '\n' )
{
pop_char(); /* go to \n, next pop_char make us go to next line */
report_error(ERROR_ILLEGAL_STR, line++, NULL );
break;
}
str_tem[i] = *p_char;
pop_char();
}
str_tem[i] = '\0';
entry.p_item = add_cst_str(str_tem );
entry.type = TYPE_CONST_STR;
pop_char(); /* get out of this token */
strcpy(str_tem, "" ); /* clear the str_tem array for next call */
pre_type = entry.type; /* 為判斷+ 和- 的意義做準(zhǔn)備 */
return entry;
}
/* 處理字符常量 */
ENTRY deal_single_ (void) /* ' */
{
ENTRY entry = { TYPE_UNDEF, NULL };
pop_char(); /* skip the first ' */
if( *p_char != '\\' )
{
str_tem[0] = *p_char;
if( *(p_char+1) != '\'' )
/* 出現(xiàn)錯(cuò)誤 沒有另一個(gè)匹配的' 或非轉(zhuǎn)義字符并且含多個(gè)字符 */
{
report_error(ERROR_ILLEGAL_CHAR, line, NULL );
/* 不再向后搜索'\'',只提示出錯(cuò)位置和類型 */
/* 該行剩余部分不再分析 跳至下一行 */
while( *p_char != '\n' )
if( !pop_char() )
break;
line++;
}
else
pop_char();
}
else
{ /* 處理轉(zhuǎn)義字符 */
pop_char(); /* skip out of '\' */
if( !is_tranmean(str_tem ) || *p_char != '\'' )
{/* 非法轉(zhuǎn)義字符 */
report_error(ERROR_ILLEGAL_CHAR, line, NULL );
/* 不再向后搜索'\'',只提示出錯(cuò)位置和類型 */
/* 該行剩余部分不再分析 跳至下一行 */
while( *p_char != '\n' )
if( !pop_char() )
break;
line++;
}
/* else , do nothing... */
/* is_tranmean() 已將轉(zhuǎn)義字符值寫入str_tem[0] */
}
entry.p_item = add_cst_char(str_tem[0] );
entry.type = TYPE_CONST_CHAR;
pop_char(); /* get out of this token */
strcpy(str_tem, "" ); /* clear the str_tem array for next call */
pre_type = entry.type; /* 為判斷+ 和- 的意義做準(zhǔn)備 */
return entry;
}
/* 處理整形常量和實(shí)型常量 */
ENTRY deal_num (void)
{
int i, n_tem;
double d_tem;
int b_dot = FALSE; /* 字串中有無. */
int b_e = FALSE; /* 字串中有無e 若既無.也無e則認(rèn)為是整型 */
ENTRY entry = { TYPE_UNDEF, NULL };
for(i=0; (is_digit() || *p_char == '.' || *p_char == 'e') ; i++ )
{/* 如果屬于整型和實(shí)型的要求的字符 則進(jìn)行處理 */
if( *p_char == '.' )
b_dot += TRUE;
if( *p_char == 'e' )
{
b_e += TRUE;
if( *(p_char+1) == '-' || *(p_char+1) == '+' )
{
str_tem[i++] = *p_char;
str_tem[i] = *(p_char+1);
p_char += 2;
continue;
}
}
str_tem[i] = *p_char;
pop_char();
}
str_tem[i] = '\0';
if( b_dot == FALSE && b_e == FALSE ) /* 整型 */
{
n_tem = strtol (str_tem, NULL, 10 );
if( pre_type == TYPE_NEGTIVE )
n_tem = 0 - n_tem;
entry.p_item = add_cst_num (n_tem );
entry.type = TYPE_CONST_NUM;
}
else if( b_dot > 1 || b_e >1 )
{ /* 錯(cuò)誤 包含非法輸入e.g. 0.45...435ee543+33 要進(jìn)行處理 */
/* 為了不影響以后的語法分析 向常量表中填入一項(xiàng) */
d_tem = atof(str_tem );
entry.p_item = add_cst_real (d_tem );
entry.type = TYPE_CONST_REAL;
/* need error handing... */
report_error(ERROR_ILLEGAL_REAL, line, NULL );
}
else /* 實(shí)型 */
{ /* */
d_tem = atof(str_tem );
if( pre_type == TYPE_NEGTIVE )
d_tem = 0 - d_tem;
entry.p_item = add_cst_real(d_tem );
entry.type = TYPE_CONST_REAL;
}
strcpy(str_tem, "" ); /* clear the str_tem array for next call */
pre_type = entry.type; /* 為判斷+ 和- 的意義做準(zhǔn)備 */
return entry;
}
/* 處理以字母開始的字串 包括保留字和標(biāo)識(shí)符 */
ENTRY deal_other (void) /* reservers and identifiers */
{
int i;
ENTRY entry = { TYPE_UNDEF, NULL };
for(i=0; is_digit() || is_letter(); i++ )
{
str_tem[i] = *p_char;
pop_char();
}
str_tem[i] = '\0';
entry = query_reserve_table(str_tem );
if( entry.type == TYPE_UNDEF )
{
entry.p_item = add_identifier(str_tem );
entry.type = TYPE_IDENTIFIER;
}
strcpy(str_tem, "" ); /* clear the str_tem array for next call */
pre_type = entry.type; /* 為判斷+ 和- 的意義做準(zhǔn)備 */
return entry;
}
/***********************************************************************/
/* 獲得一個(gè)Token的屬性 當(dāng)前字符指針后移 為取下一token做準(zhǔn)備 */
ENTRY get_token(void )
{
ENTRY entry = { TYPE_UNDEF, NULL };
/* goto token */
if( !goto_token() ) /* 如果到達(dá)文件結(jié)尾符 掃描應(yīng)結(jié)束 */
return entry;
if( is_specifier() ) /* 界符和運(yùn)算符 */
{
if( ( *p_char == '+' || *p_char == '-' )
&& ( *(p_char+1) >= 48 && *(p_char+1) <= 57 )
&& ( pre_type != TYPE_IDENTIFIER )
&& ( pre_type != TYPE_CONST_NUM )
&& ( pre_type != TYPE_CONST_REAL )
&& ( pre_type != TYPE_CONST_CHAR ) )
{/* 當(dāng)前符為+或- 且下一字符為數(shù)字,并且前一個(gè)Token類型不是標(biāo)識(shí)符和常量 */
/* 那么當(dāng)前符號(hào)是用來表示正負(fù)而不是加減的 */
pre_type = *p_char == '+' ? TYPE_POSITIVE : TYPE_NEGTIVE;
pop_char();
return deal_num();
}
return deal_specifier();
}
else if( *p_char == '\"' ) /* 字符串常量 */
{
return deal_double_();
}
else if( *p_char == '\'' ) /* 字符常量 */
{
return deal_single_();
}
else if( is_digit() ) /* 整形常量 以后應(yīng)加入實(shí)型常量處理 */
{
return deal_num();
}
else if( is_letter() ) /* 保留字或者標(biāo)識(shí)符 */
{
return deal_other();
}
else /* 未知類型 應(yīng)報(bào)錯(cuò) */
{
report_error(ERROR_UNKNOWN_CHAR, line, p_char );
pop_char();
return entry;
}
}
/**********************************end of file*************************************/
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -