www.pudn.com > ANSI_C_OOP.rar > parse.c


#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "parse.h"			/* defines NUMBER */
#include "value.h"

/*
 *	scanner
 */

static enum tokens token;	/* current input symbol */
static double number;		/* if NUMBER: numerical value */

static enum tokens scan (const char * buf)
					/* return token = next input symbol */
{	static const char * bp;

	if (buf)
		bp = buf;			/* new input line */

	while (isspace(* bp & 0xff))
		++ bp;
	if (isdigit(* bp & 0xff) || * bp == '.')
	{	errno = 0;
		token = NUMBER, number = strtod(bp, (char **) & bp);
		if (errno == ERANGE)
			error("bad value: %s", strerror(errno));
	}
	else
		token = * bp ? * bp ++ : 0;
	return token;
}

/*
 *	factor : + factor
 *			 - factor
 *			 NUMBER
 *			 ( sum )
 */

static void * sum (void);

static void * factor (void)
{	void * result;

	switch (token) {
	case '+':
		scan(0);
		return factor();
	case '-':
		scan(0);
		return new(Minus, factor());
	default:
		error("bad factor: '%c' 0x%x", token, token);
	case NUMBER:
		result = new(Value, number);
		break;
	case '(':
		scan(0);
		result = sum();
		if (token != ')')
			error("expecting )");
	}
	scan(0);
	return result;
}

/*
 *	product : factor { *|/ factor }...
 */

static void * product (void)
{	void * result = factor();
	const void * type;

	for (;;)
	{	switch (token) {
		case '*':
			type = Mult;
			break;
		case '/':
			type = Div;
			break;
		default:
			return result;
		}
		scan(0);
		result = new(type, result, factor());
	}
}

/*
 *	sum : product { +|- product }...
 */

static void * sum (void)
{	void * result = product();
	const void * type;

	for (;;)
	{	switch (token) {
		case '+':
			type = Add;
			break;
		case '-':
			type = Sub;
			break;
		default:
			return result;
		}
		scan(0);
		result = new(type, result, product());
	}
}

/*
 *	sum \n ...
 */

static jmp_buf onError;

int main (void)
{	volatile int errors = 0;
	char buf [BUFSIZ];

	if (setjmp(onError))
		++ errors;

	while (fgets(buf, sizeof buf, stdin))
		if (scan(buf))
		{	void * e = sum();

			if (token)
				error("trash after sum");
			process(e);
			delete(e);
		}

	return errors > 0;
}

void error (const char * fmt, ...)
{	va_list ap;

	va_start(ap, fmt);
	vfprintf(stderr, fmt, ap), putc('\n', stderr);
	va_end(ap);
	longjmp(onError, 1);
}