1 /* L E X I C A L A N A L Y S E R F O R I S O - P A S C A L */
22 extern long str2long();
23 extern char *Malloc();
25 #define TO_LOWER(ch) (ch |= ( ch>='A' && ch<='Z' ) ? 0x0020 : 0)
31 int idfsize = IDFSIZE;
40 int tokenseen = 0; /* Some comment-options must precede any program text */
42 /* Warning: The options specified inside comments take precedence over
43 * the ones on the command line.
49 /* Parse options inside comments */
55 case 'c': /* for strings */
56 case 'd': /* for longs */
57 case 's': /* check for standard */
58 case 'u': /* for underscores */
59 case 'C': /* for different cases */
60 case 'U': /* for underscores */
62 lexwarning("the '%c' option must precede any program text", ci);
67 if( ci == 's' && options[ci] && ch == '-')
68 lexwarning("option '%c-' overrides previous one", ci);
69 if( ch == '-' ) options[ci] = 0;
70 else if( ch == '+' ) options[ci] = 1;
74 case 'l': ci = 'L' ; /* for indexing */
76 case 'L': /* FIL & LIN instructions */
77 case 'R': /* range checks */
78 case 'a': /* assertions */
81 case 't': /* tracing */
82 case 'A': /* extra array range-checks */
84 if( ch == '-' ) options[ci] = on_on_minus;
85 else if( ch == '+' ) options[ci] = !on_on_minus;
95 while( ch >= '0' && ch <= '9' ) {
96 i = 10 * i + (ch - '0');
101 lexwarning("the '%c' option must precede any program text", ci);
105 lexwarning("bad '%c' option", ci);
116 } while (ch == ',' );
125 /* Skip ISO-Pascal comments (* ... *) or { ... }.
127 comments may not be nested (ISO 6.1.8).
128 (* and { are interchangeable, so are *) and }.
133 if (ch == '$') CommentOptions();
135 if( class(ch) == STNL ) {
141 else if( ch == '*' ) {
143 if( ch == ')' ) return; /* *) */
146 else if( ch == '}' ) return;
147 else if( ch == EOI ) {
148 lexerror("unterminated comment");
155 STATIC struct string *
159 /* Read a Pascal string, delimited by the character ' or ".
162 register struct string *str = (struct string *)
163 Malloc((unsigned) sizeof(struct string));
165 register int len = ISTRSIZE;
167 str->s_str = p = Malloc((unsigned int) ISTRSIZE);
171 fatal("non-ascii '\\%03o' read", ch & 0377);
174 if( class(ch) == STNL ) {
175 lexerror("newline in string");
183 lexerror("end-of-file in string");
192 if( p - str->s_str == len ) {
193 extern char *Srealloc();
195 str->s_str = Srealloc(str->s_str,
196 (unsigned int) len + RSTRSIZE);
197 p = str->s_str + len;
201 if( ch == EOI ) eofseen = 1;
204 str->s_length = p - str->s_str;
207 /* ISO 6.1.7: string length at least 1 */
208 if( str->s_length == 0 ) {
209 lexerror("character-string: at least one character expected");
216 static char *s_error = "illegal line directive";
218 CheckForLineDirective()
222 char buf[IDFSIZE + 2];
223 register char *c = buf;
232 * Skip to next digit. Do not skip newlines.
235 if( class(ch) == STNL ) {
240 else if( ch == EOI ) {
244 } while( class(ch) != STNUM );
245 while( class(ch) == STNUM ) {
246 i = i * 10 + (ch - '0');
252 while( ch != '"' && ch != EOI && class(ch) != STNL) LoadChar(ch);
257 if( class(ch) == STNL ) {
262 } while( ch != '"' );
266 } while( class(ch) != STNL );
268 * Remember the filename
270 if( !eofseen && strcmp(FileName, buf) ) {
271 FileName = Salloc(buf,(unsigned) strlen(buf) + 1);
284 /* LLlex() is the Lexical Analyzer.
285 The putting aside of tokens is taken into account.
287 register struct token *tk = ˙
288 register int ch, nch;
290 toktype = error_type;
292 if( ASIDE ) { /* a token is put aside */
299 tk->tk_lineno = LineNumber;
309 if( !options['C'] ) /* -C : cases are different */
312 if( (ch & 0200) && ch != EOI ) {
313 fatal("non-ascii '\\%03o' read", ch & 0377);
318 switch( class(ch) ) {
326 CheckForLineDirective();
333 if( !tokenseen && (ch == '"' || ch == '_') ) {
334 return tk->tk_symb = ch;
336 if( (unsigned) ch < 0177 )
337 lexerror("garbage char %c", ch);
339 crash("(LLlex) garbage char \\%03o", ch);
345 if( nch == '*' ) { /* (* */
347 tk->tk_lineno = LineNumber;
350 if( nch == '.' ) /* (. is [ */
351 return tk->tk_symb = '[';
352 if( nch == EOI ) eofseen = 1;
355 else if( ch == '{' ) {
357 tk->tk_lineno = LineNumber;
360 else if( ch == '@' ) ch = '^'; /* @ is ^ */
362 return tk->tk_symb = ch;
369 if( nch == '.' ) /* .. */
370 return tk->tk_symb = UPTO;
371 if( nch == ')' ) /* .) is ] */
372 return tk->tk_symb = ']';
376 if( nch == '=' ) /* := */
377 return tk->tk_symb = BECOMES;
381 if( nch == '=' ) /* <= */
382 return tk->tk_symb = LESSEQUAL;
383 if( nch == '>' ) /* <> */
384 return tk->tk_symb = NOTEQUAL;
388 if( nch == '=' ) /* >= */
389 return tk->tk_symb = GREATEREQUAL;
393 crash("(LLlex, STCOMP)");
396 if( nch == EOI ) eofseen = 1;
398 return tk->tk_symb = ch;
401 char buf[IDFSIZE + 1];
402 register char *tag = &buf[0];
403 register struct idf *id;
404 extern struct idf *str2idf();
407 if( !options['C'] ) /* -C : cases are different */
409 if( tag - buf < idfsize )
412 } while( in_idf(ch) );
415 if( ch == EOI ) eofseen = 1;
418 if( buf[0] == '_' ) lexerror("underscore starts identifier");
419 tk->TOK_IDF = id = str2idf(buf, 1);
420 return tk->tk_symb = id->id_reserved ? id->id_reserved : IDENT;
424 register struct string *str = GetString(ch);
426 if( str->s_length == 1 && ch == '\'') {
429 /* to prevent LexScan from crashing */
430 tk->tk_data.tk_str = str;
431 return tk->tk_symb = STRING;
434 tk->TOK_INT = *(str->s_str) & 0377;
441 tk->tk_data.tk_str = str;
442 toktype = standard_type(T_STRINGCONST, 1, str->s_length);
445 tk->tk_data.tk_str = str;
446 toktype = string_type;
449 return tk->tk_symb = STRING;
457 register char *np = &buf[1];
458 register int state = INT_MODE;
459 extern char *Salloc();
463 if( np <= &buf[NUMSIZE] )
466 } while( is_dig(ch) );
471 if( np <= &buf[NUMSIZE] )
474 /* fractional part */
475 if( np <= &buf[NUMSIZE] )
478 } while( is_dig(ch) );
488 if( ch == 'e' || ch == 'E' ) {
489 char *tp = np; /* save position in string */
492 if( np <= &buf[NUMSIZE] )
495 if( ch == '+' || ch == '-' ) {
496 /* signed scale factor */
497 if( np <= &buf[NUMSIZE] )
503 if( np <= &buf[NUMSIZE] )
506 } while( is_dig(ch) );
512 if( np - tp == 2 ) /* sign */
514 np = tp; /* restore position */
518 /* syntax of number is correct */
519 if( ch == EOI ) eofseen = 1;
524 if( state == INT_MODE ) {
525 if( np > &buf[NUMSIZE+1] ) {
527 lexerror("constant too long");
531 while (*np == '0') /* skip leading zeros */
533 tk->TOK_INT = str2long(np, 10);
534 if( tk->TOK_INT < 0 ||
535 strlen(np) > strlen(maxint_str) ||
536 strlen(np) == strlen(maxint_str) &&
537 strcmp(np, maxint_str) > 0 )
538 lexwarning("overflow in constant");
541 return tk->tk_symb = INTEGER;
544 tk->tk_data.tk_real = (struct real *)
545 Malloc(sizeof(struct real));
546 /* allocate struct for inverse */
547 tk->TOK_RIV = (struct real *) Malloc(sizeof(struct real));
548 tk->TOK_RIV->r_inverse = tk->tk_data.tk_real;
550 tk->TOK_RIV->r_lab = 0;
552 if( np > &buf[NUMSIZE+1] ) {
553 tk->TOK_REL = Salloc("0.0", 4);
554 tk->TOK_RIV->r_real = tk->TOK_REL;
555 lexerror("floating constant too long");
558 tk->TOK_RIV->r_real = Salloc(buf,(unsigned) (np - buf));
559 tk->TOK_REL = tk->TOK_RIV->r_real + 1;
563 return tk->tk_symb = REAL;
569 return tk->tk_symb = -1;
573 crash("(LLlex) Impossible character class");