/* * PARSER FOR THE * ====== === === * * DATA DECLARATION BUILDER * ==== =========== ======= * * This module is the parser used to interprete the high * level data declarations. * ******* Grammar for Declarations * * data = [ tEXPORT chunk ] * [ tGLOBAL chunk ] * [ tBEGIN chunk ] * tTYPE tOPENCURLY declns tCLOSECURLY * chunk = tOPENCURLY list_of_lines tCLOSECURLY * declns = list*( decln ) tEOF * decln = tID tEQ shapes tSEMI * shapes = sep-list+( shape, tOR ) * shape = tID [ tOPENBR params tCLOSEBR ] printlist * params = sep-list+( param, tCOMMA ) * param = tID tID * printlist = list( tSTR | tNUM ) */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include "struct.h" #include "lexer.h" #include "parser.h" #define COPYOF(new,old) {new=malloc(1+strlen(old));if(new)strcpy(new,old);} /* /^#ifdef HASPROTOS !/endif$ stat % */ #ifdef HASPROTOS static BOOL parse_chunk( char * ); static BOOL parse_declns( declnlist * ); static void error( char * ); static BOOL parse_decln( char ** , shapelist * ); static BOOL parse_shapes( shapelist * ); static BOOL parse_shape( char ** , paramlist * , printlist * ); static BOOL parse_params( paramlist * ); static BOOL parse_printlist( printlist * ); static BOOL parse_printitem( printitem * ); static BOOL parse_param( char ** , char ** ); #else static BOOL parse_chunk(); static BOOL parse_declns(); static void error(); static BOOL parse_decln(); static BOOL parse_shapes(); static BOOL parse_shape(); static BOOL parse_params(); static BOOL parse_printlist(); static BOOL parse_printitem(); static BOOL parse_param(); #endif #define MUSTBE(t,mesg) if( nexttok() != (t) ) {error(mesg); return FALSE;} /* * data = [ tEXPORT tOPENCURLY crap_to_} ] * [ tGLOBAL tOPENCURLY crap_to_} ] * [ tBEGIN tOPENCURLY crap_to_} ] * tTYPE tOPENCURLY declns tCLOSECURLY */ BOOL parse_data( exports, globals, begin, dp ) char *exports, *globals, *begin; declnlist *dp; { if( nexttok() == tEXPORT ) { if( ! parse_chunk( exports ) ) return FALSE; } else { *exports = '\0'; ungettok(); } if( nexttok() == tGLOBAL ) { if( ! parse_chunk( globals ) ) return FALSE; } else { *globals = '\0'; ungettok(); } if( nexttok() == tBEGIN ) { if( ! parse_chunk( begin ) ) return FALSE; } else { *begin = '\0'; ungettok(); } MUSTBE( tTYPE, "TYPE/EXPORT/GLOBAL/BEGIN expected" ); MUSTBE( tOPENCURLY, "{ expected" ); if( ! parse_declns( dp ) ) return FALSE; MUSTBE( tCLOSECURLY, "{ expected" ); MUSTBE( tEOF, "Spurious characters found beyond EOF" ); return TRUE; } /* chunk = tOPENCURLY list_of_lines tCLOSECURLY */ static BOOL parse_chunk( s ) char *s; { char line[256]; int startlineno; *s = '\0'; MUSTBE( tOPENCURLY, "'{' expected" ); startlineno = lineno; for(;;) { if( ! readnextline( line ) ) { fprintf( stderr, "Premature EOF after { - started at line %d\n", startlineno ); return FALSE; } if( streq( line, "}" ) ) break; strcat( s, line ); strcat( s, "\n" ); } return TRUE; } /* declns = list*( decln ) */ /* NB: a decln starts with a tID */ static BOOL parse_declns( dp ) declnlist *dp; { char *name; shapelist shapes; while( nexttok() == tID ) { ungettok(); if( ! parse_decln( &name, &shapes ) ) return FALSE; *dp = build_declnlist( name, shapes, (declnlist) NULL ); dp = &( (*dp)->next ); } ungettok(); return TRUE; } static void error( s ) char *s; { fprintf( stderr, "%s at line %d\n", s, lineno ); } /* decln = tID tEQ shapes tSEMI */ static BOOL parse_decln( name, shapes ) char **name; shapelist *shapes; { MUSTBE( tID, "declaration expected" ); COPYOF( *name, lexidval ); MUSTBE( tEQ, "'=' expected" ); if( ! parse_shapes( shapes ) ) return FALSE; MUSTBE( tSEMI, "';' expected" ); return TRUE; } /* shapes = sep-list+( shape, tOR ) */ static BOOL parse_shapes( sp ) shapelist *sp; { char *tagname; paramlist paras; printlist print; for(;;) { if( ! parse_shape( &tagname, ¶s, &print ) ) return FALSE; *sp = build_shapelist( tagname, paras, print, (shapelist) NULL ); if( nexttok() != tOR ) break; sp = &( (*sp)->next ); } ungettok(); return TRUE; } /* shape = tID [ tOPENBR params tCLOSEBR ] printlist */ static BOOL parse_shape( tagname, pl, print ) char **tagname; paramlist *pl; printlist *print; { *pl = (paramlist) NULL; *print = (printlist) NULL; MUSTBE( tID, "shape name expected" ); COPYOF( *tagname, lexidval ); if( nexttok() == tOPENBR ) { if( ! parse_params( pl ) ) return FALSE; MUSTBE( tCLOSEBR, "')' expected" ); } else { ungettok(); } return parse_printlist( print ); } /* params = 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, (paramlist) NULL ); 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 = (printlist) NULL; while( parse_printitem( &item ) ) { *pp = build_printlist( item, (printlist) NULL ); pp = &( (*pp)->next ); } return TRUE; } /* printitem = tSTR | tNUM */ 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; { MUSTBE( tID, "Field type expected" ); COPYOF( *type, lexidval ); MUSTBE( tID, "Field name expected" ); COPYOF( *name, lexidval ); return TRUE; }