parser.c 6.22 KB
Newer Older
dcw's avatar
dcw committed
1
2
3
4
5
6
7
8
9
10
11
12
/*
 *                           PARSER FOR THE
 *                           ====== === ===
 *
 *                      DATA DECLARATION BUILDER
 *                      ==== =========== =======
 *
 *      This module is the parser used to interprete the high
 *      level data declarations.
 *
 ******* Grammar for Declarations
 *
dcw's avatar
dcw committed
13
14
 *	data   = [ tEXPORT chunk ]
 *		 [ tGLOBAL chunk ]
dcw's avatar
dcw committed
15
 *		 [ tBEGIN chunk ]
dcw's avatar
dcw committed
16
17
18
 *		 tTYPE tOPENCURLY declns tCLOSECURLY
 *	chunk  = tOPENCURLY list_of_lines tCLOSECURLY
 *	declns = list*( decln ) tEOF
dcw's avatar
dcw committed
19
20
 *	decln  = tID tEQ shapes tSEMI
 *	shapes = sep-list+( shape, tOR )
dcw's avatar
dcw committed
21
 *	shape  = tID [ tOPENBR params tCLOSEBR ] printlist
dcw's avatar
dcw committed
22
 *	params = sep-list+( param, tCOMMA )
23
 *	param  = [tMINUS] tID tID
dcw's avatar
dcw committed
24
 *	printlist = list( tSTR | tNUM )
dcw's avatar
dcw committed
25
26
27
 */


28
29
#include <stdio.h>
#include <string.h>
30
#include <stdlib.h>
dcw's avatar
dcw committed
31
32
33
34
35
#include "struct.h"
#include "lexer.h"
#include "parser.h"


36
37
38
#define COPYOF(new,old) {new=malloc(1+strlen(old));if(new)strcpy(new,old);}


Duncan White's avatar
Duncan White committed
39
40
41
42
43
44
45
46
47
static BOOL parse_chunk( char * s );
static BOOL parse_declns( declnlist * dp );
static void error( char * s );
static BOOL parse_decln( char ** name, shapelist * shapes );
static BOOL parse_shapes( shapelist * sp );
static BOOL parse_shape( char ** tagname, paramlist * pl, printlist * print );
static BOOL parse_params( paramlist * pp );
static BOOL parse_printlist( printlist * pp );
static BOOL parse_printitem( printitem * item );
48
49
static BOOL neverfreetype( char * typename );
static BOOL parse_param( BOOL * dontfree, char ** type, char ** name );
dcw's avatar
dcw committed
50
51


dcw's avatar
dcw committed
52
53
54
#define MUSTBE(t,mesg)	if( nexttok() != (t) ) {error(mesg); return FALSE;}


dcw's avatar
dcw committed
55
56
57
/*
 *	data   = [ tEXPORT tOPENCURLY crap_to_} ]
 *		 [ tGLOBAL tOPENCURLY crap_to_} ]
dcw's avatar
dcw committed
58
 *		 [ tBEGIN tOPENCURLY crap_to_} ]
dcw's avatar
dcw committed
59
60
61
 *		 tTYPE tOPENCURLY declns tCLOSECURLY
 */

Duncan White's avatar
Duncan White committed
62
BOOL parse_data( char *exports, char *globals, char *begin, declnlist *dp )
dcw's avatar
dcw committed
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
{
	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();
	}
dcw's avatar
dcw committed
81
82
83
84
85
86
87
88
89
90
91

	if( nexttok() == tBEGIN )
	{
		if( ! parse_chunk( begin ) ) return FALSE;
	} else
	{
		*begin = '\0';
		ungettok();
	}

	MUSTBE( tTYPE, "TYPE/EXPORT/GLOBAL/BEGIN expected" );
dcw's avatar
dcw committed
92
93
	MUSTBE( tOPENCURLY, "{ expected" );
	if( ! parse_declns( dp ) ) return FALSE;
94
	MUSTBE( tCLOSECURLY, "} expected" );
dcw's avatar
dcw committed
95
96
97
98
99
100
101
102
	MUSTBE( tEOF, "Spurious characters found beyond EOF" );

	return TRUE;
}


/* chunk  = tOPENCURLY list_of_lines tCLOSECURLY */

Duncan White's avatar
Duncan White committed
103
static BOOL parse_chunk( char *s )
dcw's avatar
dcw committed
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
{
	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;
}

dcw's avatar
dcw committed
129

dcw's avatar
dcw committed
130
131
132
/* declns = list*( decln )       */
/* NB: a decln starts with a tID */

Duncan White's avatar
Duncan White committed
133
static BOOL parse_declns( declnlist *dp )
dcw's avatar
dcw committed
134
135
136
137
{
	char		*name;
	shapelist	shapes;

dcw's avatar
dcw committed
138
139
140
	while( nexttok() == tID )
	{
		ungettok();
dcw's avatar
dcw committed
141
142
		if( ! parse_decln( &name, &shapes ) ) return FALSE;
		*dp = build_declnlist( name, shapes, (declnlist) NULL );
dcw's avatar
dcw committed
143
144
		dp = &( (*dp)->next );
	}
dcw's avatar
dcw committed
145
	ungettok();
dcw's avatar
dcw committed
146
147
148
149
	return TRUE;
}


Duncan White's avatar
Duncan White committed
150
static void error( char *s )
dcw's avatar
dcw committed
151
{
dcw's avatar
dcw committed
152
	fprintf( stderr, "%s at line %d\n", s, lineno );
dcw's avatar
dcw committed
153
154
155
156
157
}


/* decln  = tID tEQ shapes tSEMI */

Duncan White's avatar
Duncan White committed
158
static BOOL parse_decln( char **name, shapelist *shapes )
dcw's avatar
dcw committed
159
{
dcw's avatar
dcw committed
160
161
	MUSTBE( tID, "declaration expected" );
	COPYOF( *name, lexidval );
dcw's avatar
dcw committed
162

dcw's avatar
dcw committed
163
	MUSTBE( tEQ, "'=' expected" );
dcw's avatar
dcw committed
164
165
166

	if( ! parse_shapes( shapes ) ) return FALSE;

dcw's avatar
dcw committed
167
	MUSTBE( tSEMI, "';' expected" );
dcw's avatar
dcw committed
168

dcw's avatar
dcw committed
169
	return TRUE;
dcw's avatar
dcw committed
170
171
172
}


dcw's avatar
dcw committed
173
/* shapes = sep-list+( shape, tOR ) */
dcw's avatar
dcw committed
174

Duncan White's avatar
Duncan White committed
175
static BOOL parse_shapes( shapelist *sp )
dcw's avatar
dcw committed
176
177
178
{
	char		*tagname;
	paramlist	paras;
179
	printlist	print;
dcw's avatar
dcw committed
180

dcw's avatar
dcw committed
181
182
183
184
	for(;;) {
		if( ! parse_shape( &tagname, &paras, &print ) ) return FALSE;
		*sp = build_shapelist( tagname, paras,
				       print, (shapelist) NULL );
dcw's avatar
dcw committed
185
186
187
188
189
190
191
192
	if( nexttok() != tOR ) break;
		sp = &( (*sp)->next );
	}
	ungettok();
	return TRUE;
}


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

Duncan White's avatar
Duncan White committed
195
static BOOL parse_shape( char **tagname, paramlist *pl, printlist *print )
dcw's avatar
dcw committed
196
{
dcw's avatar
dcw committed
197
	*pl    = (paramlist) NULL;
dcw's avatar
dcw committed
198
	*print = (printlist) NULL;
199

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

dcw's avatar
dcw committed
203
	if( nexttok() == tOPENBR )
dcw's avatar
dcw committed
204
205
206
	{
		if( ! parse_params( pl ) ) return FALSE;

207
		MUSTBE( tCLOSEBR, "',' or ')' expected" );
dcw's avatar
dcw committed
208
	} else
dcw's avatar
dcw committed
209
210
211
212
	{
		ungettok();
	}

dcw's avatar
dcw committed
213
	return parse_printlist( print );
dcw's avatar
dcw committed
214
215
216
}


dcw's avatar
dcw committed
217
/* params = sep-list+( param, tCOMMA ) */
dcw's avatar
dcw committed
218

Duncan White's avatar
Duncan White committed
219
static BOOL parse_params( paramlist *pp )
dcw's avatar
dcw committed
220
221
222
{
	char *type;
	char *name;
223
	BOOL dontfree;
dcw's avatar
dcw committed
224

dcw's avatar
dcw committed
225
	for(;;) {
226
227
		if( !parse_param( &dontfree, &type, &name ) ) return FALSE;
		*pp = build_paramlist( dontfree, type, name, (paramlist) NULL );
dcw's avatar
dcw committed
228
	if( nexttok() != tCOMMA ) break;
dcw's avatar
dcw committed
229
230
231
		pp = &( (*pp)->next );
	}
	ungettok();
dcw's avatar
dcw committed
232
233
234
235
	return TRUE;
}


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

Duncan White's avatar
Duncan White committed
239
static BOOL parse_printlist( printlist *pp )
240
241
242
{
	printitem item;

dcw's avatar
dcw committed
243
	*pp = (printlist) NULL;
244
245
246

	while( parse_printitem( &item ) )
	{
dcw's avatar
dcw committed
247
248
		*pp = build_printlist( item, (printlist) NULL );
		pp = &( (*pp)->next );
249
250
251
252
253
254
	}
	return TRUE;
}


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

Duncan White's avatar
Duncan White committed
256
static BOOL parse_printitem( printitem *item )
257
{
dcw's avatar
dcw committed
258
259
	char *temp;

260
261
	switch( nexttok() ) {
	case tSTR:
dcw's avatar
dcw committed
262
263
		COPYOF( temp, lexidval );
		*item = build_printitem_str( temp );
264
265
266
267
268
269
270
271
272
273
274
		return TRUE;
	case tNUM:
		*item = build_printitem_num( lexintval );
		return TRUE;
	default:
		ungettok();
		return FALSE;
	}
}


275
276
277
278
279
280
/* never free the following types - sorted list */
static char *neverfree[] = {
	"BOOL",
	"char",
	"int",
};
281

282
283
284
285
#define NEVERFREE_NEL (sizeof(neverfree)/sizeof(char *))


static BOOL neverfreetype( char *typename )
dcw's avatar
dcw committed
286
{
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
	int i;
	for( i=0; i<NEVERFREE_NEL; i++ )
	{
		if( strcmp( neverfree[i], typename ) == 0 )
		{
			return TRUE;
		}
	}
	return FALSE;
}


/* param     = [tMINUS] tID tID */

static BOOL parse_param( BOOL *dontfree, char **type, char **name )
{
	*dontfree = nexttok() == tMINUS;
	if( ! *dontfree )
	{
		ungettok();
	}
dcw's avatar
dcw committed
308
	MUSTBE( tID, "Field type expected" );
dcw's avatar
dcw committed
309
310
	COPYOF( *type, lexidval );

311
312
313
314
315
316
	/* apply standard "never free rules" */
	if( ! *dontfree )
	{
		*dontfree = neverfreetype( *type );
	}

dcw's avatar
dcw committed
317
	MUSTBE( tID, "Field name expected" );
dcw's avatar
dcw committed
318
	COPYOF( *name, lexidval );
319
	//printf( "debug: param(%s, %s): dontfree %d\n", *type, *name, *dontfree );
dcw's avatar
dcw committed
320
321
322

	return TRUE;
}