
/*	yylex.c		lexical scanner for the hexcalc utility
 */

#include <stdio.h>
#include <ctype.h>

#include "hexcalc.h"
#ifdef __TURBOC__
#include "ytab.h"
#else
#include "y.tab.h"
#endif

extern int lineno;
extern int radix;

#define MAXCHARS 31	/* number of significant chars in an identifier */

/******************************************************************************/

int yylex ()
{
	int c;

	while ((c = getchar()) == ' ' || c == '\t') /* skip whitespace */;
	if (c == EOF) return 0;

	if (radix == 8)
	{
		if (c >= '0' && c <= '7')
		{
			ungetc (c, stdin);
			scanf ("%lo", &yylval.val);
			return NUMBER;
		}
	}
	else if (isdigit(c))
	{
		ungetc (c, stdin);
		scanf (radix == 16 ? "%lx" : "%lu", &yylval.val);
		return NUMBER;
	}
	if (isalpha(c))
	{
		Symbol *s;
		char sbuf [MAXCHARS+1], *p = sbuf;

		do 
		{
			if (p < sbuf+MAXCHARS) *p++ = c;
		} 
		while ((c = getchar()) != EOF && isalnum(c));
		ungetc (c, stdin);
		*p = '\0';
		if ((s = lookup (sbuf)) == (Symbol *)0)
		{
			s = install (sbuf, UNDEF, (BASE_TYPE)0);
		}
		yylval.sym = s;
		return s->type == UNDEF ? VAR : s->type;
	}
	/* handle multi-char operator tokens */
	if ((c == '<') || (c == '>'))
	{
		int c2 = getchar();

		if ((c == '<') && (c2 == '<'))
		{
			return LSH;
		}
		else if ((c == '>') && (c2 == '>'))
		{
			return RSH;
		}
		else
		{
			ungetc(c2, stdin);
		}
	}
	if (c == '*')
	{
		int c2 = getchar();

		if (c2 == '*')
		{
			return POW;
		}
		else
		{
			ungetc(c2, stdin);
		}
	}
	if (c == '#')		/* handle comments */
	{
		int echo = (c = getchar()) == '#';

		if (echo != 0) putchar('\t');
		while (c != '\n')
		{
			if (echo != 0) putchar(c);
			c = getchar();
		}
		if (echo != 0) putchar(c);
	}
	if (c == '\n') ++lineno;

	return c;
}
