/* 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;
}
¤ Dauer der Verarbeitung: 0.4 Sekunden
¤
*© Formatika GbR, Deutschland