📄 lex.c
字号:
first_line: /* :::::::::::::::::::: */ c = latest_char_in_file; if ((c == EOF) || ((c = ffelex_getc_ (f)) == EOF)) { end_of_file: /* :::::::::::::::::::: */ /* Line ending in EOF instead of \n still counts as a whole line. */ ffelex_finish_statement_ (); ffewhere_line_kill (ffelex_current_wl_); ffewhere_column_kill (ffelex_current_wc_); return (ffelexHandler) ffelex_handler_; } ffelex_next_line_ (); ffelex_bad_line_ = FALSE; /* Skip over comment (and otherwise ignored) lines as quickly as possible! */ while (((lextype = ffelex_first_char_[c]) == FFELEX_typeCOMMENT) || (lextype == FFELEX_typeERROR) || (lextype == FFELEX_typeSLASH) || (lextype == FFELEX_typeHASH)) { /* Test most frequent type of line first, etc. */ if ((lextype == FFELEX_typeCOMMENT) || ((lextype == FFELEX_typeSLASH) && ((c = getc (f)) == '*'))) /* NOTE SIDE-EFFECT. */ { /* Typical case (straight comment), just ignore rest of line. */ comment_line: /* :::::::::::::::::::: */ while ((c != '\n') && (c != EOF)) c = getc (f); }#if FFECOM_targetCURRENT == FFECOM_targetGCC else if (lextype == FFELEX_typeHASH) c = ffelex_hash_ (f);#endif else if (lextype == FFELEX_typeSLASH) { /* SIDE-EFFECT ABOVE HAS HAPPENED. */ ffelex_card_image_[0] = '/'; ffelex_card_image_[1] = c; column = 2; goto bad_first_character; /* :::::::::::::::::::: */ } else /* typeERROR or unsupported typeHASH. */ { /* Bad first character, get line and display it with message. */ column = ffelex_image_char_ (c, 0); bad_first_character: /* :::::::::::::::::::: */ ffelex_bad_line_ = TRUE; while (((c = getc (f)) != '\n') && (c != EOF)) column = ffelex_image_char_ (c, column); ffelex_card_image_[column] = '\0'; ffelex_card_length_ = column; ffelex_bad_1_ (FFEBAD_FIRST_CHAR_INVALID, ffelex_linecount_current_, 1); } /* Read past last char in line. */ if (c == EOF) { ffelex_next_line_ (); goto end_of_file; /* :::::::::::::::::::: */ } c = getc (f); ffelex_next_line_ (); if (c == EOF) goto end_of_file; /* :::::::::::::::::::: */ ffelex_bad_line_ = FALSE; } /* while [c, first char, means comment] */ ffelex_saw_tab_ = (c == '&') || (ffelex_final_nontab_column_ == 0); if (lextype == FFELEX_typeDEBUG) c = ' '; /* A 'D' or 'd' in column 1 with the debug-lines option on. */ column = ffelex_image_char_ (c, 0); /* Read the entire line in as is (with whitespace processing). */ while (((c = getc (f)) != '\n') && (c != EOF)) column = ffelex_image_char_ (c, column); if (ffelex_bad_line_) { ffelex_card_image_[column] = '\0'; ffelex_card_length_ = column; goto comment_line; /* :::::::::::::::::::: */ } /* If no tab, cut off line after column 72/132. */ if (!ffelex_saw_tab_ && (column > ffelex_final_nontab_column_)) { /* Technically, we should now fill ffelex_card_image_ up thru column 72/132 with spaces, since character/hollerith constants must count them in that manner. To save CPU time in several ways (avoid a loop here that would be used only when we actually end a line in character-constant mode; avoid writing memory unnecessarily; avoid a loop later checking spaces when not scanning for character-constant characters), we don't do this, and we do the appropriate thing when we encounter end-of-line while actually processing a character constant. */ column = ffelex_final_nontab_column_; } have_line: /* :::::::::::::::::::: */ ffelex_card_image_[column] = '\0'; ffelex_card_length_ = column; /* Save next char in file so we can use register-based c while analyzing line we just read. */ latest_char_in_file = c; /* Should be either '\n' or EOF. */ have_content = FALSE; /* Handle label, if any. */ labi = 0; first_label_char = FFEWHERE_columnUNKNOWN; for (column = 0; column < 5; ++column) { switch (c = ffelex_card_image_[column]) { case '\0': case '!': goto stop_looking; /* :::::::::::::::::::: */ case ' ': break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': label_string[labi++] = c; if (first_label_char == FFEWHERE_columnUNKNOWN) first_label_char = column + 1; break; case '&': if (column != 0) { ffelex_bad_1_ (FFEBAD_LABEL_FIELD_NOT_NUMERIC, ffelex_linecount_current_, column + 1); goto beginning_of_line_again; /* :::::::::::::::::::: */ } if (ffe_is_pedantic ()) ffelex_bad_1_ (FFEBAD_AMPERSAND, ffelex_linecount_current_, 1); finish_statement = FALSE; just_do_label = FALSE; goto got_a_continuation; /* :::::::::::::::::::: */ case '/': if (ffelex_card_image_[column + 1] == '*') goto stop_looking; /* :::::::::::::::::::: */ /* Fall through. */ default: ffelex_bad_1_ (FFEBAD_LABEL_FIELD_NOT_NUMERIC, ffelex_linecount_current_, column + 1); goto beginning_of_line_again; /* :::::::::::::::::::: */ } } stop_looking: /* :::::::::::::::::::: */ label_string[labi] = '\0'; /* Find first nonblank char starting with continuation column. */ if (column == 5) /* In which case we didn't see end of line in label field. */ while ((c = ffelex_card_image_[column]) == ' ') ++column; /* Now we're trying to figure out whether this is a continuation line and whether there's anything else of substance on the line. The cases are as follows: 1. If a line has an explicit continuation character (other than the digit zero), then if it also has a label, the label is ignored and an error message is printed. Any remaining text on the line is passed to the parser tasks, thus even an all-blank line (possibly with an ignored label) aside from a positive continuation character might have meaning in the midst of a character or hollerith constant. 2. If a line has no explicit continuation character (that is, it has a space in column 6 and the first non-space character past column 6 is not a digit 0-9), then there are two possibilities: A. A label is present and/or a non-space (and non-comment) character appears somewhere after column 6. Terminate processing of the previous statement, if any, send the new label for the next statement, if any, and start processing a new statement with this non-blank character, if any. B. The line is essentially blank, except for a possible comment character. Don't terminate processing of the previous statement and don't pass any characters to the parser tasks, since the line is not flagged as a continuation line. We treat it just like a completely blank line. 3. If a line has a continuation character of zero (0), then we terminate processing of the previous statement, if any, send the new label for the next statement, if any, and start processing a new statement, if any non-blank characters are present. If, when checking to see if we should terminate the previous statement, it is found that there is no previous statement but that there is an outstanding label, substitute CONTINUE as the statement for the label and display an error message. */ finish_statement = FALSE; just_do_label = FALSE; switch (c) { case '!': /* ANSI Fortran 90 says ! in column 6 is continuation. */ /* VXT Fortran says ! anywhere is comment, even column 6. */ if (ffe_is_vxt () || (column != 5)) goto no_tokens_on_line; /* :::::::::::::::::::: */ goto got_a_continuation; /* :::::::::::::::::::: */ case '/': if (ffelex_card_image_[column + 1] != '*') goto some_other_character; /* :::::::::::::::::::: */ /* Fall through. */ if (column == 5) { /* This seems right to do. But it is close to call, since / * starting in column 6 will thus be interpreted as a continuation line beginning with '*'. */ goto got_a_continuation;/* :::::::::::::::::::: */ } /* Fall through. */ case '\0': /* End of line. Therefore may be continued-through line, so handle pending label as possible to-be-continued and drive end-of-statement for any previous statement, else treat as blank line. */ no_tokens_on_line: /* :::::::::::::::::::: */ if (ffe_is_pedantic () && (c == '/')) ffelex_bad_1_ (FFEBAD_NON_ANSI_COMMENT, ffelex_linecount_current_, column + 1); if (first_label_char != FFEWHERE_columnUNKNOWN) { /* Can't be a continued-through line if it has a label. */ finish_statement = TRUE; have_content = TRUE; just_do_label = TRUE; break; } goto beginning_of_line_again; /* :::::::::::::::::::: */ case '0': if (ffe_is_pedantic () && (column != 5)) ffelex_bad_1_ (FFEBAD_NON_ANSI_CONTINUATION_COLUMN, ffelex_linecount_current_, column + 1); finish_statement = TRUE; goto check_for_content; /* :::::::::::::::::::: */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* NOTE: This label can be reached directly from the code that lexes the label field in columns 1-5. */ got_a_continuation: /* :::::::::::::::::::: */ if (first_label_char != FFEWHERE_columnUNKNOWN) { ffelex_bad_2_ (FFEBAD_LABEL_ON_CONTINUATION, ffelex_linecount_current_, first_label_char, ffelex_linecount_current_, column + 1); first_label_char = FFEWHERE_columnUNKNOWN; } if (disallow_continuation_line) { if (!ignore_disallowed_continuation) ffelex_bad_1_ (FFEBAD_INVALID_CONTINUATION, ffelex_linecount_current_, column + 1); goto beginning_of_line_again; /* :::::::::::::::::::: */ } if (ffe_is_pedantic () && (column != 5)) ffelex_bad_1_ (FFEBAD_NON_ANSI_CONTINUATION_COLUMN, ffelex_linecount_current_, column + 1); if ((ffelex_raw_mode_ != 0) && (((c = ffelex_card_image_[column + 1]) != '\0') || !ffelex_saw_tab_)) { ++column; have_content = TRUE; break; } check_for_content: /* :::::::::::::::::::: */ while ((c = ffelex_card_image_[++column]) == ' ') ; if ((c == '\0') || (c == '!') || ((c == '/') && (ffelex_card_image_[column + 1] == '*'))) { if (ffe_is_pedantic () && (c == '/')) ffelex_bad_1_ (FFEBAD_NON_ANSI_COMMENT, ffelex_linecount_current_, column + 1); just_do_label = TRUE; } else have_content = TRUE; break; default: some_other_character: /* :::::::::::::::::::: */ if (column == 5) goto got_a_continuation;/* :::::::::::::::::::: */ /* Here is the very normal case of a regular character starting in column 7 or beyond with a blank in column 6. */ finish_statement = TRUE; have_content = TRUE; break; } if (have_content || (first_label_char != FFEWHERE_columnUNKNOWN)) { /* The line has content of some kind, install new end-statement point for error messages. Note that "content" includes cases where there's little apparent content but enough to finish a statement. That's because finishing a statement can trigger an impending INCLUDE, and that requires accurate line info being maintained by the lexer. */ if (finish_statement) ffelex_prepare_eos_ (); /* Prepare EOS before we move current pointer. */ ffewhere_line_kill (ffelex_current_wl_); ffewhere_column_kill (ffelex_current_wc_); ffelex_current_wl_ = ffewhere_line_new (ffelex_linecount_current_); ffelex_current_wc_ = ffewhere_column_new (ffelex_card_length_ + 1); } /* We delay this for a combination of reasons. Mainly, it can start INCLUDE processing, and we want to delay that until the lexer's info on the line is coherent. And we want to delay that until we're sure there's a reason to make that info coherent, to avoid saving lots of useless lines. */ if (finish_statement) ffelex_finish_statement_ (); /* If label is present, enclose it in a NUMBER token and send it along. */ if (first_label_char != FFEWHERE_columnUNKNOWN) { assert (ffelex_token_->type == FFELEX_typeNONE); ffelex_token_->type = FFELEX_typeNUMBER; ffelex_append_to_token_ ('\0'); /* Make room for label text. */ strcpy (ffelex_token_->text, label_string); ffelex_token_->where_line = ffewhere_line_use (ffelex_current_wl_); ffelex_token_->where_col = ffewhere_column_new (first_label_char); ffelex_token_->length = labi; ffelex_send_token_ (); ++ffelex_label_tokens_; } if (just_do_label) goto beginning_of_line; /* :::::::::::::::::::: */ /* Here is the main engine for parsing. c holds the character at column. It is already known that c is not a blank, end of line, or shriek, unless ffelex_raw_mode_ is not 0 (indicating we are in a character/hollerith constant). A partially filled token may already exist in ffelex_token_. One special case: if, when the end of the line is reached, continuation_line is FALSE and the only token on the line is END, then it is indeed the last statement. We don't look for continuation lines during this program unit in that case. This is according to ANSI. */ if (ffelex_raw_mode_ != 0) { parse_raw_character: /* :::::::::::::::::::: */ if (c == '\0') { ffewhereColumnNumber i; if (ffelex_saw_tab_ || (column >= ffelex_final_nontab_column_)) goto beginning_of_line; /* :::::::::::::::::::: */ /* Pad out line with "virtual" spaces. */ for (i = column; i < ffelex_final_nontab_column_; ++i) ffelex_card_image_[i] = ' '; ffelex_card_image_[i] = '\0'; ffelex_card_length_ = i; c = ' '; } switch (ffelex_raw_mode_) { case -3: c = ffelex_backslash_ (c, column); if (c == EOF) break; if (!ffelex_backslash_reconsider_) ffelex_append_to_token_ (c); ffelex_raw_mode_ = -1; break; case -2: if (c == ffelex_raw_char_) { ffelex_raw_mode_ = -1; ffelex_append_to_token_ (c); } else { ffelex_raw_mode_ = 0; ffelex_backslash_reconsider_ = TRUE; } break; case -1: if (c == ffelex_raw_char_) ffelex_raw_mode_ = -2; else { c = ffelex_backslash_ (c, column); if (c == EOF) { ffelex_raw_mode_ = -3; break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -