2
* $Id: fortran.c,v 1.41 2004/03/15 04:17:36 darren Exp $
4
* Copyright (c) 1998-2003, Darren Hiebert
6
* This source code is released for free distribution under the terms of the
7
* GNU General Public License.
9
* This module contains functions for generating tags for Fortran language
16
#include "general.h" /* must always come first */
20
#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 {
136
/* Used to determine whether keyword is valid for the token language and
139
typedef struct sKeywordDesc {
144
typedef enum eTokenType {
160
typedef enum eTagType {
176
TAG_COUNT /* must be last */
179
typedef struct sTokenInfo {
184
struct sTokenInfo *secondary;
185
unsigned long lineNumber;
193
static langType Lang_fortran;
194
static jmp_buf Exception;
196
static unsigned int Column;
197
static boolean FreeSourceForm;
198
static boolean ParsingString;
199
static tokenInfo *Parent;
201
/* indexed by tagType */
202
static kindOption FortranKinds [] = {
203
{ TRUE, 'b', "block data", "block data"},
204
{ TRUE, 'c', "common", "common blocks"},
205
{ TRUE, 'e', "entry", "entry points"},
206
{ TRUE, 'f', "function", "functions"},
207
{ FALSE, 'i', "interface", "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', "module", "modules"},
212
{ TRUE, 'n', "namelist", "namelists"},
213
{ TRUE, 'p', "program", "programs"},
214
{ TRUE, 's', "subroutine", "subroutines"},
215
{ TRUE, 't', "type", "derived types and structures"},
216
{ TRUE, 'v', "variable", "program (global) and module variables"}
219
/* For a definition of Fortran 77 with extensions:
220
* http://scienide.uwaterloo.ca/MIPSpro7/007-2362-004/sgi_html/index.html
222
* For the Compaq Fortran Reference Manual:
223
* http://h18009.www1.hp.com/fortran/docs/lrm/dflrm.htm
226
static const keywordDesc FortranKeywordTable [] = {
227
/* keyword keyword ID */
228
{ "allocatable", KEYWORD_allocatable },
229
{ "assignment", KEYWORD_assignment },
230
{ "automatic", KEYWORD_automatic },
231
{ "block", KEYWORD_block },
232
{ "byte", KEYWORD_byte },
233
{ "cexternal", KEYWORD_cexternal },
234
{ "cglobal", KEYWORD_cglobal },
235
{ "character", KEYWORD_character },
236
{ "common", KEYWORD_common },
237
{ "complex", KEYWORD_complex },
238
{ "contains", KEYWORD_contains },
239
{ "data", KEYWORD_data },
240
{ "dimension", KEYWORD_dimension },
241
{ "dll_export", KEYWORD_dllexport },
242
{ "dll_import", KEYWORD_dllimport },
243
{ "do", KEYWORD_do },
244
{ "double", KEYWORD_double },
245
{ "elemental", KEYWORD_elemental },
246
{ "end", KEYWORD_end },
247
{ "entry", KEYWORD_entry },
248
{ "equivalence", KEYWORD_equivalence },
249
{ "external", KEYWORD_external },
250
{ "format", KEYWORD_format },
251
{ "function", KEYWORD_function },
252
{ "if", KEYWORD_if },
253
{ "implicit", KEYWORD_implicit },
254
{ "include", KEYWORD_include },
255
{ "inline", KEYWORD_inline },
256
{ "integer", KEYWORD_integer },
257
{ "intent", KEYWORD_intent },
258
{ "interface", KEYWORD_interface },
259
{ "intrinsic", KEYWORD_intrinsic },
260
{ "logical", KEYWORD_logical },
261
{ "map", KEYWORD_map },
262
{ "module", KEYWORD_module },
263
{ "namelist", KEYWORD_namelist },
264
{ "operator", KEYWORD_operator },
265
{ "optional", KEYWORD_optional },
266
{ "parameter", KEYWORD_parameter },
267
{ "pascal", KEYWORD_pascal },
268
{ "pexternal", KEYWORD_pexternal },
269
{ "pglobal", KEYWORD_pglobal },
270
{ "pointer", KEYWORD_pointer },
271
{ "precision", KEYWORD_precision },
272
{ "private", KEYWORD_private },
273
{ "program", KEYWORD_program },
274
{ "public", KEYWORD_public },
275
{ "pure", KEYWORD_pure },
276
{ "real", KEYWORD_real },
277
{ "record", KEYWORD_record },
278
{ "recursive", KEYWORD_recursive },
279
{ "save", KEYWORD_save },
280
{ "select", KEYWORD_select },
281
{ "sequence", KEYWORD_sequence },
282
{ "static", KEYWORD_static },
283
{ "stdcall", KEYWORD_stdcall },
284
{ "structure", KEYWORD_structure },
285
{ "subroutine", KEYWORD_subroutine },
286
{ "target", KEYWORD_target },
287
{ "then", KEYWORD_then },
288
{ "type", KEYWORD_type },
289
{ "union", KEYWORD_union },
290
{ "use", KEYWORD_use },
291
{ "value", KEYWORD_value },
292
{ "virtual", KEYWORD_virtual },
293
{ "volatile", KEYWORD_volatile },
294
{ "where", KEYWORD_where },
295
{ "while", KEYWORD_while }
302
} Ancestors = { 0, 0, NULL };
305
* FUNCTION PROTOTYPES
307
static void parseStructureStmt (tokenInfo *const token);
308
static void parseUnionStmt (tokenInfo *const token);
309
static void parseDerivedTypeDef (tokenInfo *const token);
310
static void parseFunctionSubprogram (tokenInfo *const token);
311
static void parseSubroutineSubprogram (tokenInfo *const token);
314
* FUNCTION DEFINITIONS
317
static void ancestorPush (tokenInfo *const token)
319
enum { incrementalIncrease = 10 };
320
if (Ancestors.list == NULL)
322
Assert (Ancestors.max == 0);
324
Ancestors.max = incrementalIncrease;
325
Ancestors.list = xMalloc (Ancestors.max, tokenInfo);
327
else if (Ancestors.count == Ancestors.max)
329
Ancestors.max += incrementalIncrease;
330
Ancestors.list = xRealloc (Ancestors.list, Ancestors.max, tokenInfo);
332
Ancestors.list [Ancestors.count] = *token;
333
Ancestors.list [Ancestors.count].string = vStringNewCopy (token->string);
337
static void ancestorPop (void)
339
Assert (Ancestors.count > 0);
341
vStringDelete (Ancestors.list [Ancestors.count].string);
343
Ancestors.list [Ancestors.count].type = TOKEN_UNDEFINED;
344
Ancestors.list [Ancestors.count].keyword = KEYWORD_NONE;
345
Ancestors.list [Ancestors.count].secondary = NULL;
346
Ancestors.list [Ancestors.count].tag = TAG_UNDEFINED;
347
Ancestors.list [Ancestors.count].string = NULL;
348
Ancestors.list [Ancestors.count].lineNumber = 0L;
351
static const tokenInfo* ancestorScope (void)
353
tokenInfo *result = NULL;
355
for (i = Ancestors.count ; i > 0 && result == NULL ; --i)
357
tokenInfo *const token = Ancestors.list + i - 1;
358
if (token->type == TOKEN_IDENTIFIER &&
359
token->tag != TAG_UNDEFINED && token->tag != TAG_INTERFACE)
365
static const tokenInfo* ancestorTop (void)
367
Assert (Ancestors.count > 0);
368
return &Ancestors.list [Ancestors.count - 1];
371
#define ancestorCount() (Ancestors.count)
373
static void ancestorClear (void)
375
while (Ancestors.count > 0)
377
if (Ancestors.list != NULL)
378
eFree (Ancestors.list);
379
Ancestors.list = NULL;
384
static boolean insideInterface (void)
386
boolean result = FALSE;
388
for (i = 0 ; i < Ancestors.count && !result ; ++i)
390
if (Ancestors.list [i].tag == TAG_INTERFACE)
396
static void buildFortranKeywordHash (void)
398
const size_t count = sizeof (FortranKeywordTable) /
399
sizeof (FortranKeywordTable [0]);
401
for (i = 0 ; i < count ; ++i)
403
const keywordDesc* const p = &FortranKeywordTable [i];
404
addKeyword (p->name, Lang_fortran, (int) p->id);
409
* Tag generation functions
412
static tokenInfo *newToken (void)
414
tokenInfo *const token = xMalloc (1, tokenInfo);
416
token->type = TOKEN_UNDEFINED;
417
token->keyword = KEYWORD_NONE;
418
token->tag = TAG_UNDEFINED;
419
token->string = vStringNew ();
420
token->secondary = NULL;
421
token->lineNumber = getSourceLineNumber ();
422
token->filePosition = getInputFilePosition ();
427
static tokenInfo *newTokenFrom (tokenInfo *const token)
429
tokenInfo *result = newToken ();
431
result->string = vStringNewCopy (token->string);
432
token->secondary = NULL;
436
static void deleteToken (tokenInfo *const token)
440
vStringDelete (token->string);
441
deleteToken (token->secondary);
442
token->secondary = NULL;
447
static boolean isFileScope (const tagType type)
449
return (boolean) (type == TAG_LABEL || type == TAG_LOCAL);
452
static boolean includeTag (const tagType type)
455
Assert (type != TAG_UNDEFINED);
456
include = FortranKinds [(int) type].enabled;
457
if (include && isFileScope (type))
458
include = Option.include.fileScope;
462
static void makeFortranTag (tokenInfo *const token, tagType tag)
465
if (includeTag (token->tag))
467
const char *const name = vStringValue (token->string);
470
initTagEntry (&e, name);
472
if (token->tag == TAG_COMMON_BLOCK)
473
e.lineNumberEntry = (boolean) (Option.locate != EX_PATTERN);
475
e.lineNumber = token->lineNumber;
476
e.filePosition = token->filePosition;
477
e.isFileScope = isFileScope (token->tag);
478
e.kindName = FortranKinds [token->tag].name;
479
e.kind = FortranKinds [token->tag].letter;
480
e.truncateLine = (boolean) (token->tag != TAG_LABEL);
482
if (ancestorCount () > 0)
484
const tokenInfo* const scope = ancestorScope ();
487
e.extensionFields.scope [0] = FortranKinds [scope->tag].name;
488
e.extensionFields.scope [1] = vStringValue (scope->string);
491
if (! insideInterface () || includeTag (TAG_INTERFACE))
500
static int skipLine (void)
506
while (c != EOF && c != '\n');
511
static void makeLabelTag (vString *const label)
513
tokenInfo *token = newToken ();
514
token->type = TOKEN_LABEL;
515
vStringCopy (token->string, label);
516
makeFortranTag (token, TAG_LABEL);
520
static lineType getLineType (void)
522
static vString *label = NULL;
524
lineType type = LTYPE_UNDETERMINED;
527
label = vStringNew ();
529
do /* read in first 6 "margin" characters */
533
/* 3.2.1 Comment_Line. A comment line is any line that contains
534
* a C or an asterisk in column 1, or contains only blank characters
535
* in columns 1 through 72. A comment line that contains a C or
536
* an asterisk in column 1 may contain any character capable of
537
* representation in the processor in columns 2 through 72.
539
/* EXCEPTION! Some compilers permit '!' as a commment character here.
541
* Treat # and $ in column 1 as comment to permit preprocessor directives.
542
* Treat D and d in column 1 as comment for HP debug statements.
544
if (column == 0 && strchr ("*Cc!#$Dd", c) != NULL)
545
type = LTYPE_COMMENT;
546
else if (c == '\t') /* EXCEPTION! Some compilers permit a tab here */
549
type = LTYPE_INITIAL;
551
else if (column == 5)
553
/* 3.2.2 Initial_Line. An initial line is any line that is not
554
* a comment line and contains the character blank or the digit 0
555
* in column 6. Columns 1 through 5 may contain a statement label
556
* (3.4), or each of the columns 1 through 5 must contain the
559
if (c == ' ' || c == '0')
560
type = LTYPE_INITIAL;
562
/* 3.2.3 Continuation_Line. A continuation line is any line that
563
* contains any character of the FORTRAN character set other than
564
* the character blank or the digit 0 in column 6 and contains
565
* only blank characters in columns 1 through 5.
567
else if (vStringLength (label) == 0)
568
type = LTYPE_CONTINUATION;
570
type = LTYPE_INVALID;
578
else if (isdigit (c))
579
vStringPut (label, c);
581
type = LTYPE_INVALID;
584
} while (column < 6 && type == LTYPE_UNDETERMINED);
586
Assert (type != LTYPE_UNDETERMINED);
588
if (vStringLength (label) > 0)
590
vStringTerminate (label);
591
makeLabelTag (label);
592
vStringClear (label);
597
static int getFixedFormChar (void)
599
boolean newline = FALSE;
605
#ifdef STRICT_FIXED_FORM
606
/* EXCEPTION! Some compilers permit more than 72 characters per line.
618
newline = TRUE; /* need to check for continuation line */
621
else if (c == '!' && ! ParsingString)
624
newline = TRUE; /* need to check for continuation line */
627
else if (c == '&') /* check for free source form */
629
const int c2 = fileGetc ();
631
longjmp (Exception, (int) ExceptionFixedFormat);
638
type = getLineType ();
641
case LTYPE_UNDETERMINED:
643
longjmp (Exception, (int) ExceptionFixedFormat);
646
case LTYPE_SHORT: break;
647
case LTYPE_COMMENT: skipLine (); break;
664
/* fall through to next case */
665
case LTYPE_CONTINUATION:
671
} while (isBlank (c));
682
Assert ("Unexpected line type" == NULL);
688
static int skipToNextLine (void)
696
static int getFreeFormChar (void)
698
static boolean newline = TRUE;
699
boolean advanceLine = FALSE;
702
/* If the last nonblank, non-comment character of a FORTRAN 90
703
* free-format text line is an ampersand then the next non-comment
704
* line is a continuation line.
710
while (isspace (c) && c != '\n');
724
else if (newline && (c == '!' || c == '#'))
730
if (c == '!' || (newline && c == '#'))
732
c = skipToNextLine ();
741
newline = (boolean) (c == '\n');
745
static int getChar (void)
754
else if (FreeSourceForm)
755
c = getFreeFormChar ();
757
c = getFixedFormChar ();
762
static void ungetChar (const int c)
767
/* If a numeric is passed in 'c', this is used as the first digit of the
768
* numeric being parsed.
770
static vString *parseInteger (int c)
772
static vString *string = NULL;
775
string = vStringNew ();
776
vStringClear (string);
780
vStringPut (string, c);
783
else if (! isdigit (c))
785
while (c != EOF && isdigit (c))
787
vStringPut (string, c);
790
vStringTerminate (string);
796
while (c != EOF && isalpha (c));
803
static vString *parseNumeric (int c)
805
static vString *string = NULL;
808
string = vStringNew ();
809
vStringCopy (string, parseInteger (c));
814
vStringPut (string, c);
815
vStringCat (string, parseInteger ('\0'));
818
if (tolower (c) == 'e')
820
vStringPut (string, c);
821
vStringCat (string, parseInteger ('\0'));
826
vStringTerminate (string);
831
static void parseString (vString *const string, const int delimeter)
833
const unsigned long inputLineNumber = getInputLineNumber ();
835
ParsingString = TRUE;
837
while (c != delimeter && c != '\n' && c != EOF)
839
vStringPut (string, c);
842
if (c == '\n' || c == EOF)
844
verbose ("%s: unterminated character string at line %lu\n",
845
getInputFileName (), inputLineNumber);
847
longjmp (Exception, (int) ExceptionEOF);
848
else if (! FreeSourceForm)
849
longjmp (Exception, (int) ExceptionFixedFormat);
851
vStringTerminate (string);
852
ParsingString = FALSE;
855
/* Read a C identifier beginning with "firstChar" and places it into "name".
857
static void parseIdentifier (vString *const string, const int firstChar)
863
vStringPut (string, c);
865
} while (isident (c));
867
vStringTerminate (string);
868
ungetChar (c); /* unget non-identifier character */
871
/* Analyzes the identifier contained in a statement described by the
872
* statement structure and adjusts the structure according the significance
875
static keywordId analyzeToken (vString *const name)
877
static vString *keyword = NULL;
881
keyword = vStringNew ();
882
vStringCopyToLower (keyword, name);
883
id = (keywordId) lookupKeyword (vStringValue (keyword), Lang_fortran);
888
static void checkForLabel (void)
890
tokenInfo* token = NULL;
898
for (length = 0 ; isdigit (c) && length < 5 ; ++length)
903
token->type = TOKEN_LABEL;
905
vStringPut (token->string, c);
910
Assert (token != NULL);
911
vStringTerminate (token->string);
912
makeFortranTag (token, TAG_LABEL);
918
static void readIdentifier (tokenInfo *const token, const int c)
920
parseIdentifier (token->string, c);
921
token->keyword = analyzeToken (token->string);
922
if (! isKeyword (token, KEYWORD_NONE))
923
token->type = TOKEN_KEYWORD;
926
token->type = TOKEN_IDENTIFIER;
927
if (strncmp (vStringValue (token->string), "end", 3) == 0)
929
vString *const sub = vStringNewInit (vStringValue (token->string) + 3);
930
const keywordId kw = analyzeToken (sub);
932
if (kw != KEYWORD_NONE)
934
token->secondary = newToken ();
935
token->secondary->type = TOKEN_KEYWORD;
936
token->secondary->keyword = kw;
937
token->keyword = KEYWORD_end;
943
static void readToken (tokenInfo *const token)
947
deleteToken (token->secondary);
948
token->type = TOKEN_UNDEFINED;
949
token->tag = TAG_UNDEFINED;
950
token->keyword = KEYWORD_NONE;
951
token->secondary = NULL;
952
vStringClear (token->string);
957
token->lineNumber = getSourceLineNumber ();
958
token->filePosition = getInputFilePosition ();
962
case EOF: longjmp (Exception, (int) ExceptionEOF); break;
963
case ' ': goto getNextChar;
964
case '\t': goto getNextChar;
965
case ',': token->type = TOKEN_COMMA; break;
966
case '(': token->type = TOKEN_PAREN_OPEN; break;
967
case ')': token->type = TOKEN_PAREN_CLOSE; break;
968
case '%': token->type = TOKEN_PERCENT; break;
978
const char *const operatorChars = "*/+=<>";
980
vStringPut (token->string, c);
982
} while (strchr (operatorChars, c) != NULL);
984
vStringTerminate (token->string);
985
token->type = TOKEN_OPERATOR;
1001
/* fall through to newline case */
1003
token->type = TOKEN_STATEMENT_END;
1009
parseIdentifier (token->string, c);
1013
vStringPut (token->string, c);
1014
vStringTerminate (token->string);
1015
token->type = TOKEN_OPERATOR;
1020
token->type = TOKEN_UNDEFINED;
1026
parseString (token->string, c);
1027
token->type = TOKEN_STRING;
1031
token->type = TOKEN_STATEMENT_END;
1037
token->type = TOKEN_DOUBLE_COLON;
1041
token->type = TOKEN_UNDEFINED;
1047
readIdentifier (token, c);
1048
else if (isdigit (c))
1050
vStringCat (token->string, parseNumeric (c));
1051
token->type = TOKEN_NUMERIC;
1054
token->type = TOKEN_UNDEFINED;
1059
static void readSubToken (tokenInfo *const token)
1061
if (token->secondary == NULL)
1063
token->secondary = newToken ();
1064
readToken (token->secondary);
1066
Assert (token->secondary != NULL);
1070
* Scanning functions
1073
static void skipToToken (tokenInfo *const token, tokenType type)
1075
while (! isType (token, type) && ! isType (token, TOKEN_STATEMENT_END) &&
1076
!(token->secondary != NULL && isType (token->secondary, TOKEN_STATEMENT_END)))
1080
static void skipPast (tokenInfo *const token, tokenType type)
1082
skipToToken (token, type);
1083
if (! isType (token, TOKEN_STATEMENT_END))
1087
static void skipToNextStatement (tokenInfo *const token)
1091
skipToToken (token, TOKEN_STATEMENT_END);
1093
} while (isType (token, TOKEN_STATEMENT_END));
1096
/* skip over parenthesis enclosed contents starting at next token.
1097
* Token is left at the first token following closing parenthesis. If an
1098
* opening parenthesis is not found, `token' is moved to the end of the
1101
static void skipOverParens (tokenInfo *const token)
1105
if (isType (token, TOKEN_STATEMENT_END))
1107
else if (isType (token, TOKEN_PAREN_OPEN))
1109
else if (isType (token, TOKEN_PAREN_CLOSE))
1112
} while (level > 0);
1115
static boolean isTypeSpec (tokenInfo *const token)
1118
switch (token->keyword)
1121
case KEYWORD_integer:
1123
case KEYWORD_double:
1124
case KEYWORD_complex:
1125
case KEYWORD_character:
1126
case KEYWORD_logical:
1127
case KEYWORD_record:
1138
static boolean isSubprogramPrefix (tokenInfo *const token)
1141
switch (token->keyword)
1143
case KEYWORD_elemental:
1145
case KEYWORD_recursive:
1146
case KEYWORD_stdcall:
1157
* is INTEGER [kind-selector]
1158
* or REAL [kind-selector] is ( etc. )
1159
* or DOUBLE PRECISION
1160
* or COMPLEX [kind-selector]
1161
* or CHARACTER [kind-selector]
1162
* or LOGICAL [kind-selector]
1163
* or TYPE ( type-name )
1165
* Note that INTEGER and REAL may be followed by "*N" where "N" is an integer
1167
static void parseTypeSpec (tokenInfo *const token)
1169
/* parse type-spec, leaving `token' at first token following type-spec */
1170
Assert (isTypeSpec (token));
1171
switch (token->keyword)
1173
case KEYWORD_character:
1174
/* skip char-selector */
1176
if (isType (token, TOKEN_OPERATOR) &&
1177
strcmp (vStringValue (token->string), "*") == 0)
1179
if (isType (token, TOKEN_PAREN_OPEN))
1180
skipOverParens (token);
1181
else if (isType (token, TOKEN_NUMERIC))
1187
case KEYWORD_complex:
1188
case KEYWORD_integer:
1189
case KEYWORD_logical:
1192
if (isType (token, TOKEN_PAREN_OPEN))
1193
skipOverParens (token); /* skip kind-selector */
1194
if (isType (token, TOKEN_OPERATOR) &&
1195
strcmp (vStringValue (token->string), "*") == 0)
1202
case KEYWORD_double:
1204
if (isKeyword (token, KEYWORD_complex) ||
1205
isKeyword (token, KEYWORD_precision))
1208
skipToToken (token, TOKEN_STATEMENT_END);
1211
case KEYWORD_record:
1213
if (isType (token, TOKEN_OPERATOR) &&
1214
strcmp (vStringValue (token->string), "/") == 0)
1216
readToken (token); /* skip to structure name */
1217
readToken (token); /* skip to '/' */
1218
readToken (token); /* skip to variable name */
1224
if (isType (token, TOKEN_PAREN_OPEN))
1225
skipOverParens (token); /* skip type-name */
1227
parseDerivedTypeDef (token);
1231
skipToToken (token, TOKEN_STATEMENT_END);
1236
static boolean skipStatementIfKeyword (tokenInfo *const token, keywordId keyword)
1238
boolean result = FALSE;
1239
if (isKeyword (token, keyword))
1242
skipToNextStatement (token);
1247
/* parse a list of qualifying specifiers, leaving `token' at first token
1248
* following list. Examples of such specifiers are:
1249
* [[, attr-spec] ::]
1250
* [[, component-attr-spec-list] ::]
1254
* or access-spec (is PUBLIC or PRIVATE)
1256
* or DIMENSION ( array-spec )
1258
* or INTENT ( intent-spec )
1265
* component-attr-spec
1267
* or DIMENSION ( component-array-spec )
1269
static void parseQualifierSpecList (tokenInfo *const token)
1273
readToken (token); /* should be an attr-spec */
1274
switch (token->keyword)
1276
case KEYWORD_parameter:
1277
case KEYWORD_allocatable:
1278
case KEYWORD_external:
1279
case KEYWORD_intrinsic:
1280
case KEYWORD_optional:
1281
case KEYWORD_private:
1282
case KEYWORD_pointer:
1283
case KEYWORD_public:
1285
case KEYWORD_target:
1289
case KEYWORD_dimension:
1290
case KEYWORD_intent:
1292
skipOverParens (token);
1295
default: skipToToken (token, TOKEN_STATEMENT_END); break;
1297
} while (isType (token, TOKEN_COMMA));
1298
if (! isType (token, TOKEN_DOUBLE_COLON))
1299
skipToToken (token, TOKEN_STATEMENT_END);
1302
static tagType variableTagType (void)
1304
tagType result = TAG_VARIABLE;
1305
if (ancestorCount () > 0)
1307
const tokenInfo* const parent = ancestorTop ();
1308
switch (parent->tag)
1310
case TAG_MODULE: result = TAG_VARIABLE; break;
1311
case TAG_DERIVED_TYPE: result = TAG_COMPONENT; break;
1312
case TAG_FUNCTION: result = TAG_LOCAL; break;
1313
case TAG_SUBROUTINE: result = TAG_LOCAL; break;
1314
default: result = TAG_VARIABLE; break;
1320
static void parseEntityDecl (tokenInfo *const token)
1322
Assert (isType (token, TOKEN_IDENTIFIER));
1323
makeFortranTag (token, variableTagType ());
1325
if (isType (token, TOKEN_PAREN_OPEN))
1326
skipOverParens (token);
1327
if (isType (token, TOKEN_OPERATOR) &&
1328
strcmp (vStringValue (token->string), "*") == 0)
1330
readToken (token); /* read char-length */
1331
if (isType (token, TOKEN_PAREN_OPEN))
1332
skipOverParens (token);
1336
if (isType (token, TOKEN_OPERATOR))
1338
if (strcmp (vStringValue (token->string), "/") == 0)
1339
{ /* skip over initializations of structure field */
1341
skipPast (token, TOKEN_OPERATOR);
1343
else if (strcmp (vStringValue (token->string), "=") == 0)
1345
while (! isType (token, TOKEN_COMMA) &&
1346
! isType (token, TOKEN_STATEMENT_END))
1349
if (isType (token, TOKEN_PAREN_OPEN))
1350
skipOverParens (token);
1354
/* token left at either comma or statement end */
1357
static void parseEntityDeclList (tokenInfo *const token)
1359
if (isType (token, TOKEN_PERCENT))
1360
skipToNextStatement (token);
1361
else while (isType (token, TOKEN_IDENTIFIER) ||
1362
(isType (token, TOKEN_KEYWORD) &&
1363
!isKeyword (token, KEYWORD_function) &&
1364
!isKeyword (token, KEYWORD_subroutine)))
1366
/* compilers accept keywoeds as identifiers */
1367
if (isType (token, TOKEN_KEYWORD))
1368
token->type = TOKEN_IDENTIFIER;
1369
parseEntityDecl (token);
1370
if (isType (token, TOKEN_COMMA))
1372
else if (isType (token, TOKEN_STATEMENT_END))
1374
skipToNextStatement (token);
1380
/* type-declaration-stmt is
1381
* type-spec [[, attr-spec] ... ::] entity-decl-list
1383
static void parseTypeDeclarationStmt (tokenInfo *const token)
1385
Assert (isTypeSpec (token));
1386
parseTypeSpec (token);
1387
if (!isType (token, TOKEN_STATEMENT_END)) /* if not end of derived type... */
1389
if (isType (token, TOKEN_COMMA))
1390
parseQualifierSpecList (token);
1391
if (isType (token, TOKEN_DOUBLE_COLON))
1393
parseEntityDeclList (token);
1395
if (isType (token, TOKEN_STATEMENT_END))
1396
skipToNextStatement (token);
1400
* NAMELIST /namelist-group-name/ namelist-group-object-list
1401
* [[,]/[namelist-group-name]/ namelist-block-object-list] ...
1403
* namelist-group-object is
1407
* COMMON [/[common-block-name]/] common-block-object-list
1408
* [[,]/[common-block-name]/ common-block-object-list] ...
1410
* common-block-object is
1411
* variable-name [ ( explicit-shape-spec-list ) ]
1413
static void parseCommonNamelistStmt (tokenInfo *const token, tagType type)
1415
Assert (isKeyword (token, KEYWORD_common) ||
1416
isKeyword (token, KEYWORD_namelist));
1420
if (isType (token, TOKEN_OPERATOR) &&
1421
strcmp (vStringValue (token->string), "/") == 0)
1424
if (isType (token, TOKEN_IDENTIFIER))
1426
makeFortranTag (token, type);
1429
skipPast (token, TOKEN_OPERATOR);
1431
if (isType (token, TOKEN_IDENTIFIER))
1432
makeFortranTag (token, TAG_LOCAL);
1434
if (isType (token, TOKEN_PAREN_OPEN))
1435
skipOverParens (token); /* skip explicit-shape-spec-list */
1436
if (isType (token, TOKEN_COMMA))
1438
} while (! isType (token, TOKEN_STATEMENT_END));
1439
skipToNextStatement (token);
1442
static void parseFieldDefinition (tokenInfo *const token)
1444
if (isTypeSpec (token))
1445
parseTypeDeclarationStmt (token);
1446
else if (isKeyword (token, KEYWORD_structure))
1447
parseStructureStmt (token);
1448
else if (isKeyword (token, KEYWORD_union))
1449
parseUnionStmt (token);
1451
skipToNextStatement (token);
1454
static void parseMap (tokenInfo *const token)
1456
Assert (isKeyword (token, KEYWORD_map));
1457
skipToNextStatement (token);
1458
while (! isKeyword (token, KEYWORD_end))
1459
parseFieldDefinition (token);
1460
readSubToken (token);
1461
Assert (isSecondaryKeyword (token, KEYWORD_map));
1462
skipToNextStatement (token);
1467
* [field-definition] [field-definition] ...
1470
* [field-definition] [field-definition] ...
1473
* [field-definition]
1474
* [field-definition] ...
1479
* Typed data declarations (variables or arrays) in structure declarations
1480
* have the form of normal Fortran typed data declarations. Data items with
1481
* different types can be freely intermixed within a structure declaration.
1483
* Unnamed fields can be declared in a structure by specifying the pseudo
1484
* name %FILL in place of an actual field name. You can use this mechanism to
1485
* generate empty space in a record for purposes such as alignment.
1487
* All mapped field declarations that are made within a UNION declaration
1488
* share a common location within the containing structure. When initializing
1489
* the fields within a UNION, the final initialization value assigned
1490
* overlays any value previously assigned to a field definition that shares
1493
static void parseUnionStmt (tokenInfo *const token)
1495
Assert (isKeyword (token, KEYWORD_union));
1496
skipToNextStatement (token);
1497
while (isKeyword (token, KEYWORD_map))
1499
Assert (isKeyword (token, KEYWORD_end));
1500
readSubToken (token);
1501
Assert (isSecondaryKeyword (token, KEYWORD_union));
1502
skipToNextStatement (token);
1505
/* STRUCTURE [/structure-name/] [field-names]
1506
* [field-definition]
1507
* [field-definition] ...
1511
* identifies the structure in a subsequent RECORD statement.
1512
* Substructures can be established within a structure by means of either
1513
* a nested STRUCTURE declaration or a RECORD statement.
1516
* (for substructure declarations only) one or more names having the
1517
* structure of the substructure being defined.
1520
* can be one or more of the following:
1522
* Typed data declarations, which can optionally include one or more
1523
* data initialization values.
1525
* Substructure declarations (defined by either RECORD statements or
1526
* subsequent STRUCTURE statements).
1528
* UNION declarations, which are mapped fields defined by a block of
1529
* statements. The syntax of a UNION declaration is described below.
1531
* PARAMETER statements, which do not affect the form of the
1534
static void parseStructureStmt (tokenInfo *const token)
1537
Assert (isKeyword (token, KEYWORD_structure));
1539
if (isType (token, TOKEN_OPERATOR) &&
1540
strcmp (vStringValue (token->string), "/") == 0)
1541
{ /* read structure name */
1543
if (isType (token, TOKEN_IDENTIFIER))
1544
makeFortranTag (token, TAG_DERIVED_TYPE);
1545
name = newTokenFrom (token);
1546
skipPast (token, TOKEN_OPERATOR);
1549
{ /* fake out anonymous structure */
1551
name->type = TOKEN_IDENTIFIER;
1552
name->tag = TAG_DERIVED_TYPE;
1553
vStringCopyS (name->string, "anonymous");
1555
while (isType (token, TOKEN_IDENTIFIER))
1556
{ /* read field names */
1557
makeFortranTag (token, TAG_COMPONENT);
1559
if (isType (token, TOKEN_COMMA))
1562
skipToNextStatement (token);
1563
ancestorPush (name);
1564
while (! isKeyword (token, KEYWORD_end))
1565
parseFieldDefinition (token);
1566
readSubToken (token);
1567
Assert (isSecondaryKeyword (token, KEYWORD_structure));
1568
skipToNextStatement (token);
1573
/* specification-stmt
1574
* is access-stmt (is access-spec [[::] access-id-list)
1575
* or allocatable-stmt (is ALLOCATABLE [::] array-name etc.)
1576
* or common-stmt (is COMMON [ / [common-block-name] /] etc.)
1577
* or data-stmt (is DATA data-stmt-list [[,] data-stmt-set] ...)
1578
* or dimension-stmt (is DIMENSION [::] array-name etc.)
1579
* or equivalence-stmt (is EQUIVALENCE equivalence-set-list)
1580
* or external-stmt (is EXTERNAL etc.)
1581
* or intent-stmt (is INTENT ( intent-spec ) [::] etc.)
1582
* or instrinsic-stmt (is INTRINSIC etc.)
1583
* or namelist-stmt (is NAMELIST / namelist-group-name / etc.)
1584
* or optional-stmt (is OPTIONAL [::] etc.)
1585
* or pointer-stmt (is POINTER [::] object-name etc.)
1586
* or save-stmt (is SAVE etc.)
1587
* or target-stmt (is TARGET [::] object-name etc.)
1589
* access-spec is PUBLIC or PRIVATE
1591
static boolean parseSpecificationStmt (tokenInfo *const token)
1593
boolean result = TRUE;
1594
switch (token->keyword)
1596
case KEYWORD_common:
1597
parseCommonNamelistStmt (token, TAG_COMMON_BLOCK);
1600
case KEYWORD_namelist:
1601
parseCommonNamelistStmt (token, TAG_NAMELIST);
1604
case KEYWORD_structure:
1605
parseStructureStmt (token);
1608
case KEYWORD_allocatable:
1610
case KEYWORD_dimension:
1611
case KEYWORD_equivalence:
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
Assert (isSecondaryKeyword (token, KEYWORD_type));
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
Assert (isSecondaryKeyword (token, KEYWORD_interface));
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
Assert (isSecondaryKeyword (token, KEYWORD_NONE) ||
1932
isSecondaryKeyword (token, KEYWORD_block));
1933
skipToNextStatement (token);
1937
/* internal-subprogram-part is
1938
* contains-stmt (is CONTAINS)
1939
* internal-subprogram
1940
* [internal-subprogram] ...
1942
* internal-subprogram
1943
* is function-subprogram
1944
* or subroutine-subprogram
1946
static void parseInternalSubprogramPart (tokenInfo *const token)
1948
boolean done = FALSE;
1949
if (isKeyword (token, KEYWORD_contains))
1950
skipToNextStatement (token);
1953
switch (token->keyword)
1955
case KEYWORD_function: parseFunctionSubprogram (token); break;
1956
case KEYWORD_subroutine: parseSubroutineSubprogram (token); break;
1957
case KEYWORD_end: done = TRUE; break;
1960
if (isSubprogramPrefix (token))
1962
else if (isTypeSpec (token))
1963
parseTypeSpec (token);
1972
* mudule-stmt (is MODULE module-name)
1973
* [specification-part]
1974
* [module-subprogram-part]
1975
* end-module-stmt (is END [MODULE [module-name]])
1977
* module-subprogram-part
1978
* contains-stmt (is CONTAINS)
1980
* [module-subprogram] ...
1983
* is function-subprogram
1984
* or subroutine-subprogram
1986
static void parseModule (tokenInfo *const token)
1988
Assert (isKeyword (token, KEYWORD_module));
1990
if (isType (token, TOKEN_IDENTIFIER))
1991
makeFortranTag (token, TAG_MODULE);
1992
ancestorPush (token);
1993
skipToNextStatement (token);
1994
parseSpecificationPart (token);
1995
if (isKeyword (token, KEYWORD_contains))
1996
parseInternalSubprogramPart (token);
1997
while (! isKeyword (token, KEYWORD_end))
1998
skipToNextStatement (token);
1999
readSubToken (token);
2000
Assert (isSecondaryKeyword (token, KEYWORD_NONE) ||
2001
isSecondaryKeyword (token, KEYWORD_module));
2002
skipToNextStatement (token);
2007
* executable-construct
2009
* executable-contstruct is
2010
* execution-part-construct [execution-part-construct]
2012
* execution-part-construct
2013
* is executable-construct
2018
static boolean parseExecutionPart (tokenInfo *const token)
2020
boolean result = FALSE;
2021
boolean done = FALSE;
2024
switch (token->keyword)
2027
if (isSubprogramPrefix (token))
2030
skipToNextStatement (token);
2035
parseEntryStmt (token);
2039
case KEYWORD_contains:
2040
case KEYWORD_function:
2041
case KEYWORD_subroutine:
2046
readSubToken (token);
2047
if (isSecondaryKeyword (token, KEYWORD_do) ||
2048
isSecondaryKeyword (token, KEYWORD_if) ||
2049
isSecondaryKeyword (token, KEYWORD_select) ||
2050
isSecondaryKeyword (token, KEYWORD_where))
2052
skipToNextStatement (token);
2063
static void parseSubprogram (tokenInfo *const token, const tagType tag)
2065
Assert (isKeyword (token, KEYWORD_program) ||
2066
isKeyword (token, KEYWORD_function) ||
2067
isKeyword (token, KEYWORD_subroutine));
2069
if (isType (token, TOKEN_IDENTIFIER))
2070
makeFortranTag (token, tag);
2071
ancestorPush (token);
2072
skipToNextStatement (token);
2073
parseSpecificationPart (token);
2074
parseExecutionPart (token);
2075
if (isKeyword (token, KEYWORD_contains))
2076
parseInternalSubprogramPart (token);
2077
Assert (isKeyword (token, KEYWORD_end));
2078
readSubToken (token);
2079
Assert (isSecondaryKeyword (token, KEYWORD_NONE) ||
2080
isSecondaryKeyword (token, KEYWORD_program) ||
2081
isSecondaryKeyword (token, KEYWORD_function) ||
2082
isSecondaryKeyword (token, KEYWORD_subroutine));
2083
skipToNextStatement (token);
2088
/* function-subprogram is
2089
* function-stmt (is [prefix] FUNCTION function-name etc.)
2090
* [specification-part]
2092
* [internal-subprogram-part]
2093
* end-function-stmt (is END [FUNCTION [function-name]])
2096
* is type-spec [RECURSIVE]
2097
* or [RECURSIVE] type-spec
2099
static void parseFunctionSubprogram (tokenInfo *const token)
2101
parseSubprogram (token, TAG_FUNCTION);
2104
/* subroutine-subprogram is
2105
* subroutine-stmt (is [RECURSIVE] SUBROUTINE subroutine-name etc.)
2106
* [specification-part]
2108
* [internal-subprogram-part]
2109
* end-subroutine-stmt (is END [SUBROUTINE [function-name]])
2111
static void parseSubroutineSubprogram (tokenInfo *const token)
2113
parseSubprogram (token, TAG_SUBROUTINE);
2117
* [program-stmt] (is PROGRAM program-name)
2118
* [specification-part]
2120
* [internal-subprogram-part ]
2123
static void parseMainProgram (tokenInfo *const token)
2125
parseSubprogram (token, TAG_PROGRAM);
2130
* or external-subprogram (is function-subprogram or subroutine-subprogram)
2134
static void parseProgramUnit (tokenInfo *const token)
2139
if (isType (token, TOKEN_STATEMENT_END))
2141
else switch (token->keyword)
2143
case KEYWORD_block: parseBlockData (token); break;
2144
case KEYWORD_end: skipToNextStatement (token); break;
2145
case KEYWORD_function: parseFunctionSubprogram (token); break;
2146
case KEYWORD_module: parseModule (token); break;
2147
case KEYWORD_program: parseMainProgram (token); break;
2148
case KEYWORD_subroutine: parseSubroutineSubprogram (token); break;
2151
if (isSubprogramPrefix (token))
2155
boolean one = parseSpecificationPart (token);
2156
boolean two = parseExecutionPart (token);
2165
static boolean findFortranTags (const unsigned int passCount)
2168
exception_t exception;
2171
Assert (passCount < 3);
2172
Parent = newToken ();
2173
token = newToken ();
2174
FreeSourceForm = (boolean) (passCount > 1);
2176
exception = (exception_t) setjmp (Exception);
2177
if (exception == ExceptionEOF)
2179
else if (exception == ExceptionFixedFormat && ! FreeSourceForm)
2181
verbose ("%s: not fixed source form; retry as free source form\n",
2182
getInputFileName ());
2187
parseProgramUnit (token);
2191
deleteToken (token);
2192
deleteToken (Parent);
2197
static void initialize (const langType language)
2199
Lang_fortran = language;
2200
buildFortranKeywordHash ();
2203
extern parserDefinition* FortranParser (void)
2205
static const char *const extensions [] = {
2206
"f", "for", "ftn", "f77", "f90", "f95",
2207
#ifndef CASE_INSENSITIVE_FILENAMES
2208
"F", "FOR", "FTN", "F77", "F90", "F95",
2212
parserDefinition* def = parserNew ("Fortran");
2213
def->kinds = FortranKinds;
2214
def->kindCount = KIND_COUNT (FortranKinds);
2215
def->extensions = extensions;
2216
def->parser2 = findFortranTags;
2217
def->initialize = initialize;
2221
/* vi:set tabstop=8 shiftwidth=4: */