Subversion Repositories tendra.SVN

Rev

Rev 5 | Details | Compare with Previous | Last modification | View Log | RSS feed

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