2 * Copyright (c) 1998-2003, Darren Hiebert
4 * This source code is released for free distribution under the terms of the
5 * GNU General Public License version 2 or (at your option) any later version.
7 * This module contains functions for generating tags for Fortran language
14 #include "general.h" /* must always come first */
18 #include <ctype.h> /* to define tolower () */
35 #define isident(c) (isalnum(c) || (c) == '_')
36 #define isBlank(c) (boolean) (c == ' ' || c == '\t')
37 #define isType(token,t) (boolean) ((token)->type == (t))
38 #define isKeyword(token,k) (boolean) ((token)->keyword == (k))
39 #define isSecondaryKeyword(token,k) (boolean) ((token)->secondary == NULL ? \
40 FALSE : (token)->secondary->keyword == (k))
46 typedef enum eException
{
47 ExceptionNone
, ExceptionEOF
, ExceptionFixedFormat
, ExceptionLoop
50 /* Used to designate type of line read in fixed source form.
52 typedef enum eFortranLineType
{
62 /* Used to specify type of keyword.
64 typedef enum eKeywordId
{
146 typedef enum eTokenType
{
164 typedef enum eTagType
{
182 TAG_COUNT
/* must be last */
185 typedef struct sTokenInfo
{
190 struct sTokenInfo
*secondary
;
191 unsigned long lineNumber
;
199 static langType Lang_fortran
;
200 static langType Lang_f77
;
201 static jmp_buf Exception
;
202 static int Ungetc
= '\0';
203 static unsigned int Column
= 0;
204 static boolean FreeSourceForm
= FALSE
;
205 static boolean ParsingString
;
206 static tokenInfo
*Parent
= NULL
;
207 static boolean NewLine
= TRUE
;
208 static unsigned int contextual_fake_count
= 0;
210 /* indexed by tagType */
211 static kindOption FortranKinds
[TAG_COUNT
] = {
212 { TRUE
, 'b', "blockData", "block data"},
213 { TRUE
, 'c', "common", "common blocks"},
214 { TRUE
, 'e', "entry", "entry points"},
215 { TRUE
, 'f', "function", "functions"},
216 { TRUE
, 'i', "interface", "interface contents, generic names, and operators"},
217 { TRUE
, 'k', "component", "type and structure components"},
218 { TRUE
, 'l', "label", "labels"},
219 { FALSE
, 'L', "local", "local, common block, and namelist variables"},
220 { TRUE
, 'm', "module", "modules"},
221 { TRUE
, 'n', "namelist", "namelists"},
222 { TRUE
, 'p', "program", "programs"},
223 { TRUE
, 's', "subroutine", "subroutines"},
224 { TRUE
, 't', "type", "derived types and structures"},
225 { TRUE
, 'v', "variable", "program (global) and module variables"},
226 { TRUE
, 'E', "enum", "enumerations"},
227 { TRUE
, 'N', "enumerator", "enumeration values"},
230 /* For efinitions of Fortran 77 with extensions:
231 * http://www.fortran.com/fortran/F77_std/rjcnf0001.html
232 * http://scienide.uwaterloo.ca/MIPSpro7/007-2362-004/sgi_html/index.html
234 * For the Compaq Fortran Reference Manual:
235 * http://h18009.www1.hp.com/fortran/docs/lrm/dflrm.htm
238 static const keywordTable FortranKeywordTable
[] = {
239 /* keyword keyword ID */
240 { "allocatable", KEYWORD_allocatable
},
241 { "assignment", KEYWORD_assignment
},
242 { "associate", KEYWORD_associate
},
243 { "automatic", KEYWORD_automatic
},
244 { "bind", KEYWORD_bind
},
245 { "block", KEYWORD_block
},
246 { "byte", KEYWORD_byte
},
247 { "cexternal", KEYWORD_cexternal
},
248 { "cglobal", KEYWORD_cglobal
},
249 { "character", KEYWORD_character
},
250 { "codimension", KEYWORD_codimension
},
251 { "common", KEYWORD_common
},
252 { "complex", KEYWORD_complex
},
253 { "contains", KEYWORD_contains
},
254 { "data", KEYWORD_data
},
255 { "dimension", KEYWORD_dimension
},
256 { "dll_export", KEYWORD_dllexport
},
257 { "dll_import", KEYWORD_dllimport
},
258 { "do", KEYWORD_do
},
259 { "double", KEYWORD_double
},
260 { "elemental", KEYWORD_elemental
},
261 { "end", KEYWORD_end
},
262 { "entry", KEYWORD_entry
},
263 { "enum", KEYWORD_enum
},
264 { "enumerator", KEYWORD_enumerator
},
265 { "equivalence", KEYWORD_equivalence
},
266 { "extends", KEYWORD_extends
},
267 { "external", KEYWORD_external
},
268 { "forall", KEYWORD_forall
},
269 { "format", KEYWORD_format
},
270 { "function", KEYWORD_function
},
271 { "if", KEYWORD_if
},
272 { "implicit", KEYWORD_implicit
},
273 { "include", KEYWORD_include
},
274 { "inline", KEYWORD_inline
},
275 { "integer", KEYWORD_integer
},
276 { "intent", KEYWORD_intent
},
277 { "interface", KEYWORD_interface
},
278 { "intrinsic", KEYWORD_intrinsic
},
279 { "kind", KEYWORD_kind
},
280 { "len", KEYWORD_len
},
281 { "logical", KEYWORD_logical
},
282 { "map", KEYWORD_map
},
283 { "module", KEYWORD_module
},
284 { "namelist", KEYWORD_namelist
},
285 { "operator", KEYWORD_operator
},
286 { "optional", KEYWORD_optional
},
287 { "parameter", KEYWORD_parameter
},
288 { "pascal", KEYWORD_pascal
},
289 { "pexternal", KEYWORD_pexternal
},
290 { "pglobal", KEYWORD_pglobal
},
291 { "pointer", KEYWORD_pointer
},
292 { "precision", KEYWORD_precision
},
293 { "private", KEYWORD_private
},
294 { "procedure", KEYWORD_procedure
},
295 { "program", KEYWORD_program
},
296 { "public", KEYWORD_public
},
297 { "pure", KEYWORD_pure
},
298 { "real", KEYWORD_real
},
299 { "record", KEYWORD_record
},
300 { "recursive", KEYWORD_recursive
},
301 { "save", KEYWORD_save
},
302 { "select", KEYWORD_select
},
303 { "sequence", KEYWORD_sequence
},
304 { "static", KEYWORD_static
},
305 { "stdcall", KEYWORD_stdcall
},
306 { "structure", KEYWORD_structure
},
307 { "subroutine", KEYWORD_subroutine
},
308 { "target", KEYWORD_target
},
309 { "then", KEYWORD_then
},
310 { "type", KEYWORD_type
},
311 { "union", KEYWORD_union
},
312 { "use", KEYWORD_use
},
313 { "value", KEYWORD_value
},
314 { "virtual", KEYWORD_virtual
},
315 { "volatile", KEYWORD_volatile
},
316 { "where", KEYWORD_where
},
317 { "while", KEYWORD_while
}
324 } Ancestors
= { 0, 0, NULL
};
327 * FUNCTION PROTOTYPES
329 static void parseStructureStmt (tokenInfo
*const token
);
330 static void parseUnionStmt (tokenInfo
*const token
);
331 static void parseDerivedTypeDef (tokenInfo
*const token
);
332 static void parseFunctionSubprogram (tokenInfo
*const token
);
333 static void parseSubroutineSubprogram (tokenInfo
*const token
);
336 * FUNCTION DEFINITIONS
339 static void ancestorPush (tokenInfo
*const token
)
341 enum { incrementalIncrease
= 10 };
342 if (Ancestors
.list
== NULL
)
344 Assert (Ancestors
.max
== 0);
346 Ancestors
.max
= incrementalIncrease
;
347 Ancestors
.list
= xMalloc (Ancestors
.max
, tokenInfo
);
349 else if (Ancestors
.count
== Ancestors
.max
)
351 Ancestors
.max
+= incrementalIncrease
;
352 Ancestors
.list
= xRealloc (Ancestors
.list
, Ancestors
.max
, tokenInfo
);
354 Ancestors
.list
[Ancestors
.count
] = *token
;
355 Ancestors
.list
[Ancestors
.count
].string
= vStringNewCopy (token
->string
);
359 static void ancestorPop (void)
361 Assert (Ancestors
.count
> 0);
363 vStringDelete (Ancestors
.list
[Ancestors
.count
].string
);
365 Ancestors
.list
[Ancestors
.count
].type
= TOKEN_UNDEFINED
;
366 Ancestors
.list
[Ancestors
.count
].keyword
= KEYWORD_NONE
;
367 Ancestors
.list
[Ancestors
.count
].secondary
= NULL
;
368 Ancestors
.list
[Ancestors
.count
].tag
= TAG_UNDEFINED
;
369 Ancestors
.list
[Ancestors
.count
].string
= NULL
;
370 Ancestors
.list
[Ancestors
.count
].lineNumber
= 0L;
373 static const tokenInfo
* ancestorScope (void)
375 tokenInfo
*result
= NULL
;
377 for (i
= Ancestors
.count
; i
> 0 && result
== NULL
; --i
)
379 tokenInfo
*const token
= Ancestors
.list
+ i
- 1;
380 if (token
->type
== TOKEN_IDENTIFIER
&&
381 token
->tag
!= TAG_UNDEFINED
)
387 static const tokenInfo
* ancestorTop (void)
389 Assert (Ancestors
.count
> 0);
390 return &Ancestors
.list
[Ancestors
.count
- 1];
393 #define ancestorCount() (Ancestors.count)
395 static void ancestorClear (void)
397 while (Ancestors
.count
> 0)
399 if (Ancestors
.list
!= NULL
)
400 eFree (Ancestors
.list
);
401 Ancestors
.list
= NULL
;
406 static boolean
insideInterface (void)
408 boolean result
= FALSE
;
410 for (i
= 0 ; i
< Ancestors
.count
&& !result
; ++i
)
412 if (Ancestors
.list
[i
].tag
== TAG_INTERFACE
)
419 * Tag generation functions
422 static tokenInfo
*newToken (void)
424 tokenInfo
*const token
= xMalloc (1, tokenInfo
);
426 token
->type
= TOKEN_UNDEFINED
;
427 token
->keyword
= KEYWORD_NONE
;
428 token
->tag
= TAG_UNDEFINED
;
429 token
->string
= vStringNew ();
430 token
->secondary
= NULL
;
431 token
->lineNumber
= getInputLineNumber ();
432 token
->filePosition
= getInputFilePosition ();
437 static tokenInfo
*newTokenFrom (tokenInfo
*const token
)
439 tokenInfo
*result
= newToken ();
441 result
->string
= vStringNewCopy (token
->string
);
442 token
->secondary
= NULL
;
446 static tokenInfo
*newAnonTokenFrom (tokenInfo
*const token
, const char *type
)
449 tokenInfo
*result
= newTokenFrom (token
);
450 sprintf (buffer
, "%s#%u", type
, contextual_fake_count
++);
451 vStringClear (result
->string
);
452 vStringCatS (result
->string
, buffer
);
456 static void deleteToken (tokenInfo
*const token
)
460 vStringDelete (token
->string
);
461 deleteToken (token
->secondary
);
462 token
->secondary
= NULL
;
467 static boolean
isFileScope (const tagType type
)
469 return (boolean
) (type
== TAG_LABEL
|| type
== TAG_LOCAL
);
472 static boolean
includeTag (const tagType type
)
475 Assert (type
> TAG_UNDEFINED
&& type
< TAG_COUNT
);
476 include
= FortranKinds
[(int) type
].enabled
;
477 if (include
&& isFileScope (type
))
478 include
= Option
.include
.fileScope
;
482 static void makeFortranTag (tokenInfo
*const token
, tagType tag
)
485 if (includeTag (token
->tag
))
487 const char *const name
= vStringValue (token
->string
);
490 initTagEntry (&e
, name
, &(FortranKinds
[token
->tag
]));
492 if (token
->tag
== TAG_COMMON_BLOCK
)
493 e
.lineNumberEntry
= (boolean
) (Option
.locate
!= EX_PATTERN
);
495 e
.lineNumber
= token
->lineNumber
;
496 e
.filePosition
= token
->filePosition
;
497 e
.isFileScope
= isFileScope (token
->tag
);
498 e
.truncateLine
= (boolean
) (token
->tag
!= TAG_LABEL
);
500 if (ancestorCount () > 0)
502 const tokenInfo
* const scope
= ancestorScope ();
505 e
.extensionFields
.scopeKind
= &(FortranKinds
[scope
->tag
]);
506 e
.extensionFields
.scopeName
= vStringValue (scope
->string
);
509 if (! insideInterface () /*|| includeTag (TAG_INTERFACE)*/)
518 static int skipLine (void)
523 c
= getcFromInputFile ();
524 while (c
!= EOF
&& c
!= '\n');
529 static void makeLabelTag (vString
*const label
)
531 tokenInfo
*token
= newToken ();
532 token
->type
= TOKEN_LABEL
;
533 vStringCopy (token
->string
, label
);
534 makeFortranTag (token
, TAG_LABEL
);
538 static lineType
getLineType (void)
540 vString
*label
= vStringNew ();
542 lineType type
= LTYPE_UNDETERMINED
;
544 do /* read in first 6 "margin" characters */
546 int c
= getcFromInputFile ();
548 /* 3.2.1 Comment_Line. A comment line is any line that contains
549 * a C or an asterisk in column 1, or contains only blank characters
550 * in columns 1 through 72. A comment line that contains a C or
551 * an asterisk in column 1 may contain any character capable of
552 * representation in the processor in columns 2 through 72.
554 /* EXCEPTION! Some compilers permit '!' as a comment character here.
556 * Treat # and $ in column 1 as comment to permit preprocessor directives.
557 * Treat D and d in column 1 as comment for HP debug statements.
559 if (column
== 0 && strchr ("*Cc!#$Dd", c
) != NULL
)
560 type
= LTYPE_COMMENT
;
561 else if (c
== '\t') /* EXCEPTION! Some compilers permit a tab here */
564 type
= LTYPE_INITIAL
;
566 else if (column
== 5)
568 /* 3.2.2 Initial_Line. An initial line is any line that is not
569 * a comment line and contains the character blank or the digit 0
570 * in column 6. Columns 1 through 5 may contain a statement label
571 * (3.4), or each of the columns 1 through 5 must contain the
574 if (c
== ' ' || c
== '0')
575 type
= LTYPE_INITIAL
;
577 /* 3.2.3 Continuation_Line. A continuation line is any line that
578 * contains any character of the FORTRAN character set other than
579 * the character blank or the digit 0 in column 6 and contains
580 * only blank characters in columns 1 through 5.
582 else if (vStringLength (label
) == 0)
583 type
= LTYPE_CONTINUATION
;
585 type
= LTYPE_INVALID
;
593 else if (isdigit (c
))
594 vStringPut (label
, c
);
596 type
= LTYPE_INVALID
;
599 } while (column
< 6 && type
== LTYPE_UNDETERMINED
);
601 Assert (type
!= LTYPE_UNDETERMINED
);
603 if (vStringLength (label
) > 0)
605 vStringTerminate (label
);
606 makeLabelTag (label
);
608 vStringDelete (label
);
612 static int getFixedFormChar (void)
614 boolean newline
= FALSE
;
620 #ifdef STRICT_FIXED_FORM
621 /* EXCEPTION! Some compilers permit more than 72 characters per line.
628 c
= getcFromInputFile ();
633 newline
= TRUE
; /* need to check for continuation line */
636 else if (c
== '!' && ! ParsingString
)
639 newline
= TRUE
; /* need to check for continuation line */
642 else if (c
== '&') /* check for free source form */
644 const int c2
= getcFromInputFile ();
646 longjmp (Exception
, (int) ExceptionFixedFormat
);
648 ungetcToInputFile (c2
);
653 type
= getLineType ();
656 case LTYPE_UNDETERMINED
:
658 longjmp (Exception
, (int) ExceptionFixedFormat
);
661 case LTYPE_SHORT
: break;
662 case LTYPE_COMMENT
: skipLine (); break;
679 /* fall through to next case */
680 case LTYPE_CONTINUATION
:
684 c
= getcFromInputFile ();
686 } while (isBlank (c
));
691 ungetcToInputFile (c
);
697 Assert ("Unexpected line type" == NULL
);
703 static int skipToNextLine (void)
707 c
= getcFromInputFile ();
711 static int getFreeFormChar (boolean inComment
)
713 boolean advanceLine
= FALSE
;
714 int c
= getcFromInputFile ();
716 /* If the last nonblank, non-comment character of a FORTRAN 90
717 * free-format text line is an ampersand then the next non-comment
718 * line is a continuation line.
720 if (! inComment
&& c
== '&')
723 c
= getcFromInputFile ();
724 while (isspace (c
) && c
!= '\n');
734 ungetcToInputFile (c
);
738 else if (NewLine
&& (c
== '!' || c
== '#'))
743 c
= getcFromInputFile ();
744 if (c
== '!' || (NewLine
&& c
== '#'))
746 c
= skipToNextLine ();
751 c
= getcFromInputFile ();
755 NewLine
= (boolean
) (c
== '\n');
759 static int getChar (void)
768 else if (FreeSourceForm
)
769 c
= getFreeFormChar (FALSE
);
771 c
= getFixedFormChar ();
775 static void ungetChar (const int c
)
780 /* If a numeric is passed in 'c', this is used as the first digit of the
781 * numeric being parsed.
783 static vString
*parseInteger (int c
)
785 vString
*string
= vStringNew ();
789 vStringPut (string
, c
);
792 else if (! isdigit (c
))
794 while (c
!= EOF
&& isdigit (c
))
796 vStringPut (string
, c
);
799 vStringTerminate (string
);
805 while (c
!= EOF
&& isalpha (c
));
812 static vString
*parseNumeric (int c
)
814 vString
*string
= vStringNew ();
815 vString
*integer
= parseInteger (c
);
816 vStringCopy (string
, integer
);
817 vStringDelete (integer
);
822 integer
= parseInteger ('\0');
823 vStringPut (string
, c
);
824 vStringCat (string
, integer
);
825 vStringDelete (integer
);
828 if (tolower (c
) == 'e')
830 integer
= parseInteger ('\0');
831 vStringPut (string
, c
);
832 vStringCat (string
, integer
);
833 vStringDelete (integer
);
838 vStringTerminate (string
);
843 static void parseString (vString
*const string
, const int delimiter
)
845 const unsigned long inputLineNumber
= getInputLineNumber ();
847 ParsingString
= TRUE
;
849 while (c
!= delimiter
&& c
!= '\n' && c
!= EOF
)
851 vStringPut (string
, c
);
854 if (c
== '\n' || c
== EOF
)
856 verbose ("%s: unterminated character string at line %lu\n",
857 getInputFileName (), inputLineNumber
);
859 longjmp (Exception
, (int) ExceptionEOF
);
860 else if (! FreeSourceForm
)
861 longjmp (Exception
, (int) ExceptionFixedFormat
);
863 vStringTerminate (string
);
864 ParsingString
= FALSE
;
867 /* Read a C identifier beginning with "firstChar" and places it into "name".
869 static void parseIdentifier (vString
*const string
, const int firstChar
)
875 vStringPut (string
, c
);
877 } while (isident (c
));
879 vStringTerminate (string
);
880 ungetChar (c
); /* unget non-identifier character */
883 static void checkForLabel (void)
885 tokenInfo
* token
= NULL
;
893 for (length
= 0 ; isdigit (c
) && length
< 5 ; ++length
)
898 token
->type
= TOKEN_LABEL
;
900 vStringPut (token
->string
, c
);
903 if (length
> 0 && token
!= NULL
)
905 vStringTerminate (token
->string
);
906 makeFortranTag (token
, TAG_LABEL
);
912 /* Analyzes the identifier contained in a statement described by the
913 * statement structure and adjusts the structure according the significance
916 static keywordId
analyzeToken (vString
*const name
, langType language
)
918 static vString
*keyword
= NULL
;
922 keyword
= vStringNew ();
923 vStringCopyToLower (keyword
, name
);
924 id
= (keywordId
) lookupKeyword (vStringValue (keyword
), language
);
929 static void readIdentifier (tokenInfo
*const token
, const int c
)
931 parseIdentifier (token
->string
, c
);
932 token
->keyword
= analyzeToken (token
->string
, Lang_fortran
);
933 if (! isKeyword (token
, KEYWORD_NONE
))
934 token
->type
= TOKEN_KEYWORD
;
937 token
->type
= TOKEN_IDENTIFIER
;
938 if (strncmp (vStringValue (token
->string
), "end", 3) == 0)
940 vString
*const sub
= vStringNewInit (vStringValue (token
->string
) + 3);
941 const keywordId kw
= analyzeToken (sub
, Lang_fortran
);
943 if (kw
!= KEYWORD_NONE
)
945 token
->secondary
= newToken ();
946 token
->secondary
->type
= TOKEN_KEYWORD
;
947 token
->secondary
->keyword
= kw
;
948 token
->keyword
= KEYWORD_end
;
954 static void readToken (tokenInfo
*const token
)
958 deleteToken (token
->secondary
);
959 token
->type
= TOKEN_UNDEFINED
;
960 token
->tag
= TAG_UNDEFINED
;
961 token
->keyword
= KEYWORD_NONE
;
962 token
->secondary
= NULL
;
963 vStringClear (token
->string
);
968 token
->lineNumber
= getInputLineNumber ();
969 token
->filePosition
= getInputFilePosition ();
973 case EOF
: longjmp (Exception
, (int) ExceptionEOF
); break;
974 case ' ': goto getNextChar
;
975 case '\t': goto getNextChar
;
976 case ',': token
->type
= TOKEN_COMMA
; break;
977 case '(': token
->type
= TOKEN_PAREN_OPEN
; break;
978 case ')': token
->type
= TOKEN_PAREN_CLOSE
; break;
979 case '[': token
->type
= TOKEN_SQUARE_OPEN
; break;
980 case ']': token
->type
= TOKEN_SQUARE_CLOSE
; break;
981 case '%': token
->type
= TOKEN_PERCENT
; break;
991 const char *const operatorChars
= "*/+=<>";
993 vStringPut (token
->string
, c
);
995 } while (strchr (operatorChars
, c
) != NULL
);
997 vStringTerminate (token
->string
);
998 token
->type
= TOKEN_OPERATOR
;
1006 c
= getFreeFormChar (TRUE
);
1007 while (c
!= '\n' && c
!= EOF
);
1014 /* fall through to newline case */
1016 token
->type
= TOKEN_STATEMENT_END
;
1022 parseIdentifier (token
->string
, c
);
1026 vStringPut (token
->string
, c
);
1027 vStringTerminate (token
->string
);
1028 token
->type
= TOKEN_OPERATOR
;
1033 token
->type
= TOKEN_UNDEFINED
;
1039 parseString (token
->string
, c
);
1040 token
->type
= TOKEN_STRING
;
1044 token
->type
= TOKEN_STATEMENT_END
;
1050 token
->type
= TOKEN_DOUBLE_COLON
;
1054 token
->type
= TOKEN_UNDEFINED
;
1060 readIdentifier (token
, c
);
1061 else if (isdigit (c
))
1063 vString
*numeric
= parseNumeric (c
);
1064 vStringCat (token
->string
, numeric
);
1065 vStringDelete (numeric
);
1066 token
->type
= TOKEN_NUMERIC
;
1069 token
->type
= TOKEN_UNDEFINED
;
1074 static void readSubToken (tokenInfo
*const token
)
1076 if (token
->secondary
== NULL
)
1078 token
->secondary
= newToken ();
1079 readToken (token
->secondary
);
1084 * Scanning functions
1087 static void skipToToken (tokenInfo
*const token
, tokenType type
)
1089 while (! isType (token
, type
) && ! isType (token
, TOKEN_STATEMENT_END
) &&
1090 !(token
->secondary
!= NULL
&& isType (token
->secondary
, TOKEN_STATEMENT_END
)))
1094 static void skipPast (tokenInfo
*const token
, tokenType type
)
1096 skipToToken (token
, type
);
1097 if (! isType (token
, TOKEN_STATEMENT_END
))
1101 static void skipToNextStatement (tokenInfo
*const token
)
1105 skipToToken (token
, TOKEN_STATEMENT_END
);
1107 } while (isType (token
, TOKEN_STATEMENT_END
));
1110 /* skip over paired tokens, managing nested pairs and stopping at statement end
1111 * or right after closing token, whatever comes first.
1113 static void skipOverPair (tokenInfo
*const token
, tokenType topen
, tokenType tclose
)
1117 if (isType (token
, TOKEN_STATEMENT_END
))
1119 else if (isType (token
, topen
))
1121 else if (isType (token
, tclose
))
1124 } while (level
> 0);
1127 static void skipOverParens (tokenInfo
*const token
)
1129 skipOverPair (token
, TOKEN_PAREN_OPEN
, TOKEN_PAREN_CLOSE
);
1132 static void skipOverSquares (tokenInfo
*const token
)
1134 skipOverPair (token
, TOKEN_SQUARE_OPEN
, TOKEN_SQUARE_CLOSE
);
1137 static boolean
isTypeSpec (tokenInfo
*const token
)
1140 switch (token
->keyword
)
1143 case KEYWORD_integer
:
1145 case KEYWORD_double
:
1146 case KEYWORD_complex
:
1147 case KEYWORD_character
:
1148 case KEYWORD_logical
:
1149 case KEYWORD_record
:
1151 case KEYWORD_procedure
:
1152 case KEYWORD_enumerator
:
1162 static boolean
isSubprogramPrefix (tokenInfo
*const token
)
1165 switch (token
->keyword
)
1167 case KEYWORD_elemental
:
1169 case KEYWORD_recursive
:
1170 case KEYWORD_stdcall
:
1180 static void parseKindSelector (tokenInfo
*const token
)
1182 if (isType (token
, TOKEN_PAREN_OPEN
))
1183 skipOverParens (token
); /* skip kind-selector */
1184 if (isType (token
, TOKEN_OPERATOR
) &&
1185 strcmp (vStringValue (token
->string
), "*") == 0)
1188 if (isType (token
, TOKEN_PAREN_OPEN
))
1189 skipOverParens (token
);
1196 * is INTEGER [kind-selector]
1197 * or REAL [kind-selector] is ( etc. )
1198 * or DOUBLE PRECISION
1199 * or COMPLEX [kind-selector]
1200 * or CHARACTER [kind-selector]
1201 * or LOGICAL [kind-selector]
1202 * or TYPE ( type-name )
1204 * Note that INTEGER and REAL may be followed by "*N" where "N" is an integer
1206 static void parseTypeSpec (tokenInfo
*const token
)
1208 /* parse type-spec, leaving `token' at first token following type-spec */
1209 Assert (isTypeSpec (token
));
1210 switch (token
->keyword
)
1212 case KEYWORD_character
:
1213 /* skip char-selector */
1215 if (isType (token
, TOKEN_OPERATOR
) &&
1216 strcmp (vStringValue (token
->string
), "*") == 0)
1218 if (isType (token
, TOKEN_PAREN_OPEN
))
1219 skipOverParens (token
);
1220 else if (isType (token
, TOKEN_NUMERIC
))
1226 case KEYWORD_complex
:
1227 case KEYWORD_integer
:
1228 case KEYWORD_logical
:
1230 case KEYWORD_procedure
:
1232 parseKindSelector (token
);
1235 case KEYWORD_double
:
1237 if (isKeyword (token
, KEYWORD_complex
) ||
1238 isKeyword (token
, KEYWORD_precision
))
1241 skipToToken (token
, TOKEN_STATEMENT_END
);
1244 case KEYWORD_record
:
1246 if (isType (token
, TOKEN_OPERATOR
) &&
1247 strcmp (vStringValue (token
->string
), "/") == 0)
1249 readToken (token
); /* skip to structure name */
1250 readToken (token
); /* skip to '/' */
1251 readToken (token
); /* skip to variable name */
1257 if (isType (token
, TOKEN_PAREN_OPEN
))
1258 skipOverParens (token
); /* skip type-name */
1260 parseDerivedTypeDef (token
);
1263 case KEYWORD_enumerator
:
1268 skipToToken (token
, TOKEN_STATEMENT_END
);
1273 static boolean
skipStatementIfKeyword (tokenInfo
*const token
, keywordId keyword
)
1275 boolean result
= FALSE
;
1276 if (isKeyword (token
, keyword
))
1279 skipToNextStatement (token
);
1284 /* parse a list of qualifying specifiers, leaving `token' at first token
1285 * following list. Examples of such specifiers are:
1286 * [[, attr-spec] ::]
1287 * [[, component-attr-spec-list] ::]
1291 * or access-spec (is PUBLIC or PRIVATE)
1293 * or DIMENSION ( array-spec )
1295 * or INTENT ( intent-spec )
1302 * component-attr-spec
1304 * or DIMENSION ( component-array-spec )
1305 * or EXTENDS ( type name )
1307 static void parseQualifierSpecList (tokenInfo
*const token
)
1311 readToken (token
); /* should be an attr-spec */
1312 switch (token
->keyword
)
1314 case KEYWORD_parameter
:
1315 case KEYWORD_allocatable
:
1316 case KEYWORD_external
:
1317 case KEYWORD_intrinsic
:
1320 case KEYWORD_optional
:
1321 case KEYWORD_private
:
1322 case KEYWORD_pointer
:
1323 case KEYWORD_public
:
1325 case KEYWORD_target
:
1329 case KEYWORD_codimension
:
1331 skipOverSquares (token
);
1334 case KEYWORD_dimension
:
1335 case KEYWORD_extends
:
1336 case KEYWORD_intent
:
1338 skipOverParens (token
);
1341 default: skipToToken (token
, TOKEN_STATEMENT_END
); break;
1343 } while (isType (token
, TOKEN_COMMA
));
1344 if (! isType (token
, TOKEN_DOUBLE_COLON
))
1345 skipToToken (token
, TOKEN_STATEMENT_END
);
1348 static tagType
variableTagType (void)
1350 tagType result
= TAG_VARIABLE
;
1351 if (ancestorCount () > 0)
1353 const tokenInfo
* const parent
= ancestorTop ();
1354 switch (parent
->tag
)
1356 case TAG_MODULE
: result
= TAG_VARIABLE
; break;
1357 case TAG_DERIVED_TYPE
: result
= TAG_COMPONENT
; break;
1358 case TAG_FUNCTION
: result
= TAG_LOCAL
; break;
1359 case TAG_SUBROUTINE
: result
= TAG_LOCAL
; break;
1360 case TAG_ENUM
: result
= TAG_ENUMERATOR
; break;
1361 default: result
= TAG_VARIABLE
; break;
1367 static void parseEntityDecl (tokenInfo
*const token
)
1369 Assert (isType (token
, TOKEN_IDENTIFIER
));
1370 makeFortranTag (token
, variableTagType ());
1372 /* we check for both '()' and '[]'
1373 * coarray syntax permits variable(), variable[], or variable()[]
1375 if (isType (token
, TOKEN_PAREN_OPEN
))
1376 skipOverParens (token
);
1377 if (isType (token
, TOKEN_SQUARE_OPEN
))
1378 skipOverSquares (token
);
1379 if (isType (token
, TOKEN_OPERATOR
) &&
1380 strcmp (vStringValue (token
->string
), "*") == 0)
1382 readToken (token
); /* read char-length */
1383 if (isType (token
, TOKEN_PAREN_OPEN
))
1384 skipOverParens (token
);
1388 if (isType (token
, TOKEN_OPERATOR
))
1390 if (strcmp (vStringValue (token
->string
), "/") == 0)
1391 { /* skip over initializations of structure field */
1393 skipPast (token
, TOKEN_OPERATOR
);
1395 else if (strcmp (vStringValue (token
->string
), "=") == 0 ||
1396 strcmp (vStringValue (token
->string
), "=>") == 0)
1398 while (! isType (token
, TOKEN_COMMA
) &&
1399 ! isType (token
, TOKEN_STATEMENT_END
))
1402 /* another coarray check, for () and [] */
1403 if (isType (token
, TOKEN_PAREN_OPEN
))
1404 skipOverParens (token
);
1405 if (isType (token
, TOKEN_SQUARE_OPEN
))
1406 skipOverSquares (token
);
1410 /* token left at either comma or statement end */
1413 static void parseEntityDeclList (tokenInfo
*const token
)
1415 if (isType (token
, TOKEN_PERCENT
))
1416 skipToNextStatement (token
);
1417 else while (isType (token
, TOKEN_IDENTIFIER
) ||
1418 (isType (token
, TOKEN_KEYWORD
) &&
1419 !isKeyword (token
, KEYWORD_function
) &&
1420 !isKeyword (token
, KEYWORD_subroutine
)))
1422 /* compilers accept keywords as identifiers */
1423 if (isType (token
, TOKEN_KEYWORD
))
1424 token
->type
= TOKEN_IDENTIFIER
;
1425 parseEntityDecl (token
);
1426 if (isType (token
, TOKEN_COMMA
))
1428 else if (isType (token
, TOKEN_STATEMENT_END
))
1430 skipToNextStatement (token
);
1436 /* type-declaration-stmt is
1437 * type-spec [[, attr-spec] ... ::] entity-decl-list
1439 static void parseTypeDeclarationStmt (tokenInfo
*const token
)
1441 Assert (isTypeSpec (token
));
1442 parseTypeSpec (token
);
1443 if (!isType (token
, TOKEN_STATEMENT_END
)) /* if not end of derived type... */
1445 if (isType (token
, TOKEN_COMMA
))
1446 parseQualifierSpecList (token
);
1447 if (isType (token
, TOKEN_DOUBLE_COLON
))
1449 parseEntityDeclList (token
);
1451 if (isType (token
, TOKEN_STATEMENT_END
))
1452 skipToNextStatement (token
);
1456 * NAMELIST /namelist-group-name/ namelist-group-object-list
1457 * [[,]/[namelist-group-name]/ namelist-block-object-list] ...
1459 * namelist-group-object is
1463 * COMMON [/[common-block-name]/] common-block-object-list
1464 * [[,]/[common-block-name]/ common-block-object-list] ...
1466 * common-block-object is
1467 * variable-name [ ( explicit-shape-spec-list ) ]
1469 static void parseCommonNamelistStmt (tokenInfo
*const token
, tagType type
)
1471 Assert (isKeyword (token
, KEYWORD_common
) ||
1472 isKeyword (token
, KEYWORD_namelist
));
1476 if (isType (token
, TOKEN_OPERATOR
) &&
1477 strcmp (vStringValue (token
->string
), "/") == 0)
1480 if (isType (token
, TOKEN_IDENTIFIER
))
1482 makeFortranTag (token
, type
);
1485 skipPast (token
, TOKEN_OPERATOR
);
1487 if (isType (token
, TOKEN_IDENTIFIER
))
1488 makeFortranTag (token
, TAG_LOCAL
);
1490 if (isType (token
, TOKEN_PAREN_OPEN
))
1491 skipOverParens (token
); /* skip explicit-shape-spec-list */
1492 if (isType (token
, TOKEN_COMMA
))
1494 } while (! isType (token
, TOKEN_STATEMENT_END
));
1495 skipToNextStatement (token
);
1498 static void parseFieldDefinition (tokenInfo
*const token
)
1500 if (isTypeSpec (token
))
1501 parseTypeDeclarationStmt (token
);
1502 else if (isKeyword (token
, KEYWORD_structure
))
1503 parseStructureStmt (token
);
1504 else if (isKeyword (token
, KEYWORD_union
))
1505 parseUnionStmt (token
);
1507 skipToNextStatement (token
);
1510 static void parseMap (tokenInfo
*const token
)
1512 Assert (isKeyword (token
, KEYWORD_map
));
1513 skipToNextStatement (token
);
1514 while (! isKeyword (token
, KEYWORD_end
))
1515 parseFieldDefinition (token
);
1516 readSubToken (token
);
1517 /* should be at KEYWORD_map token */
1518 skipToNextStatement (token
);
1523 * [field-definition] [field-definition] ...
1526 * [field-definition] [field-definition] ...
1529 * [field-definition]
1530 * [field-definition] ...
1535 * Typed data declarations (variables or arrays) in structure declarations
1536 * have the form of normal Fortran typed data declarations. Data items with
1537 * different types can be freely intermixed within a structure declaration.
1539 * Unnamed fields can be declared in a structure by specifying the pseudo
1540 * name %FILL in place of an actual field name. You can use this mechanism to
1541 * generate empty space in a record for purposes such as alignment.
1543 * All mapped field declarations that are made within a UNION declaration
1544 * share a common location within the containing structure. When initializing
1545 * the fields within a UNION, the final initialization value assigned
1546 * overlays any value previously assigned to a field definition that shares
1549 static void parseUnionStmt (tokenInfo
*const token
)
1551 Assert (isKeyword (token
, KEYWORD_union
));
1552 skipToNextStatement (token
);
1553 while (isKeyword (token
, KEYWORD_map
))
1555 /* should be at KEYWORD_end token */
1556 readSubToken (token
);
1557 /* secondary token should be KEYWORD_end token */
1558 skipToNextStatement (token
);
1561 /* STRUCTURE [/structure-name/] [field-names]
1562 * [field-definition]
1563 * [field-definition] ...
1567 * identifies the structure in a subsequent RECORD statement.
1568 * Substructures can be established within a structure by means of either
1569 * a nested STRUCTURE declaration or a RECORD statement.
1572 * (for substructure declarations only) one or more names having the
1573 * structure of the substructure being defined.
1576 * can be one or more of the following:
1578 * Typed data declarations, which can optionally include one or more
1579 * data initialization values.
1581 * Substructure declarations (defined by either RECORD statements or
1582 * subsequent STRUCTURE statements).
1584 * UNION declarations, which are mapped fields defined by a block of
1585 * statements. The syntax of a UNION declaration is described below.
1587 * PARAMETER statements, which do not affect the form of the
1590 static void parseStructureStmt (tokenInfo
*const token
)
1592 tokenInfo
*name
= NULL
;
1593 Assert (isKeyword (token
, KEYWORD_structure
));
1595 if (isType (token
, TOKEN_OPERATOR
) &&
1596 strcmp (vStringValue (token
->string
), "/") == 0)
1597 { /* read structure name */
1599 if (isType (token
, TOKEN_IDENTIFIER
) || isType (token
, TOKEN_KEYWORD
))
1601 name
= newTokenFrom (token
);
1602 name
->type
= TOKEN_IDENTIFIER
;
1604 skipPast (token
, TOKEN_OPERATOR
);
1607 { /* fake out anonymous structure */
1608 name
= newAnonTokenFrom (token
, "Structure");
1609 name
->type
= TOKEN_IDENTIFIER
;
1610 name
->tag
= TAG_DERIVED_TYPE
;
1612 makeFortranTag (name
, TAG_DERIVED_TYPE
);
1613 while (isType (token
, TOKEN_IDENTIFIER
))
1614 { /* read field names */
1615 makeFortranTag (token
, TAG_COMPONENT
);
1617 if (isType (token
, TOKEN_COMMA
))
1620 skipToNextStatement (token
);
1621 ancestorPush (name
);
1622 while (! isKeyword (token
, KEYWORD_end
))
1623 parseFieldDefinition (token
);
1624 readSubToken (token
);
1625 /* secondary token should be KEYWORD_structure token */
1626 skipToNextStatement (token
);
1631 /* specification-stmt
1632 * is access-stmt (is access-spec [[::] access-id-list)
1633 * or allocatable-stmt (is ALLOCATABLE [::] array-name etc.)
1634 * or common-stmt (is COMMON [ / [common-block-name] /] etc.)
1635 * or data-stmt (is DATA data-stmt-list [[,] data-stmt-set] ...)
1636 * or dimension-stmt (is DIMENSION [::] array-name etc.)
1637 * or equivalence-stmt (is EQUIVALENCE equivalence-set-list)
1638 * or external-stmt (is EXTERNAL etc.)
1639 * or intent-stmt (is INTENT ( intent-spec ) [::] etc.)
1640 * or intrinsic-stmt (is INTRINSIC etc.)
1641 * or namelist-stmt (is NAMELIST / namelist-group-name / etc.)
1642 * or optional-stmt (is OPTIONAL [::] etc.)
1643 * or pointer-stmt (is POINTER [::] object-name etc.)
1644 * or save-stmt (is SAVE etc.)
1645 * or target-stmt (is TARGET [::] object-name etc.)
1647 * access-spec is PUBLIC or PRIVATE
1649 static boolean
parseSpecificationStmt (tokenInfo
*const token
)
1651 boolean result
= TRUE
;
1652 switch (token
->keyword
)
1654 case KEYWORD_common
:
1655 parseCommonNamelistStmt (token
, TAG_COMMON_BLOCK
);
1658 case KEYWORD_namelist
:
1659 parseCommonNamelistStmt (token
, TAG_NAMELIST
);
1662 case KEYWORD_structure
:
1663 parseStructureStmt (token
);
1666 case KEYWORD_allocatable
:
1668 case KEYWORD_dimension
:
1669 case KEYWORD_equivalence
:
1670 case KEYWORD_extends
:
1671 case KEYWORD_external
:
1672 case KEYWORD_intent
:
1673 case KEYWORD_intrinsic
:
1674 case KEYWORD_optional
:
1675 case KEYWORD_pointer
:
1676 case KEYWORD_private
:
1677 case KEYWORD_public
:
1679 case KEYWORD_target
:
1680 skipToNextStatement (token
);
1690 /* component-def-stmt is
1691 * type-spec [[, component-attr-spec-list] ::] component-decl-list
1694 * component-name [ ( component-array-spec ) ] [ * char-length ]
1696 static void parseComponentDefStmt (tokenInfo
*const token
)
1698 Assert (isTypeSpec (token
));
1699 parseTypeSpec (token
);
1700 if (isType (token
, TOKEN_COMMA
))
1701 parseQualifierSpecList (token
);
1702 if (isType (token
, TOKEN_DOUBLE_COLON
))
1704 parseEntityDeclList (token
);
1707 /* derived-type-def is
1708 * derived-type-stmt is (TYPE [[, access-spec] ::] type-name
1709 * [private-sequence-stmt] ... (is PRIVATE or SEQUENCE)
1710 * component-def-stmt
1711 * [component-def-stmt] ...
1714 static void parseDerivedTypeDef (tokenInfo
*const token
)
1716 if (isType (token
, TOKEN_COMMA
))
1717 parseQualifierSpecList (token
);
1718 if (isType (token
, TOKEN_DOUBLE_COLON
))
1720 if (isType (token
, TOKEN_IDENTIFIER
) || isType (token
, TOKEN_KEYWORD
))
1722 token
->type
= TOKEN_IDENTIFIER
;
1723 makeFortranTag (token
, TAG_DERIVED_TYPE
);
1725 ancestorPush (token
);
1726 skipToNextStatement (token
);
1727 if (isKeyword (token
, KEYWORD_private
) ||
1728 isKeyword (token
, KEYWORD_sequence
))
1730 skipToNextStatement (token
);
1732 while (! isKeyword (token
, KEYWORD_end
))
1734 if (isTypeSpec (token
))
1735 parseComponentDefStmt (token
);
1737 skipToNextStatement (token
);
1739 readSubToken (token
);
1740 /* secondary token should be KEYWORD_type token */
1741 skipToToken (token
, TOKEN_STATEMENT_END
);
1746 * interface-stmt (is INTERFACE [generic-spec])
1748 * [module-procedure-stmt] ...
1749 * end-interface-stmt (is END INTERFACE)
1753 * or OPERATOR ( defined-operator )
1754 * or ASSIGNMENT ( = )
1758 * [specification-part]
1760 * or subroutine-stmt
1761 * [specification-part]
1762 * end-subroutine-stmt
1764 * module-procedure-stmt is
1765 * MODULE PROCEDURE procedure-name-list
1767 static void parseInterfaceBlock (tokenInfo
*const token
)
1769 tokenInfo
*name
= NULL
;
1770 Assert (isKeyword (token
, KEYWORD_interface
));
1772 if (isKeyword (token
, KEYWORD_assignment
) ||
1773 isKeyword (token
, KEYWORD_operator
))
1776 if (isType (token
, TOKEN_PAREN_OPEN
))
1778 if (isType (token
, TOKEN_OPERATOR
))
1779 name
= newTokenFrom (token
);
1781 else if (isType (token
, TOKEN_IDENTIFIER
) || isType (token
, TOKEN_KEYWORD
))
1783 name
= newTokenFrom (token
);
1784 name
->type
= TOKEN_IDENTIFIER
;
1788 name
= newAnonTokenFrom (token
, "Interface");
1789 name
->type
= TOKEN_IDENTIFIER
;
1790 name
->tag
= TAG_INTERFACE
;
1792 makeFortranTag (name
, TAG_INTERFACE
);
1793 ancestorPush (name
);
1794 while (! isKeyword (token
, KEYWORD_end
))
1796 switch (token
->keyword
)
1798 case KEYWORD_function
: parseFunctionSubprogram (token
); break;
1799 case KEYWORD_subroutine
: parseSubroutineSubprogram (token
); break;
1802 if (isSubprogramPrefix (token
))
1804 else if (isTypeSpec (token
))
1805 parseTypeSpec (token
);
1807 skipToNextStatement (token
);
1811 readSubToken (token
);
1812 /* secondary token should be KEYWORD_interface token */
1813 skipToNextStatement (token
);
1819 * enum-stmt (is ENUM, BIND(C) [ :: type-alias-name ]
1820 * or ENUM [ kind-selector ] [ :: ] [ type-alias-name ])
1821 * [ enum-body (is ENUMERATOR [ :: ] enumerator-list) ]
1822 * end-enum-stmt (is END ENUM)
1824 static void parseEnumBlock (tokenInfo
*const token
)
1826 tokenInfo
*name
= NULL
;
1827 Assert (isKeyword (token
, KEYWORD_enum
));
1829 if (isType (token
, TOKEN_COMMA
))
1832 if (isType (token
, TOKEN_KEYWORD
))
1834 if (isType (token
, TOKEN_PAREN_OPEN
))
1835 skipOverParens (token
);
1837 parseKindSelector (token
);
1838 if (isType (token
, TOKEN_DOUBLE_COLON
))
1840 if (isType (token
, TOKEN_IDENTIFIER
) || isType (token
, TOKEN_KEYWORD
))
1842 name
= newTokenFrom (token
);
1843 name
->type
= TOKEN_IDENTIFIER
;
1847 name
= newAnonTokenFrom (token
, "Enum");
1848 name
->type
= TOKEN_IDENTIFIER
;
1849 name
->tag
= TAG_ENUM
;
1851 makeFortranTag (name
, TAG_ENUM
);
1852 skipToNextStatement (token
);
1853 ancestorPush (name
);
1854 while (! isKeyword (token
, KEYWORD_end
))
1856 if (isTypeSpec (token
))
1857 parseTypeDeclarationStmt (token
);
1859 skipToNextStatement (token
);
1861 readSubToken (token
);
1862 /* secondary token should be KEYWORD_enum token */
1863 skipToNextStatement (token
);
1869 * ENTRY entry-name [ ( dummy-arg-list ) ]
1871 static void parseEntryStmt (tokenInfo
*const token
)
1873 Assert (isKeyword (token
, KEYWORD_entry
));
1875 if (isType (token
, TOKEN_IDENTIFIER
))
1876 makeFortranTag (token
, TAG_ENTRY_POINT
);
1877 skipToNextStatement (token
);
1880 /* stmt-function-stmt is
1881 * function-name ([dummy-arg-name-list]) = scalar-expr
1883 static boolean
parseStmtFunctionStmt (tokenInfo
*const token
)
1885 boolean result
= FALSE
;
1886 Assert (isType (token
, TOKEN_IDENTIFIER
));
1887 #if 0 /* cannot reliably parse this yet */
1888 makeFortranTag (token
, TAG_FUNCTION
);
1891 if (isType (token
, TOKEN_PAREN_OPEN
))
1893 skipOverParens (token
);
1894 result
= (boolean
) (isType (token
, TOKEN_OPERATOR
) &&
1895 strcmp (vStringValue (token
->string
), "=") == 0);
1897 skipToNextStatement (token
);
1901 static boolean
isIgnoredDeclaration (tokenInfo
*const token
)
1904 switch (token
->keyword
)
1906 case KEYWORD_cexternal
:
1907 case KEYWORD_cglobal
:
1908 case KEYWORD_dllexport
:
1909 case KEYWORD_dllimport
:
1910 case KEYWORD_external
:
1911 case KEYWORD_format
:
1912 case KEYWORD_include
:
1913 case KEYWORD_inline
:
1914 case KEYWORD_parameter
:
1915 case KEYWORD_pascal
:
1916 case KEYWORD_pexternal
:
1917 case KEYWORD_pglobal
:
1918 case KEYWORD_static
:
1920 case KEYWORD_virtual
:
1921 case KEYWORD_volatile
:
1932 /* declaration-construct
1933 * [derived-type-def]
1935 * [type-declaration-stmt]
1936 * [specification-stmt]
1937 * [parameter-stmt] (is PARAMETER ( named-constant-def-list )
1938 * [format-stmt] (is FORMAT format-specification)
1940 * [stmt-function-stmt]
1942 static boolean
parseDeclarationConstruct (tokenInfo
*const token
)
1944 boolean result
= TRUE
;
1945 switch (token
->keyword
)
1947 case KEYWORD_entry
: parseEntryStmt (token
); break;
1948 case KEYWORD_interface
: parseInterfaceBlock (token
); break;
1949 case KEYWORD_enum
: parseEnumBlock (token
); break;
1950 case KEYWORD_stdcall
: readToken (token
); break;
1951 /* derived type handled by parseTypeDeclarationStmt(); */
1953 case KEYWORD_automatic
:
1955 if (isTypeSpec (token
))
1956 parseTypeDeclarationStmt (token
);
1958 skipToNextStatement (token
);
1963 if (isIgnoredDeclaration (token
))
1964 skipToNextStatement (token
);
1965 else if (isTypeSpec (token
))
1967 parseTypeDeclarationStmt (token
);
1970 else if (isType (token
, TOKEN_IDENTIFIER
))
1971 result
= parseStmtFunctionStmt (token
);
1973 result
= parseSpecificationStmt (token
);
1979 /* implicit-part-stmt
1980 * is [implicit-stmt] (is IMPLICIT etc.)
1981 * or [parameter-stmt] (is PARAMETER etc.)
1982 * or [format-stmt] (is FORMAT etc.)
1983 * or [entry-stmt] (is ENTRY entry-name etc.)
1985 static boolean
parseImplicitPartStmt (tokenInfo
*const token
)
1987 boolean result
= TRUE
;
1988 switch (token
->keyword
)
1990 case KEYWORD_entry
: parseEntryStmt (token
); break;
1992 case KEYWORD_implicit
:
1993 case KEYWORD_include
:
1994 case KEYWORD_parameter
:
1995 case KEYWORD_format
:
1996 skipToNextStatement (token
);
1999 default: result
= FALSE
; break;
2004 /* specification-part is
2005 * [use-stmt] ... (is USE module-name etc.)
2006 * [implicit-part] (is [implicit-part-stmt] ... [implicit-stmt])
2007 * [declaration-construct] ...
2009 static boolean
parseSpecificationPart (tokenInfo
*const token
)
2011 boolean result
= FALSE
;
2012 while (skipStatementIfKeyword (token
, KEYWORD_use
))
2014 while (parseImplicitPartStmt (token
))
2016 while (parseDeclarationConstruct (token
))
2022 * block-data-stmt (is BLOCK DATA [block-data-name]
2023 * [specification-part]
2024 * end-block-data-stmt (is END [BLOCK DATA [block-data-name]])
2026 static void parseBlockData (tokenInfo
*const token
)
2028 Assert (isKeyword (token
, KEYWORD_block
));
2030 if (isKeyword (token
, KEYWORD_data
))
2033 if (isType (token
, TOKEN_IDENTIFIER
))
2034 makeFortranTag (token
, TAG_BLOCK_DATA
);
2036 ancestorPush (token
);
2037 skipToNextStatement (token
);
2038 parseSpecificationPart (token
);
2039 while (! isKeyword (token
, KEYWORD_end
))
2040 skipToNextStatement (token
);
2041 readSubToken (token
);
2042 /* secondary token should be KEYWORD_NONE or KEYWORD_block token */
2043 skipToNextStatement (token
);
2047 /* internal-subprogram-part is
2048 * contains-stmt (is CONTAINS)
2049 * internal-subprogram
2050 * [internal-subprogram] ...
2052 * internal-subprogram
2053 * is function-subprogram
2054 * or subroutine-subprogram
2056 static void parseInternalSubprogramPart (tokenInfo
*const token
)
2058 boolean done
= FALSE
;
2059 if (isKeyword (token
, KEYWORD_contains
))
2060 skipToNextStatement (token
);
2063 switch (token
->keyword
)
2065 case KEYWORD_function
: parseFunctionSubprogram (token
); break;
2066 case KEYWORD_subroutine
: parseSubroutineSubprogram (token
); break;
2067 case KEYWORD_end
: done
= TRUE
; break;
2070 if (isSubprogramPrefix (token
))
2072 else if (isTypeSpec (token
))
2073 parseTypeSpec (token
);
2082 * module-stmt (is MODULE module-name)
2083 * [specification-part]
2084 * [module-subprogram-part]
2085 * end-module-stmt (is END [MODULE [module-name]])
2087 * module-subprogram-part
2088 * contains-stmt (is CONTAINS)
2090 * [module-subprogram] ...
2093 * is function-subprogram
2094 * or subroutine-subprogram
2096 static void parseModule (tokenInfo
*const token
)
2098 Assert (isKeyword (token
, KEYWORD_module
));
2100 if (isType (token
, TOKEN_IDENTIFIER
) || isType (token
, TOKEN_KEYWORD
))
2102 token
->type
= TOKEN_IDENTIFIER
;
2103 makeFortranTag (token
, TAG_MODULE
);
2105 ancestorPush (token
);
2106 skipToNextStatement (token
);
2107 parseSpecificationPart (token
);
2108 if (isKeyword (token
, KEYWORD_contains
))
2109 parseInternalSubprogramPart (token
);
2110 while (! isKeyword (token
, KEYWORD_end
))
2111 skipToNextStatement (token
);
2112 readSubToken (token
);
2113 /* secondary token should be KEYWORD_NONE or KEYWORD_module token */
2114 skipToNextStatement (token
);
2119 * executable-construct
2121 * executable-construct is
2122 * execution-part-construct [execution-part-construct]
2124 * execution-part-construct
2125 * is executable-construct
2130 static boolean
parseExecutionPart (tokenInfo
*const token
)
2132 boolean result
= FALSE
;
2133 boolean done
= FALSE
;
2136 switch (token
->keyword
)
2139 if (isSubprogramPrefix (token
))
2142 skipToNextStatement (token
);
2147 parseEntryStmt (token
);
2151 case KEYWORD_contains
:
2152 case KEYWORD_function
:
2153 case KEYWORD_subroutine
:
2158 readSubToken (token
);
2159 if (isSecondaryKeyword (token
, KEYWORD_do
) ||
2160 isSecondaryKeyword (token
, KEYWORD_enum
) ||
2161 isSecondaryKeyword (token
, KEYWORD_if
) ||
2162 isSecondaryKeyword (token
, KEYWORD_select
) ||
2163 isSecondaryKeyword (token
, KEYWORD_where
) ||
2164 isSecondaryKeyword (token
, KEYWORD_forall
) ||
2165 isSecondaryKeyword (token
, KEYWORD_associate
))
2167 skipToNextStatement (token
);
2178 static void parseSubprogram (tokenInfo
*const token
, const tagType tag
)
2180 Assert (isKeyword (token
, KEYWORD_program
) ||
2181 isKeyword (token
, KEYWORD_function
) ||
2182 isKeyword (token
, KEYWORD_subroutine
));
2184 if (isType (token
, TOKEN_IDENTIFIER
) || isType (token
, TOKEN_KEYWORD
))
2186 token
->type
= TOKEN_IDENTIFIER
;
2187 makeFortranTag (token
, tag
);
2189 ancestorPush (token
);
2190 skipToNextStatement (token
);
2191 parseSpecificationPart (token
);
2192 parseExecutionPart (token
);
2193 if (isKeyword (token
, KEYWORD_contains
))
2194 parseInternalSubprogramPart (token
);
2195 /* should be at KEYWORD_end token */
2196 readSubToken (token
);
2197 /* secondary token should be one of KEYWORD_NONE, KEYWORD_program,
2198 * KEYWORD_function, KEYWORD_function
2200 skipToNextStatement (token
);
2205 /* function-subprogram is
2206 * function-stmt (is [prefix] FUNCTION function-name etc.)
2207 * [specification-part]
2209 * [internal-subprogram-part]
2210 * end-function-stmt (is END [FUNCTION [function-name]])
2213 * is type-spec [RECURSIVE]
2214 * or [RECURSIVE] type-spec
2216 static void parseFunctionSubprogram (tokenInfo
*const token
)
2218 parseSubprogram (token
, TAG_FUNCTION
);
2221 /* subroutine-subprogram is
2222 * subroutine-stmt (is [RECURSIVE] SUBROUTINE subroutine-name etc.)
2223 * [specification-part]
2225 * [internal-subprogram-part]
2226 * end-subroutine-stmt (is END [SUBROUTINE [function-name]])
2228 static void parseSubroutineSubprogram (tokenInfo
*const token
)
2230 parseSubprogram (token
, TAG_SUBROUTINE
);
2234 * [program-stmt] (is PROGRAM program-name)
2235 * [specification-part]
2237 * [internal-subprogram-part ]
2240 static void parseMainProgram (tokenInfo
*const token
)
2242 parseSubprogram (token
, TAG_PROGRAM
);
2247 * or external-subprogram (is function-subprogram or subroutine-subprogram)
2251 static void parseProgramUnit (tokenInfo
*const token
)
2256 if (isType (token
, TOKEN_STATEMENT_END
))
2258 else switch (token
->keyword
)
2260 case KEYWORD_block
: parseBlockData (token
); break;
2261 case KEYWORD_end
: skipToNextStatement (token
); break;
2262 case KEYWORD_function
: parseFunctionSubprogram (token
); break;
2263 case KEYWORD_module
: parseModule (token
); break;
2264 case KEYWORD_program
: parseMainProgram (token
); break;
2265 case KEYWORD_subroutine
: parseSubroutineSubprogram (token
); break;
2268 if (isSubprogramPrefix (token
))
2272 boolean one
= parseSpecificationPart (token
);
2273 boolean two
= parseExecutionPart (token
);
2282 static boolean
findFortranTags (const unsigned int passCount
)
2285 exception_t exception
;
2288 Assert (passCount
< 3);
2289 Parent
= newToken ();
2290 token
= newToken ();
2291 FreeSourceForm
= (boolean
) (passCount
> 1);
2292 contextual_fake_count
= 0;
2295 exception
= (exception_t
) setjmp (Exception
);
2296 if (exception
== ExceptionEOF
)
2298 else if (exception
== ExceptionFixedFormat
&& ! FreeSourceForm
)
2300 verbose ("%s: not fixed source form; retry as free source form\n",
2301 getInputFileName ());
2306 parseProgramUnit (token
);
2310 deleteToken (token
);
2311 deleteToken (Parent
);
2316 static void initializeFortran (const langType language
)
2318 Lang_fortran
= language
;
2321 static void initializeF77 (const langType language
)
2323 Lang_f77
= language
;
2326 extern parserDefinition
* FortranParser (void)
2328 static const char *const extensions
[] = {
2329 "f90", "f95", "f03",
2330 #ifndef CASE_INSENSITIVE_FILENAMES
2331 "F90", "F95", "F03",
2335 parserDefinition
* def
= parserNew ("Fortran");
2336 def
->kinds
= FortranKinds
;
2337 def
->kindCount
= ARRAY_SIZE (FortranKinds
);
2338 def
->extensions
= extensions
;
2339 def
->parser2
= findFortranTags
;
2340 def
->initialize
= initializeFortran
;
2341 def
->keywordTable
= FortranKeywordTable
;
2342 def
->keywordCount
= ARRAY_SIZE (FortranKeywordTable
);
2346 extern parserDefinition
* F77Parser (void)
2348 static const char *const extensions
[] = {
2349 "f", "for", "ftn", "f77",
2350 #ifndef CASE_INSENSITIVE_FILENAMES
2351 "F", "FOR", "FTN", "F77",
2355 parserDefinition
* def
= parserNew ("F77");
2356 def
->kinds
= FortranKinds
;
2357 def
->kindCount
= ARRAY_SIZE (FortranKinds
);
2358 def
->extensions
= extensions
;
2359 def
->parser2
= findFortranTags
;
2360 def
->initialize
= initializeF77
;
2361 def
->keywordTable
= FortranKeywordTable
;
2362 def
->keywordCount
= ARRAY_SIZE (FortranKeywordTable
);
2365 /* vi:set tabstop=4 shiftwidth=4: */