V10/cmd/pico/lex.c

Compare this file to the similar file:
Show the results in this format:

#include <stdio.h>
#include <ctype.h>
#include "pico.h"
#include "y.tab.h"

#define Prompt2		/* if (INPUT == stdin) fprintf(stderr, ":%d ", pline) */

extern FILE	*INPUT;

Symbol	*whichcmd(), *lookup(), *getname();
char	*getstring();

int	linenumber = 1;
int	pline	   =  0;
int	lexlast    = -1;
int	LO	   = -1;
char	lastyy     = '\n';
char	nolf	   = 1;
char	nesting    = 0;
char	operator   = 0;
char	lastdepth  = 0;

/*
 * if the last token seen was not an operator the next
 * newline will be interpreted as a statement separator
 */

#define ADDEQ	210
#define SUBEQ	211
#define MULEQ	212
#define DIVEQ	213
#define MODEQ	214
#define INC	215
#define DEC	216

yylex()
{ int c;
	while ((c = ylexlex()) == SCOM)
	{	do c = ylexlex();
		while (c != ECOM);
	}
	/* fprintf(stderr, "lex: %d [[%c]]\n", c, (isalnum(c))?c:'-');/*  */
	switch (c) {
	case '+':	case '-':	case '*':
	case '/':	case '%':	case '^':
	case POW:	case GT:	case GE:
	case LT:	case LE:	case EQ:
	case NE:	case ANDAND:	case OROR:
	case OR:	case AND:	case LSH:
	case RSH:	case ',':	case NOT:
	case '~':	case '?':	case ':':
	case ASSIGN:	case '(':	case '[':
		operator = 1;
		break;
	case ADDEQ:	operator = 1; LO = OADD; return OPER;
	case SUBEQ:	operator = 1; LO = OSUB; return OPER;
	case MULEQ:	operator = 1; LO = OMUL; return OPER;
	case DIVEQ:	operator = 1; LO = DIVV; return OPER;
	case MODEQ:	operator = 1; LO = MODU; return OPER;
	case INC:	operator = 0; LO = OADD; return POST;
	case DEC:	operator = 0; LO = OSUB; return POST;
	default:
		operator = 0;
		break;
	}
	return c;
}

ylexlex()
{ int c;

again:	switch (c = getc(INPUT)) {
	case  EOF: undirect(); checkit();
	case  ' ':
	case   27:
	case '\t': goto again;

	case '\\': if ((c = getc(INPUT)) == '\n')
			goto again;
		   else
			break;
	case '\n': if (nesting > 0 && (operator || lastyy == '\n'))
		   {	Prompt2;
			pline++;
			goto again;
		   }
	default  : break;
	}

	nolf = (c != '\n');

	if (c == '\"')
	{	yylval.resu = (int) getstring();
		lastyy = '\0';
		return STRING;
	}
	if (isdigit(c))
	{	lexlast = 0;
		do
		{	lexlast = lexlast*10 + c - '0';
			c = getc(INPUT);
		} while (isdigit(c));
		ungetc(c, INPUT);
		lastyy = '\0';

		yylval.resu = lexlast;
		return VAL;
	}

	if (isalpha(c) || c == '_')
	{	yylval.sym = getname(c);
		lastyy = '\0';
		return yylval.sym->type;
	}

	lastyy = '\0';
	switch (c) {
	case '{' : if (++nesting == 1) pline = 1; lastyy = '\n'; return OPEN;
	case '}' : sympurge();
		   if (nesting-- == 1) pline = 0;
		   else ungetc(';', INPUT);
		   return CLOSE;
	case '/' : return follow('=', DIVEQ, follow('*', SCOM, '/'));
	case '%' : return follow('=', MODEQ, '%');
	case '+' : return follow('+', INC, follow('=', ADDEQ, '+'));
	case '-' : return follow('-', DEC, follow('=', SUBEQ, '-'));
	case '*' : return follow('*', POW, follow('=',MULEQ, follow('/',ECOM,'*')));
	case '>' : return follow('=', GE,  follow('>', RSH, GT));
	case '<' : return follow('=', LE,  follow('<', LSH, LT));
	case '=' : return follow('=', EQ, ASSIGN);
	case '!' : return follow('=', NE, NOT);
	case '|' : return follow('|', OROR, OR);
	case '&' : return follow('&', ANDAND, AND);
	case '\n': if (nesting == 0)
			linenumber++;	/* fall through */
		   else
		   {	Prompt2;
			pline++;
		   }
	case ';' : lastyy = '\n';
		   return ';';
	default  : return c;
	}
}

follow(expect, ifyes, ifno)
{
	int c = getc(INPUT);

	if (c == expect)
		return ifyes;

	ungetc(c, INPUT);
	return ifno;
}

Symbol *
getname(cc)
	char cc;
{	char c=cc, sbuf[128], *p = sbuf;

	do
	{	if (p >= sbuf + sizeof(sbuf) - 1)
		{	*p = '\0';
			yyerror("name too long: %s", sbuf);
		}
		*p++ = c;
	} while ((c=getc(INPUT)) != EOF && (isalnum(c) || c == '_'));
	ungetc(c, INPUT);
	*p = '\0';

	if (nesting == 0 && lastyy == '\n')
		return whichcmd(sbuf);
	else
		return lookup(sbuf);
}

char *
getstring()
{	char c, *sbuf, *p;
	sbuf = (char *) Emalloc(512);
	p = sbuf;

	while ((c=getc(INPUT)) != EOF && c != '\"')
	{	if (c == '\\')
			c = follow('n', '\n', follow('t', '\t', '\\'));
		*p++ = c;
		if (p >= sbuf + 512 - 1)
		{	*p = '\0';
			yyerror("string too long: %s", sbuf);
		}
	} ;
	*p = '\0';

	return sbuf;
}