411 lines
		
	
	
	
		
			7.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			411 lines
		
	
	
	
		
			7.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* L E X I C A L   A N A L Y S E R   F O R   I S O - P A S C A L */
 | 
						|
 | 
						|
#include	"debug.h"
 | 
						|
#include	"idfsize.h"
 | 
						|
#include	"numsize.h"
 | 
						|
#include	"strsize.h"
 | 
						|
 | 
						|
#include	<alloc.h>
 | 
						|
#include	<em_arith.h>
 | 
						|
#include	<em_label.h>
 | 
						|
 | 
						|
#include	"LLlex.h"
 | 
						|
#include	"Lpars.h"
 | 
						|
#include	"class.h"
 | 
						|
#include	"const.h"
 | 
						|
#include	"f_info.h"
 | 
						|
#include	"idf.h"
 | 
						|
#include	"input.h"
 | 
						|
#include	"main.h"
 | 
						|
#include	"type.h"
 | 
						|
 | 
						|
extern long	str2long();
 | 
						|
extern char	*Malloc();
 | 
						|
 | 
						|
#define	TO_LOWER(ch)	(ch |= ( ch>='A' && ch<='Z' ) ? 0x0020 : 0)
 | 
						|
 | 
						|
#ifdef DEBUG
 | 
						|
extern int cntlines;
 | 
						|
#endif
 | 
						|
 | 
						|
int idfsize = IDFSIZE;
 | 
						|
struct token	dot,
 | 
						|
		aside;
 | 
						|
 | 
						|
struct type	*toktype,
 | 
						|
		*asidetype;
 | 
						|
 | 
						|
static int	eofseen;
 | 
						|
 | 
						|
STATIC
 | 
						|
SkipComment()
 | 
						|
{
 | 
						|
	/*	Skip ISO-Pascal comments (* ... *) or { ... }.
 | 
						|
		Note :
 | 
						|
			comments may not be nested (ISO 6.1.8).
 | 
						|
			(* and { are interchangeable, so are *) and }.
 | 
						|
	*/
 | 
						|
	register int ch;
 | 
						|
 | 
						|
	LoadChar(ch);
 | 
						|
	for (;;)	{
 | 
						|
		if( class(ch) == STNL )	{
 | 
						|
			LineNumber++;
 | 
						|
#ifdef DEBUG
 | 
						|
			cntlines++;
 | 
						|
#endif
 | 
						|
		}
 | 
						|
		else if( ch == '*' )	{
 | 
						|
			LoadChar(ch);
 | 
						|
			if( ch == ')' ) return;		/* *) */
 | 
						|
			else continue;
 | 
						|
		}
 | 
						|
		else if( ch == '}' ) return;
 | 
						|
		else if( ch == EOI )	{
 | 
						|
			lexerror("unterminated comment");
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		LoadChar(ch);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
STATIC struct string *
 | 
						|
GetString()
 | 
						|
{
 | 
						|
	/*	Read a Pascal string, delimited by the character "'".
 | 
						|
	*/
 | 
						|
	register int ch;
 | 
						|
	register struct string *str = (struct string *)
 | 
						|
				Malloc((unsigned) sizeof(struct string));
 | 
						|
	register char *p;
 | 
						|
	register int len = ISTRSIZE;
 | 
						|
	
 | 
						|
	str->s_str = p = Malloc((unsigned int) ISTRSIZE);
 | 
						|
	for( ; ; )	{
 | 
						|
		LoadChar(ch);
 | 
						|
		if( ch & 0200 )
 | 
						|
			fatal("non-ascii '\\%03o' read", ch & 0377);
 | 
						|
			/*NOTREACHED*/
 | 
						|
		if( class(ch) == STNL )	{
 | 
						|
			lexerror("newline in string");
 | 
						|
			LineNumber++;
 | 
						|
#ifdef DEBUG
 | 
						|
			cntlines++;
 | 
						|
#endif
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		if( ch == EOI )	{
 | 
						|
			lexerror("end-of-file in string");
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		if( ch == '\'' )	{
 | 
						|
			LoadChar(ch);
 | 
						|
			if( ch != '\'' )
 | 
						|
				break;
 | 
						|
		}
 | 
						|
		*p++ = ch;
 | 
						|
		if( p - str->s_str == len )	{
 | 
						|
			extern char *Srealloc();
 | 
						|
 | 
						|
			str->s_str = Srealloc(str->s_str,
 | 
						|
					(unsigned int) len + RSTRSIZE);
 | 
						|
			p = str->s_str + len;
 | 
						|
			len += RSTRSIZE;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if( ch == EOI ) eofseen = 1;
 | 
						|
	else PushBack();
 | 
						|
 | 
						|
	str->s_length = p - str->s_str;
 | 
						|
	*p++ = '\0';
 | 
						|
 | 
						|
	/* ISO 6.1.7: string length at least 1 */
 | 
						|
	if( str->s_length == 0 )	{
 | 
						|
		lexerror("character-string: at least one character expected");
 | 
						|
		str->s_length = 1;
 | 
						|
	}
 | 
						|
 | 
						|
	return str;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
LLlex()
 | 
						|
{
 | 
						|
	/*	LLlex() is the Lexical Analyzer.
 | 
						|
		The putting aside of tokens is taken into account.
 | 
						|
	*/
 | 
						|
	register struct token *tk = ˙
 | 
						|
	register int ch, nch;
 | 
						|
 | 
						|
	toktype = error_type;
 | 
						|
 | 
						|
	if( ASIDE )	{	/* a token is put aside */
 | 
						|
		*tk = aside;
 | 
						|
		toktype = asidetype;
 | 
						|
		ASIDE = 0;
 | 
						|
		return tk->tk_symb;
 | 
						|
	}
 | 
						|
 | 
						|
	tk->tk_lineno = LineNumber;
 | 
						|
 | 
						|
	if( eofseen )	{
 | 
						|
		eofseen = 0;
 | 
						|
		ch = EOI;
 | 
						|
	}
 | 
						|
	else	{
 | 
						|
again:
 | 
						|
		LoadChar(ch);
 | 
						|
		if( !options['C'] )		/* -C : cases are different */
 | 
						|
			TO_LOWER(ch);
 | 
						|
 | 
						|
		if( (ch & 0200) && ch != EOI )
 | 
						|
			fatal("non-ascii '\\%03o' read", ch & 0377);
 | 
						|
			/*NOTREACHED*/
 | 
						|
	}
 | 
						|
 | 
						|
	switch( class(ch) )	{
 | 
						|
 | 
						|
	case STNL:
 | 
						|
		LineNumber++;
 | 
						|
		tk->tk_lineno++;
 | 
						|
#ifdef DEBUG
 | 
						|
		cntlines++;
 | 
						|
#endif
 | 
						|
		goto again;
 | 
						|
 | 
						|
	case STSKIP:
 | 
						|
		goto again;
 | 
						|
 | 
						|
	case STGARB:
 | 
						|
		if( (unsigned) ch < 0177 )
 | 
						|
			lexerror("garbage char %c", ch);
 | 
						|
		else
 | 
						|
			crash("(LLlex) garbage char \\%03o", ch);
 | 
						|
		goto again;
 | 
						|
 | 
						|
	case STSIMP:
 | 
						|
		if( ch == '(' )	{
 | 
						|
			LoadChar(nch);
 | 
						|
			if( nch == '*' )	{		/* (* */
 | 
						|
				SkipComment();
 | 
						|
				tk->tk_lineno = LineNumber;
 | 
						|
				goto again;
 | 
						|
			}
 | 
						|
			if( nch == '.' )			/* (. is [ */
 | 
						|
				return tk->tk_symb = '[';
 | 
						|
			if( nch == EOI ) eofseen = 1;
 | 
						|
			else PushBack();
 | 
						|
		}
 | 
						|
		else if( ch == '{' )	{
 | 
						|
			SkipComment();
 | 
						|
			tk->tk_lineno = LineNumber;
 | 
						|
			goto again;
 | 
						|
		}
 | 
						|
		else if( ch == '@' ) ch = '^';		/* @ is ^ */
 | 
						|
 | 
						|
		return tk->tk_symb = ch;
 | 
						|
 | 
						|
	case STCOMP:
 | 
						|
		LoadChar(nch);
 | 
						|
		switch( ch )	{
 | 
						|
 | 
						|
		case '.':
 | 
						|
			if( nch == '.' )			/* .. */
 | 
						|
				return tk->tk_symb = UPTO;
 | 
						|
			if( nch == ')' )			/* .) is ] */
 | 
						|
				return tk->tk_symb = ']';
 | 
						|
			break;
 | 
						|
 | 
						|
		case ':':
 | 
						|
			if( nch == '=' )			/* := */
 | 
						|
				return tk->tk_symb = BECOMES;
 | 
						|
			break;
 | 
						|
 | 
						|
		case '<':
 | 
						|
			if( nch == '=' )			/* <= */
 | 
						|
				return tk->tk_symb = LESSEQUAL;
 | 
						|
			if( nch == '>' )			/* <> */
 | 
						|
				return tk->tk_symb = NOTEQUAL;
 | 
						|
			break;
 | 
						|
 | 
						|
		case '>':
 | 
						|
			if( nch == '=' )			/* >= */
 | 
						|
				return tk->tk_symb = GREATEREQUAL;
 | 
						|
			break;
 | 
						|
 | 
						|
		default :
 | 
						|
			crash("(LLlex, STCOMP)");
 | 
						|
			/*NOTREACHED*/
 | 
						|
		}
 | 
						|
		if( nch == EOI ) eofseen = 1;
 | 
						|
		else PushBack();
 | 
						|
		return tk->tk_symb = ch;
 | 
						|
 | 
						|
	case STIDF:	{
 | 
						|
		char buf[IDFSIZE + 1];
 | 
						|
		register char *tag = &buf[0];
 | 
						|
		register struct idf *id;
 | 
						|
		extern struct idf *str2idf();
 | 
						|
 | 
						|
		do	{
 | 
						|
			if( !options['C'] )	/* -C : cases are different */
 | 
						|
				TO_LOWER(ch);
 | 
						|
			if( tag - buf < idfsize )
 | 
						|
				*tag++ = ch;
 | 
						|
			LoadChar(ch);
 | 
						|
		} while( in_idf(ch) );
 | 
						|
		*tag = '\0';
 | 
						|
 | 
						|
		if( ch == EOI ) eofseen = 1;
 | 
						|
		else PushBack();
 | 
						|
 | 
						|
		tk->TOK_IDF = id = str2idf(buf, 1);
 | 
						|
		return tk->tk_symb = id->id_reserved ? id->id_reserved : IDENT;
 | 
						|
	}
 | 
						|
 | 
						|
	case STSTR:	{
 | 
						|
		register struct string *str = GetString();
 | 
						|
 | 
						|
		if( str->s_length == 1 )	{
 | 
						|
#ifdef DEBUG
 | 
						|
			if( options['l'] )	{
 | 
						|
				/* to prevent LexScan from crashing */
 | 
						|
				tk->tk_data.tk_str = str;
 | 
						|
				return tk->tk_symb = STRING;
 | 
						|
			}
 | 
						|
#endif
 | 
						|
			tk->TOK_INT = *(str->s_str) & 0377;
 | 
						|
			toktype = char_type;
 | 
						|
			free(str->s_str);
 | 
						|
			free((char *) str);
 | 
						|
		}
 | 
						|
		else	{
 | 
						|
			tk->tk_data.tk_str = str;
 | 
						|
			toktype = standard_type(T_STRING, 1, str->s_length);
 | 
						|
		}
 | 
						|
		return tk->tk_symb = STRING;
 | 
						|
	}
 | 
						|
 | 
						|
	case STNUM:	{
 | 
						|
#define INT_MODE	0
 | 
						|
#define REAL_MODE	1
 | 
						|
 | 
						|
		char buf[NUMSIZE+2];
 | 
						|
		register char *np = buf;
 | 
						|
		register int state = INT_MODE;
 | 
						|
		extern char *Salloc();
 | 
						|
 | 
						|
		do	{
 | 
						|
			if( np <= &buf[NUMSIZE] )
 | 
						|
				*np++ = ch;
 | 
						|
			LoadChar(ch);
 | 
						|
		} while( is_dig(ch) );
 | 
						|
 | 
						|
		if( ch == '.' )	{
 | 
						|
			LoadChar(ch);
 | 
						|
			if( is_dig(ch) )	{
 | 
						|
				if( np <= &buf[NUMSIZE] )
 | 
						|
					*np++ = '.';
 | 
						|
				do	{
 | 
						|
					/* fractional part */
 | 
						|
					if( np <= &buf[NUMSIZE] )
 | 
						|
						*np++ = ch;
 | 
						|
					LoadChar(ch);
 | 
						|
				} while( is_dig(ch) );
 | 
						|
				state = REAL_MODE;
 | 
						|
			}
 | 
						|
			else	{
 | 
						|
				PushBack();
 | 
						|
				PushBack();
 | 
						|
				goto end;
 | 
						|
			}
 | 
						|
				
 | 
						|
		}
 | 
						|
		if( ch == 'e' || ch == 'E' )	{
 | 
						|
			char *tp = np;		/* save position in string */
 | 
						|
 | 
						|
			/* scale factor */
 | 
						|
			if( np <= &buf[NUMSIZE] )
 | 
						|
				*np++ = ch;
 | 
						|
			LoadChar(ch);
 | 
						|
			if( ch == '+' || ch == '-' )	{
 | 
						|
				/* signed scale factor */
 | 
						|
				if( np <= &buf[NUMSIZE] )
 | 
						|
					*np++ = ch;
 | 
						|
				LoadChar(ch);
 | 
						|
			}
 | 
						|
			if( is_dig(ch) )	{
 | 
						|
				do	{
 | 
						|
					if( np <= &buf[NUMSIZE] )
 | 
						|
						*np++ = ch;
 | 
						|
					LoadChar(ch);
 | 
						|
				} while( is_dig(ch) );
 | 
						|
				state = REAL_MODE;
 | 
						|
			}
 | 
						|
			else	{
 | 
						|
				PushBack();
 | 
						|
				PushBack();
 | 
						|
				if( np - tp == 2 )	/* sign */
 | 
						|
					PushBack();
 | 
						|
				np = tp;		/* restore position */
 | 
						|
				goto end;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		/* syntax of number is correct */
 | 
						|
		if( ch == EOI ) eofseen = 1;
 | 
						|
		else PushBack();
 | 
						|
	end:
 | 
						|
		*np++ = '\0';
 | 
						|
 | 
						|
		if( state == INT_MODE )	{
 | 
						|
			if( np > &buf[NUMSIZE+1] )	{
 | 
						|
				tk->TOK_INT = 1;
 | 
						|
				lexerror("constant too long");
 | 
						|
			}
 | 
						|
			else	{
 | 
						|
				np = buf;
 | 
						|
				while (*np == '0')	/* skip leading zeros */
 | 
						|
					np++;
 | 
						|
				tk->TOK_INT = str2long(np, 10);
 | 
						|
				if( tk->TOK_INT < 0 ||
 | 
						|
				    strlen(np) > strlen(maxint_str) ||
 | 
						|
					strlen(np) == strlen(maxint_str) &&
 | 
						|
					strcmp(np, maxint_str) > 0 )
 | 
						|
					     lexwarning("overflow in constant");
 | 
						|
			}
 | 
						|
			toktype = int_type;
 | 
						|
			return tk->tk_symb = INTEGER;
 | 
						|
		}
 | 
						|
		/* REAL_MODE */
 | 
						|
		tk->tk_data.tk_real = (struct real *)
 | 
						|
						Malloc(sizeof(struct real));
 | 
						|
		/* allocate struct for inverse */
 | 
						|
		tk->TOK_RIV = (struct real *) Malloc(sizeof(struct real));
 | 
						|
		tk->TOK_RIV->r_inverse = tk->tk_data.tk_real;
 | 
						|
 | 
						|
		/* sign */
 | 
						|
		tk->TOK_RSI = 0;
 | 
						|
		tk->TOK_RIV->r_sign = 1;
 | 
						|
 | 
						|
		if( np > &buf[NUMSIZE+1] )	{
 | 
						|
			tk->TOK_REL = Salloc("0.0", 4);
 | 
						|
			lexerror("floating constant too long");
 | 
						|
		}
 | 
						|
		else tk->TOK_REL = Salloc(buf, np - buf);
 | 
						|
 | 
						|
		toktype = real_type;
 | 
						|
		return tk->tk_symb = REAL;
 | 
						|
 | 
						|
		/*NOTREACHED*/
 | 
						|
	}
 | 
						|
 | 
						|
	case STEOI:
 | 
						|
		return tk->tk_symb = -1;
 | 
						|
 | 
						|
	case STCHAR:
 | 
						|
	default:
 | 
						|
		crash("(LLlex) Impossible character class");
 | 
						|
		/*NOTREACHED*/
 | 
						|
	}
 | 
						|
	/*NOTREACHED*/
 | 
						|
}
 |