blob: 4c243a7e542f55ce9a7ba3aef8df0fda9602c807 [file] [log] [blame]
/* token_stream.cc */
/*
Copyright (C) 2003 Unique Software Designs
This file is part of the program "lambda".
The program "lambda" is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
The program "lambda" is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with "lambda"; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A copy of the GNU General Public License may also be found at:
http://www.gnu.org/copyleft/gpl.html
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <config.h>
#include "token_stream.h"
static struct header_def{
token_stream::header_type type;
char* value;
} headers[] = {
{token_stream::DEF, "def"},
{token_stream::LOAD, "load"},
{token_stream::SAVE, "save"},
{token_stream::QUIT, "quit"},
{token_stream::LIST, "list"},
{token_stream::SET, "set"},
{token_stream::EXT, "ext"},
{token_stream::NOTHDR, NULL} };
token_stream::
token_stream(const char* filename)
{
in = 0;
file_name_v = 0;
paren_level_v = 0;
linenum_v = 0;
need_new_line_v = 0;
open(filename);
}
Boolean token_stream::
open(const char* filename)
{
read_error = False;
if( filename ){
if( in ) fclose(in);
in = fopen(filename,"r" );
if( !in ){
read_error = True;
dderrmsg("Cannot Open \"%s\":%s\n",
filename, strerror(errno));
}
file_name_v = new char[strlen(filename)+1];
if( file_name_v ) strcpy(file_name_v,filename);
}else{
in = stdin;
file_name_v = 0;
}
read_EOF = False;
push_token(NOTOKEN,"");
ptok = 0;
linenum_v = 0;
paren_level_v = 0;
need_new_line_v = 1;
return (in!=0);
}
token_stream::
~token_stream()
{
if( in ) fclose(in);
if( file_name_v ) delete [] file_name_v;
}
void token_stream::
reset_token()
{
paren_level_v = 0;
#if 1
pushed_token = NOTOKEN;
need_new_line_v = 1;
ptok = linebuf;
*ptok = '\0';
#endif
}
void token_stream::
close()
{
if( in && file_name_v) fclose(in);
in = 0;
}
void token_stream::
dderrmsg(char* format,...)
{
va_list args;
va_start(args, format);
//format = va_arg(args,char*);
#if defined _WINDOWS
char msg[512];
sprintf(msg, "***line %d:\n", linenum_v);
vsprintf(msg+strlen(msg), format, args );
AfxMessageBox(msg);
#else
if(linenum_v>=0)
fprintf(stderr,"\n*** line %d: ",linenum_v);
vfprintf(stderr,format,args);
#endif
va_end(args);
fflush(stderr);
}
char *token_stream::
read_line()
{
//#define READ_BUF_SIZE 512
//static char linebuf[READ_BUF_SIZE];
int n;
char *res = fgets(linebuf,READ_BUF_SIZE,in);
if( res != NULL ){
linenum_v++;
n = strlen(linebuf);
if( n>0 ){
n -= 1;
if( linebuf[n]=='\n' ) linebuf[n] = '\0';
}
} else {
if( ferror(in) ){
n = errno;
printf(
"*error reading line %d of DataDesc input file: %s\n",
linenum_v,strerror(errno) );
read_error = True;
}else if( feof(in) ){
read_EOF = True;
}
}
need_new_line_v = 0;
return res;
}
token_stream::header_type token_stream::
is_header(token_type tok, char *ptk )
{
header_def* phdr;
header_type res = NOTHDR;
if( NAME==tok ){
for(phdr = headers; phdr->type!=NOTHDR; phdr++ ){
if( strcmp(ptk,phdr->value)==0 ){
res = phdr->type;
break;
}
}
}
return res;
}
void token_stream::
push_token(token_type tok, char *ptk )
{
pushed_token = tok;
if( ptk!=NULL && token!=ptk ) strncpy(token,ptk,MAX_TOKEN_SIZE-1);
token[MAX_TOKEN_SIZE-1] = '\0';
}
token_stream::token_type token_stream::
get_token(char **atok)
{
char *ttok;
token_stream::token_type res;
register char chr;
Boolean found;
if( !in ) return NOTOKEN;
if( pushed_token!=NOTOKEN ){
*atok = token;
res = pushed_token;
pushed_token = NOTOKEN;
return res;
}
res = NOTOKEN;
*atok = NULL;
found = False;
while( !found ){
if( NULL==ptok || '\0'==ptok[0] ){
if( 0==paren_level_v && !need_new_line_v ) {
need_new_line_v = 1;
token[0] = '\0';
res = EOE;
break;
}
if( paren_level_v > 0 )
printf("*need %d )%s*<< ", paren_level_v,
paren_level_v > 1 ? "'s" : "" );
ptok = read_line();
}
if( NULL==ptok ) break;
found = True;
while( (chr=ptok[0])!='\0' && chr<=' ' ) ptok++;
token[0] = ptok[0];
token[1] = '\0';
switch( ptok[0] ){
case '\0':
case '#':
found = False;
ptok = NULL;
break;
case '^':
res = LAMBDA;
ptok++;
break;
case '.':
res = PERIOD;
ptok++;
break;
case '(':
res = LPAREN;
paren_level_v++;
ptok++;
break;
case ')':
res = RPAREN;
paren_level_v--;
ptok++;
break;
case '{':
res = LBRACE;
ptok++;
break;
case '}':
res = RBRACE;
ptok++;
break;
case ',':
res = COMMA;
ptok++;
break;
case ';':
res = SEMICOLON;
ptok++;
break;
case '"':
res = STRING;
for( ttok=token,ptok++;
ttok<token+MAX_TOKEN_SIZE-1;
ttok++,ptok++
){
while( '\\'==ptok[0] && '\0'==ptok[1] ){
ptok = read_line();
if( NULL==ptok ){
res = NOTOKEN;
goto endit;
}
}
chr = ptok[0];
if( chr=='\\' ){
ptok++;
chr = ptok[0];
if( chr=='n' ) chr = '\n';
else if( chr=='t' ) chr = '\t';
}else{
if( '\0'==chr ) break;
if( '"' ==chr ){
ptok++;
break;
}
}
ttok[0] = chr;
}
ttok[0] = '\0';
break;
default:
res = NAME;
for( ttok=token;
ttok<token+MAX_TOKEN_SIZE-1
&& '\0'!=ptok[0];
ttok++,ptok++
){
chr = ptok[0];
if( NULL!=strchr(" .(){},;\"",chr) ) break;
ttok[0] = chr;
}
ttok[0] = '\0';
}
}
endit:
if( res!=NOTOKEN ) *atok = token;
#ifdef PRINTTOKENS
if( res!=NOTOKEN ){
/*fprintf(stderr,"%s ",tokname[tok] );*/
fprintf(stderr," %s%s%s",
res==STRING? "\"":
res==LBRACE? "\n":
"",
token,
res==STRING? "\"" :
res==SEMICOLON? "\n":
is_header(res,token)? "\n":
""
);
}else{
fprintf(stderr,"\nEnd of Token Stream!\n");
}
fflush(stderr);
#endif
if( res!=NOTOKEN ) *atok = token;
return res;
}