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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 690 - (hide annotations) (download)
Thu Jun 22 00:48:31 2006 UTC (14 years, 7 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 johnpye 690 %{
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