home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1997 March
/
VPR9703A.ISO
/
VPR_DATA
/
DOGA
/
SOURCES
/
POLYEDIT.LZH
/
ML
/
SCANNER.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-06-05
|
15KB
|
834 lines
/*
* トークンの切り出し
*
* T.Kobayashi 1993.8.5
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <io.h>
#include <sys\stat.h>
#include <assert.h>
#include "strclass.h"
#include "scanner.h"
#include "err.h"
#include "inlib.h"
/*#define static*/
#if 0
#define iskanji( c ) ( ( (c) & 0x80 ) != 0 )
#endif
#define iskanji( c ) (( 0x80 <= (c) && (c) < 0x9f) || ( 0xe0 <= (c) && (c) < 0xfc))
/* 予約語リスト */
static char *ResWord[] = {
NULL,
"break",
"const",
"continue",
"do",
"else",
"for",
"function",
"if",
"private",
"return",
"var",
"while",
NULL
};
/* 定数リスト */
int SysConsts ;
ConstStruct SysConst[MAX_SYSCONST] ;
static char *BoolConstName[] = {
"TRUE",
"FALSE",
"ON",
"OFF",
NULL
};
static BoolData BoolConst[] = {
{TYPE_BOOLEAN, 0, TRUE},
{TYPE_BOOLEAN, 0, FALSE},
{TYPE_BOOLEAN, 0, TRUE},
{TYPE_BOOLEAN, 0, FALSE},
};
static char *TypeConstName[] = {
"NOASSIGN",
"BOOLEAN",
"INT",
"REAL",
"TYPE",
"ARRAY",
"FUNC",
"OBJECT",
NULL,
};
static TypeData TypeConst[] = {
{TYPE_TYPE, 0, TYPE_NOASN},
{TYPE_TYPE, 0, TYPE_BOOLEAN},
{TYPE_TYPE, 0, TYPE_INT},
{TYPE_TYPE, 0, TYPE_REAL},
{TYPE_TYPE, 0, TYPE_TYPE},
{TYPE_TYPE, 0, TYPE_ARRAY},
{TYPE_TYPE, 0, TYPE_FUNC},
{TYPE_TYPE, 0, TYPE_OBJECT},
};
/* 大域変数 */
InputStruct Input ;
char *InputFile;
int InputLine ;
static int GetChar( void );
static int NextChar( void );
static int Comment( void );
static int isword1( int );
static int isword2( int );
static int isnum( int );
static int ishex( int );
static void GetNum( DataStruct*, char* );
static void GetString( DataStruct* );
#if 0
static inline int strcmp(const char *p1, const char *p2)
{
while (*p1 == *p2) {
if (*p1 == '\0') {
return 0;
}
p1++;
p2++;
}
return *p1 - *p2;
}
#endif
/* 初期化 */
void ScannerInit()
{
int i ;
SysConsts = 0 ;
for( i = 0 ; BoolConstName[i] != NULL ; i++ )
SetSystemConst( BoolConstName[i], (DataStruct*)&BoolConst[i] );
for( i = 0 ; TypeConstName[i] != NULL ; i++ )
SetSystemConst( TypeConstName[i], (DataStruct*)&TypeConst[i] );
}
/* システム定数の設定 */
void SetSystemConst( name, c )
char *name ;
DataStruct *c ;
{
extern void (*ErrorExec)() ;
if ( SysConsts >= MAX_SYSCONST )
(*ErrorExec)( "システム定数用バッファが確保できません。" );
#if 0
SysConst[SysConsts].name = name ;
SysConst[SysConsts].data = *c ;
SysConsts ++ ;
#else
{
int i, i1, i2, j;
i1 = -1;
i2 = SysConsts;
while (i1 < i2-1) {
i = (i1+i2)/2;
j = strcmp(Input.str, SysConst[i].name);
if (j == 0) {
(*ErrorExec)( "システム定数名が重複しています。" );
} else if (j < 0) {
i2 = i;
} else {
i1 = i;
}
}
if (i2 < SysConsts) {
for (i = SysConsts; i > i2; --i) {
SysConst[i].name = SysConst[i-1].name;
SysConst[i].data = SysConst[i-1].data;
}
}
SysConst[i2].name = name ;
SysConst[i2].data = *c ;
SysConsts ++ ;
}
#endif
}
/* ソース入力用バッファの初期化 */
void FileOpen( name )
char *name ;
{
int size ;
FILE *fp ;
struct stat sbuf ;
if ( name != NULL )
{
fp = fopen( name, "rb" );
if ( fp == NULL )
{
ParseError( "ファイル %s がオープンできません。", name );
return ;
}
stat( name, &sbuf );
Input.buf = MemoryAlloc( sbuf.st_size + 1 );
size = fread( Input.buf, 1, sbuf.st_size, fp );
if ( size > sbuf.st_size )
{
ParseError( "ファイルサイズが不正です。" );
return ;
}
Input.ptr = Input.buf ;
Input.last = Input.buf + size ;
Input.buf[size] = Input.buf[size-1];
#if 0
printf( "size : %d : %d\n", size, sbuf.st_size );
Input.buf[size] = 0 ;
printf( "[%x][%x][%x]\n", Input.buf[sbuf.st_size-3],
Input.buf[sbuf.st_size-2], Input.buf[sbuf.st_size-1] );
printf( "last : [%s]\n", &Input.buf[sbuf.st_size-20] );
#endif
Input.fp = fp ;
#if 0
if (InputFile != NULL) {
MemoryFree(InputFile);
}
#endif
{
char *p;
if ((p = strrchr(name, '\\')) == NULL) {
p = name;
} else {
p++;
}
InputFile = MemoryAlloc( strlen(p) + 1 );
if ( InputFile == NULL )
{
ParseError( "メモリが確保できません。(FileOpen)" );
return ;
}
strcpy( InputFile, p);
}
}
InputLine = 1 ;
Input.ch = 0 ;
Input.ch1 = 0 ;
GetChar();
GetToken();
}
/* ソース入力終了 */
void FileClose()
{
fclose( Input.fp );
MemoryFree( Input.buf );
#if 0
InputFile[0] = '\0';
#endif
}
/* 1文字入力 */
static int GetChar()
{
/* 既にEOF */
if ( Input.ch == EOF )
return EOF ;
if ( Input.ch1 == 0 )
{
if ( Input.ptr == Input.last )
Input.ch = EOF ;
else
Input.ch = *Input.ptr++ ;
}
else
{
Input.ch = Input.ch1 ;
Input.ch1 = 0 ;
}
if ( Input.ch == '\n' )
InputLine ++ ;
return Input.ch ;
}
#ifndef __GNUC__
#define inline
#endif
/* 1文字先読み */
static inline int NextChar()
{
if ( Input.ch1 == 0 )
{
if ( Input.ptr == Input.last )
Input.ch1 = EOF ;
else
Input.ch1 = *Input.ptr++ ;
}
return Input.ch1 ;
}
/* コメントとスペースの処理 */
static int Comment()
{
do {
while ( 0 <= Input.ch && Input.ch <= 0x20 )
{
GetChar();
}
while( Input.ch == '/' )
{
NextChar();
switch( Input.ch1 )
{
case '*': /* */
GetChar(); /* '*' */
do
{
GetChar();
if ( Input.ch == '*' )
NextChar();
}
while( Input.ch != '*' || Input.ch1 != '/' );
GetChar(); /* '/' */
GetChar(); /* next char */
break ;
case '/': /* 行末までコメント */
do
{
GetChar();
}
while( Input.ch != '\n' );
GetChar(); /* next char */
break ;
default :
return '/' ;
}
}
} while ( 0 <= Input.ch && Input.ch <= 0x20 );
return Input.ch ;
}
/* ワードの1バイト目チェック */
static inline int isword1( c )
int c ;
{
return c == '_' || isalpha( c );
}
/* ワードの2バイト目以降チェック */
static inline int isword2( c )
int c ;
{
return c == '_' || isalnum( c );
}
/* 数字の1バイト目チェック */
static inline int isnum( c )
int c ;
{
return isdigit( c ) ;
}
/* 16進数のチェック */
static inline int ishex( c )
int c ;
{
#if 0
return isdigit( c ) || ( 'a' <= c && c <= 'f' ) || ( 'A' <= c && c <= 'F' ) ;
#endif
return isxdigit( c );
}
/* 数値定数 */
static void GetNum( data, buf )
DataStruct *data ;
char *buf ;
{
int i, flag ;
NextChar();
if ( Input.ch == '0' && Input.ch1 == 'x' )
{
/* 16進数 */
i = 0 ;
*buf++ = Input.ch ;
GetChar();
*buf++ = Input.ch ;
GetChar();
while( ishex( Input.ch ) )
{
if ( '0' <= Input.ch && Input.ch <= '9' )
i = i * 16 + ( Input.ch - '0' );
else
i = i * 16 + ( tolower( Input.ch ) - 'a' + 10 );
*buf++ = Input.ch ;
GetChar();
}
data->type = TYPE_INT ;
data->id.i = i ;
*buf = '\0' ;
return ;
}
else
{
char str[256], *p = str ;
flag = TYPE_INT ;
do
{
*p++ = Input.ch ;
if ( ! isdigit( Input.ch ) )
flag = TYPE_REAL ;
GetChar();
if ( Input.ch == 'E' || Input.ch == 'e' )
NextChar();
}
while(
isnum( Input.ch ) ||
( Input.ch == '.' ) ||
( ( Input.ch == 'E' || Input.ch == 'e' ) && ( Input.ch1 == '+' || Input.ch1 == '-' ) )
);
*p = '\0' ;
strcpy( buf, str );
data->type = flag ;
if ( flag == TYPE_INT )
data->id.i = atoi( str );
else
data->rd.r = atof( str );
return ;
}
}
/* 文字列定数 */
static void GetString( data )
DataStruct *data ;
{
int ch ;
int len ;
char str[STRING_CHARS] ;
assert( Input.ch == '\"' );
len = 0 ;
do
{
GetChar();
switch( Input.ch )
{
case '\\':
GetChar();
switch( Input.ch )
{
case 'n':
ch = '\n' ;
break ;
case 't':
ch = '\t' ;
break ;
case 'x': /* hex */
ch = 0 ;
NextChar();
while( ishex( Input.ch1 ) )
{
GetChar();
if ( '0' <= Input.ch && Input.ch <= '9' )
ch = ch * 16 + ( Input.ch - '0' );
else
ch = ch * 16 + ( tolower( Input.ch ) - 'a' + 10 );
NextChar();
}
break ;
case '0': case '1': case '2': case '3': /* oct */
case '4': case '5': case '6': case '7':
ch = 0 ;
NextChar();
while( '0' <= Input.ch1 && Input.ch1 <= '7' )
{
GetChar();
ch = ch * 8 + ( Input.ch - '0' );
NextChar();
}
break ;
default:
ch = Input.ch ;
}
break ;
case '\"':
GetChar(); /* next char */
Comment();
if ( Input.ch == '\"' )
continue ;
else
ch = '\0';
break ;
case EOF:
ch = '\0';
break ;
default:
ch = Input.ch ;
break ;
}
if ( len < STRING_CHARS )
str[len++] = ch ;
if ( iskanji( ch ) )
{
GetChar();
str[len++] = Input.ch ;
}
}
while( ch != '\0' );
str[len] = '\0' ;
data->type = TYPE_OBJECT ;
data->od.ptr = (Object*)StringSet( str );
return ;
}
/* トークンの切り出し */
int GetToken()
{
int i, twochar ;
Comment();
if ( Input.ch == EOF )
{
Input.token = SYM_EOF ;
return SYM_EOF ;
}
if ( isnum( Input.ch ) )
{
/* 数値定数 */
Input.token = SYM_CONSTDATA ;
GetNum( &Input.data, Input.str );
}
else if ( Input.ch == '\'' )
{
/* 単一文字 */
Input.token = SYM_CONSTDATA ;
Input.data.type = TYPE_INT ;
Input.data.id.i = 0 ;
GetChar();
while( Input.ch != '\'' )
{
Input.data.id.i = ( Input.data.id.i << 8 ) | Input.ch ;
GetChar();
}
GetChar();
}
else if ( Input.ch == '\"' )
{
/* 文字列定数 */
Input.token = SYM_CONSTDATA ;
GetString( &Input.data );
strcpy( Input.str, "" );
}
else if ( isword1( Input.ch ) )
{
/* ワード切り出し */
i = 0 ;
do
{
if ( i < IDENT_CHARS )
{
Input.str[i] = Input.ch ;
i++ ;
}
GetChar();
}
while( isword2( Input.ch ) );
Input.str[i] = '\0' ;
/* 予約語のチェック */
#if 0
for( i = 1 ; ResWord[i] != NULL ; i++ )
{
if ( strcmp( Input.str, ResWord[i] ) == 0 )
{
Input.token = SYM_RESERVED + i ;
return Input.token ;
}
}
#else
{
int i1, i2, j;
i1 = 0;
i2 = (sizeof(ResWord)/sizeof(ResWord[0]))-1;
while (i1 < i2-1) {
i = (i1+i2)/2;
j = strcmp(Input.str, ResWord[i]);
if (j == 0) {
Input.token = SYM_RESERVED + i ;
return Input.token ;
} else if (j < 0) {
i2 = i;
} else {
i1 = i;
}
}
}
#endif
#if 1
/* システム定数のチェック */
for( i = 0 ; i < SysConsts ; i++ )
{
if ( strcmp( Input.str, SysConst[i].name ) == 0 )
{
Input.token = SYM_CONSTDATA ;
Input.data = SysConst[i].data ;
return Input.token ;
}
}
#else
{
int i1, i2, j;
i1 = -1;
i2 = SysConsts;
while (i1 < i2-1) {
i = (i1+i2)/2;
j = strcmp(Input.str, SysConst[i].name);
if (j == 0) {
Input.token = SYM_CONSTDATA ;
Input.data = SysConst[i].data ;
return Input.token ;
} else if (j < 0) {
i2 = i;
} else {
i1 = i;
}
}
}
#endif
/* 識別子 */
Input.token = SYM_IDENT ;
}
else
{
twochar = FALSE ;
switch( Input.ch )
{
/* かっこ */
case '(':
Input.token = SYM_OPEN1 ;
break ;
case ')':
Input.token = SYM_CLOSE1 ;
break ;
case '{':
Input.token = SYM_OPEN2 ;
break ;
case '}':
Input.token = SYM_CLOSE2 ;
break ;
case '[':
Input.token = SYM_OPEN3 ;
break ;
case ']':
Input.token = SYM_CLOSE3 ;
break ;
/* 四則演算&代入 */
case '+':
NextChar();
if ( Input.ch1 == '=' )
{
Input.token = SYM_ASN_PLUS ;
twochar = TRUE ;
}
else if ( Input.ch1 == '+' )
{
Input.token = SYM_ASN_INC ;
twochar = TRUE ;
}
else
Input.token = SYM_PLUS ;
break ;
case '-':
NextChar();
if ( Input.ch1 == '=' )
{
Input.token = SYM_ASN_MINUS ;
twochar = TRUE ;
}
else if ( Input.ch1 == '-' )
{
Input.token = SYM_ASN_DEC ;
twochar = TRUE ;
}
else if ( Input.ch1 == '>' )
{
Input.token = SYM_REFER ;
twochar = TRUE ;
}
else
Input.token = SYM_MINUS ;
break ;
case '.':
Input.token = SYM_DOT ;
break ;
case '*':
NextChar();
if ( Input.ch1 == '=' )
{
Input.token = SYM_ASN_MULT ;
twochar = TRUE ;
}
else
Input.token = SYM_MULT ;
break ;
case '/':
NextChar();
if ( Input.ch1 == '=' )
{
Input.token = SYM_ASN_DIVIDE ;
twochar = TRUE ;
}
else
Input.token = SYM_DIVIDE ;
break ;
case '%':
Input.token = SYM_MOD ;
break ;
case '&':
NextChar();
if ( Input.ch1 == '=' )
{
Input.token = SYM_ASN_AND;
twochar = TRUE ;
}
else
Input.token = SYM_AND ;
break ;
case '|':
NextChar();
if ( Input.ch1 == '=' )
{
Input.token = SYM_ASN_OR ;
twochar = TRUE ;
}
else
Input.token = SYM_OR ;
break ;
case '^':
NextChar();
if ( Input.ch1 == '=' )
{
Input.token = SYM_ASN_XOR ;
twochar = TRUE ;
}
else
Input.token = SYM_XOR ;
break ;
case '!':
NextChar();
if ( Input.ch1 == '=' )
{
Input.token = SYM_NOTEQ ;
twochar = TRUE ;
}
else
Input.token = SYM_NOT ;
break ;
case '=':
NextChar();
if ( Input.ch1 == '=' )
{
Input.token = SYM_EQ ;
twochar = TRUE ;
}
else
Input.token = SYM_ASSIGN ;
break ;
/* 比較 */
case '<':
NextChar();
if ( Input.ch1 == '=' )
{
Input.token = SYM_LSSEQ ;
twochar = TRUE ;
}
else if ( Input.ch1 == '<' )
{
Input.token = SYM_LSFT ;
twochar = TRUE ;
}
else
Input.token = SYM_LSS ;
break ;
case '>':
NextChar();
if ( Input.ch1 == '=' )
{
Input.token = SYM_GTREQ ;
twochar = TRUE ;
}
else if ( Input.ch1 == '>' )
{
Input.token = SYM_RSFT ;
twochar = TRUE ;
}
else
Input.token = SYM_GTR ;
break ;
/* その他 */
case ',':
Input.token = SYM_COMMA ;
break ;
case ';':
Input.token = SYM_SEMCLN ;
break ;
case ':':
Input.token = SYM_COLON ;
break ;
case '#':
Input.token = SYM_PREPROC ;
break ;
case EOF:
Input.token = SYM_EOF ;
break ;
default:
Input.token = SYM_UNKNOWN ;
break ;
}
Input.str[0] = Input.ch ;
if ( twochar )
{
GetChar();
Input.str[1] = Input.ch ;
Input.str[2] = '\0' ;
}
else
Input.str[1] = '\0' ;
GetChar();
}
return Input.token ;
}