📄 fortran.c
字号:
* character blank. */ if (c == ' ' || c == '0') type = LTYPE_INITIAL; /* 3.2.3 Continuation_Line. A continuation line is any line that * contains any character of the FORTRAN character set other than * the character blank or the digit 0 in column 6 and contains * only blank characters in columns 1 through 5. */ else if (vStringLength (label) == 0) type = LTYPE_CONTINUATION; else type = LTYPE_INVALID; } else if (c == ' ') ; else if (c == EOF) type = LTYPE_EOF; else if (c == '\n') type = LTYPE_SHORT; else if (isdigit (c)) vStringPut (label, c); else type = LTYPE_INVALID; ++column; } while (column < 6 && type == LTYPE_UNDETERMINED); Assert (type != LTYPE_UNDETERMINED); if (vStringLength (label) > 0) { vStringTerminate (label); makeLabelTag (label); vStringClear (label); } return type;}static int getFixedFormChar (void){ boolean newline = FALSE; lineType type; int c = '\0'; if (Column > 0) {#ifdef STRICT_FIXED_FORM /* EXCEPTION! Some compilers permit more than 72 characters per line. */ if (Column > 71) c = skipLine (); else#endif { c = fileGetc (); ++Column; } if (c == '\n') { newline = TRUE; /* need to check for continuation line */ Column = 0; } else if (c == '!' && ! ParsingString) { c = skipLine (); newline = TRUE; /* need to check for continuation line */ Column = 0; } else if (c == '&') /* check for free source form */ { const int c2 = fileGetc (); if (c2 == '\n') longjmp (Exception, (int) ExceptionFixedFormat); else fileUngetc (c2); } } while (Column == 0) { type = getLineType (); switch (type) { case LTYPE_UNDETERMINED: case LTYPE_INVALID: longjmp (Exception, (int) ExceptionFixedFormat); break; case LTYPE_SHORT: break; case LTYPE_COMMENT: skipLine (); break; case LTYPE_EOF: Column = 6; if (newline) c = '\n'; else c = EOF; break; case LTYPE_INITIAL: if (newline) { c = '\n'; Column = 6; break; } /* fall through to next case */ case LTYPE_CONTINUATION: Column = 5; do { c = fileGetc (); ++Column; } while (isBlank (c)); if (c == '\n') Column = 0; else if (Column > 6) { fileUngetc (c); c = ' '; } break; default: Assert ("Unexpected line type" == NULL); } } return c;}static int skipToNextLine (void){ int c = skipLine (); if (c != EOF) c = fileGetc (); return c;}static int getFreeFormChar (void){ static boolean newline = TRUE; boolean advanceLine = FALSE; int c = fileGetc (); /* If the last nonblank, non-comment character of a FORTRAN 90 * free-format text line is an ampersand then the next non-comment * line is a continuation line. */ if (c == '&') { do c = fileGetc (); while (isspace (c) && c != '\n'); if (c == '\n') { newline = TRUE; advanceLine = TRUE; } else if (c == '!') advanceLine = TRUE; else { fileUngetc (c); c = '&'; } } else if (newline && (c == '!' || c == '#')) advanceLine = TRUE; while (advanceLine) { while (isspace (c)) c = fileGetc (); if (c == '!' || (newline && c == '#')) { c = skipToNextLine (); newline = TRUE; continue; } if (c == '&') c = fileGetc (); else advanceLine = FALSE; } newline = (boolean) (c == '\n'); return c;}static int getChar (void){ int c; if (Ungetc != '\0') { c = Ungetc; Ungetc = '\0'; } else if (FreeSourceForm) c = getFreeFormChar (); else c = getFixedFormChar (); return c;}static void ungetChar (const int c){ Ungetc = c;}/* If a numeric is passed in 'c', this is used as the first digit of the * numeric being parsed. */static vString *parseInteger (int c){ static vString *string = NULL; if (string == NULL) string = vStringNew (); vStringClear (string); if (c == '-') { vStringPut (string, c); c = getChar (); } else if (! isdigit (c)) c = getChar (); while (c != EOF && isdigit (c)) { vStringPut (string, c); c = getChar (); } vStringTerminate (string); if (c == '_') { do c = getChar (); while (c != EOF && isalpha (c)); } ungetChar (c); return string;}static vString *parseNumeric (int c){ static vString *string = NULL; if (string == NULL) string = vStringNew (); vStringCopy (string, parseInteger (c)); c = getChar (); if (c == '.') { vStringPut (string, c); vStringCat (string, parseInteger ('\0')); c = getChar (); } if (tolower (c) == 'e') { vStringPut (string, c); vStringCat (string, parseInteger ('\0')); } else ungetChar (c); vStringTerminate (string); return string;}static void parseString (vString *const string, const int delimeter){ const unsigned long inputLineNumber = getInputLineNumber (); int c; ParsingString = TRUE; c = getChar (); while (c != delimeter && c != '\n' && c != EOF) { vStringPut (string, c); c = getChar (); } if (c == '\n' || c == EOF) { verbose ("%s: unterminated character string at line %lu\n", getInputFileName (), inputLineNumber); if (c == EOF) longjmp (Exception, (int) ExceptionEOF); else if (! FreeSourceForm) longjmp (Exception, (int) ExceptionFixedFormat); } vStringTerminate (string); ParsingString = FALSE;}/* Read a C identifier beginning with "firstChar" and places it into "name". */static void parseIdentifier (vString *const string, const int firstChar){ int c = firstChar; do { vStringPut (string, c); c = getChar (); } while (isident (c)); vStringTerminate (string); ungetChar (c); /* unget non-identifier character */}/* Analyzes the identifier contained in a statement described by the * statement structure and adjusts the structure according the significance * of the identifier. */static keywordId analyzeToken (vString *const name){ static vString *keyword = NULL; keywordId id; if (keyword == NULL) keyword = vStringNew (); vStringCopyToLower (keyword, name); id = (keywordId) lookupKeyword (vStringValue (keyword), Lang_fortran); return id;}static void checkForLabel (void){ tokenInfo* token = NULL; int length; int c; do c = getChar (); while (isBlank (c)); for (length = 0 ; isdigit (c) && length < 5 ; ++length) { if (token == NULL) { token = newToken (); token->type = TOKEN_LABEL; } vStringPut (token->string, c); c = getChar (); } if (length > 0) { Assert (token != NULL); vStringTerminate (token->string); makeFortranTag (token, TAG_LABEL); deleteToken (token); } ungetChar (c);}static void readIdentifier (tokenInfo *const token, const int c){ parseIdentifier (token->string, c); token->keyword = analyzeToken (token->string); if (! isKeyword (token, KEYWORD_NONE)) token->type = TOKEN_KEYWORD; else { token->type = TOKEN_IDENTIFIER; if (strncmp (vStringValue (token->string), "end", 3) == 0) { vString *const sub = vStringNewInit (vStringValue (token->string) + 3); const keywordId kw = analyzeToken (sub); vStringDelete (sub); if (kw != KEYWORD_NONE) { token->secondary = newToken (); token->secondary->type = TOKEN_KEYWORD; token->secondary->keyword = kw; token->keyword = KEYWORD_end; } } }}static void readToken (tokenInfo *const token){ int c; deleteToken (token->secondary); token->type = TOKEN_UNDEFINED; token->tag = TAG_UNDEFINED; token->keyword = KEYWORD_NONE; token->secondary = NULL; vStringClear (token->string);getNextChar: c = getChar (); token->lineNumber = getSourceLineNumber (); token->filePosition = getInputFilePosition (); switch (c) { case EOF: longjmp (Exception, (int) ExceptionEOF); break; case ' ': goto getNextChar; case '\t': goto getNextChar; case ',': token->type = TOKEN_COMMA; break; case '(': token->type = TOKEN_PAREN_OPEN; break; case ')': token->type = TOKEN_PAREN_CLOSE; break; case '%': token->type = TOKEN_PERCENT; break; case '*': case '/': case '+': case '-': case '=': case '<': case '>': { const char *const operatorChars = "*/+=<>"; do { vStringPut (token->string, c); c = getChar (); } while (strchr (operatorChars, c) != NULL); ungetChar (c); vStringTerminate (token->string); token->type = TOKEN_OPERATOR; break; } case '!': if (FreeSourceForm) { do c = getChar (); while (c != '\n'); } else { skipLine (); Column = 0; } /* fall through to newline case */ case '\n': token->type = TOKEN_STATEMENT_END; if (FreeSourceForm) checkForLabel (); break; case '.': parseIdentifier (token->string, c); c = getChar (); if (c == '.') { vStringPut (token->string, c); vStringTerminate (token->string); token->type = TOKEN_OPERATOR; } else { ungetChar (c); token->type = TOKEN_UNDEFINED; } break; case '"': case '\'': parseString (token->string, c); token->type = TOKEN_STRING; break; case ';': token->type = TOKEN_STATEMENT_END; break; case ':': c = getChar (); if (c == ':') token->type = TOKEN_DOUBLE_COLON; else { ungetChar (c); token->type = TOKEN_UNDEFINED; } break; default: if (isalpha (c)) readIdentifier (token, c); else if (isdigit (c)) { vStringCat (token->string, parseNumeric (c)); token->type = TOKEN_NUMERIC; } else token->type = TOKEN_UNDEFINED; break; }}static void readSubToken (tokenInfo *const token){ if (token->secondary == NULL) { token->secondary = newToken (); readToken (token->secondary); } Assert (token->secondary != NULL);}/** Scanning functions*/static void skipToToken (tokenInfo *const token, tokenType type){ while (! isType (token, type) && ! isType (token, TOKEN_STATEMENT_END) && !(token->secondary != NULL && isType (token->secondary, TOKEN_STATEMENT_END))) readToken (token);}static void skipPast (tokenInfo *const token, tokenType type){ skipToToken (token, type); if (! isType (token, TOKEN_STATEMENT_END)) readToken (token);}static void skipToNextStatement (tokenInfo *const token){ do { skipToToken (token, TOKEN_STATEMENT_END); readToken (token); } while (isType (token, TOKEN_STATEMENT_END));}/* skip over parenthesis enclosed contents starting at next token. * Token is left at the first token following closing parenthesis. If an * opening parenthesis is not found, `token' is moved to the end of the * statement. */static void skipOverParens (tokenInfo *const token){ int level = 0; do { if (isType (token, TOKEN_STATEMENT_END)) break; else if (isType (token, TOKEN_PAREN_OPEN)) ++level; else if (isType (token, TOKEN_PAREN_CLOSE)) --level; readToken (token); } while (level > 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -