parser.c 5.49 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
23
 *	params = sep-list+( param, tCOMMA )
 *	param  = 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
48
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 );
static BOOL parse_param( char ** type, char ** name );
dcw's avatar
dcw committed
49
50


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


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

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

	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
91
92
93
94
95
96
97
98
99
100
101
	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 */

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

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

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

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


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


/* decln  = tID tEQ shapes tSEMI */

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

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

	if( ! parse_shapes( shapes ) ) return FALSE;

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

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


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

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

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


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

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

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

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

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

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


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

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

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


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

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

dcw's avatar
dcw committed
241
	*pp = (printlist) NULL;
242
243
244

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


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

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

258
259
	switch( nexttok() ) {
	case tSTR:
dcw's avatar
dcw committed
260
261
		COPYOF( temp, lexidval );
		*item = build_printitem_str( temp );
262
263
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;
	}
}


/* param     = tID tID */

Duncan White's avatar
Duncan White committed
275
static BOOL parse_param( char **type, char **name )
dcw's avatar
dcw committed
276
{
dcw's avatar
dcw committed
277
	MUSTBE( tID, "Field type expected" );
dcw's avatar
dcw committed
278
279
	COPYOF( *type, lexidval );

dcw's avatar
dcw committed
280
	MUSTBE( tID, "Field name expected" );
dcw's avatar
dcw committed
281
282
283
284
	COPYOF( *name, lexidval );

	return TRUE;
}