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

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