/[ascend]/trunk/base/generic/compiler/scanner.l
ViewVC logotype

Contents of /trunk/base/generic/compiler/scanner.l

Parent Directory Parent Directory | Revision Log Revision Log


Revision 412 - (show annotations) (download)
Mon Apr 3 03:31:30 2006 UTC (18 years, 2 months ago) by johnpye
File size: 32311 byte(s)
Trying to fix problems with the parser 'yy' and 'zz' stuff so that it works with SCons and hopefuly autotools at same time.
1 %{
2 /*
3 * ASCEND Lexing Program
4 *
5 * This file is part of the Ascend Language Interpreter.
6 *
7 * The Ascend Language Interpreter is free software; you can redistribute
8 * it and/or modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
11 *
12 * The Ascend Language Interpreter is distributed in hope that it will be
13 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with the program; if not, write to the Free Software Foundation,
19 * Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named
20 * COPYING.
21 *
22 * This module is the input file for Flex (Lexical Analyzer
23 * Generator). Its goal is to convert a stream of characters into a
24 * stream of tokens. It has been defined to be consistent with the
25 * routines required by the common compiler-compiler yacc.
26 */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <math.h>
32 #include "utilities/ascConfig.h"
33 #include "utilities/ascMalloc.h"
34 #include "compiler/compiler.h"
35 /* everything between here and the next comment is only here */
36 #include "compiler/fractions.h"
37 #include "compiler/dimen.h"
38 #include "compiler/functype.h"
39 #include "compiler/func.h"
40 #include "compiler/types.h"
41 #include "compiler/stattypes.h"
42 #include "compiler/fractions.h"
43 #include "compiler/proc.h"
44 /* because ascParse.h has a nasty union we can't digest without them. */
45 #include "compiler/ascParse.h"
46 /* these below we actually need */
47 #include "general/list.h"
48 #include "compiler/module.h"
49 #include "compiler/scanner.h"
50 #include "compiler/symtab.h"
51 #include "compiler/parser.h"
52
53 #define YY_BREAK
54 /* Defining yybreak as above means that all of our matches must end
55 * in break or return because the normal flex supplied yybreak will
56 * be preempted by our empty one.
57 * In cases where matches contain a conditional return, make sure a
58 * break follows in the failure case.
59 */
60
61 #define ENDTOK 0
62 /* Return value when we reach the end of the input.
63 * This to must be 0 or negative according to yacc
64 */
65
66 #define MAX_REQUIRE_DEPTH 10
67 /* The maximum number of REQUIREd file nesting we will accept.
68 * See RequireStack below.
69 */
70
71 #define WORKBUF_INIT_SIZE 4095
72 /* We need a temporary buffer to copy yytext into before returning
73 * to the scanner (see g_workbuf below).
74 * WORKBUF_INIT_SIZE is the initial size of g_workbuf
75 */
76
77 static unsigned long yy_line = 1;
78 /* The current line number;
79 * every match of newline (\n) needs to ++ this variable.
80 */
81
82 static unsigned long start_line = 0;
83 /* The ine number where an open-comment, open-brace, or
84 * open-double-quote occurs. We use this to help in error reporting.
85 */
86
87 static int CommentNestLevel = 0;
88 /* Nesting level of (* comments *)
89 */
90
91 static int BracesNestLevel = 0;
92 /* Nesting level of {braced} expressions
93 */
94
95 static int MatchedBackslash = 0;
96 /* If this variable is positive, we matched a backslash \ in a DoubleQuote
97 * or BracedText state, and we should call ProcessBackslashes() to
98 * process them.
99 */
100
101 static int RequireIndex = 0;
102 /* The current nesting level of REQUIREd files
103 */
104
105 static YY_BUFFER_STATE RequireStack[MAX_REQUIRE_DEPTH];
106 /* The Flex buffers used for the REQUIREd files
107 */
108
109 static char *g_workbuf = NULL;
110 /* We need a place to keep doubly-quoted-text and braced-text for passing
111 * it back to the parser. yytext will not work since the parser may ask
112 * the scanner to read another token, at which point the value in yytext
113 * gets lost.
114 *
115 * The initial size of g_workbuf is WORKBUF_INIT_SIZE, and g_workbuf
116 * doubles when it needs more space.
117 *
118 * A call to CopyIntoWorkBuffer(yytext,yyleng) will copy yyleng characters
119 * of yytext into the working buffer.
120 *
121 * Note that having a single work buffer will not work if we ever create
122 * yacc productions that scan multiple chunks of doubly-quoted-text and/or
123 * braced-text before acting on them.
124 */
125
126
127 /* Forward declaration of functions
128 * provided at the end of this file.
129 */
130 static int Asc_ScannerPopBuffer(void);
131 static char *CopyIntoWorkBuffer(CONST char *, unsigned long);
132 static int Process_Backslashes(void);
133 static void ErrMsg_BracesEOF(void);
134 static void ErrMsg_CommentEOF(void);
135 static void ErrMsg_DoubleQuoteEOF(void);
136 static void ErrMsg_LongID(void);
137 static void ErrMsg_LongSymbol(void);
138 static void ErrMsg_SymbolEOF(void);
139 static void ErrMsg_SymbolEOL(void);
140 static void ErrMsg_UnexpectedChar(void);
141
142 %}
143
144 %x Comment
145 %x Symbol
146 %x BracedText
147 %x DoubleQuote
148
149 blank [\f\r\t\v ]
150 digit [0-9]
151 letter [a-zA-Z]
152
153 exp ([eE][-+]?{digit}+)
154 real (((({digit}+"."{digit}*)|("."{digit}+)){exp}?)|({digit}+{exp}))
155 integer {digit}+
156 IDChar {letter}({integer}|{letter}|_)*
157
158 %%
159
160 <INITIAL>"<=" { return LEQ_T; }
161 <INITIAL>">=" { return GEQ_T; }
162 <INITIAL>"<>" { return NEQ_T; }
163 <INITIAL>".." { return DOTDOT_T; }
164 <INITIAL>"::" { return DBLCOLON_T;}
165 <INITIAL>":=" { return ASSIGN_T; }
166 <INITIAL>":==" { return CASSIGN_T; }
167 <INITIAL>"==" { return BEQ_T ; }
168 <INITIAL>"!=" { return BNE_T ; }
169
170 <INITIAL>"=" { return '=' ;}
171 <INITIAL>">" { return '>' ;}
172 <INITIAL>"<" { return '<' ;}
173 <INITIAL>"," { return ',' ;}
174 <INITIAL>"." { return '.' ;}
175 <INITIAL>";" { return ';' ;}
176 <INITIAL>":" { return ':' ;}
177 <INITIAL>"[" { return '[' ;}
178 <INITIAL>"]" { return ']' ;}
179 <INITIAL>"(" { return '(' ;}
180 <INITIAL>")" { return ')' ;}
181 <INITIAL>"+" { return '+' ;}
182 <INITIAL>"-" { return '-' ;}
183 <INITIAL>"*" { return '*' ;}
184 <INITIAL>"/" { return '/' ;}
185 <INITIAL>"^" { return '^' ;}
186 <INITIAL>"|" { return '|' ;}
187
188 /**** Reserved Keywords ****/
189
190 <INITIAL>"ADD" { return ADD_T ; }
191 <INITIAL>"ALIASES" { return ALIASES_T ; }
192 <INITIAL>"AND" { return AND_T ; }
193 <INITIAL>"ANY" { return ANY_T ; }
194 <INITIAL>"ARE_ALIKE" { return AREALIKE_T ; }
195 <INITIAL>"ARE_THE_SAME" { return ARETHESAME_T ; }
196 <INITIAL>"ARRAY" { return ARRAY_T ; }
197 <INITIAL>"ATOM" { return ATOM_T ; }
198 <INITIAL>"BREAK" { return BREAK_T ; }
199 <INITIAL>"CALL" { return CALL_T ; }
200 <INITIAL>"CARD" { return CARD_T ; }
201 <INITIAL>"CASE" { return CASE_T ; }
202 <INITIAL>"CHECK" { return CHECK_T ; }
203 <INITIAL>"CHOICE" { return CHOICE_T ; }
204 <INITIAL>"CONDITIONAL" { return CONDITIONAL_T ; }
205 <INITIAL>"CONSTANT" { return CONSTANT_T ; }
206 <INITIAL>"CONTINUE" { return CONTINUE_T ; }
207 <INITIAL>"CREATE" { return CREATE_T ; }
208 <INITIAL>"DATA" { return DATA_T ; }
209 <INITIAL>"DECREASING" { return DECREASING_T ; }
210 <INITIAL>"DEFAULT" { return DEFAULT_T ; }
211 <INITIAL>"DEFINITION" { return DEFINITION_T ; }
212 <INITIAL>"DIMENSION" { return DIMENSION_T ; }
213 <INITIAL>"DIMENSIONLESS" { return DIMENSIONLESS_T ; }
214 <INITIAL>"DO" { return DO_T ; }
215 <INITIAL>"ELSE" { return ELSE_T ; }
216 <INITIAL>"END" { return END_T ; }
217 <INITIAL>"EXPECT" { return EXPECT_T ; }
218 <INITIAL>"EXTERNAL" { return EXTERNAL_T ; }
219 <INITIAL>"FALSE" { return FALSE_T ; }
220 <INITIAL>"FALL_THROUGH" { return FALLTHRU_T ; }
221 <INITIAL>"FIX" { return FIX_T ; }
222 <INITIAL>"FREE" { return FREE_T ; }
223 <INITIAL>"FOR" { return FOR_T ; }
224 <INITIAL>"FROM" { return FROM_T ; }
225 <INITIAL>"GLOBAL" { return GLOBAL_T ; }
226 <INITIAL>"ASSERT" { return ASSERT_T ; }
227 <INITIAL>"IF" { return IF_T ; }
228 <INITIAL>"IMPORT" { return IMPORT_T ; }
229 <INITIAL>"IN" { return IN_T ; }
230 <INITIAL>"INCREASING" { return INCREASING_T ; }
231 <INITIAL>"INPUT" { return INPUT_T ; }
232 <INITIAL>"INTERSECTION" { return INTERSECTION_T ; }
233 <INITIAL>"IS_A" { return ISA_T ; }
234 <INITIAL>"IS_REFINED_TO" { return ISREFINEDTO_T ; }
235 <INITIAL>"MAXIMIZE" { return MAXIMIZE_T ; }
236 <INITIAL>"MAX_INTEGER" { return MAXINTEGER_T ; }
237 <INITIAL>"MAX_REAL" { return MAXREAL_T ; }
238 <INITIAL>"METHOD" { return METHOD_T ; }
239 <INITIAL>"METHODS" { return METHODS_T ; }
240 <INITIAL>"MINIMIZE" { return MINIMIZE_T ; }
241 <INITIAL>"MODEL" { return MODEL_T ; }
242 <INITIAL>"NOT" { return NOT_T ; }
243 <INITIAL>"NOTES" { return NOTES_T ; }
244 <INITIAL>"OF" { return OF_T ; }
245 <INITIAL>"OR" { return OR_T ; }
246 <INITIAL>"OTHERWISE" { return OTHERWISE_T ; }
247 <INITIAL>"OUTPUT" { return OUTPUT_T ; }
248 <INITIAL>"PROD" { return PROD_T ; }
249 <INITIAL>"PROVIDE" { return PROVIDE_T ; }
250 <INITIAL>"REFINES" { return REFINES_T ; }
251 <INITIAL>"REPLACE" { return REPLACE_T ; }
252 <INITIAL>"REQUIRE" { return REQUIRE_T ; }
253 <INITIAL>"RETURN" { return RETURN_T ; }
254 <INITIAL>"RUN" { return RUN_T ; }
255 <INITIAL>"SATISFIED" { return SATISFIED_T ; }
256 <INITIAL>"SELECT" { return SELECT_T ; }
257 <INITIAL>"SUCH_THAT" { return SUCHTHAT_T ; }
258 <INITIAL>"SUM" { return SUM_T ; }
259 <INITIAL>"SIZE" { return SIZE_T ; }
260 <INITIAL>"SWITCH" { return SWITCH_T ; }
261 <INITIAL>"STOP" { return STOP_T ; }
262 <INITIAL>"THEN" { return THEN_T ; }
263 <INITIAL>"TRUE" { return TRUE_T ; }
264 <INITIAL>"UNION" { return UNION_T ; }
265 <INITIAL>"UNITS" { return UNITS_T ; }
266 <INITIAL>"UNIVERSAL" { return UNIVERSAL_T ; }
267 <INITIAL>"USE" { return USE_T ; }
268 <INITIAL>"VALUE" { return VALUE_T ; }
269 <INITIAL>"WHEN" { return WHEN_T ; }
270 <INITIAL>"WHERE" { return WHERE_T ; }
271 <INITIAL>"WHILE" { return WHILE_T ; }
272 <INITIAL>"WILL_BE" { return WILLBE_T ; }
273 <INITIAL>"WILL_BE_THE_SAME" { return WILLBETHESAME_T ; }
274 <INITIAL>"WILL_NOT_BE_THE_SAME" { return WILLNOTBETHESAME_T ; }
275 <INITIAL>"WITH" { return WITH_T ; }
276 <INITIAL>"WITH_VALUE" { return WITH_VALUE_T ; }
277
278 /*
279 * Code to handle (* Comments *)
280 *
281 * "(*" puts us into the Comment state. Comments nest, so in the
282 * Comment state we need to look for "(*" that increases the nesting
283 * level and "*)" that will lower it.
284 * Flex is faster if we match as much as possible, so we repeat
285 * patterns with and without the "\n" (although it is more difficult
286 * for the maintainer to understand) to avoid the overhead of a
287 * separate "\n" rule.
288 * Do NOT try to match \(\*+ since that causes "(****)" to parse
289 * incorrectly.
290 */
291
292 <INITIAL>\(\* {
293 /* Match "(" followed by "*" puts us into
294 * the COMMENT state. Don't use \*+ since
295 * that will parse "(***)" incorrectly.
296 * Initialize the nesting level.
297 * Store the current line for ErrMsg use.
298 */
299 BEGIN (Comment);
300 CommentNestLevel = 1;
301 start_line = yy_line;
302 break;
303 }
304 <Comment>\(\*[^*(\n]* {
305 /* Match "(" followed "*" followed by
306 * anything that's not "(" nor "*".
307 * Increase the commment nesting level.
308 */
309 CommentNestLevel++;
310 break;
311 }
312 <Comment>\(\*[^*(\n]*\n {
313 /* Match "(" followed by "*" followed by
314 * anything that's not "(" nor "*".
315 * Increase the commment nesting level.
316 */
317 yy_line++;
318 CommentNestLevel++;
319 break;
320 }
321 <Comment>[^*(\n]*\*+\) {
322 /* Match anything not "*" or "(" followed
323 * by one or more "*"s followed by ")".
324 * This decreases the comment nesting level
325 * and kicks us out if we're back to zero.
326 */
327 CommentNestLevel--;
328 if (CommentNestLevel == 0) {
329 BEGIN (INITIAL);
330 }
331 break;
332 }
333 <Comment>[^*(\n]* {
334 /* Eat anything that's not a "*" nor a "("
335 */
336 break;
337 }
338 <Comment>[^*(\n]*\n {
339 /* Eat anything that's not a "*" nor a "("
340 * that is followed by a newline.
341 * This rule also matches empty line.
342 */
343 yy_line++;
344 break;
345 }
346 <Comment>\(+[^*(\n]* {
347 /* Eat "("s not followed by "*"
348 */
349 break;
350 }
351 <Comment>\(+[^*(\n]*\n {
352 /* Eat "("s not followed by "*" plus a "\n"
353 */
354 yy_line++;
355 break;
356 }
357 <Comment>\*+[^*()\n]* {
358 /* Eat "*"s not followed by ")"
359 */
360 break;
361 }
362 <Comment>\*+[^*()\n]*\n {
363 /* Eat "*" not followed by ")" plus a "\n"
364 */
365 yy_line++;
366 break;
367 }
368 <Comment><<EOF>> {
369 /* An EOF in a Comment means bad nesting.
370 * Print an error and pop back a level
371 * or return ENDTOK if no more input.
372 */
373 ErrMsg_CommentEOF();
374 CommentNestLevel = 0;
375 if ( Asc_ScannerPopBuffer() == 1 ) {
376 return ENDTOK;
377 }
378 break;
379 }
380
381
382 /*
383 * Code to handle 'Symbols'
384 *
385 * Symbols are simple: they are 'singely quoted strings' that
386 * exist on a single line. Look for anything that is not
387 * a quote or a newline to get the text of the symbol.
388 */
389
390 <INITIAL>\' {
391 /* A single quote (') in the INITIAL state
392 * puts us into the Symbol state.
393 */
394 BEGIN (Symbol);
395 break;
396 }
397 <Symbol>[^'\n]*\' {
398 /* Anything that is not a (') nor a newline
399 * followed by a (') is the symbol's text.
400 * Return to the INITIAL state, store the
401 * symbol in the symbol table and return
402 * SYMBOL_T to the parser.
403 */
404 BEGIN (INITIAL);
405 /* strip off the final (')
406 */
407 yytext[--yyleng] = '\0';
408 if (yyleng > YY_MAXLEN) {
409 ErrMsg_LongSymbol();
410 break;
411 }
412 zz_lval.sym_ptr = AddSymbolL(yytext,yyleng);
413 return SYMBOL_T;
414 }
415 <Symbol>[^'\n]*\n {
416 /* If we find a newline before a ('), the
417 * symbol is unterminated. Print an error
418 * message and return to the INITIAL state.
419 */
420 ErrMsg_SymbolEOL();
421 yy_line++;
422 BEGIN(INITIAL);
423 break;
424 }
425 <Symbol><<EOF>> {
426 /* If we find an EOF before a ('), the
427 * symbol is unterminated. Print an error
428 * message and pop to the previously
429 * REQUIREd file or return ENDTOK if the
430 * pop fails due to no more input.
431 */
432 ErrMsg_SymbolEOF();
433 if ( Asc_ScannerPopBuffer() == 1 ) {
434 return ENDTOK;
435 }
436 break;
437 }
438
439
440 /*
441 * Code to handle "Text in Double Quotes"
442 *
443 * The DoubleQuote state begins with a double quote and ends
444 * with a double quote; double quotes can be included by
445 * escaping them with a backslash (e.g. \"). There is no
446 * nesting level to worry about.
447 * Flex is faster if we match as much as possible, so we repeat
448 * patterns with and without the "\n" (although it is more difficult
449 * for the maintainer to understand) to avoid the overhead of a
450 * separate "\n" rule.
451 * We want to keep the text, so we need to call yymore().
452 */
453
454 <INITIAL>\" {
455 /* A double quote puts us into the
456 * DoubleQuote state. Save the line
457 * number for error reporting.
458 */
459 BEGIN (DoubleQuote);
460 start_line = yy_line;
461 break;
462 }
463 <DoubleQuote>[^\\"\n]*\\. {
464 /* A backslash \ in the DoubleQuote
465 * state protects any character.
466 */
467 MatchedBackslash++;
468 yymore();
469 break;
470 }
471 <DoubleQuote>[^\\"\n]*\\\n {
472 /* A backslash \ in the DoubleQuote
473 * state protects a newline.
474 */
475 MatchedBackslash++;
476 yy_line++;
477 yymore();
478 break;
479 }
480 <DoubleQuote>[^\\"\n]*\" {
481 /* A double quote in the DoubleQuote state
482 * (that is not protected by backslash)
483 * will put us back in the INITIAL state.
484 * Process the string and return DQUOTE_T
485 * to the parser.
486 */
487 BEGIN (INITIAL);
488 /* Remove the final double quote
489 */
490 yytext[--yyleng] = '\0';
491 /* Do backslash substitutions on the string
492 * before returing it to the scanner.
493 */
494 if ( MatchedBackslash != 0 ) {
495 Process_Backslashes();
496 MatchedBackslash = 0;
497 }
498 zz_lval.dquote_ptr =
499 CopyIntoWorkBuffer(yytext,yyleng);
500 return DQUOTE_T;
501 }
502 <DoubleQuote>[^\\"\n]* {
503 /* Match anything that is not backslash nor
504 * doublequote and add it to the text.
505 */
506 yymore();
507 break;
508 }
509 <DoubleQuote>[^\\"\n]*\n {
510 /* Match anything that is not backslash nor
511 * doublequote and add it to the text.
512 * This also matches an empty line.
513 */
514 yy_line++;
515 yymore();
516 break;
517 }
518 <DoubleQuote><<EOF>> {
519 /* End of File in a DoubleQuote state
520 * means no matching double quote.
521 * Print an error and pop next buffer
522 * off the RequireStack or return ENDTOK
523 * if there is no more input.
524 */
525 ErrMsg_DoubleQuoteEOF();
526 MatchedBackslash = 0;
527 if ( Asc_ScannerPopBuffer() == 1 ) {
528 return ENDTOK;
529 }
530 break;
531 }
532
533
534 /*
535 * Code to handle { Text in Braces }
536 *
537 * "{" puts us into the BracedText state. Braces nest, so
538 * in the BracedText state we need to look for "{" that increases
539 * the nesting level and "}" that will lower it.
540 * Flex is faster if we match as much as possible, so we repeat
541 * patterns with and without the "\n" (although it is more difficult
542 * for the maintainer to understand) to avoid the overhead of a
543 * separate "\n" rule.
544 * We want to keep the text we scan, so we have to call yymore().
545 */
546
547 <INITIAL>\{{blank}*\n { /* A "{" puts us into the BracedText state.
548 * If from the opening "{" to the first
549 * newline is all whitespace, then ignore
550 * it.
551 * Initialize the nesting level.
552 * Save the current line number for
553 * error message reporting.
554 */
555 BEGIN (BracedText);
556 BracesNestLevel = 1;
557 start_line = yy_line;
558 yy_line++;
559 break;
560 }
561 <INITIAL>\{ {
562 /* A "{" puts us into the BracedText state.
563 * Initialize the nesting level.
564 * Save the current line number for
565 * error message reporting.
566 */
567 BEGIN (BracedText);
568 BracesNestLevel = 1;
569 start_line = yy_line;
570 break;
571 }
572 <BracedText>[^\\{}\n]*\\. {
573 /* A backslash \ in the BracedText state
574 * protects any character and does not
575 * affect the Nesting Level.
576 */
577 MatchedBackslash++;
578 yymore();
579 break;
580 }
581 <BracedText>[^\\{}\n]*\\\n {
582 /* A backslash \ in the BracedText state
583 * protects a newline.
584 */
585 MatchedBackslash++;
586 yy_line++;
587 yymore();
588 break;
589 }
590 <BracedText>\{[^\\{}\n]* {
591 /* A "{" in the braces state gets added to
592 * the text and increase the nesting level.
593 */
594 BracesNestLevel++;
595 yymore();
596 break;
597 }
598 <BracedText>\{[^\\{}\n]*\n {
599 /* A "{" in the braces state gets added to
600 * the text and increase the nesting level.
601 */
602 yy_line++;
603 BracesNestLevel++;
604 yymore();
605 break;
606 }
607 <BracedText>[^\\{}\n]*\} {
608 /* A "}" will reduce the nesting level.
609 * If the nesting level is zero, go back to
610 * the INITIAL level, save the text as a
611 * Symbol, do the backslash substitution,
612 * and return BRACEDTEXT_T to the
613 * parse; otherwise, add the "}" to the
614 * text and keep scanning.
615 */
616 BracesNestLevel--;
617 if (BracesNestLevel == 0) {
618 BEGIN (INITIAL);
619 /* Remove the final "}"
620 */
621 yytext[--yyleng] = '\0';
622 /* Do backslash substitutions on the text
623 * before returing it to the scanner.
624 */
625 if ( MatchedBackslash != 0 ) {
626 Process_Backslashes();
627 MatchedBackslash = 0;
628 }
629 zz_lval.braced_ptr =
630 CopyIntoWorkBuffer(yytext,yyleng);
631 return BRACEDTEXT_T;
632 }
633 yymore();
634 break;
635 }
636 <BracedText>[^\\{}\n]* {
637 /* Match anything that is not "{" nor "}"
638 * nor "\\"(backslash) and add it to text.
639 */
640 yymore();
641 break;
642 }
643 <BracedText>[^\\{}\n]*\n {
644 /* Match anything that is not "{" nor "}"
645 * nor "\\"(backslash) followed by a "\n"
646 * and add it to text.
647 * This also matches an empty line.
648 */
649 yy_line++;
650 yymore();
651 break;
652 }
653 <BracedText><<EOF>> {
654 /* End of File in braces means bad nesting.
655 * Print an error message and pop to the
656 * previously REQUIREd file or return
657 * ENDTOK if no more input.
658 */
659 ErrMsg_BracesEOF();
660 BracesNestLevel = 0;
661 MatchedBackslash = 0;
662 if ( Asc_ScannerPopBuffer() == 1 ) {
663 return ENDTOK;
664 }
665 break;
666 }
667
668
669 /*
670 * Code to handle Miscellaneous types.
671 *
672 */
673
674 <INITIAL>{integer} {
675 /* An integer. Defn near top of file.
676 */
677 zz_lval.int_value = atol(yytext);
678 return INTEGER_T;
679 }
680
681 <INITIAL>{integer}/".." {
682 /* An integer as the first number in a
683 * range (need to avoid parsing "1..2"
684 * as the real numbers 1.0 and 0.2).
685 */
686 zz_lval.int_value = atol(yytext);
687 return INTEGER_T;
688 }
689
690 <INITIAL>{real} {
691 /* A real number. Defn near top of file.
692 */
693 zz_lval.real_value = atof(yytext);
694 return REAL_T;
695 }
696
697 <INITIAL>{IDChar}+ {
698 /* An identifier. Defn near top of file.
699 */
700 if (yyleng >YY_MAXLEN) {
701 ErrMsg_LongID();
702 break;
703 }
704 zz_lval.id_ptr = AddSymbolL(yytext,yyleng);
705 return IDENTIFIER_T;
706 }
707
708 <INITIAL>{blank}* {
709 /* Ignore whitespace. */
710 break;
711 }
712 <INITIAL>{blank}*\n {
713 /* Ignore whitespace. */
714 yy_line++;
715 break;
716 }
717
718
719 <INITIAL>. {
720 /* Unknown character. Print error
721 * message and keep going.
722 */
723 ErrMsg_UnexpectedChar();
724 break;
725 }
726
727 <INITIAL><<EOF>> {
728 /* Print an error message if we
729 * reached EOF in the middle of a
730 * type definition. Pop to the
731 * previously REQUIREd file or return
732 * ENDTOK if no more input.
733 */
734 Asc_ErrMsgTypeDefnEOF();
735 if ( Asc_ScannerPopBuffer() == 1 ) {
736 return ENDTOK;
737 }
738 break;
739 }
740
741 %%
742 /*
743 * int yywrap(void);
744 *
745 * This returns 1 if the scanner should stop parsing, or
746 * 0 if the scanner should continue. Flex requires this
747 * function unless %option noyywrap is defined.
748 */
749 int
750 yywrap(void)
751 {
752 return 1;
753 }
754
755
756 /*
757 * See the header file scanner.h for a description of this function.
758 */
759 unsigned long
760 LineNum(void)
761 {
762 return yy_line;
763 }
764
765
766 /*
767 * See the header file scanner.h for a description of this function.
768 */
769 void
770 Asc_ScannerAssignFile(FILE *f, unsigned long linenum)
771 {
772 yyin = f;
773 yy_line = linenum;
774 if ( RequireIndex == 0 ) {
775 yyrestart(f);
776 }
777 }
778
779 /*
780 * See the header file scanner.h for a description of this function.
781 */
782 void
783 Asc_ScannerAssignString(void *yybs, unsigned long linenum, int first)
784 {
785 /* yyin = f; */
786 yy_line = linenum;
787 yy_switch_to_buffer((YY_BUFFER_STATE)yybs);
788 if (first) {
789 BEGIN(INITIAL);
790 }
791 if ( RequireIndex == 0 ) {
792 yyrestart((FILE *)NULL); /* ? ? ? should be reading from a string buffer... */
793 }
794 }
795
796
797 /*
798 * See the header file scanner.h for a description of this function.
799 */
800 int
801 Asc_ScannerPushBuffer(CONST char *filename)
802 {
803 int status; /* status returned from Asc_RequireModule */
804
805 if ( RequireIndex >= MAX_REQUIRE_DEPTH ) {
806 FPRINTF(ASCERR,
807 "Error:\tREQUIRE nested too deeply (%d levels) on line %s:%lu.\n"
808 "\tFile \"%s\" not read.\n",
809 RequireIndex,
810 Asc_ModuleBestName(Asc_CurrentModule()),
811 yy_line,
812 filename);
813 return 1;
814 }
815
816 /* The current Flex buffer is not on the RequireStack yet, so add it
817 * before calling Asc_OpenModule. We need to increment RequireIndex
818 * before calling Asc_OpenModule due to the check in
819 * Asc_ScannerAssignFile.
820 */
821 RequireStack[RequireIndex++] = YY_CURRENT_BUFFER;
822
823 Asc_RequireModule( filename, &status );
824 if( status == 5 ) {
825 /* already required */
826 RequireIndex--;
827 FPRINTF(ASCINF, "REQUIREd module \"%s\" already PROVIDEd\n", filename);
828 return 1;
829 }
830 if( status == 4 ) {
831 /* recursive require */
832 RequireIndex--;
833 FPRINTF(ASCWAR, "Asc-Warn: Recursive REQUIRE for module \"%s\", ignored\n",
834 filename);
835 return 1;
836 }
837 if ( status != 0 ) {
838 /* The open failed. Decrement RequireIndex and print an error.
839 */
840 RequireIndex--;
841 FPRINTF(ASCERR,
842 "Error:\tREQUIRE cannot open module \"%s\" on line %s:%lu\n",
843 filename,
844 Asc_ModuleBestName(Asc_CurrentModule()),
845 yy_line);
846 return 2;
847 }
848
849 /* Asc_OpenModule was successful, so print a message, switch to the
850 * new buffer in the INITIAL state.
851 * SHOULD never reach here with a string buffer as they cannot be
852 * REQUIREd.
853 */
854 Asc_FPrintf(stderr,"REQUIREing file \"%s\"\n", filename);
855 yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE));
856 BEGIN (INITIAL);
857 return 0;
858 }
859
860
861 /*
862 * int Asc_ScannerPopBuffer()
863 *
864 * When we reach an End Of File (EOF) in the scanner, we call this
865 * function to pop us to the file which REQUIREd the file we just
866 * reached the end of and return 0. If there are no more files on the
867 * RequireStack, return 1.
868 */
869 static int
870 Asc_ScannerPopBuffer(void)
871 {
872 Asc_CloseCurrentModule(); /* the current module may be NULL. */
873 if ( RequireIndex == 0 ) {
874 return 1;
875 }
876
877 yy_delete_buffer(YY_CURRENT_BUFFER);
878 yy_switch_to_buffer( RequireStack[--RequireIndex] );
879 BEGIN(INITIAL);
880 return 0;
881 }
882
883 void Asc_ScannerReleaseStringBuffer(void *yybs)
884 {
885 yy_delete_buffer((YY_BUFFER_STATE)yybs);
886 yy_switch_to_buffer( RequireStack[--RequireIndex] );
887 BEGIN(INITIAL);
888 }
889
890 void *Asc_ScannerCreateStringBuffer(CONST char *string, int len)
891 {
892 /* we hope to god yy_scan_bytes does not change current buffer */
893 YY_BUFFER_STATE yybs;
894 /* push current, don't care its name or type. */
895 RequireStack[RequireIndex++] = YY_CURRENT_BUFFER;
896 yybs = yy_scan_bytes(string, len);
897 assert(yybs);
898 return (void *)yybs;
899 }
900
901 /*
902 * g_workbuf = CopyIntoWorkBuffer(str, len)
903 * char *g_workbuf;
904 * CONST char *str;
905 * unsigned long len;
906 *
907 * Copy the string `str' having length `len' into the Scanner's Working
908 * Buffer g_workbuf and return g_workbuf if successful or NULL if
909 * unsuccessful (due to lack of memory).
910 * If g_workbuf is too short to hold `str', it is repeatably doubled until
911 * either it is big enough or memory is exhausted.
912 * We actually copy len+1 characters of `str' into g_workbuf so that the
913 * final \0 gets copied also.
914 * Global Effects: Modifies the contents of g_workbuf
915 * Possibly changes the address of g_workbuf (on realloc)
916 */
917 static char *
918 CopyIntoWorkBuffer(CONST char *str, unsigned long len)
919 {
920 static size_t g_workbuf_len = WORKBUF_INIT_SIZE; /* length of g_workbuf */
921
922 assert(str[len]=='\0'); /* is this true for all yacc? */
923 len++; /* add one to make sure we have a final '\0' */
924 if (( len >= g_workbuf_len ) || ( g_workbuf == NULL )) {
925 while( len >= g_workbuf_len ) {
926 g_workbuf_len *= 2;
927 }
928 if (g_workbuf == NULL ) {
929 g_workbuf = (char*)ascmalloc( g_workbuf_len );
930 } else {
931 g_workbuf = (char*)ascrealloc( (void*)g_workbuf, g_workbuf_len );
932 }
933 if ( g_workbuf == NULL ) {
934 return NULL;
935 }
936 }
937 return strncpy(g_workbuf, str, len); /* does not add a NULL char */
938 }
939
940
941 extern void
942 Asc_DestroyScannerWorkBuffer(void)
943 {
944 if (g_workbuf != NULL) {
945 ascfree(g_workbuf);
946 }
947 g_workbuf = NULL;
948 }
949
950 void Asc_DestroyScannerInputBuffer(void)
951 {
952 if (YY_CURRENT_BUFFER != NULL) {
953 yy_delete_buffer(YY_CURRENT_BUFFER);
954 }
955 }
956
957 /*
958 * int Process_Backslashes(void)
959 *
960 * Covert any backslash \ escapes into the correct character.
961 * Operates on and modifies in place the value of yytext; yyleng
962 * is adjusted accordingly. Returns the number of backslash
963 * substitutions made. The following are supported:
964 * \a (alert)
965 * \b (backspace)
966 * \f (formfeed)
967 * \n (newline)
968 * \r (carriage return)
969 * \t (horizontal tab)
970 * \v (vertical tab)
971 * \xhh (hexadecimal hh) ***** NOT IMPLEMENTED *****
972 * \ooo (octal ooo where o == [0-7]) ***** NOT IMPLEMENTED *****
973 * \\n (backslash before newline removes the backslash and newline)
974 * \. (any other char produces that char)
975 */
976 static int
977 Process_Backslashes(void)
978 {
979 int old_index;
980 int new_index;
981 int substitution_count = 0;
982
983 for (old_index=0, new_index=0; old_index<yyleng; old_index++) {
984 if (yytext[old_index] != '\\') {
985 yytext[new_index++] = yytext[old_index];
986 } else {
987 if (++old_index < yyleng) {
988 switch(yytext[old_index]) {
989 case 'a':
990 yytext[new_index++] = '\a';
991 substitution_count++;
992 break;
993 case 'b':
994 yytext[new_index++] = '\b';
995 substitution_count++;
996 break;
997 case 'f':
998 yytext[new_index++] = '\f';
999 substitution_count++;
1000 break;
1001 case 'n':
1002 yytext[new_index++] = '\n';
1003 substitution_count++;
1004 break;
1005 case 'r':
1006 yytext[new_index++] = '\r';
1007 substitution_count++;
1008 break;
1009 case 't':
1010 yytext[new_index++] = '\t';
1011 substitution_count++;
1012 break;
1013 case 'v':
1014 yytext[new_index++] = '\v';
1015 substitution_count++;
1016 break;
1017 case 'x':
1018 /* need to add processing for
1019 * hexadecimal numbers \xhh here
1020 */
1021 yytext[new_index++] = yytext[old_index];
1022 substitution_count++;
1023 break;
1024 case '0':
1025 case '1':
1026 case '2':
1027 case '3':
1028 case '4':
1029 case '5':
1030 case '6':
1031 case '7':
1032 /* need to add processing for
1033 * octal numbers \ooo here
1034 */
1035 yytext[new_index++] = yytext[old_index];
1036 substitution_count++;
1037 break;
1038 case '\n':
1039 /* Backslash at the end of the line removes
1040 * the slash and the newline from the result,
1041 * so no futher processing is needed.
1042 */
1043 substitution_count++;
1044 break;
1045 default:
1046 yytext[new_index++] = yytext[old_index];
1047 substitution_count++;
1048 break;
1049 }
1050 }
1051 }
1052 }
1053 yytext[new_index] = '\0';
1054 yyleng = new_index;
1055 return substitution_count;
1056 }
1057
1058
1059 /*
1060 * void ErrMsg_*(void)
1061 *
1062 * The following all print error messages to the file handle ASCERR.
1063 * The type of error is indicated by the function's name and the
1064 * arguments to fprintf.
1065 */
1066 static void
1067 ErrMsg_BracesEOF(void)
1068 {
1069 FPRINTF(ASCERR,
1070 "Error:\tEnd of file reached within a unit, data table, or "
1071 "explanation.\n"
1072 "\tNo close brace found for open brace on line %s:%lu\n",
1073 Asc_ModuleBestName(Asc_CurrentModule()), start_line);
1074 }
1075
1076
1077 static void
1078 ErrMsg_CommentEOF(void)
1079 {
1080 FPRINTF(ASCERR,
1081 "Error:\tEnd of file reached within a comment.\n"
1082 "\tNo close-comment found for comment starting on line %s:%lu\n",
1083 Asc_ModuleBestName(Asc_CurrentModule()), start_line);
1084 }
1085
1086
1087 static void
1088 ErrMsg_LongID(void)
1089 {
1090 FPRINTF(ASCERR,
1091 "Error:\tIdentifier too long on line %s:%lu.\n"
1092 "\tIdentifier \"%s\" exceeds the maximum identifier size of %d\n",
1093 Asc_ModuleBestName(Asc_CurrentModule()),
1094 yy_line,
1095 yytext,
1096 YY_MAXLEN);
1097 }
1098
1099
1100 static void
1101 ErrMsg_LongSymbol(void)
1102 {
1103 FPRINTF(ASCERR,
1104 "Error:\tSymbol too long on line %s:%lu.\n"
1105 "\tSymbol %s exceeds the maximum symbol size of %d\n",
1106 Asc_ModuleBestName(Asc_CurrentModule()),
1107 yy_line,
1108 yytext,
1109 YY_MAXLEN);
1110 }
1111
1112
1113 static void
1114 ErrMsg_DoubleQuoteEOF(void)
1115 {
1116 FPRINTF(ASCERR,
1117 "Error:\tEnd of file reached with a double quoted string.\n"
1118 "\tNo close quote found for the open quote on line %s:%lu\n",
1119 Asc_ModuleBestName(Asc_CurrentModule()), start_line);
1120 }
1121
1122
1123 static void
1124 ErrMsg_SymbolEOF(void)
1125 {
1126 FPRINTF(ASCERR,
1127 "Error:\tEnd of file reached within a symbol.\n"
1128 "\tNo close quote found for symbol on line %s:%lu\n",
1129 Asc_ModuleBestName(Asc_CurrentModule()), yy_line);
1130 }
1131
1132
1133 static void
1134 ErrMsg_SymbolEOL(void)
1135 {
1136 FPRINTF(ASCERR,
1137 "Error:\tEnd of line reached within a symbol.\n"
1138 "\tNo close quote found for symbol on line %s:%lu\n",
1139 Asc_ModuleBestName(Asc_CurrentModule()), yy_line);
1140 }
1141
1142
1143 static void
1144 ErrMsg_UnexpectedChar()
1145 {
1146 FPRINTF(ASCERR,
1147 "Error:\tUnexpected character \"%s\" in input on line %s:%lu.\n",
1148 yytext,
1149 Asc_ModuleBestName(Asc_CurrentModule()),
1150 yy_line);
1151 }

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22