📄 fortran.c
字号:
static boolean isTypeSpec (tokenInfo *const token){ boolean result; switch (token->keyword) { case KEYWORD_byte: case KEYWORD_integer: case KEYWORD_real: case KEYWORD_double: case KEYWORD_complex: case KEYWORD_character: case KEYWORD_logical: case KEYWORD_record: case KEYWORD_type: result = TRUE; break; default: result = FALSE; break; } return result;}static boolean isSubprogramPrefix (tokenInfo *const token){ boolean result; switch (token->keyword) { case KEYWORD_elemental: case KEYWORD_pure: case KEYWORD_recursive: case KEYWORD_stdcall: result = TRUE; break; default: result = FALSE; break; } return result;}/* type-spec * is INTEGER [kind-selector] * or REAL [kind-selector] is ( etc. ) * or DOUBLE PRECISION * or COMPLEX [kind-selector] * or CHARACTER [kind-selector] * or LOGICAL [kind-selector] * or TYPE ( type-name ) * * Note that INTEGER and REAL may be followed by "*N" where "N" is an integer */static void parseTypeSpec (tokenInfo *const token){ /* parse type-spec, leaving `token' at first token following type-spec */ Assert (isTypeSpec (token)); switch (token->keyword) { case KEYWORD_character: /* skip char-selector */ readToken (token); if (isType (token, TOKEN_OPERATOR) && strcmp (vStringValue (token->string), "*") == 0) readToken (token); if (isType (token, TOKEN_PAREN_OPEN)) skipOverParens (token); else if (isType (token, TOKEN_NUMERIC)) readToken (token); break; case KEYWORD_byte: case KEYWORD_complex: case KEYWORD_integer: case KEYWORD_logical: case KEYWORD_real: readToken (token); if (isType (token, TOKEN_PAREN_OPEN)) skipOverParens (token); /* skip kind-selector */ if (isType (token, TOKEN_OPERATOR) && strcmp (vStringValue (token->string), "*") == 0) { readToken (token); readToken (token); } break; case KEYWORD_double: readToken (token); if (isKeyword (token, KEYWORD_complex) || isKeyword (token, KEYWORD_precision)) readToken (token); else skipToToken (token, TOKEN_STATEMENT_END); break; case KEYWORD_record: readToken (token); if (isType (token, TOKEN_OPERATOR) && strcmp (vStringValue (token->string), "/") == 0) { readToken (token); /* skip to structure name */ readToken (token); /* skip to '/' */ readToken (token); /* skip to variable name */ } break; case KEYWORD_type: readToken (token); if (isType (token, TOKEN_PAREN_OPEN)) skipOverParens (token); /* skip type-name */ else parseDerivedTypeDef (token); break; default: skipToToken (token, TOKEN_STATEMENT_END); break; }}static boolean skipStatementIfKeyword (tokenInfo *const token, keywordId keyword){ boolean result = FALSE; if (isKeyword (token, keyword)) { result = TRUE; skipToNextStatement (token); } return result;}/* parse a list of qualifying specifiers, leaving `token' at first token * following list. Examples of such specifiers are: * [[, attr-spec] ::] * [[, component-attr-spec-list] ::] * * attr-spec * is PARAMETER * or access-spec (is PUBLIC or PRIVATE) * or ALLOCATABLE * or DIMENSION ( array-spec ) * or EXTERNAL * or INTENT ( intent-spec ) * or INTRINSIC * or OPTIONAL * or POINTER * or SAVE * or TARGET * * component-attr-spec * is POINTER * or DIMENSION ( component-array-spec ) */static void parseQualifierSpecList (tokenInfo *const token){ do { readToken (token); /* should be an attr-spec */ switch (token->keyword) { case KEYWORD_parameter: case KEYWORD_allocatable: case KEYWORD_external: case KEYWORD_intrinsic: case KEYWORD_optional: case KEYWORD_private: case KEYWORD_pointer: case KEYWORD_public: case KEYWORD_save: case KEYWORD_target: readToken (token); break; case KEYWORD_dimension: case KEYWORD_intent: readToken (token); skipOverParens (token); break; default: skipToToken (token, TOKEN_STATEMENT_END); break; } } while (isType (token, TOKEN_COMMA)); if (! isType (token, TOKEN_DOUBLE_COLON)) skipToToken (token, TOKEN_STATEMENT_END);}static tagType variableTagType (void){ tagType result = TAG_VARIABLE; if (ancestorCount () > 0) { const tokenInfo* const parent = ancestorTop (); switch (parent->tag) { case TAG_MODULE: result = TAG_VARIABLE; break; case TAG_DERIVED_TYPE: result = TAG_COMPONENT; break; case TAG_FUNCTION: result = TAG_LOCAL; break; case TAG_SUBROUTINE: result = TAG_LOCAL; break; default: result = TAG_VARIABLE; break; } } return result;}static void parseEntityDecl (tokenInfo *const token){ Assert (isType (token, TOKEN_IDENTIFIER)); makeFortranTag (token, variableTagType ()); readToken (token); if (isType (token, TOKEN_PAREN_OPEN)) skipOverParens (token); if (isType (token, TOKEN_OPERATOR) && strcmp (vStringValue (token->string), "*") == 0) { readToken (token); /* read char-length */ if (isType (token, TOKEN_PAREN_OPEN)) skipOverParens (token); else readToken (token); } if (isType (token, TOKEN_OPERATOR)) { if (strcmp (vStringValue (token->string), "/") == 0) { /* skip over initializations of structure field */ readToken (token); skipPast (token, TOKEN_OPERATOR); } else if (strcmp (vStringValue (token->string), "=") == 0) { while (! isType (token, TOKEN_COMMA) && ! isType (token, TOKEN_STATEMENT_END)) { readToken (token); if (isType (token, TOKEN_PAREN_OPEN)) skipOverParens (token); } } } /* token left at either comma or statement end */}static void parseEntityDeclList (tokenInfo *const token){ if (isType (token, TOKEN_PERCENT)) skipToNextStatement (token); else while (isType (token, TOKEN_IDENTIFIER) || (isType (token, TOKEN_KEYWORD) && !isKeyword (token, KEYWORD_function) && !isKeyword (token, KEYWORD_subroutine))) { /* compilers accept keywoeds as identifiers */ if (isType (token, TOKEN_KEYWORD)) token->type = TOKEN_IDENTIFIER; parseEntityDecl (token); if (isType (token, TOKEN_COMMA)) readToken (token); else if (isType (token, TOKEN_STATEMENT_END)) { skipToNextStatement (token); break; } }}/* type-declaration-stmt is * type-spec [[, attr-spec] ... ::] entity-decl-list */static void parseTypeDeclarationStmt (tokenInfo *const token){ Assert (isTypeSpec (token)); parseTypeSpec (token); if (!isType (token, TOKEN_STATEMENT_END)) /* if not end of derived type... */ { if (isType (token, TOKEN_COMMA)) parseQualifierSpecList (token); if (isType (token, TOKEN_DOUBLE_COLON)) readToken (token); parseEntityDeclList (token); } if (isType (token, TOKEN_STATEMENT_END)) skipToNextStatement (token);}/* namelist-stmt is * NAMELIST /namelist-group-name/ namelist-group-object-list * [[,]/[namelist-group-name]/ namelist-block-object-list] ... * * namelist-group-object is * variable-name * * common-stmt is * COMMON [/[common-block-name]/] common-block-object-list * [[,]/[common-block-name]/ common-block-object-list] ... * * common-block-object is * variable-name [ ( explicit-shape-spec-list ) ] */static void parseCommonNamelistStmt (tokenInfo *const token, tagType type){ Assert (isKeyword (token, KEYWORD_common) || isKeyword (token, KEYWORD_namelist)); readToken (token); do { if (isType (token, TOKEN_OPERATOR) && strcmp (vStringValue (token->string), "/") == 0) { readToken (token); if (isType (token, TOKEN_IDENTIFIER)) { makeFortranTag (token, type); readToken (token); } skipPast (token, TOKEN_OPERATOR); } if (isType (token, TOKEN_IDENTIFIER)) makeFortranTag (token, TAG_LOCAL); readToken (token); if (isType (token, TOKEN_PAREN_OPEN)) skipOverParens (token); /* skip explicit-shape-spec-list */ if (isType (token, TOKEN_COMMA)) readToken (token); } while (! isType (token, TOKEN_STATEMENT_END)); skipToNextStatement (token);}static void parseFieldDefinition (tokenInfo *const token){ if (isTypeSpec (token)) parseTypeDeclarationStmt (token); else if (isKeyword (token, KEYWORD_structure)) parseStructureStmt (token); else if (isKeyword (token, KEYWORD_union)) parseUnionStmt (token); else skipToNextStatement (token);}static void parseMap (tokenInfo *const token){ Assert (isKeyword (token, KEYWORD_map)); skipToNextStatement (token); while (! isKeyword (token, KEYWORD_end)) parseFieldDefinition (token); readSubToken (token); Assert (isSecondaryKeyword (token, KEYWORD_map)); skipToNextStatement (token);}/* UNION * MAP * [field-definition] [field-definition] ... * END MAP * MAP * [field-definition] [field-definition] ... * END MAP * [MAP * [field-definition] * [field-definition] ... * END MAP] ... * END UNION * * * * Typed data declarations (variables or arrays) in structure declarations * have the form of normal Fortran typed data declarations. Data items with * different types can be freely intermixed within a structure declaration. * * Unnamed fields can be declared in a structure by specifying the pseudo * name %FILL in place of an actual field name. You can use this mechanism to * generate empty space in a record for purposes such as alignment. * * All mapped field declarations that are made within a UNION declaration * share a common location within the containing structure. When initializing * the fields within a UNION, the final initialization value assigned * overlays any value previously assigned to a field definition that shares * that field. */static void parseUnionStmt (tokenInfo *const token){ Assert (isKeyword (token, KEYWORD_union)); skipToNextStatement (token); while (isKeyword (token, KEYWORD_map)) parseMap (token); Assert (isKeyword (token, KEYWORD_end)); readSubToken (token); Assert (isSecondaryKeyword (token, KEYWORD_union)); skipToNextStatement (token);}/* STRUCTURE [/structure-name/] [field-names] * [field-definition] * [field-definition] ... * END STRUCTURE * * structure-name * identifies the structure in a subsequent RECORD statement. * Substructures can be established within a structure by means of either * a nested STRUCTURE declaration or a RECORD statement. * * field-names * (for substructure declarations only) one or more names having the * structure of the substructure being defined. * * field-definition * can be one or more of the following: * * Typed data declarations, which can optionally include one or more * data initialization values. * * Substructure declarations (defined by either RECORD statements or * subsequent STRUCTURE statements). * * UNION declarations, which are mapped fields defined by a block of * statements. The syntax of a UNION declaration is described below. * * PARAMETER statements, which do not affect the form of the * structure. */static void parseStructureStmt (tokenInfo *const token){ tokenInfo *name; Assert (isKeyword (token, KEYWORD_structure)); readToken (token); if (isType (token, TOKEN_OPERATOR) && strcmp (vStringValue (token->string), "/") == 0) { /* read structure name */ readToken (token); if (isType (token, TOKEN_IDENTIFIER)) makeFortranTag (token, TAG_DERIVED_TYPE); name = newTokenFrom (token); skipPast (token, TOKEN_OPERATOR); } else { /* fake out anonymous structure */ name = newToken (); name->type = TOKEN_IDENTIFIER; name->tag = TAG_DERIVED_TYPE; vStringCopyS (name->string, "anonymous"); } while (isType (token, TOKEN_IDENTIFIER)) { /* read field names */ makeFortranTag (token, TAG_COMPONENT); readToken (token); if (isType (token, TOKEN_COMMA)) readToken (token); } skipToNextStatement (token); ancestorPush (name); while (! isKeyword (token, KEYWORD_end)) parseFieldDefinition (token); readSubToken (token); Assert (isSecondaryKeyword (token, KEYWORD_structure)); skipToNextStatement (token); ancestorPop (); deleteToken (name);}/* specification-stmt * is access-stmt (is access-spec [[::] access-id-list) * or allocatable-stmt (is ALLOCATABLE [::] array-name etc.) * or common-stmt (is COMMON [ / [common-block-name] /] etc.) * or data-stmt (is DATA data-stmt-list [[,] data-stmt-set] ...) * or dimension-stmt (is DIMENSION [::] array-name etc.) * or equivalence-stmt (is EQUIVALENCE equivalence-set-list) * or external-stmt (is EXTERNAL etc.) * or intent-stmt (is INTENT ( intent-spec ) [::] etc.) * or instrinsic-stmt (is INTRINSIC etc.) * or namelist-stmt (is NAMELIST / namelist-group-name / etc.) * or optional-stmt (is OPTIONAL [::] etc.) * or pointer-stmt (is POINTER [::] object-name etc.) * or save-stmt (is SAVE etc.) * or target-stmt (is TARGET [::] object-name etc.) * * access-spec is PUBLIC or PRIVATE */static boolean parseSpecificationStmt (tokenInfo *const token){ boolean result = TRUE; switch (token->keyword) { case KEYWORD_common: parseCommonNamelistStmt (token, TAG_COMMON_BLOCK); break; case KEYWORD_namelist: parseCommonNamelistStmt (token, TAG_NAMELIST); break; case KEYWORD_structure: parseStructureStmt (token); break; case KEYWORD_allocatable: case KEYWORD_data: case KEYWORD_dimension: case KEYWORD_equivalence: case KEYWORD_external: case KEYWORD_intent: case KEYWORD_intrinsic: case KEYWORD_optional: case KEYWORD_pointer: case KEYWORD_private: case KEYWORD_public: case KEYWORD_save: case KEYWORD_target: skipToNextStatement (token); break; default: result = FALSE; break; } return result;}/* component-def-stmt is * type-spec [[, component-attr-spec-list] ::] component-decl-list * * component-decl is * component-name [ ( component-array-spec ) ] [ * char-length ] */static void parseComponentDefStmt (tokenInfo *const token){ Assert (isTypeSpec (token)); parseTypeSpec (token); if (isType (token, TOKEN_COMMA)) parseQualifierSpecList (token); if (isType (token, TOKEN_DOUBLE_COLON)) readToken (token); parseEntityDeclList (token);}/* derived-type-def is * derived-type-stmt is (TYPE [[, access-spec] ::] type-name * [private-sequence-stmt] ... (is PRIVATE or SEQUENCE) * component-def-stmt * [component-def-stmt] ... * end-type-stmt */static void parseDerivedTypeDef (tokenInfo *const token){ if (isType (token, TOKEN_COMMA)) parseQualifierSpecList (token); if (isType (token, TOKEN_DOUBLE_COLON)) readToken (token); if (isType (token, TOKEN_IDENTIFIER)) makeFortranTag (token, TAG_DERIVED_TYPE); ancestorPush (token); skipToNextStatement (token); if (isKeyword (token, KEYWORD_private) || isKeyword (token, KEYWORD_sequence)) { skipToNextStatement (token); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -