Skip to content
Snippets Groups Projects
parser.c 4.02 KiB
Newer Older
dcw's avatar
dcw committed
/*
 *                           PARSER FOR THE
 *                           ====== === ===
 *
 *                      DATA DECLARATION BUILDER
 *                      ==== =========== =======
 *
 *      This module is the parser used to interprete the high
 *      level data declarations.
 *
 ******* Grammar for Declarations
 *
 *      declns = ne-list( decln ) tEOF
 *      decln  = tID tEQ shapes tSEMI
 *	shapes = ne-sep-list( shape, tOR )
 *	shape  = tID [ tOPENBR params tCLOSEBR ] printlist
dcw's avatar
dcw committed
 *	params = ne-sep-list( param, tCOMMA )
 *      param  = tID tID
 *	printlist = list( tSTR | tNUM )
dcw's avatar
dcw committed
 */


#include <dcw.h>
#include "struct.h"
#include "lexer.h"
#include "parser.h"


#ifdef HASPROTOS
static BOOL parse_decln( char ** , shapelist * );
static BOOL parse_shapes( shapelist * );
static BOOL parse_shape( char ** , paramlist *, printlist * );
dcw's avatar
dcw committed
static BOOL parse_params( paramlist * );
static BOOL parse_param( char ** , char ** );
static BOOL parse_printlist( printlist * );
static BOOL parse_printitem( printitem * );
dcw's avatar
dcw committed
#else
static BOOL parse_decln();
static BOOL parse_shapes();
static BOOL parse_shape();
static BOOL parse_params();
static BOOL parse_param();
static BOOL parse_printlist();
static BOOL parse_printitem();
dcw's avatar
dcw committed
#endif


/* declns = ne-list( decln ) tEOF */

BOOL parse_declns( dp ) declnlist *dp;
{
	char		*name;
	shapelist	shapes;

        for(;;) {
                if( ! parse_decln( &name, &shapes ) ) return FALSE;
		*dp = build_declnlist( name, shapes, NULL );
	if( nexttok() == tEOF ) break;
		ungettok();
		dp = &( (*dp)->next );
	}
	return TRUE;
}


static void expected( s ) char *s;
{
	fprintf( stderr, "%s expected at line %d\n", s, lineno );
}


#define MUSTBE(t,mesg)	if( nexttok() != (t) ) {expected(mesg); return FALSE;}


/* decln  = tID tEQ shapes tSEMI */

static BOOL parse_decln( name, shapes ) char **name; shapelist *shapes;
{
        MUSTBE( tID, "declaration" );
        COPYOF( *name, lexidval );

        MUSTBE( tEQ, "'='" );

	if( ! parse_shapes( shapes ) ) return FALSE;

	MUSTBE( tSEMI, "';'" );

        return TRUE;
}


/* shapes = ne-sep-list( shape, tOR ) */

static BOOL parse_shapes( sp ) shapelist *sp;
{
	char		*tagname;
	paramlist	paras;
dcw's avatar
dcw committed

        for(;;) {
                if( ! parse_shape( &tagname, &paras, &print ) ) return FALSE;
		*sp = build_shapelist( tagname, paras, print, NULL );
dcw's avatar
dcw committed
	if( nexttok() != tOR ) break;
		sp = &( (*sp)->next );
	}
	ungettok();
	return TRUE;
}


/* shape = tID [ tOPENBR params tCLOSEBR ] printlist */
dcw's avatar
dcw committed

static BOOL parse_shape( tagname, pl, print ) char **tagname; paramlist *pl; printlist *print;
dcw's avatar
dcw committed
{
	*pl = NULL;
	*print = NULL;

dcw's avatar
dcw committed
        MUSTBE( tID, "shape name" );
        COPYOF( *tagname, lexidval );

        if( nexttok() == tOPENBR )
	{
		if( ! parse_params( pl ) ) return FALSE;

		MUSTBE( tCLOSEBR, "')'" );
	} else
dcw's avatar
dcw committed
	{
		ungettok();
	}

	return parse_printlist( print );
dcw's avatar
dcw committed
}


/* params = ne-sep-list( param, tCOMMA ) */

static BOOL parse_params( pp ) paramlist *pp;
{
	char *type;
	char *name;

        for(;;) {
		if( !parse_param( &type, &name ) ) return FALSE;
		*pp = build_paramlist( type, name, NULL );
dcw's avatar
dcw committed
	if( nexttok() != tCOMMA ) break;
                pp = &( (*pp)->next );
        }
        ungettok();
	return TRUE;
}


/* printlist = list( printitem ) */
/* NB: Never fails, cos items are one token long */

static BOOL parse_printlist( pp ) printlist *pp;
{
	printitem item;

	*pp = NULL;

	while( parse_printitem( &item ) )
	{
		*pp = build_printlist( item, NULL );
                pp = &( (*pp)->next );
	}
	return TRUE;
}


/* printitem = tSTR | tNUM */
dcw's avatar
dcw committed

static BOOL parse_printitem( item ) printitem *item;
{
	char *temp;

	switch( nexttok() ) {
	case tSTR:
		COPYOF( temp, lexidval );
		*item = build_printitem_str( temp );
		return TRUE;
	case tNUM:
		*item = build_printitem_num( lexintval );
		return TRUE;
	default:
		ungettok();
		return FALSE;
	}
}


/* param     = tID tID */

static BOOL parse_param( type, name ) char **type, **name;
dcw's avatar
dcw committed
{
	MUSTBE( tID, "Field type" );
	COPYOF( *type, lexidval );

	MUSTBE( tID, "Field name" );
	COPYOF( *name, lexidval );

	return TRUE;
}