Subversion Repositories tendra.SVN

Rev

Rev 2 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/*** lexer.c --- SID lexical analyser.
32
 *
33
 ** Author: Steve Folkes <smf@hermes.mod.uk>
34
 *
35
 *** Commentary:
36
 *
37
 * This file implements the interface for the SID lexical analyser.  Any
38
 * changes to the syntax of SID identifiers should be made to the language
39
 * specifc lexical analyser files as well.
40
 *
41
 *** Change Log:
42
 * $Log: lexer.c,v $
43
 * Revision 1.1.1.1  1998/01/17  15:57:42  release
44
 * First version to be checked into rolling release.
45
 *
46
 * Revision 1.2  1994/12/15  09:57:27  smf
47
 * Brought into line with OSSG C Coding Standards Document, as per
48
 * "CR94_178.sid+tld-update".
49
 *
50
 * Revision 1.1.1.1  1994/07/25  16:04:23  smf
51
 * Initial import of SID 1.8 non shared files.
52
 *
53
**/
54
 
55
/****************************************************************************/
56
 
57
#include "lexer.h"
58
#include "gen-errors.h"
59
#include "syntax.h"
60
 
61
/*--------------------------------------------------------------------------*/
62
 
63
#define LEXER_READ_ONE_CHAR(istream, redo, eof, id) \
64
    switch ((id) = ISTREAM_READ_CHAR (istream)) { \
65
      case '\0': \
66
        ISTREAM_HANDLE_NULL ((istream), redo, eof); \
67
        break; \
68
      case '\n': \
69
        istream_inc_line (istream); \
70
        break; \
71
      default: \
72
        break; \
73
    }
74
 
75
/*--------------------------------------------------------------------------*/
76
 
77
static BoolT
78
lexer_skip_bracketed_comment PROTO_N ((istream))
79
			     PROTO_T (IStreamP istream)
80
{
81
    char c1;
82
    char c2;
83
 
84
  redo1:
85
    LEXER_READ_ONE_CHAR (istream, redo1, eof, c1);
86
  redo2:
87
    LEXER_READ_ONE_CHAR (istream, redo2, eof, c2);
88
    for (;;) {
89
	if ((c1 == '/') && (c2 == '*')) {
90
	    if (!lexer_skip_bracketed_comment (istream)) {
91
		goto eof;
92
	    }
93
	  redo3:
94
	    LEXER_READ_ONE_CHAR (istream, redo3, eof, c2);
95
	} else if ((c1 == '*') && (c2 == '/')) {
96
	    return (TRUE);
97
	}
98
	c1 = c2;
99
      redo4:
100
	LEXER_READ_ONE_CHAR (istream, redo4, eof, c2);
101
    }
102
  eof:
103
    return (FALSE);
104
}
105
 
106
static char
107
lexer_skip_white_space PROTO_N ((istream))
108
		       PROTO_T (IStreamP istream)
109
{
110
    for (;;) {
111
	char c;
112
 
113
      redo1:
114
	switch (c = ISTREAM_READ_CHAR (istream)) {
115
	  case '\0':
116
	    ISTREAM_HANDLE_NULL (istream, redo1, eof);
117
	    break;
118
	  case '\n':
119
	    istream_inc_line (istream);
120
	    break;
121
	  case '/':
122
	  redo2:
123
	    switch (c = ISTREAM_READ_CHAR (istream)) {
124
	      case '\0':
125
		ISTREAM_HANDLE_NULL (istream, redo2, eof_in_comment);
126
		goto illegal_in_comment;
127
	      case '\n':
128
		istream_inc_line (istream);
129
		goto illegal_in_comment;
130
	      case '*':
131
		if (!lexer_skip_bracketed_comment (istream)) {
132
		  eof_in_comment:
133
		    E_eof_in_comment (istream);
134
		    return ('\0'); /*FOR EOF*/
135
		}
136
		break;
137
	      case '/':
138
		do {
139
		  redo3:
140
		    LEXER_READ_ONE_CHAR (istream, redo3, eof, c);
141
		} while (c != '\n');
142
		break;
143
	      default:
144
	      illegal_in_comment:
145
		E_illegal_comment_character (istream, c);
146
		break;
147
	    }
148
	    break;
149
	  default:
150
	    if (!syntax_is_white_space (c)) {
151
		return (c);
152
	    }
153
	    break;
154
	}
155
    }
156
  eof:
157
    return ('\0'); /*FOR EOF*/
158
}
159
 
160
static void
161
lexer_read_builtin PROTO_N ((istream, token))
162
		   PROTO_T (IStreamP istream X
163
			    LexP     token)
164
{
165
    DStringT dstring;
166
    CStringP cstring;
167
 
168
    dstring_init (&dstring);
169
    for (;;) {
170
	char c;
171
 
172
      redo:
173
	switch (c = ISTREAM_READ_CHAR (istream)) {
174
	  case '\0':
175
	    ISTREAM_HANDLE_NULL (istream, redo, eof);
176
	    E_null_character_in_builtin (istream);
177
	    break;
178
	  case '\n':
179
	    istream_inc_line (istream);
180
	    E_newline_in_builtin (istream);
181
	    goto done;
182
	  case '%':
183
	    goto done;
184
	  default:
185
	    dstring_append_char (&dstring, c);
186
	}
187
    }
188
  eof:
189
    E_eof_in_builtin (istream);
190
  done:
191
    cstring = dstring_destroy_to_cstring (&dstring);
192
    if (cstring_ci_equal (cstring, "types")) {
193
	token->t = LEXER_TOK_BLT_TYPES;
194
    } else if (cstring_ci_equal (cstring, "terminals")) {
195
	token->t = LEXER_TOK_BLT_TERMINALS;
196
    } else if (cstring_ci_equal (cstring, "productions")) {
197
	token->t = LEXER_TOK_BLT_PRODUCTIONS;
198
    } else if (cstring_ci_equal (cstring, "entry")) {
199
	token->t = LEXER_TOK_BLT_ENTRY;
200
    } else {
201
	E_unknown_builtin (istream, cstring);
202
	UNREACHED;
203
    }
204
    DEALLOCATE (cstring);
205
}
206
 
207
static void
208
lexer_read_identifier PROTO_N ((istream, c, token))
209
		      PROTO_T (IStreamP istream X
210
			       char     c X
211
			       LexP     token)
212
{
213
    DStringT dstring;
214
 
215
    dstring_init (&dstring);
216
    dstring_append_char (&dstring, c);
217
    for (;;) {
218
      redo1:
219
	switch (c = ISTREAM_PEEK_CHAR (istream)) {
220
	  case '\0':
221
	    ISTREAM_HANDLE_NULL (istream, redo1, done);
222
	    goto done;
223
	  default:
224
	    if ((syntax_is_letter (c)) || (syntax_is_digit (c)) ||
225
		(c == '_') || (c == '-')) {
226
	      redo2:
227
		LEXER_READ_ONE_CHAR (istream, redo2, done, c);
228
		dstring_append_char (&dstring, c);
229
	    } else {
230
		goto done;
231
	    }
232
	    break;
233
	}
234
    }
235
  done:
236
    token->t = LEXER_TOK_IDENTIFIER;
237
    dstring_to_nstring (&dstring, &(token->u.string));
238
    dstring_destroy (&dstring);
239
}
240
 
241
/*--------------------------------------------------------------------------*/
242
 
243
void
244
lexer_init PROTO_N ((stream, istream))
245
	   PROTO_T (LexerStreamP stream X
246
		    IStreamP     istream)
247
{
248
    istream_assign (&(stream->istream), istream);
249
    lexer_next_token (stream);
250
}
251
 
252
#ifdef FS_FAST
253
#undef lexer_close
254
#endif /* defined (FS_FAST) */
255
void
256
lexer_close PROTO_N ((stream))
257
	    PROTO_T (LexerStreamP stream)
258
{
259
    istream_close (&(stream->istream));
260
}
261
#ifdef FS_FAST
262
#define lexer_close(s) (istream_close (&((s)->istream)))
263
#endif /* defined (FS_FAST) */
264
 
265
#ifdef FS_FAST
266
#undef lexer_stream_name
267
#endif /* defined (FS_FAST) */
268
CStringP
269
lexer_stream_name PROTO_N ((stream))
270
		  PROTO_T (LexerStreamP stream)
271
{
272
    return (istream_name (&(stream->istream)));
273
}
274
#ifdef FS_FAST
275
#define lexer_stream_name(s) (istream_name (&((s)->istream)))
276
#endif /* defined (FS_FAST) */
277
 
278
#ifdef FS_FAST
279
#undef lexer_stream_line
280
#endif /* defined (FS_FAST) */
281
unsigned
282
lexer_stream_line PROTO_N ((stream))
283
		  PROTO_T (LexerStreamP stream)
284
{
285
    return (istream_line (&(stream->istream)));
286
}
287
#ifdef FS_FAST
288
#define lexer_stream_line(s) (istream_line (&((s)->istream)))
289
#endif /* defined (FS_FAST) */
290
 
291
#ifdef FS_FAST
292
#undef lexer_get_terminal
293
#endif /* defined (FS_FAST) */
294
LexerTokenT
295
lexer_get_terminal PROTO_N ((stream))
296
		   PROTO_T (LexerStreamP stream)
297
{
298
    return (stream->token.t);
299
}
300
#ifdef FS_FAST
301
#define lexer_get_terminal(s) ((s)->token.t)
302
#endif /* defined (FS_FAST) */
303
 
304
void
305
lexer_next_token PROTO_N ((stream))
306
		 PROTO_T (LexerStreamP stream)
307
{
308
    IStreamP istream = &(stream->istream);
309
    LexT     token;
310
    char     c;
311
 
312
  retry:
313
    switch (c = lexer_skip_white_space (istream)) {
314
      case '\0': /*FOR EOF*/
315
	token.t = LEXER_TOK_EOF;
316
	break;
317
      case '#':
318
	if ((istream_peek_char (istream, &c)) && (c == '#')) {
319
	    (void) istream_read_char (istream, &c);
320
	    token.t = LEXER_TOK_HANDLER_SEP;
321
	    break;
322
	}
323
	E_expected_hash (istream);
324
	goto retry;
325
      case '$':
326
	token.t = LEXER_TOK_EMPTY;
327
	break;
328
      case '%':
329
	lexer_read_builtin (istream, &token);
330
	break;
331
      case '|':
332
	if ((istream_peek_char (istream, &c)) && (c == '|')) {
333
	    (void) istream_read_char (istream, &c);
334
	    token.t = LEXER_TOK_ALT_SEP;
335
	    break;
336
	}
337
	E_expected_pipe (istream);
338
	goto retry;
339
      case ',':
340
	token.t = LEXER_TOK_SEPARATOR;
341
	break;	
342
      case ':':
343
	if ((istream_peek_char (istream, &c)) && (c == ':')) {
344
	    (void) istream_read_char (istream, &c);
345
	    token.t = LEXER_TOK_SCOPEMARK;
346
	    break;
347
	}
348
	token.t = LEXER_TOK_TYPEMARK;
349
	break;
350
      case ';':
351
	token.t = LEXER_TOK_TERMINATOR;
352
	break;
353
      case '<':
354
	token.t = LEXER_TOK_BEGIN_ACTION;
355
	break;
356
      case '=':
357
	token.t = LEXER_TOK_DEFINE;
358
	break;
359
      case '>':
360
	token.t = LEXER_TOK_END_ACTION;
361
	break;
362
      case '?':
363
	token.t = LEXER_TOK_PRED_RESULT;
364
	break;
365
      case '!':
366
	token.t = LEXER_TOK_IGNORE;
367
	break;
368
      case '{':
369
	token.t = LEXER_TOK_BEGIN_RULE;
370
	break;
371
      case '}':
372
	token.t = LEXER_TOK_END_RULE;
373
	break;
374
      case '[':
375
	token.t = LEXER_TOK_BEGIN_SCOPE;
376
	break;
377
      case ']':
378
	token.t = LEXER_TOK_END_SCOPE;
379
	break;
380
      case '(':
381
	token.t = LEXER_TOK_OPEN_TUPLE;
382
	break;
383
      case ')':
384
	token.t = LEXER_TOK_CLOSE_TUPLE;
385
	break;
386
      case '&':
387
	token.t = LEXER_TOK_REFERENCE;
388
	break;
389
      case '-':
390
	if ((istream_peek_char (istream, &c)) && (c == '>')) {
391
	    (void) istream_read_char (istream, &c);
392
	    token.t = LEXER_TOK_ARROW;
393
	    break;
394
	}
395
	lexer_read_identifier (istream, '-', &token);
396
	break;
397
      default:
398
	if ((syntax_is_letter (c)) || (c == '_')) {
399
	    lexer_read_identifier (istream, c, &token);
400
	} else {
401
	    E_illegal_character (istream, c);
402
	    goto retry;
403
	}
404
	break;
405
    }
406
    stream->token = token;
407
}
408
 
409
#ifdef FS_FAST
410
#undef lexer_string_value
411
#endif /* defined (FS_FAST) */
412
NStringP
413
lexer_string_value PROTO_N ((stream))
414
		   PROTO_T (LexerStreamP stream)
415
{
416
    ASSERT (stream->token.t == LEXER_TOK_IDENTIFIER);
417
    return (&(stream->token.u.string));
418
}
419
#ifdef FS_FAST
420
#define lexer_string_value(s) (&((s)->token.u.string))
421
#endif /* defined (FS_FAST) */
422
 
423
void
424
lexer_save_terminal PROTO_N ((stream, error_terminal))
425
		    PROTO_T (LexerStreamP stream X
426
			     LexerTokenT  error_terminal)
427
{
428
    ASSERT (stream->token.t != error_terminal);
429
    stream->saved_terminal = stream->token.t;
430
    stream->token.t        = error_terminal;
431
}
432
 
433
void
434
lexer_restore_terminal PROTO_N ((stream))
435
		       PROTO_T (LexerStreamP stream)
436
{
437
    stream->token.t = stream->saved_terminal;
438
}
439
 
440
/*
441
 * Local variables(smf):
442
 * eval: (include::add-path-entry "../os-interface" "../library")
443
 * eval: (include::add-path-entry "../transforms" "../generated")
444
 * end:
445
**/