/* File token.c. */
#define COMMENT_CHAR '\"'
#define ALT_COMMENT_CHAR '&'
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "group.h"
#include "groupio.h"
#include "errmesg.h"
CHECK( token)
static FILE *inFile; /* File to read from. */
static Unsigned lineNo; /* Line number in file. */
static BOOLEAN bufferNonempty; /* True if a token has been read but not
returned. */
static Token tokenBuffer; /* The token read but not returned. */
static BOOLEAN endOfFileReached; /* True if end of file has been reached. */
static const char *inString; /* String to read from. */
static Unsigned stringPosition; /* First position in string not read. */
static BOOLEAN sBufferNonempty; /* True if a token has been read from string
but not returned. */
static Token sTokenBuffer; /* The token read from string but not
returned. */
static BOOLEAN endOfStringReached; /* True if end of string has been reached. */
static BOOLEAN recognizeKeywordFlag = TRUE ; /* If false, a colon is treated as an
ordinary character. Keywords are not
recognized. */
/*-------------------------- lowerCase -----------------------------------*/
/* The function lowerCase(s) converts the string s to lower case and returns
a pointer to s. */
char *lowerCase(
char *s)
{
Unsigned i;
for ( i = 0 ; i < strlen(s) ; ++i )
#ifdef EBCDIC
s[i] = ( s[i] >= 'A' && s[i] <= 'I' ||
s[i] >= 'J' && s[i] <= 'R' ||
s[i] >= 'S' && s[i] <= 'Z' ) ? (s[i] + 'a' - 'A' ) : s[i];
#else
s[i] = (s[i] >= 'A' && s[i] <= 'Z' ) ? (s[i] + 'a' - 'A' ) : s[i];
#endif
return s;
}
/*-------------------------- setInputFile --------------------------------*/
void setInputFile(
FILE *newFile)
{
inFile = newFile;
lineNo = 1;
endOfFileReached = FALSE ;
bufferNonempty = FALSE ;
}
/*-------------------------- setInputString ------------------------------*/
void setInputString(
const char *const newString)
{
inString = newString;
stringPosition = 0;
endOfStringReached = FALSE ;
sBufferNonempty = FALSE ;
}
/*-------------------------- discardThruChar --------------------------------*/
static void discardThruChar(
Unsigned stopDiscard,
Unsigned *lineNoPtr )
{
Unsigned ch;
do {
ch = getc(inFile);
if ( ch == '\n' )
++(*lineNoPtr);
} while ( ch != '\n' && ch != stopDiscard);
}
/*-------------------------- readToken -----------------------------------*/
Token readToken( void )
{
Token token;
int ch;
Unsigned lastPos;
char buffer[100];
/* If a token has been read but not returned, return that token and exit. */
if ( bufferNonempty ) {
bufferNonempty = FALSE ;
return tokenBuffer;
}
/* If end of file has already been reached, return eof as token type. */
if ( endOfFileReached ) {
token.type = eof;
return token;
}
/* Skip over white space, but keep track of line numbers in the file. */
while ( (ch = getc(inFile)) == ' ' || ch == '\t' ||
(ch == '\n' ? (++lineNo,TRUE ) : FALSE ) ||
( (ch == COMMENT_CHAR || ch == ALT_COMMENT_CHAR) ?
(discardThruChar( ch, &lineNo),TRUE ) : FALSE ) )
;
/* This code handles keyword and identifier tokens. */
if ( isalpha(ch) || ch == '_' ) {
buffer[0] = ch;
lastPos = 0;
while ( (ch = getc(inFile)) , isalpha(ch) || isdigit(ch) || ch == '_' )
if ( lastPos < MAX_TOKEN_LENGTH-1 )
buffer[++lastPos] = ch;
else
ERROR1i( "readToken" , "Token length exceed maximum of " ,
MAX_TOKEN_LENGTH, "." )
token.type = ( ch == ':' && recognizeKeywordFlag ) ? keyword : identifier;
buffer[lastPos+1] = '\0' ;
if ( token.type == keyword )
strcpy( token.value.keyValue, buffer);
else
strcpy( token.value.identValue, buffer);
if ( token.type == identifier) {
if ( ch != EOF )
ungetc( ch, inFile);
else
endOfFileReached = TRUE ;
}
}
/* This code handles integer tokens. */
else if ( isdigit(ch) ) {
ungetc( ch, inFile);
if ( fscanf( inFile, SCANF_Int_FORMAT, &token.value.intValue) == 1 )
token.type = integer;
else
ERROR( "readToken" , "Error in reading integer token." )
}
/* This code handles end-of-file tokens. */
else if ( ch == EOF ) {
token.type = eof;
endOfFileReached = TRUE ;
}
/* This code handles single-character tokens. */
else switch ( ch ) {
case '(' : token.type = leftParen; break ;
case ')' : token.type = rightParen; break ;
case '[' : token.type = leftBracket; break ;
case ']' : token.type = rightBracket; break ;
case '<' : token.type = leftAngle; break ;
case '>' : token.type = rightAngle; break ;
case ';' : token.type = semicolon; break ;
case '=' : token.type = equal; break ;
case '*' : token.type = asterisk; break ;
case '^' : token.type = caret; break ;
case ',' : token.type = comma; break ;
case '/' : token.type = slash; break ;
case '.' : token.type = period; break ;
case ':' : token.type = colon; break ;
default : token.type = other; token.value.charValue = ch;
}
return token;
}
/*-------------------------- nkReadToken ---------------------------------*/
Token nkReadToken(void )
{
Token token;
recognizeKeywordFlag = FALSE ;
token = readToken();
if ( token.type == identifier )
lowerCase( token.value.identValue);
recognizeKeywordFlag = TRUE ;
return token;
}
/*-------------------------- sReadToken ----------------------------------*/
Token sReadToken( void )
{
Token token;
char ch;
Unsigned lastPos;
char sBuffer[100];
/* If a token has been read but not returned, return that token and exit. */
if ( sBufferNonempty ) {
sBufferNonempty = FALSE ;
return sTokenBuffer;
}
/* If end of string has already been reached, return eof as token type. */
if ( endOfStringReached ) {
token.type = eof;
return token;
}
/* Skip over white space, but keep track of line numbers in the file. */
while ( (ch = inString[stringPosition++]) == ' ' || ch == '\t' ||
ch == '\n' )
;
/* This code handles keyword and identifier tokens. */
if ( isalpha(ch) || ch == '_' ) {
sBuffer[0] = ch;
lastPos = 0;
while ( (ch = inString[stringPosition++]) , isalpha(ch) || isdigit(ch) ||
ch == '_' )
if ( lastPos < MAX_TOKEN_LENGTH-1 )
sBuffer[++lastPos] = ch;
else
ERROR1i( "sReadToken" , "Token length exceed maximum of " ,
MAX_TOKEN_LENGTH, "." )
token.type = ( ch == ':' && recognizeKeywordFlag ) ? keyword : identifier;
sBuffer[lastPos+1] = '\0' ;
if ( token.type == keyword )
strcpy( token.value.keyValue, sBuffer);
else
strcpy( token.value.identValue, sBuffer);
if ( token.type == identifier) {
if ( ch != '\0' )
--stringPosition;
else
endOfStringReached = TRUE ;
}
}
/* This code handles integer tokens. */
else if ( isdigit(ch) ) {
--stringPosition;
if ( sscanf( inString+stringPosition, SCANF_Int_FORMAT,
&token.value.intValue) == 1 ) {
token.type = integer;
while ( isdigit( inString[++stringPosition]) )
;
}
else
ERROR( "sReadToken" , "Error in reading integer token." )
}
/* This code handles end-of-string tokens. */
else if ( ch == '\0' ) {
token.type = eof;
endOfStringReached = TRUE ;
}
/* This code handles single-character tokens. */
else switch ( ch ) {
case '(' : token.type = leftParen; break ;
case ')' : token.type = rightParen; break ;
case '[' : token.type = leftBracket; break ;
case ']' : token.type = rightBracket; break ;
case '<' : token.type = leftAngle; break ;
case '>' : token.type = rightAngle; break ;
case ';' : token.type = semicolon; break ;
case '=' : token.type = equal; break ;
case '*' : token.type = asterisk; break ;
case '^' : token.type = caret; break ;
case ',' : token.type = comma; break ;
case '/' : token.type = slash; break ;
case '.' : token.type = period; break ;
case ':' : token.type = colon; break ;
default : token.type = other; token.value.charValue = ch;
}
return token;
}
/*-------------------------- unreadToken ---------------------------------*/
void unreadToken(
Token tokenToUnread)
{
tokenBuffer = tokenToUnread;
bufferNonempty = TRUE ;
}
/*-------------------------- sUnreadToken --------------------------------*/
void sUnreadToken(
Token tokenToUnread)
{
sTokenBuffer = tokenToUnread;
sBufferNonempty = TRUE ;
}
Messung V0.5 C=93 H=88 G=90
¤ Dauer der Verarbeitung: 0.7 Sekunden
¤
*© Formatika GbR, Deutschland