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.
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 () */
33 #define isident(c) (isalnum(c) || (c) == '_')
34 #define isBlank(c) (boolean) (c == ' ' || c == '\t')
35 #define isType(token,t) (boolean) ((token)->type == (t))
36 #define isKeyword(token,k) (boolean) ((token)->keyword == (k))
37 #define isSecondaryKeyword(token,k) (boolean) ((token)->secondary == NULL ? \
38 FALSE : (token)->secondary->keyword == (k))
44 typedef enum eException
{
45 ExceptionNone
, ExceptionEOF
, ExceptionFixedFormat
, ExceptionLoop
48 /* Used to designate type of line read in fixed source form.
50 typedef enum eFortranLineType
{
60 /* Used to specify type of keyword.
62 typedef enum eKeywordId
{
135 /* Used to determine whether keyword is valid for the token language and
138 typedef struct sKeywordDesc
{
143 typedef enum eTokenType
{
159 typedef enum eTagType
{
175 TAG_COUNT
/* must be last */
178 typedef struct sTokenInfo
{
183 struct sTokenInfo
*secondary
;
184 unsigned long lineNumber
;
192 static langType Lang_fortran
;
193 static langType Lang_f77
;
194 static jmp_buf Exception
;
195 static int Ungetc
= '\0';
196 static unsigned int Column
= 0;
197 static boolean FreeSourceForm
= FALSE
;
198 static boolean ParsingString
;
199 static tokenInfo
*Parent
= NULL
;
201 /* indexed by tagType */
202 static kindOption FortranKinds
[] = {
203 { TRUE
, 'b', "block data", "block data"},
204 { TRUE
, 'c', "macro", "common blocks"},
205 { TRUE
, 'e', "entry", "entry points"},
206 { TRUE
, 'f', "function", "functions"},
207 { FALSE
, 'i', "struct", "interface contents, generic names, and operators"},
208 { TRUE
, 'k', "component", "type and structure components"},
209 { TRUE
, 'l', "label", "labels"},
210 { FALSE
, 'L', "local", "local, common block, and namelist variables"},
211 { TRUE
, 'm', "namespace", "modules"},
212 { TRUE
, 'n', "namelist", "namelists"},
213 { TRUE
, 'p', "package", "programs"},
214 { TRUE
, 's', "member", "subroutines"},
215 { TRUE
, 't', "typedef", "derived types and structures"},
216 { TRUE
, 'v', "variable", "program (global) and module variables"}
219 /* For efinitions of Fortran 77 with extensions:
220 * http://www.fortran.com/fortran/F77_std/rjcnf0001.html
221 * http://scienide.uwaterloo.ca/MIPSpro7/007-2362-004/sgi_html/index.html
223 * For the Compaq Fortran Reference Manual:
224 * http://h18009.www1.hp.com/fortran/docs/lrm/dflrm.htm
227 static const keywordDesc FortranKeywordTable
[] = {
228 /* keyword keyword ID */
229 { "allocatable", KEYWORD_allocatable
},
230 { "assignment", KEYWORD_assignment
},
231 { "automatic", KEYWORD_automatic
},
232 { "block", KEYWORD_block
},
233 { "byte", KEYWORD_byte
},
234 { "cexternal", KEYWORD_cexternal
},
235 { "cglobal", KEYWORD_cglobal
},
236 { "character", KEYWORD_character
},
237 { "common", KEYWORD_common
},
238 { "complex", KEYWORD_complex
},
239 { "contains", KEYWORD_contains
},
240 { "data", KEYWORD_data
},
241 { "dimension", KEYWORD_dimension
},
242 { "dll_export", KEYWORD_dllexport
},
243 { "dll_import", KEYWORD_dllimport
},
244 { "do", KEYWORD_do
},
245 { "double", KEYWORD_double
},
246 { "elemental", KEYWORD_elemental
},
247 { "end", KEYWORD_end
},
248 { "entry", KEYWORD_entry
},
249 { "equivalence", KEYWORD_equivalence
},
250 { "extends", KEYWORD_extends
},
251 { "external", KEYWORD_external
},
252 { "format", KEYWORD_format
},
253 { "function", KEYWORD_function
},
254 { "if", KEYWORD_if
},
255 { "implicit", KEYWORD_implicit
},
256 { "include", KEYWORD_include
},
257 { "inline", KEYWORD_inline
},
258 { "integer", KEYWORD_integer
},
259 { "intent", KEYWORD_intent
},
260 { "interface", KEYWORD_interface
},
261 { "intrinsic", KEYWORD_intrinsic
},
262 { "logical", KEYWORD_logical
},
263 { "map", KEYWORD_map
},
264 { "module", KEYWORD_module
},
265 { "namelist", KEYWORD_namelist
},
266 { "operator", KEYWORD_operator
},
267 { "optional", KEYWORD_optional
},
268 { "parameter", KEYWORD_parameter
},
269 { "pascal", KEYWORD_pascal
},
270 { "pexternal", KEYWORD_pexternal
},
271 { "pglobal", KEYWORD_pglobal
},
272 { "pointer", KEYWORD_pointer
},
273 { "precision", KEYWORD_precision
},
274 { "private", KEYWORD_private
},
275 { "program", KEYWORD_program
},
276 { "public", KEYWORD_public
},
277 { "pure", KEYWORD_pure
},
278 { "real", KEYWORD_real
},
279 { "record", KEYWORD_record
},
280 { "recursive", KEYWORD_recursive
},
281 { "save", KEYWORD_save
},
282 { "select", KEYWORD_select
},
283 { "sequence", KEYWORD_sequence
},
284 { "static", KEYWORD_static
},
285 { "stdcall", KEYWORD_stdcall
},
286 { "structure", KEYWORD_structure
},
287 { "subroutine", KEYWORD_subroutine
},
288 { "target", KEYWORD_target
},
289 { "then", KEYWORD_then
},
290 { "type", KEYWORD_type
},
291 { "union", KEYWORD_union
},
292 { "use", KEYWORD_use
},
293 { "value", KEYWORD_value
},
294 { "virtual", KEYWORD_virtual
},
295 { "volatile", KEYWORD_volatile
},
296 { "where", KEYWORD_where
},
297 { "while", KEYWORD_while
}
304 } Ancestors
= { 0, 0, NULL
};
307 * FUNCTION PROTOTYPES
309 static void parseStructureStmt (tokenInfo
*const token
);
310 static void parseUnionStmt (tokenInfo
*const token
);
311 static void parseDerivedTypeDef (tokenInfo
*const token
);
312 static void parseFunctionSubprogram (tokenInfo
*const token
);
313 static void parseSubroutineSubprogram (tokenInfo
*const token
);
316 * FUNCTION DEFINITIONS
319 static void ancestorPush (tokenInfo
*const token
)
321 enum { incrementalIncrease
= 10 };
322 if (Ancestors
.list
== NULL
)
324 Assert (Ancestors
.max
== 0);
326 Ancestors
.max
= incrementalIncrease
;
327 Ancestors
.list
= xMalloc (Ancestors
.max
, tokenInfo
);
329 else if (Ancestors
.count
== Ancestors
.max
)
331 Ancestors
.max
+= incrementalIncrease
;
332 Ancestors
.list
= xRealloc (Ancestors
.list
, Ancestors
.max
, tokenInfo
);
334 Ancestors
.list
[Ancestors
.count
] = *token
;
335 Ancestors
.list
[Ancestors
.count
].string
= vStringNewCopy (token
->string
);
339 static void ancestorPop (void)
341 Assert (Ancestors
.count
> 0);
343 vStringDelete (Ancestors
.list
[Ancestors
.count
].string
);
345 Ancestors
.list
[Ancestors
.count
].type
= TOKEN_UNDEFINED
;
346 Ancestors
.list
[Ancestors
.count
].keyword
= KEYWORD_NONE
;
347 Ancestors
.list
[Ancestors
.count
].secondary
= NULL
;
348 Ancestors
.list
[Ancestors
.count
].tag
= TAG_UNDEFINED
;
349 Ancestors
.list
[Ancestors
.count
].string
= NULL
;
350 Ancestors
.list
[Ancestors
.count
].lineNumber
= 0L;
353 static const tokenInfo
* ancestorScope (void)
355 tokenInfo
*result
= NULL
;
357 for (i
= Ancestors
.count
; i
> 0 && result
== NULL
; --i
)
359 tokenInfo
*const token
= Ancestors
.list
+ i
- 1;
360 if (token
->type
== TOKEN_IDENTIFIER
&&
361 token
->tag
!= TAG_UNDEFINED
&& token
->tag
!= TAG_INTERFACE
)
367 static const tokenInfo
* ancestorTop (void)
369 Assert (Ancestors
.count
> 0);
370 return &Ancestors
.list
[Ancestors
.count
- 1];
373 #define ancestorCount() (Ancestors.count)
375 static void ancestorClear (void)
377 while (Ancestors
.count
> 0)
379 if (Ancestors
.list
!= NULL
)
380 eFree (Ancestors
.list
);
381 Ancestors
.list
= NULL
;
386 static boolean
insideInterface (void)
388 boolean result
= FALSE
;
390 for (i
= 0 ; i
< Ancestors
.count
&& !result
; ++i
)
392 if (Ancestors
.list
[i
].tag
== TAG_INTERFACE
)
398 static void buildFortranKeywordHash (const langType language
)
401 sizeof (FortranKeywordTable
) / sizeof (FortranKeywordTable
[0]);
403 for (i
= 0 ; i
< count
; ++i
)
405 const keywordDesc
* const p
= &FortranKeywordTable
[i
];
406 addKeyword (p
->name
, language
, (int) p
->id
);
411 * Tag generation functions
414 static tokenInfo
*newToken (void)
416 tokenInfo
*const token
= xMalloc (1, tokenInfo
);
418 token
->type
= TOKEN_UNDEFINED
;
419 token
->keyword
= KEYWORD_NONE
;
420 token
->tag
= TAG_UNDEFINED
;
421 token
->string
= vStringNew ();
422 token
->secondary
= NULL
;
423 token
->lineNumber
= getSourceLineNumber ();
424 token
->filePosition
= getInputFilePosition ();
429 static tokenInfo
*newTokenFrom (tokenInfo
*const token
)
431 tokenInfo
*result
= newToken ();
433 result
->string
= vStringNewCopy (token
->string
);
434 token
->secondary
= NULL
;
438 static void deleteToken (tokenInfo
*const token
)
442 vStringDelete (token
->string
);
443 deleteToken (token
->secondary
);
444 token
->secondary
= NULL
;
449 static boolean
isFileScope (const tagType type
)
451 return (boolean
) (type
== TAG_LABEL
|| type
== TAG_LOCAL
);
454 static boolean
includeTag (const tagType type
)
457 Assert (type
!= TAG_UNDEFINED
);
458 include
= FortranKinds
[(int) type
].enabled
;
459 if (include
&& isFileScope (type
))
460 include
= Option
.include
.fileScope
;
464 static void makeFortranTag (tokenInfo
*const token
, tagType tag
)
467 if (includeTag (token
->tag
))
469 const char *const name
= vStringValue (token
->string
);
472 initTagEntry (&e
, name
);
474 if (token
->tag
== TAG_COMMON_BLOCK
)
475 e
.lineNumberEntry
= (boolean
) (Option
.locate
!= EX_PATTERN
);
477 e
.lineNumber
= token
->lineNumber
;
478 e
.filePosition
= token
->filePosition
;
479 e
.isFileScope
= isFileScope (token
->tag
);
480 e
.kindName
= FortranKinds
[token
->tag
].name
;
481 e
.kind
= FortranKinds
[token
->tag
].letter
;
482 e
.truncateLine
= (boolean
) (token
->tag
!= TAG_LABEL
);
484 if (ancestorCount () > 0)
486 const tokenInfo
* const scope
= ancestorScope ();
489 e
.extensionFields
.scope
[0] = FortranKinds
[scope
->tag
].name
;
490 e
.extensionFields
.scope
[1] = vStringValue (scope
->string
);
493 if (! insideInterface () || includeTag (TAG_INTERFACE
))
502 static int skipLine (void)
508 while (c
!= EOF
&& c
!= '\n');
513 static void makeLabelTag (vString
*const label
)
515 tokenInfo
*token
= newToken ();
516 token
->type
= TOKEN_LABEL
;
517 vStringCopy (token
->string
, label
);
518 makeFortranTag (token
, TAG_LABEL
);
522 static lineType
getLineType (void)
524 vString
*label
= vStringNew ();
526 lineType type
= LTYPE_UNDETERMINED
;
528 do /* read in first 6 "margin" characters */
532 /* 3.2.1 Comment_Line. A comment line is any line that contains
533 * a C or an asterisk in column 1, or contains only blank characters
534 * in columns 1 through 72. A comment line that contains a C or
535 * an asterisk in column 1 may contain any character capable of
536 * representation in the processor in columns 2 through 72.
538 /* EXCEPTION! Some compilers permit '!' as a commment character here.
540 * Treat # and $ in column 1 as comment to permit preprocessor directives.
541 * Treat D and d in column 1 as comment for HP debug statements.
543 if (column
== 0 && strchr ("*Cc!#$Dd", c
) != NULL
)
544 type
= LTYPE_COMMENT
;
545 else if (c
== '\t') /* EXCEPTION! Some compilers permit a tab here */
548 type
= LTYPE_INITIAL
;
550 else if (column
== 5)
552 /* 3.2.2 Initial_Line. An initial line is any line that is not
553 * a comment line and contains the character blank or the digit 0
554 * in column 6. Columns 1 through 5 may contain a statement label
555 * (3.4), or each of the columns 1 through 5 must contain the
558 if (c
== ' ' || c
== '0')
559 type
= LTYPE_INITIAL
;
561 /* 3.2.3 Continuation_Line. A continuation line is any line that
562 * contains any character of the FORTRAN character set other than
563 * the character blank or the digit 0 in column 6 and contains
564 * only blank characters in columns 1 through 5.
566 else if (vStringLength (label
) == 0)
567 type
= LTYPE_CONTINUATION
;
569 type
= LTYPE_INVALID
;
577 else if (isdigit (c
))
578 vStringPut (label
, c
);
580 type
= LTYPE_INVALID
;
583 } while (column
< 6 && type
== LTYPE_UNDETERMINED
);
585 Assert (type
!= LTYPE_UNDETERMINED
);
587 if (vStringLength (label
) > 0)
589 vStringTerminate (label
);
590 makeLabelTag (label
);
592 vStringDelete (label
);
596 static int getFixedFormChar (void)
598 boolean newline
= FALSE
;
604 #ifdef STRICT_FIXED_FORM
605 /* EXCEPTION! Some compilers permit more than 72 characters per line.
617 newline
= TRUE
; /* need to check for continuation line */
620 else if (c
== '!' && ! ParsingString
)
623 newline
= TRUE
; /* need to check for continuation line */
626 else if (c
== '&') /* check for free source form */
628 const int c2
= fileGetc ();
630 longjmp (Exception
, (int) ExceptionFixedFormat
);
637 type
= getLineType ();
640 case LTYPE_UNDETERMINED
:
642 longjmp (Exception
, (int) ExceptionFixedFormat
);
645 case LTYPE_SHORT
: break;
646 case LTYPE_COMMENT
: skipLine (); break;
663 /* fall through to next case */
664 case LTYPE_CONTINUATION
:
670 } while (isBlank (c
));
681 Assert ("Unexpected line type" == NULL
);
687 static int skipToNextLine (void)
695 static int getFreeFormChar (void)
697 static boolean newline
= TRUE
;
698 boolean advanceLine
= FALSE
;
701 /* If the last nonblank, non-comment character of a FORTRAN 90
702 * free-format text line is an ampersand then the next non-comment
703 * line is a continuation line.
709 while (isspace (c
) && c
!= '\n');
723 else if (newline
&& (c
== '!' || c
== '#'))
729 if (c
== '!' || (newline
&& c
== '#'))
731 c
= skipToNextLine ();
740 newline
= (boolean
) (c
== '\n');
744 static int getChar (void)
753 else if (FreeSourceForm
)
754 c
= getFreeFormChar ();
756 c
= getFixedFormChar ();
760 static void ungetChar (const int c
)
765 /* If a numeric is passed in 'c', this is used as the first digit of the
766 * numeric being parsed.
768 static vString
*parseInteger (int c
)
770 vString
*string
= vStringNew ();
774 vStringPut (string
, c
);
777 else if (! isdigit (c
))
779 while (c
!= EOF
&& isdigit (c
))
781 vStringPut (string
, c
);
784 vStringTerminate (string
);
790 while (c
!= EOF
&& isalpha (c
));
797 static vString
*parseNumeric (int c
)
799 vString
*string
= vStringNew ();
800 vString
*integer
= parseInteger (c
);
801 vStringCopy (string
, integer
);
802 vStringDelete (integer
);
807 integer
= parseInteger ('\0');
808 vStringPut (string
, c
);
809 vStringCat (string
, integer
);
810 vStringDelete (integer
);
813 if (tolower (c
) == 'e')
815 integer
= parseInteger ('\0');
816 vStringPut (string
, c
);
817 vStringCat (string
, integer
);
818 vStringDelete (integer
);
823 vStringTerminate (string
);
828 static void parseString (vString
*const string
, const int delimiter
)
830 const unsigned long inputLineNumber
= getInputLineNumber ();
832 ParsingString
= TRUE
;
834 while (c
!= delimiter
&& c
!= '\n' && c
!= EOF
)
836 vStringPut (string
, c
);
839 if (c
== '\n' || c
== EOF
)
841 verbose ("%s: unterminated character string at line %lu\n",
842 getInputFileName (), inputLineNumber
);
844 longjmp (Exception
, (int) ExceptionEOF
);
845 else if (! FreeSourceForm
)
846 longjmp (Exception
, (int) ExceptionFixedFormat
);
848 vStringTerminate (string
);
849 ParsingString
= FALSE
;
852 /* Read a C identifier beginning with "firstChar" and places it into "name".
854 static void parseIdentifier (vString
*const string
, const int firstChar
)
860 vStringPut (string
, c
);
862 } while (isident (c
));
864 vStringTerminate (string
);
865 ungetChar (c
); /* unget non-identifier character */
868 static void checkForLabel (void)
870 tokenInfo
* token
= NULL
;
878 for (length
= 0 ; isdigit (c
) && length
< 5 ; ++length
)
883 token
->type
= TOKEN_LABEL
;
885 vStringPut (token
->string
, c
);
888 if (length
> 0 && token
!= NULL
)
890 vStringTerminate (token
->string
);
891 makeFortranTag (token
, TAG_LABEL
);
897 /* Analyzes the identifier contained in a statement described by the
898 * statement structure and adjusts the structure according the significance
901 static keywordId
analyzeToken (vString
*const name
, langType language
)
903 static vString
*keyword
= NULL
;
907 keyword
= vStringNew ();
908 vStringCopyToLower (keyword
, name
);
909 id
= (keywordId
) lookupKeyword (vStringValue (keyword
), language
);
914 static void readIdentifier (tokenInfo
*const token
, const int c
)
916 parseIdentifier (token
->string
, c
);
917 token
->keyword
= analyzeToken (token
->string
, Lang_fortran
);
918 if (! isKeyword (token
, KEYWORD_NONE
))
919 token
->type
= TOKEN_KEYWORD
;
922 token
->type
= TOKEN_IDENTIFIER
;
923 if (strncmp (vStringValue (token
->string
), "end", 3) == 0)
925 vString
*const sub
= vStringNewInit (vStringValue (token
->string
) + 3);
926 const keywordId kw
= analyzeToken (sub
, Lang_fortran
);
928 if (kw
!= KEYWORD_NONE
)
930 token
->secondary
= newToken ();
931 token
->secondary
->type
= TOKEN_KEYWORD
;
932 token
->secondary
->keyword
= kw
;
933 token
->keyword
= KEYWORD_end
;
939 static void readToken (tokenInfo
*const token
)
943 deleteToken (token
->secondary
);
944 token
->type
= TOKEN_UNDEFINED
;
945 token
->tag
= TAG_UNDEFINED
;
946 token
->keyword
= KEYWORD_NONE
;
947 token
->secondary
= NULL
;
948 vStringClear (token
->string
);
953 token
->lineNumber
= getSourceLineNumber ();
954 token
->filePosition
= getInputFilePosition ();
958 case EOF
: longjmp (Exception
, (int) ExceptionEOF
); break;
959 case ' ': goto getNextChar
;
960 case '\t': goto getNextChar
;
961 case ',': token
->type
= TOKEN_COMMA
; break;
962 case '(': token
->type
= TOKEN_PAREN_OPEN
; break;
963 case ')': token
->type
= TOKEN_PAREN_CLOSE
; break;
964 case '%': token
->type
= TOKEN_PERCENT
; break;
974 const char *const operatorChars
= "*/+=<>";
976 vStringPut (token
->string
, c
);
978 } while (strchr (operatorChars
, c
) != NULL
);
980 vStringTerminate (token
->string
);
981 token
->type
= TOKEN_OPERATOR
;
990 while (c
!= '\n' && c
!= EOF
);
997 /* fall through to newline case */
999 token
->type
= TOKEN_STATEMENT_END
;
1005 parseIdentifier (token
->string
, c
);
1009 vStringPut (token
->string
, c
);
1010 vStringTerminate (token
->string
);
1011 token
->type
= TOKEN_OPERATOR
;
1016 token
->type
= TOKEN_UNDEFINED
;
1022 parseString (token
->string
, c
);
1023 token
->type
= TOKEN_STRING
;
1027 token
->type
= TOKEN_STATEMENT_END
;
1033 token
->type
= TOKEN_DOUBLE_COLON
;
1037 token
->type
= TOKEN_UNDEFINED
;
1043 readIdentifier (token
, c
);
1044 else if (isdigit (c
))
1046 vString
*numeric
= parseNumeric (c
);
1047 vStringCat (token
->string
, numeric
);
1048 vStringDelete (numeric
);
1049 token
->type
= TOKEN_NUMERIC
;
1052 token
->type
= TOKEN_UNDEFINED
;
1057 static void readSubToken (tokenInfo
*const token
)
1059 if (token
->secondary
== NULL
)
1061 token
->secondary
= newToken ();
1062 readToken (token
->secondary
);
1067 * Scanning functions
1070 static void skipToToken (tokenInfo
*const token
, tokenType type
)
1072 while (! isType (token
, type
) && ! isType (token
, TOKEN_STATEMENT_END
) &&
1073 !(token
->secondary
!= NULL
&& isType (token
->secondary
, TOKEN_STATEMENT_END
)))
1077 static void skipPast (tokenInfo
*const token
, tokenType type
)
1079 skipToToken (token
, type
);
1080 if (! isType (token
, TOKEN_STATEMENT_END
))
1084 static void skipToNextStatement (tokenInfo
*const token
)
1088 skipToToken (token
, TOKEN_STATEMENT_END
);
1090 } while (isType (token
, TOKEN_STATEMENT_END
));
1093 /* skip over parenthesis enclosed contents starting at next token.
1094 * Token is left at the first token following closing parenthesis. If an
1095 * opening parenthesis is not found, `token' is moved to the end of the
1098 static void skipOverParens (tokenInfo
*const token
)
1102 if (isType (token
, TOKEN_STATEMENT_END
))
1104 else if (isType (token
, TOKEN_PAREN_OPEN
))
1106 else if (isType (token
, TOKEN_PAREN_CLOSE
))
1109 } while (level
> 0);
1112 static boolean
isTypeSpec (tokenInfo
*const token
)
1115 switch (token
->keyword
)
1118 case KEYWORD_integer
:
1120 case KEYWORD_double
:
1121 case KEYWORD_complex
:
1122 case KEYWORD_character
:
1123 case KEYWORD_logical
:
1124 case KEYWORD_record
:
1135 static boolean
isSubprogramPrefix (tokenInfo
*const token
)
1138 switch (token
->keyword
)
1140 case KEYWORD_elemental
:
1142 case KEYWORD_recursive
:
1143 case KEYWORD_stdcall
:
1154 * is INTEGER [kind-selector]
1155 * or REAL [kind-selector] is ( etc. )
1156 * or DOUBLE PRECISION
1157 * or COMPLEX [kind-selector]
1158 * or CHARACTER [kind-selector]
1159 * or LOGICAL [kind-selector]
1160 * or TYPE ( type-name )
1162 * Note that INTEGER and REAL may be followed by "*N" where "N" is an integer
1164 static void parseTypeSpec (tokenInfo
*const token
)
1166 /* parse type-spec, leaving `token' at first token following type-spec */
1167 Assert (isTypeSpec (token
));
1168 switch (token
->keyword
)
1170 case KEYWORD_character
:
1171 /* skip char-selector */
1173 if (isType (token
, TOKEN_OPERATOR
) &&
1174 strcmp (vStringValue (token
->string
), "*") == 0)
1176 if (isType (token
, TOKEN_PAREN_OPEN
))
1177 skipOverParens (token
);
1178 else if (isType (token
, TOKEN_NUMERIC
))
1184 case KEYWORD_complex
:
1185 case KEYWORD_integer
:
1186 case KEYWORD_logical
:
1189 if (isType (token
, TOKEN_PAREN_OPEN
))
1190 skipOverParens (token
); /* skip kind-selector */
1191 if (isType (token
, TOKEN_OPERATOR
) &&
1192 strcmp (vStringValue (token
->string
), "*") == 0)
1199 case KEYWORD_double
:
1201 if (isKeyword (token
, KEYWORD_complex
) ||
1202 isKeyword (token
, KEYWORD_precision
))
1205 skipToToken (token
, TOKEN_STATEMENT_END
);
1208 case KEYWORD_record
:
1210 if (isType (token
, TOKEN_OPERATOR
) &&
1211 strcmp (vStringValue (token
->string
), "/") == 0)
1213 readToken (token
); /* skip to structure name */
1214 readToken (token
); /* skip to '/' */
1215 readToken (token
); /* skip to variable name */
1221 if (isType (token
, TOKEN_PAREN_OPEN
))
1222 skipOverParens (token
); /* skip type-name */
1224 parseDerivedTypeDef (token
);
1228 skipToToken (token
, TOKEN_STATEMENT_END
);
1233 static boolean
skipStatementIfKeyword (tokenInfo
*const token
, keywordId keyword
)
1235 boolean result
= FALSE
;
1236 if (isKeyword (token
, keyword
))
1239 skipToNextStatement (token
);
1244 /* parse a list of qualifying specifiers, leaving `token' at first token
1245 * following list. Examples of such specifiers are:
1246 * [[, attr-spec] ::]
1247 * [[, component-attr-spec-list] ::]
1251 * or access-spec (is PUBLIC or PRIVATE)
1253 * or DIMENSION ( array-spec )
1255 * or INTENT ( intent-spec )
1262 * component-attr-spec
1264 * or DIMENSION ( component-array-spec )
1265 * or EXTENDS ( type name )
1267 static void parseQualifierSpecList (tokenInfo
*const token
)
1271 readToken (token
); /* should be an attr-spec */
1272 switch (token
->keyword
)
1274 case KEYWORD_parameter
:
1275 case KEYWORD_allocatable
:
1276 case KEYWORD_external
:
1277 case KEYWORD_intrinsic
:
1278 case KEYWORD_optional
:
1279 case KEYWORD_private
:
1280 case KEYWORD_pointer
:
1281 case KEYWORD_public
:
1283 case KEYWORD_target
:
1287 case KEYWORD_dimension
:
1288 case KEYWORD_extends
:
1289 case KEYWORD_intent
:
1291 skipOverParens (token
);
1294 default: skipToToken (token
, TOKEN_STATEMENT_END
); break;
1296 } while (isType (token
, TOKEN_COMMA
));
1297 if (! isType (token
, TOKEN_DOUBLE_COLON
))
1298 skipToToken (token
, TOKEN_STATEMENT_END
);
1301 static tagType
variableTagType (void)
1303 tagType result
= TAG_VARIABLE
;
1304 if (ancestorCount () > 0)
1306 const tokenInfo
* const parent
= ancestorTop ();
1307 switch (parent
->tag
)
1309 case TAG_MODULE
: result
= TAG_VARIABLE
; break;
1310 case TAG_DERIVED_TYPE
: result
= TAG_COMPONENT
; break;
1311 case TAG_FUNCTION
: result
= TAG_LOCAL
; break;
1312 case TAG_SUBROUTINE
: result
= TAG_LOCAL
; break;
1313 default: result
= TAG_VARIABLE
; break;
1319 static void parseEntityDecl (tokenInfo
*const token
)
1321 Assert (isType (token
, TOKEN_IDENTIFIER
));
1322 makeFortranTag (token
, variableTagType ());
1324 if (isType (token
, TOKEN_PAREN_OPEN
))
1325 skipOverParens (token
);
1326 if (isType (token
, TOKEN_OPERATOR
) &&
1327 strcmp (vStringValue (token
->string
), "*") == 0)
1329 readToken (token
); /* read char-length */
1330 if (isType (token
, TOKEN_PAREN_OPEN
))
1331 skipOverParens (token
);
1335 if (isType (token
, TOKEN_OPERATOR
))
1337 if (strcmp (vStringValue (token
->string
), "/") == 0)
1338 { /* skip over initializations of structure field */
1340 skipPast (token
, TOKEN_OPERATOR
);
1342 else if (strcmp (vStringValue (token
->string
), "=") == 0)
1344 while (! isType (token
, TOKEN_COMMA
) &&
1345 ! isType (token
, TOKEN_STATEMENT_END
))
1348 if (isType (token
, TOKEN_PAREN_OPEN
))
1349 skipOverParens (token
);
1353 /* token left at either comma or statement end */
1356 static void parseEntityDeclList (tokenInfo
*const token
)
1358 if (isType (token
, TOKEN_PERCENT
))
1359 skipToNextStatement (token
);
1360 else while (isType (token
, TOKEN_IDENTIFIER
) ||
1361 (isType (token
, TOKEN_KEYWORD
) &&
1362 !isKeyword (token
, KEYWORD_function
) &&
1363 !isKeyword (token
, KEYWORD_subroutine
)))
1365 /* compilers accept keywoeds as identifiers */
1366 if (isType (token
, TOKEN_KEYWORD
))
1367 token
->type
= TOKEN_IDENTIFIER
;
1368 parseEntityDecl (token
);
1369 if (isType (token
, TOKEN_COMMA
))
1371 else if (isType (token
, TOKEN_STATEMENT_END
))
1373 skipToNextStatement (token
);
1379 /* type-declaration-stmt is
1380 * type-spec [[, attr-spec] ... ::] entity-decl-list
1382 static void parseTypeDeclarationStmt (tokenInfo
*const token
)
1384 Assert (isTypeSpec (token
));
1385 parseTypeSpec (token
);
1386 if (!isType (token
, TOKEN_STATEMENT_END
)) /* if not end of derived type... */
1388 if (isType (token
, TOKEN_COMMA
))
1389 parseQualifierSpecList (token
);
1390 if (isType (token
, TOKEN_DOUBLE_COLON
))
1392 parseEntityDeclList (token
);
1394 if (isType (token
, TOKEN_STATEMENT_END
))
1395 skipToNextStatement (token
);
1399 * NAMELIST /namelist-group-name/ namelist-group-object-list
1400 * [[,]/[namelist-group-name]/ namelist-block-object-list] ...
1402 * namelist-group-object is
1406 * COMMON [/[common-block-name]/] common-block-object-list
1407 * [[,]/[common-block-name]/ common-block-object-list] ...
1409 * common-block-object is
1410 * variable-name [ ( explicit-shape-spec-list ) ]
1412 static void parseCommonNamelistStmt (tokenInfo
*const token
, tagType type
)
1414 Assert (isKeyword (token
, KEYWORD_common
) ||
1415 isKeyword (token
, KEYWORD_namelist
));
1419 if (isType (token
, TOKEN_OPERATOR
) &&
1420 strcmp (vStringValue (token
->string
), "/") == 0)
1423 if (isType (token
, TOKEN_IDENTIFIER
))
1425 makeFortranTag (token
, type
);
1428 skipPast (token
, TOKEN_OPERATOR
);
1430 if (isType (token
, TOKEN_IDENTIFIER
))
1431 makeFortranTag (token
, TAG_LOCAL
);
1433 if (isType (token
, TOKEN_PAREN_OPEN
))
1434 skipOverParens (token
); /* skip explicit-shape-spec-list */
1435 if (isType (token
, TOKEN_COMMA
))
1437 } while (! isType (token
, TOKEN_STATEMENT_END
));
1438 skipToNextStatement (token
);
1441 static void parseFieldDefinition (tokenInfo
*const token
)
1443 if (isTypeSpec (token
))
1444 parseTypeDeclarationStmt (token
);
1445 else if (isKeyword (token
, KEYWORD_structure
))
1446 parseStructureStmt (token
);
1447 else if (isKeyword (token
, KEYWORD_union
))
1448 parseUnionStmt (token
);
1450 skipToNextStatement (token
);
1453 static void parseMap (tokenInfo
*const token
)
1455 Assert (isKeyword (token
, KEYWORD_map
));
1456 skipToNextStatement (token
);
1457 while (! isKeyword (token
, KEYWORD_end
))
1458 parseFieldDefinition (token
);
1459 readSubToken (token
);
1460 /* should be at KEYWORD_map token */
1461 skipToNextStatement (token
);
1466 * [field-definition] [field-definition] ...
1469 * [field-definition] [field-definition] ...
1472 * [field-definition]
1473 * [field-definition] ...
1478 * Typed data declarations (variables or arrays) in structure declarations
1479 * have the form of normal Fortran typed data declarations. Data items with
1480 * different types can be freely intermixed within a structure declaration.
1482 * Unnamed fields can be declared in a structure by specifying the pseudo
1483 * name %FILL in place of an actual field name. You can use this mechanism to
1484 * generate empty space in a record for purposes such as alignment.
1486 * All mapped field declarations that are made within a UNION declaration
1487 * share a common location within the containing structure. When initializing
1488 * the fields within a UNION, the final initialization value assigned
1489 * overlays any value previously assigned to a field definition that shares
1492 static void parseUnionStmt (tokenInfo
*const token
)
1494 Assert (isKeyword (token
, KEYWORD_union
));
1495 skipToNextStatement (token
);
1496 while (isKeyword (token
, KEYWORD_map
))
1498 /* should be at KEYWORD_end token */
1499 readSubToken (token
);
1500 /* secondary token should be KEYWORD_end token */
1501 skipToNextStatement (token
);
1504 /* STRUCTURE [/structure-name/] [field-names]
1505 * [field-definition]
1506 * [field-definition] ...
1510 * identifies the structure in a subsequent RECORD statement.
1511 * Substructures can be established within a structure by means of either
1512 * a nested STRUCTURE declaration or a RECORD statement.
1515 * (for substructure declarations only) one or more names having the
1516 * structure of the substructure being defined.
1519 * can be one or more of the following:
1521 * Typed data declarations, which can optionally include one or more
1522 * data initialization values.
1524 * Substructure declarations (defined by either RECORD statements or
1525 * subsequent STRUCTURE statements).
1527 * UNION declarations, which are mapped fields defined by a block of
1528 * statements. The syntax of a UNION declaration is described below.
1530 * PARAMETER statements, which do not affect the form of the
1533 static void parseStructureStmt (tokenInfo
*const token
)
1536 Assert (isKeyword (token
, KEYWORD_structure
));
1538 if (isType (token
, TOKEN_OPERATOR
) &&
1539 strcmp (vStringValue (token
->string
), "/") == 0)
1540 { /* read structure name */
1542 if (isType (token
, TOKEN_IDENTIFIER
))
1543 makeFortranTag (token
, TAG_DERIVED_TYPE
);
1544 name
= newTokenFrom (token
);
1545 skipPast (token
, TOKEN_OPERATOR
);
1548 { /* fake out anonymous structure */
1550 name
->type
= TOKEN_IDENTIFIER
;
1551 name
->tag
= TAG_DERIVED_TYPE
;
1552 vStringCopyS (name
->string
, "anonymous");
1554 while (isType (token
, TOKEN_IDENTIFIER
))
1555 { /* read field names */
1556 makeFortranTag (token
, TAG_COMPONENT
);
1558 if (isType (token
, TOKEN_COMMA
))
1561 skipToNextStatement (token
);
1562 ancestorPush (name
);
1563 while (! isKeyword (token
, KEYWORD_end
))
1564 parseFieldDefinition (token
);
1565 readSubToken (token
);
1566 /* secondary token should be KEYWORD_structure token */
1567 skipToNextStatement (token
);
1572 /* specification-stmt
1573 * is access-stmt (is access-spec [[::] access-id-list)
1574 * or allocatable-stmt (is ALLOCATABLE [::] array-name etc.)
1575 * or common-stmt (is COMMON [ / [common-block-name] /] etc.)
1576 * or data-stmt (is DATA data-stmt-list [[,] data-stmt-set] ...)
1577 * or dimension-stmt (is DIMENSION [::] array-name etc.)
1578 * or equivalence-stmt (is EQUIVALENCE equivalence-set-list)
1579 * or external-stmt (is EXTERNAL etc.)
1580 * or intent-stmt (is INTENT ( intent-spec ) [::] etc.)
1581 * or instrinsic-stmt (is INTRINSIC etc.)
1582 * or namelist-stmt (is NAMELIST / namelist-group-name / etc.)
1583 * or optional-stmt (is OPTIONAL [::] etc.)
1584 * or pointer-stmt (is POINTER [::] object-name etc.)
1585 * or save-stmt (is SAVE etc.)
1586 * or target-stmt (is TARGET [::] object-name etc.)
1588 * access-spec is PUBLIC or PRIVATE
1590 static boolean
parseSpecificationStmt (tokenInfo
*const token
)
1592 boolean result
= TRUE
;
1593 switch (token
->keyword
)
1595 case KEYWORD_common
:
1596 parseCommonNamelistStmt (token
, TAG_COMMON_BLOCK
);
1599 case KEYWORD_namelist
:
1600 parseCommonNamelistStmt (token
, TAG_NAMELIST
);
1603 case KEYWORD_structure
:
1604 parseStructureStmt (token
);
1607 case KEYWORD_allocatable
:
1609 case KEYWORD_dimension
:
1610 case KEYWORD_equivalence
:
1611 case KEYWORD_extends
:
1612 case KEYWORD_external
:
1613 case KEYWORD_intent
:
1614 case KEYWORD_intrinsic
:
1615 case KEYWORD_optional
:
1616 case KEYWORD_pointer
:
1617 case KEYWORD_private
:
1618 case KEYWORD_public
:
1620 case KEYWORD_target
:
1621 skipToNextStatement (token
);
1631 /* component-def-stmt is
1632 * type-spec [[, component-attr-spec-list] ::] component-decl-list
1635 * component-name [ ( component-array-spec ) ] [ * char-length ]
1637 static void parseComponentDefStmt (tokenInfo
*const token
)
1639 Assert (isTypeSpec (token
));
1640 parseTypeSpec (token
);
1641 if (isType (token
, TOKEN_COMMA
))
1642 parseQualifierSpecList (token
);
1643 if (isType (token
, TOKEN_DOUBLE_COLON
))
1645 parseEntityDeclList (token
);
1648 /* derived-type-def is
1649 * derived-type-stmt is (TYPE [[, access-spec] ::] type-name
1650 * [private-sequence-stmt] ... (is PRIVATE or SEQUENCE)
1651 * component-def-stmt
1652 * [component-def-stmt] ...
1655 static void parseDerivedTypeDef (tokenInfo
*const token
)
1657 if (isType (token
, TOKEN_COMMA
))
1658 parseQualifierSpecList (token
);
1659 if (isType (token
, TOKEN_DOUBLE_COLON
))
1661 if (isType (token
, TOKEN_IDENTIFIER
))
1662 makeFortranTag (token
, TAG_DERIVED_TYPE
);
1663 ancestorPush (token
);
1664 skipToNextStatement (token
);
1665 if (isKeyword (token
, KEYWORD_private
) ||
1666 isKeyword (token
, KEYWORD_sequence
))
1668 skipToNextStatement (token
);
1670 while (! isKeyword (token
, KEYWORD_end
))
1672 if (isTypeSpec (token
))
1673 parseComponentDefStmt (token
);
1675 skipToNextStatement (token
);
1677 readSubToken (token
);
1678 /* secondary token should be KEYWORD_type token */
1679 skipToToken (token
, TOKEN_STATEMENT_END
);
1684 * interface-stmt (is INTERFACE [generic-spec])
1686 * [module-procedure-stmt] ...
1687 * end-interface-stmt (is END INTERFACE)
1691 * or OPERATOR ( defined-operator )
1692 * or ASSIGNMENT ( = )
1696 * [specification-part]
1698 * or subroutine-stmt
1699 * [specification-part]
1700 * end-subroutine-stmt
1702 * module-procedure-stmt is
1703 * MODULE PROCEDURE procedure-name-list
1705 static void parseInterfaceBlock (tokenInfo
*const token
)
1707 tokenInfo
*name
= NULL
;
1708 Assert (isKeyword (token
, KEYWORD_interface
));
1710 if (isType (token
, TOKEN_IDENTIFIER
))
1712 makeFortranTag (token
, TAG_INTERFACE
);
1713 name
= newTokenFrom (token
);
1715 else if (isKeyword (token
, KEYWORD_assignment
) ||
1716 isKeyword (token
, KEYWORD_operator
))
1719 if (isType (token
, TOKEN_PAREN_OPEN
))
1721 if (isType (token
, TOKEN_OPERATOR
))
1723 makeFortranTag (token
, TAG_INTERFACE
);
1724 name
= newTokenFrom (token
);
1730 name
->type
= TOKEN_IDENTIFIER
;
1731 name
->tag
= TAG_INTERFACE
;
1733 ancestorPush (name
);
1734 while (! isKeyword (token
, KEYWORD_end
))
1736 switch (token
->keyword
)
1738 case KEYWORD_function
: parseFunctionSubprogram (token
); break;
1739 case KEYWORD_subroutine
: parseSubroutineSubprogram (token
); break;
1742 if (isSubprogramPrefix (token
))
1744 else if (isTypeSpec (token
))
1745 parseTypeSpec (token
);
1747 skipToNextStatement (token
);
1751 readSubToken (token
);
1752 /* secondary token should be KEYWORD_interface token */
1753 skipToNextStatement (token
);
1759 * ENTRY entry-name [ ( dummy-arg-list ) ]
1761 static void parseEntryStmt (tokenInfo
*const token
)
1763 Assert (isKeyword (token
, KEYWORD_entry
));
1765 if (isType (token
, TOKEN_IDENTIFIER
))
1766 makeFortranTag (token
, TAG_ENTRY_POINT
);
1767 skipToNextStatement (token
);
1770 /* stmt-function-stmt is
1771 * function-name ([dummy-arg-name-list]) = scalar-expr
1773 static boolean
parseStmtFunctionStmt (tokenInfo
*const token
)
1775 boolean result
= FALSE
;
1776 Assert (isType (token
, TOKEN_IDENTIFIER
));
1777 #if 0 /* cannot reliably parse this yet */
1778 makeFortranTag (token
, TAG_FUNCTION
);
1781 if (isType (token
, TOKEN_PAREN_OPEN
))
1783 skipOverParens (token
);
1784 result
= (boolean
) (isType (token
, TOKEN_OPERATOR
) &&
1785 strcmp (vStringValue (token
->string
), "=") == 0);
1787 skipToNextStatement (token
);
1791 static boolean
isIgnoredDeclaration (tokenInfo
*const token
)
1794 switch (token
->keyword
)
1796 case KEYWORD_cexternal
:
1797 case KEYWORD_cglobal
:
1798 case KEYWORD_dllexport
:
1799 case KEYWORD_dllimport
:
1800 case KEYWORD_external
:
1801 case KEYWORD_format
:
1802 case KEYWORD_include
:
1803 case KEYWORD_inline
:
1804 case KEYWORD_parameter
:
1805 case KEYWORD_pascal
:
1806 case KEYWORD_pexternal
:
1807 case KEYWORD_pglobal
:
1808 case KEYWORD_static
:
1810 case KEYWORD_virtual
:
1811 case KEYWORD_volatile
:
1822 /* declaration-construct
1823 * [derived-type-def]
1825 * [type-declaration-stmt]
1826 * [specification-stmt]
1827 * [parameter-stmt] (is PARAMETER ( named-constant-def-list )
1828 * [format-stmt] (is FORMAT format-specification)
1830 * [stmt-function-stmt]
1832 static boolean
parseDeclarationConstruct (tokenInfo
*const token
)
1834 boolean result
= TRUE
;
1835 switch (token
->keyword
)
1837 case KEYWORD_entry
: parseEntryStmt (token
); break;
1838 case KEYWORD_interface
: parseInterfaceBlock (token
); break;
1839 case KEYWORD_stdcall
: readToken (token
); break;
1840 /* derived type handled by parseTypeDeclarationStmt(); */
1842 case KEYWORD_automatic
:
1844 if (isTypeSpec (token
))
1845 parseTypeDeclarationStmt (token
);
1847 skipToNextStatement (token
);
1852 if (isIgnoredDeclaration (token
))
1853 skipToNextStatement (token
);
1854 else if (isTypeSpec (token
))
1856 parseTypeDeclarationStmt (token
);
1859 else if (isType (token
, TOKEN_IDENTIFIER
))
1860 result
= parseStmtFunctionStmt (token
);
1862 result
= parseSpecificationStmt (token
);
1868 /* implicit-part-stmt
1869 * is [implicit-stmt] (is IMPLICIT etc.)
1870 * or [parameter-stmt] (is PARAMETER etc.)
1871 * or [format-stmt] (is FORMAT etc.)
1872 * or [entry-stmt] (is ENTRY entry-name etc.)
1874 static boolean
parseImplicitPartStmt (tokenInfo
*const token
)
1876 boolean result
= TRUE
;
1877 switch (token
->keyword
)
1879 case KEYWORD_entry
: parseEntryStmt (token
); break;
1881 case KEYWORD_implicit
:
1882 case KEYWORD_include
:
1883 case KEYWORD_parameter
:
1884 case KEYWORD_format
:
1885 skipToNextStatement (token
);
1888 default: result
= FALSE
; break;
1893 /* specification-part is
1894 * [use-stmt] ... (is USE module-name etc.)
1895 * [implicit-part] (is [implicit-part-stmt] ... [implicit-stmt])
1896 * [declaration-construct] ...
1898 static boolean
parseSpecificationPart (tokenInfo
*const token
)
1900 boolean result
= FALSE
;
1901 while (skipStatementIfKeyword (token
, KEYWORD_use
))
1903 while (parseImplicitPartStmt (token
))
1905 while (parseDeclarationConstruct (token
))
1911 * block-data-stmt (is BLOCK DATA [block-data-name]
1912 * [specification-part]
1913 * end-block-data-stmt (is END [BLOCK DATA [block-data-name]])
1915 static void parseBlockData (tokenInfo
*const token
)
1917 Assert (isKeyword (token
, KEYWORD_block
));
1919 if (isKeyword (token
, KEYWORD_data
))
1922 if (isType (token
, TOKEN_IDENTIFIER
))
1923 makeFortranTag (token
, TAG_BLOCK_DATA
);
1925 ancestorPush (token
);
1926 skipToNextStatement (token
);
1927 parseSpecificationPart (token
);
1928 while (! isKeyword (token
, KEYWORD_end
))
1929 skipToNextStatement (token
);
1930 readSubToken (token
);
1931 /* secondary token should be KEYWORD_NONE or KEYWORD_block token */
1932 skipToNextStatement (token
);
1936 /* internal-subprogram-part is
1937 * contains-stmt (is CONTAINS)
1938 * internal-subprogram
1939 * [internal-subprogram] ...
1941 * internal-subprogram
1942 * is function-subprogram
1943 * or subroutine-subprogram
1945 static void parseInternalSubprogramPart (tokenInfo
*const token
)
1947 boolean done
= FALSE
;
1948 if (isKeyword (token
, KEYWORD_contains
))
1949 skipToNextStatement (token
);
1952 switch (token
->keyword
)
1954 case KEYWORD_function
: parseFunctionSubprogram (token
); break;
1955 case KEYWORD_subroutine
: parseSubroutineSubprogram (token
); break;
1956 case KEYWORD_end
: done
= TRUE
; break;
1959 if (isSubprogramPrefix (token
))
1961 else if (isTypeSpec (token
))
1962 parseTypeSpec (token
);
1971 * module-stmt (is MODULE module-name)
1972 * [specification-part]
1973 * [module-subprogram-part]
1974 * end-module-stmt (is END [MODULE [module-name]])
1976 * module-subprogram-part
1977 * contains-stmt (is CONTAINS)
1979 * [module-subprogram] ...
1982 * is function-subprogram
1983 * or subroutine-subprogram
1985 static void parseModule (tokenInfo
*const token
)
1987 Assert (isKeyword (token
, KEYWORD_module
));
1989 if (isType (token
, TOKEN_IDENTIFIER
))
1990 makeFortranTag (token
, TAG_MODULE
);
1991 ancestorPush (token
);
1992 skipToNextStatement (token
);
1993 parseSpecificationPart (token
);
1994 if (isKeyword (token
, KEYWORD_contains
))
1995 parseInternalSubprogramPart (token
);
1996 while (! isKeyword (token
, KEYWORD_end
))
1997 skipToNextStatement (token
);
1998 readSubToken (token
);
1999 /* secondary token should be KEYWORD_NONE or KEYWORD_module token */
2000 skipToNextStatement (token
);
2005 * executable-construct
2007 * executable-contstruct is
2008 * execution-part-construct [execution-part-construct]
2010 * execution-part-construct
2011 * is executable-construct
2016 static boolean
parseExecutionPart (tokenInfo
*const token
)
2018 boolean result
= FALSE
;
2019 boolean done
= FALSE
;
2022 switch (token
->keyword
)
2025 if (isSubprogramPrefix (token
))
2028 skipToNextStatement (token
);
2033 parseEntryStmt (token
);
2037 case KEYWORD_contains
:
2038 case KEYWORD_function
:
2039 case KEYWORD_subroutine
:
2044 readSubToken (token
);
2045 if (isSecondaryKeyword (token
, KEYWORD_do
) ||
2046 isSecondaryKeyword (token
, KEYWORD_if
) ||
2047 isSecondaryKeyword (token
, KEYWORD_select
) ||
2048 isSecondaryKeyword (token
, KEYWORD_where
))
2050 skipToNextStatement (token
);
2061 static void parseSubprogram (tokenInfo
*const token
, const tagType tag
)
2063 Assert (isKeyword (token
, KEYWORD_program
) ||
2064 isKeyword (token
, KEYWORD_function
) ||
2065 isKeyword (token
, KEYWORD_subroutine
));
2067 if (isType (token
, TOKEN_IDENTIFIER
))
2068 makeFortranTag (token
, tag
);
2069 ancestorPush (token
);
2070 skipToNextStatement (token
);
2071 parseSpecificationPart (token
);
2072 parseExecutionPart (token
);
2073 if (isKeyword (token
, KEYWORD_contains
))
2074 parseInternalSubprogramPart (token
);
2075 /* should be at KEYWORD_end token */
2076 readSubToken (token
);
2077 /* secondary token should be one of KEYWORD_NONE, KEYWORD_program,
2078 * KEYWORD_function, KEYWORD_function
2080 skipToNextStatement (token
);
2085 /* function-subprogram is
2086 * function-stmt (is [prefix] FUNCTION function-name etc.)
2087 * [specification-part]
2089 * [internal-subprogram-part]
2090 * end-function-stmt (is END [FUNCTION [function-name]])
2093 * is type-spec [RECURSIVE]
2094 * or [RECURSIVE] type-spec
2096 static void parseFunctionSubprogram (tokenInfo
*const token
)
2098 parseSubprogram (token
, TAG_FUNCTION
);
2101 /* subroutine-subprogram is
2102 * subroutine-stmt (is [RECURSIVE] SUBROUTINE subroutine-name etc.)
2103 * [specification-part]
2105 * [internal-subprogram-part]
2106 * end-subroutine-stmt (is END [SUBROUTINE [function-name]])
2108 static void parseSubroutineSubprogram (tokenInfo
*const token
)
2110 parseSubprogram (token
, TAG_SUBROUTINE
);
2114 * [program-stmt] (is PROGRAM program-name)
2115 * [specification-part]
2117 * [internal-subprogram-part ]
2120 static void parseMainProgram (tokenInfo
*const token
)
2122 parseSubprogram (token
, TAG_PROGRAM
);
2127 * or external-subprogram (is function-subprogram or subroutine-subprogram)
2131 static void parseProgramUnit (tokenInfo
*const token
)
2136 if (isType (token
, TOKEN_STATEMENT_END
))
2138 else switch (token
->keyword
)
2140 case KEYWORD_block
: parseBlockData (token
); break;
2141 case KEYWORD_end
: skipToNextStatement (token
); break;
2142 case KEYWORD_function
: parseFunctionSubprogram (token
); break;
2143 case KEYWORD_module
: parseModule (token
); break;
2144 case KEYWORD_program
: parseMainProgram (token
); break;
2145 case KEYWORD_subroutine
: parseSubroutineSubprogram (token
); break;
2148 if (isSubprogramPrefix (token
))
2152 boolean one
= parseSpecificationPart (token
);
2153 boolean two
= parseExecutionPart (token
);
2162 static boolean
findFortranTags (const unsigned int passCount
)
2165 exception_t exception
;
2168 Assert (passCount
< 3);
2169 Parent
= newToken ();
2170 token
= newToken ();
2171 FreeSourceForm
= (boolean
) (passCount
> 1);
2173 exception
= (exception_t
) setjmp (Exception
);
2174 if (exception
== ExceptionEOF
)
2176 else if (exception
== ExceptionFixedFormat
&& ! FreeSourceForm
)
2178 verbose ("%s: not fixed source form; retry as free source form\n",
2179 getInputFileName ());
2184 parseProgramUnit (token
);
2188 deleteToken (token
);
2189 deleteToken (Parent
);
2194 static void initializeFortran (const langType language
)
2196 Lang_fortran
= language
;
2197 buildFortranKeywordHash (language
);
2200 static void initializeF77 (const langType language
)
2202 Lang_f77
= language
;
2203 buildFortranKeywordHash (language
);
2206 extern parserDefinition
* FortranParser (void)
2208 static const char *const extensions
[] = {
2209 "f90", "f95", "f03",
2210 #ifndef CASE_INSENSITIVE_FILENAMES
2211 "F90", "F95", "F03",
2215 parserDefinition
* def
= parserNew ("Fortran");
2216 def
->kinds
= FortranKinds
;
2217 def
->kindCount
= KIND_COUNT (FortranKinds
);
2218 def
->extensions
= extensions
;
2219 def
->parser2
= findFortranTags
;
2220 def
->initialize
= initializeFortran
;
2224 extern parserDefinition
* F77Parser (void)
2226 static const char *const extensions
[] = {
2227 "f", "for", "ftn", "f77",
2228 #ifndef CASE_INSENSITIVE_FILENAMES
2229 "F", "FOR", "FTN", "F77",
2233 parserDefinition
* def
= parserNew ("F77");
2234 def
->kinds
= FortranKinds
;
2235 def
->kindCount
= KIND_COUNT (FortranKinds
);
2236 def
->extensions
= extensions
;
2237 def
->parser2
= findFortranTags
;
2238 def
->initialize
= initializeF77
;
2241 /* vi:set tabstop=4 shiftwidth=4: */