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
/*** c-lexer.c --- SID C lexical analyser.
32
 *
33
 ** Author: Steve Folkes <smf@hermes.mod.uk>
34
 *
35
 *** Commentary:
36
 *
37
 * This file implements the SID C lexical analyser.  Any changes to the syntax
38
 * of SID identifiers should be made both here and in the file
39
 * "../parser/lexer.c".
40
 *
41
 *** Change Log:
42
 * $Log: c-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:55:56  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:13  smf
51
 * Initial import of SID 1.8 non shared files.
52
 *
53
**/
54
 
55
/****************************************************************************/
56
 
57
#include "c-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
c_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 (!c_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
c_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 (!c_lexer_skip_bracketed_comment (istream)) {
132
		  eof_in_comment:
133
		    E_c_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_c_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
c_lexer_read_builtin PROTO_N ((istream, token))
162
		     PROTO_T (IStreamP istream X
163
			      CLexP    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_c_null_character_in_builtin (istream);
177
	    break;
178
	  case '\n':
179
	    istream_inc_line (istream);
180
	    E_c_newline_in_builtin (istream);
181
	    goto done;
182
	  case '%':
183
	    goto done;
184
	  default:
185
	    dstring_append_char (&dstring, c);
186
	    break;
187
	}
188
    }
189
  eof:
190
    E_c_eof_in_builtin (istream);
191
  done:
192
    cstring = dstring_destroy_to_cstring (&dstring);
193
    if (cstring_ci_equal (cstring, "prefixes")) {
194
	token->t = C_TOK_BLT_PREFIXES;
195
    } else if (cstring_ci_equal (cstring, "maps")) {
196
	token->t = C_TOK_BLT_MAPS;
197
    } else if (cstring_ci_equal (cstring, "assignments")) {
198
	token->t = C_TOK_BLT_ASSIGNMENTS;
199
    } else if (cstring_ci_equal (cstring, "assign")) {
200
	token->t = C_TOK_BLT_ASSIGNMENTS;
201
    } else if (cstring_ci_equal (cstring, "terminals")) {
202
	token->t = C_TOK_BLT_TERMINALS;
203
    } else if (cstring_ci_equal (cstring, "header")) {
204
	token->t = C_TOK_BLT_HEADER;
205
    } else if (cstring_ci_equal (cstring, "actions")) {
206
	token->t = C_TOK_BLT_ACTIONS;
207
    } else if (cstring_ci_equal (cstring, "trailer")) {
208
	token->t = C_TOK_BLT_TRAILER;
209
    } else if (cstring_ci_equal (cstring, "result-assignments")) {
210
	token->t = C_TOK_BLT_RESULT_ASSIGN;
211
    } else if (cstring_ci_equal (cstring, "result-assign")) {
212
	token->t = C_TOK_BLT_RESULT_ASSIGN;
213
    } else if (cstring_ci_equal (cstring, "parameter-assignments")) {
214
	token->t = C_TOK_BLT_PARAM_ASSIGN;
215
    } else if (cstring_ci_equal (cstring, "parameter-assign")) {
216
	token->t = C_TOK_BLT_PARAM_ASSIGN;
217
    } else if (cstring_ci_equal (cstring, "param-assignments")) {
218
	token->t = C_TOK_BLT_PARAM_ASSIGN;
219
    } else if (cstring_ci_equal (cstring, "param-assign")) {
220
	token->t = C_TOK_BLT_PARAM_ASSIGN;
221
    } else {
222
	E_c_unknown_builtin (istream, cstring);
223
	UNREACHED;
224
    }
225
    DEALLOCATE (cstring);
226
}
227
 
228
static void
229
c_lexer_read_identifier PROTO_N ((istream, c, token))
230
			PROTO_T (IStreamP istream X
231
				 char     c X
232
				 CLexP    token)
233
{
234
    BoolT    c_ident = (c != '-');
235
    DStringT dstring;
236
 
237
    dstring_init (&dstring);
238
    dstring_append_char (&dstring, c);
239
    for (;;) {
240
      redo1:
241
	switch (c = ISTREAM_PEEK_CHAR (istream)) {
242
	  case '\0':
243
	    ISTREAM_HANDLE_NULL (istream, redo1, done);
244
	    goto done;
245
	  default:
246
	    if ((syntax_is_letter (c)) || (syntax_is_digit (c)) ||
247
		(c == '_') || (c == '-')) {
248
	      redo2:
249
		LEXER_READ_ONE_CHAR (istream, redo2, done, c);
250
		dstring_append_char (&dstring, c);
251
		if (c == '-') {
252
		    c_ident = FALSE;
253
		}
254
	    } else {
255
		goto done;
256
	    }
257
	    break;
258
	}
259
    }
260
  done:
261
    if (c_ident) {
262
	token->t = C_TOK_C_IDENTIFIER;
263
    } else {
264
	token->t = C_TOK_SID_IDENTIFIER;
265
    }
266
    dstring_to_nstring (&dstring, &(token->u.string));
267
    dstring_destroy (&dstring);
268
}
269
 
270
static void
271
c_lexer_read_code_id PROTO_N ((istream, c, nstring))
272
		     PROTO_T (IStreamP istream X
273
			      char     c X
274
			      NStringP nstring)
275
{
276
    BoolT    numbers_ok = (syntax_is_letter (c) || (c == '_'));
277
    DStringT dstring;
278
    char     c1;
279
 
280
    dstring_init (&dstring);
281
    if (numbers_ok) {
282
	dstring_append_char (&dstring, c);
283
    }
284
    for (;;) {
285
      redo1:
286
	switch (c1 = ISTREAM_PEEK_CHAR (istream)) {
287
	  case '\0':
288
	    ISTREAM_HANDLE_NULL (istream, redo1, done);
289
	    goto done;
290
	  default:
291
	    if (syntax_is_letter (c1) || (c1 == '_') ||
292
		(numbers_ok && syntax_is_digit (c1))) {
293
	      redo2:
294
		LEXER_READ_ONE_CHAR (istream, redo2, done, c1);
295
		dstring_append_char (&dstring, c1);
296
		numbers_ok = TRUE;
297
	    } else {
298
		goto done;
299
	    }
300
	    break;
301
	}
302
    }
303
  done:
304
    if (!numbers_ok) {
305
	E_c_expected_at_id (istream, c);
306
    }
307
    dstring_to_nstring (&dstring, nstring);
308
    dstring_destroy (&dstring);
309
}
310
 
311
static void
312
c_lexer_flush_string PROTO_N ((dstring, code, force_nl))
313
		     PROTO_T (DStringP dstring X
314
			      CCodeP   code X
315
			      BoolT    force_nl)
316
{
317
    NStringT nstring;
318
 
319
    if (dstring_length (dstring) > 0) {
320
	if (force_nl && (!dstring_last_char_equal (dstring, '\n'))) {
321
	    dstring_append_char (dstring, '\n');
322
	}
323
	dstring_to_nstring (dstring, &nstring);
324
	c_code_append_string (code, &nstring);
325
	dstring_destroy (dstring);
326
	dstring_init (dstring);
327
    } else if (force_nl) {
328
	nstring_copy_cstring (&nstring, "\n");
329
	c_code_append_string (code, &nstring);
330
    }
331
}
332
 
333
static BoolT
334
c_lexer_read_at PROTO_N ((istream, dstring, code))
335
		PROTO_T (IStreamP istream X
336
			 DStringP dstring X
337
			 CCodeP   code)
338
{
339
    char     c;
340
    NStringT nstring;
341
 
342
  redo:
343
    switch (c = ISTREAM_READ_CHAR (istream)) {
344
      case '\0':
345
	ISTREAM_HANDLE_NULL (istream, redo, error);
346
	goto error;
347
      case '\n':
348
	istream_inc_line (istream);
349
	goto error;
350
      case '@':
351
	dstring_append_char (dstring, c);
352
	break;
353
      case '}':
354
	return (TRUE);
355
      case '!':
356
	c_lexer_flush_string (dstring, code, FALSE);
357
	c_code_append_exception (code);
358
	break;
359
      case '.':
360
	c_lexer_flush_string (dstring, code, FALSE);
361
	c_code_append_terminal (code);
362
	break;
363
      case '>':
364
	c_lexer_flush_string (dstring, code, FALSE);
365
	c_code_append_advance (code);
366
	break;
367
      case ':':
368
	c_lexer_flush_string (dstring, code, FALSE);
369
	c_lexer_read_code_id (istream, ':', &nstring);
370
	c_code_append_label (code, &nstring);
371
	break;
372
      case '&':
373
	c_lexer_flush_string (dstring, code, FALSE);
374
	c_lexer_read_code_id (istream, '&', &nstring);
375
	c_code_append_reference (code, &nstring);
376
	break;
377
      case '=':
378
	c_lexer_flush_string (dstring, code, FALSE);
379
	c_lexer_read_code_id (istream, '=', &nstring);
380
	c_code_append_modifiable (code, &nstring);
381
	break;
382
      default:
383
	if (syntax_is_letter (c) || (c == '_')) {
384
	    c_lexer_flush_string (dstring, code, FALSE);
385
	    c_lexer_read_code_id (istream, c, &nstring);
386
	    c_code_append_identifier (code, &nstring);
387
	} else {
388
	  error:
389
	    E_c_illegal_at_char (istream, c);
390
	}
391
	break;
392
    }
393
    return (FALSE);
394
}
395
 
396
static void
397
c_lexer_read_code PROTO_N ((istream, token))
398
		  PROTO_T (IStreamP istream X
399
			   CLexP    token)
400
{
401
    CCodeP   code = c_code_create (istream_name (istream),
402
				   istream_line (istream));
403
    DStringT dstring;
404
    char     c;
405
 
406
  redo1:
407
    switch (ISTREAM_PEEK_CHAR (istream)) {
408
      case '\0':
409
	ISTREAM_HANDLE_NULL (istream, redo1, error);
410
	goto error;
411
      case '{':
412
      redo2:
413
	LEXER_READ_ONE_CHAR (istream, redo2, error, c);
414
	UNUSED (c);
415
	break;
416
      default:
417
      error:
418
	E_c_code_block_syntax (istream);
419
	break;
420
    }
421
    dstring_init (&dstring);
422
    for (;;) {
423
      redo3:
424
	switch (c = ISTREAM_READ_CHAR (istream)) {
425
	  case '\0':
426
	    ISTREAM_HANDLE_NULL (istream, redo3, eof);
427
	    dstring_append_char (&dstring, c);
428
	    break;
429
	  case '\n':
430
	    istream_inc_line (istream);
431
	    dstring_append_char (&dstring, c);
432
	    break;
433
	  case '@':
434
	    if (c_lexer_read_at (istream, &dstring, code)) {
435
		goto done;
436
	    }
437
	    break;
438
	  default:
439
	    dstring_append_char (&dstring, c);
440
	    break;
441
	}
442
    }
443
  eof:
444
    E_c_eof_in_code (istream);
445
  done:
446
    token->t = C_TOK_CODE;
447
    c_lexer_flush_string (&dstring, code, TRUE);
448
    dstring_destroy (&dstring);
449
    token->u.code = code;
450
}
451
 
452
/*--------------------------------------------------------------------------*/
453
 
454
void
455
c_lexer_init PROTO_N ((stream, istream))
456
	     PROTO_T (CLexerStreamP stream X
457
		      IStreamP      istream)
458
{
459
    istream_assign (&(stream->istream), istream);
460
    c_lexer_next_token (stream);
461
}
462
 
463
#ifdef FS_FAST
464
#undef c_lexer_close
465
#endif /* defined (FS_FAST) */
466
void
467
c_lexer_close PROTO_N ((stream))
468
	      PROTO_T (CLexerStreamP stream)
469
{
470
    istream_close (&(stream->istream));
471
}
472
#ifdef FS_FAST
473
#define c_lexer_close(s) (istream_close (&((s)->istream)))
474
#endif /* defined (FS_FAST) */
475
 
476
#ifdef FS_FAST
477
#undef c_lexer_stream_name
478
#endif /* defined (FS_FAST) */
479
CStringP
480
c_lexer_stream_name PROTO_N ((stream))
481
		    PROTO_T (CLexerStreamP stream)
482
{
483
    return (istream_name (&(stream->istream)));
484
}
485
#ifdef FS_FAST
486
#define c_lexer_stream_name(s) (istream_name (&((s)->istream)))
487
#endif /* defined (FS_FAST) */
488
 
489
#ifdef FS_FAST
490
#undef c_lexer_stream_line
491
#endif /* defined (FS_FAST) */
492
unsigned
493
c_lexer_stream_line PROTO_N ((stream))
494
		    PROTO_T (CLexerStreamP stream)
495
{
496
    return (istream_line (&(stream->istream)));
497
}
498
#ifdef FS_FAST
499
#define c_lexer_stream_line(s) (istream_line (&((s)->istream)))
500
#endif /* defined (FS_FAST) */
501
 
502
#ifdef FS_FAST
503
#undef c_lexer_get_terminal
504
#endif /* defined (FS_FAST) */
505
CTokenT
506
c_lexer_get_terminal PROTO_N ((stream))
507
		     PROTO_T (CLexerStreamP stream)
508
{
509
    return (stream->token.t);
510
}
511
#ifdef FS_FAST
512
#define c_lexer_get_terminal(s) ((s)->token.t)
513
#endif /* defined (FS_FAST) */
514
 
515
void
516
c_lexer_next_token PROTO_N ((stream))
517
		   PROTO_T (CLexerStreamP stream)
518
{
519
    IStreamP istream = &(stream->istream);
520
    CLexT    token;
521
    char     c;
522
 
523
  retry:
524
    switch (c = c_lexer_skip_white_space (istream)) {
525
      case '\0': /*FOR EOF*/
526
	token.t = C_TOK_EOF;
527
	break;
528
      case '%':
529
	c_lexer_read_builtin (istream, &token);
530
	break;
531
      case ',':
532
	token.t = C_TOK_SEPARATOR;
533
	break;
534
      case ':':
535
	token.t = C_TOK_TYPEMARK;
536
	break;
537
      case ';':
538
	token.t = C_TOK_TERMINATOR;
539
	break;
540
      case '<':
541
	token.t = C_TOK_BEGIN_ACTION;
542
	break;
543
      case '=':
544
	token.t = C_TOK_DEFINE;
545
	break;
546
      case '>':
547
	token.t = C_TOK_END_ACTION;
548
	break;
549
      case '(':
550
	token.t = C_TOK_OPEN_TUPLE;
551
	break;
552
      case ')':
553
	token.t = C_TOK_CLOSE_TUPLE;
554
	break;
555
      case '&':
556
	token.t = C_TOK_REFERENCE;
557
	break;
558
      case '@':
559
	c_lexer_read_code (istream, &token);
560
	break;
561
      case '-':
562
	if ((istream_peek_char (istream, &c)) && (c == '>')) {
563
	    (void) istream_read_char (istream, &c);
564
	    token.t = C_TOK_ARROW;
565
	    break;
566
	}
567
	c_lexer_read_identifier (istream, '-', &token);
568
	break;
569
      default:
570
	if ((syntax_is_letter (c)) || (c == '_')) {
571
	    c_lexer_read_identifier (istream, c, &token);
572
	} else {
573
	    E_c_illegal_character (istream, c);
574
	    goto retry;
575
	}
576
	break;
577
    }
578
    stream->token = token;
579
}
580
 
581
#ifdef FS_FAST
582
#undef c_lexer_string_value
583
#endif /* defined (FS_FAST) */
584
NStringP
585
c_lexer_string_value PROTO_N ((stream))
586
		     PROTO_T (CLexerStreamP stream)
587
{
588
    ASSERT ((stream->token.t == C_TOK_C_IDENTIFIER) ||
589
	    (stream->token.t == C_TOK_SID_IDENTIFIER));
590
    return (&(stream->token.u.string));
591
}
592
#ifdef FS_FAST
593
#define c_lexer_string_value(s) (&((s)->token.u.string))
594
#endif /* defined (FS_FAST) */
595
 
596
#ifdef FS_FAST
597
#undef c_lexer_code_value
598
#endif /* defined (FS_FAST) */
599
CCodeP
600
c_lexer_code_value PROTO_N ((stream))
601
		   PROTO_T (CLexerStreamP stream)
602
{
603
    ASSERT (stream->token.t == C_TOK_CODE);
604
    return (stream->token.u.code);
605
}
606
#ifdef FS_FAST
607
#define c_lexer_code_value(s) ((s)->token.u.code)
608
#endif /* defined (FS_FAST) */
609
 
610
void
611
c_lexer_save_terminal PROTO_N ((stream, error_terminal))
612
		      PROTO_T (CLexerStreamP stream X
613
			       CTokenT       error_terminal)
614
{
615
    ASSERT (stream->token.t != error_terminal);
616
    stream->saved_terminal = stream->token.t;
617
    stream->token.t        = error_terminal;
618
}
619
 
620
void
621
c_lexer_restore_terminal PROTO_N ((stream))
622
			 PROTO_T (CLexerStreamP stream)
623
{
624
    stream->token.t = stream->saved_terminal;
625
}
626
 
627
/*
628
 * Local variables(smf):
629
 * eval: (include::add-path-entry "../os-interface" "../library")
630
 * eval: (include::add-path-entry "../transforms" "../output")
631
 * eval: (include::add-path-entry "../c-output" "../generated")
632
 * end:
633
**/