📄 scan-gram.l
字号:
token_name (token_type)); obstack_sgrow (&obstack_for_string, "{}"); STRING_FINISH; val->chars = last_string; BEGIN INITIAL; return token_type; } } <<EOF>> unexpected_eof (scanner_cursor, "{}"); BEGIN INITIAL;} /*---------------------------------------------------------------. | Scanning some code in braces (%union and actions). The initial | | "{" is already eaten. | `---------------------------------------------------------------*/<SC_BRACED_CODE>{ "{"|"<"{splice}"%" STRING_GROW; braces_level++; "%"{splice}">" STRING_GROW; braces_level--; "}" { bool outer_brace = --braces_level < 0; /* As an undocumented Bison extension, append `;' before the last brace in braced code, so that the user code can omit trailing `;'. But do not append `;' if emulating Yacc, since Yacc does not append one. FIXME: Bison should warn if a semicolon seems to be necessary here, and should omit the semicolon if it seems unnecessary (e.g., after ';', '{', or '}', each followed by comments or white space). Such a warning shouldn't depend on --yacc; it should depend on a new --pedantic option, which would cause Bison to warn if it detects an extension to POSIX. --pedantic should also diagnose other Bison extensions like %yacc. Perhaps there should also be a GCC-style --pedantic-errors option, so that such warnings are diagnosed as errors. */ if (outer_brace && token_type == BRACED_CODE && ! yacc_flag) obstack_1grow (&obstack_for_string, ';'); obstack_1grow (&obstack_for_string, '}'); if (outer_brace) { STRING_FINISH; rule_length++; loc->start = code_start; val->chars = last_string; BEGIN INITIAL; return token_type; } } /* Tokenize `<<%' correctly (as `<<' `%') rather than incorrrectly (as `<' `<%'). */ "<"{splice}"<" STRING_GROW; "$"("<"{tag}">")?(-?[0-9]+|"$") handle_dollar (token_type, yytext, *loc); "@"(-?[0-9]+|"$") handle_at (token_type, yytext, *loc); <<EOF>> unexpected_eof (code_start, "}"); BEGIN INITIAL;} /*--------------------------------------------------------------. | Scanning some prologue: from "%{" (already scanned) to "%}". | `--------------------------------------------------------------*/<SC_PROLOGUE>{ "%}" { STRING_FINISH; loc->start = code_start; val->chars = last_string; BEGIN INITIAL; return PROLOGUE; } <<EOF>> unexpected_eof (code_start, "%}"); BEGIN INITIAL;} /*---------------------------------------------------------------. | Scanning the epilogue (everything after the second "%%", which | | has already been eaten). | `---------------------------------------------------------------*/<SC_EPILOGUE>{ <<EOF>> { STRING_FINISH; loc->start = code_start; val->chars = last_string; BEGIN INITIAL; return EPILOGUE; }} /*-----------------------------------------. | Escape M4 quoting characters in C code. | `-----------------------------------------*/<SC_COMMENT,SC_LINE_COMMENT,SC_STRING,SC_CHARACTER,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>{ \$ obstack_sgrow (&obstack_for_string, "$]["); \@ obstack_sgrow (&obstack_for_string, "@@"); \[ obstack_sgrow (&obstack_for_string, "@{"); \] obstack_sgrow (&obstack_for_string, "@}");} /*-----------------------------------------------------. | By default, grow the string obstack with the input. | `-----------------------------------------------------*/<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE,SC_STRING,SC_CHARACTER,SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>. |<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>\n STRING_GROW;%%/* Keeps track of the maximum number of semantic values to the left of a handle (those referenced by $0, $-1, etc.) are required by the semantic actions of this grammar. */int max_left_semantic_context = 0;/* Set *LOC and adjust scanner cursor to account for token TOKEN of size SIZE. */static voidadjust_location (location *loc, char const *token, size_t size){ int line = scanner_cursor.line; int column = scanner_cursor.column; char const *p0 = token; char const *p = token; char const *lim = token + size; loc->start = scanner_cursor; for (p = token; p < lim; p++) switch (*p) { case '\n': line++; column = 1; p0 = p + 1; break; case '\t': column += mbsnwidth (p0, p - p0, 0); column += 8 - ((column - 1) & 7); p0 = p + 1; break; } scanner_cursor.line = line; scanner_cursor.column = column + mbsnwidth (p0, p - p0, 0); loc->end = scanner_cursor;}/* Read bytes from FP into buffer BUF of size SIZE. Return the number of bytes read. Remove '\r' from input, treating \r\n and isolated \r as \n. */static size_tno_cr_read (FILE *fp, char *buf, size_t size){ size_t bytes_read = fread (buf, 1, size, fp); if (bytes_read) { char *w = memchr (buf, '\r', bytes_read); if (w) { char const *r = ++w; char const *lim = buf + bytes_read; for (;;) { /* Found an '\r'. Treat it like '\n', but ignore any '\n' that immediately follows. */ w[-1] = '\n'; if (r == lim) { int ch = getc (fp); if (ch != '\n' && ungetc (ch, fp) != ch) break; } else if (*r == '\n') r++; /* Copy until the next '\r'. */ do { if (r == lim) return w - buf; } while ((*w++ = *r++) != '\r'); } return w - buf; } } return bytes_read;}/*------------------------------------------------------------------.| TEXT is pointing to a wannabee semantic value (i.e., a `$'). || || Possible inputs: $[<TYPENAME>]($|integer) || || Output to OBSTACK_FOR_STRING a reference to this semantic value. |`------------------------------------------------------------------*/static inline boolhandle_action_dollar (char *text, location loc){ const char *type_name = NULL; char *cp = text + 1; if (! current_rule) return false; /* Get the type name if explicit. */ if (*cp == '<') { type_name = ++cp; while (*cp != '>') ++cp; *cp = '\0'; ++cp; } if (*cp == '$') { if (!type_name) type_name = symbol_list_n_type_name_get (current_rule, loc, 0); if (!type_name && typed) complain_at (loc, _("$$ of `%s' has no declared type"), current_rule->sym->tag); if (!type_name) type_name = ""; obstack_fgrow1 (&obstack_for_string, "]b4_lhs_value([%s])[", type_name); } else { long int num; set_errno (0); num = strtol (cp, 0, 10); if (INT_MIN <= num && num <= rule_length && ! get_errno ()) { int n = num; if (1-n > max_left_semantic_context) max_left_semantic_context = 1-n; if (!type_name && n > 0) type_name = symbol_list_n_type_name_get (current_rule, loc, n); if (!type_name && typed) complain_at (loc, _("$%d of `%s' has no declared type"), n, current_rule->sym->tag); if (!type_name) type_name = ""; obstack_fgrow3 (&obstack_for_string, "]b4_rhs_value([%d], [%d], [%s])[", rule_length, n, type_name); } else complain_at (loc, _("integer out of range: %s"), quote (text)); } return true;}/*----------------------------------------------------------------.| Map `$?' onto the proper M4 symbol, depending on its TOKEN_TYPE || (are we in an action?). |`----------------------------------------------------------------*/static voidhandle_dollar (int token_type, char *text, location loc){ switch (token_type) { case BRACED_CODE: if (handle_action_dollar (text, loc)) return; break; case PERCENT_DESTRUCTOR: case PERCENT_INITIAL_ACTION: case PERCENT_PRINTER: if (text[1] == '$') { obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar["); return; } break; default: break; } complain_at (loc, _("invalid value: %s"), quote (text));}/*------------------------------------------------------.| TEXT is a location token (i.e., a `@...'). Output to || OBSTACK_FOR_STRING a reference to this location. |`------------------------------------------------------*/static inline boolhandle_action_at (char *text, location loc){ char *cp = text + 1; locations_flag = true; if (! current_rule) return false; if (*cp == '$') obstack_sgrow (&obstack_for_string, "]b4_lhs_location["); else { long int num; set_errno (0); num = strtol (cp, 0, 10); if (INT_MIN <= num && num <= rule_length && ! get_errno ()) { int n = num; obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location([%d], [%d])[", rule_length, n); } else complain_at (loc, _("integer out of range: %s"), quote (text)); } return true;}/*----------------------------------------------------------------.| Map `@?' onto the proper M4 symbol, depending on its TOKEN_TYPE || (are we in an action?). |`----------------------------------------------------------------*/static voidhandle_at (int token_type, char *text, location loc){ switch (token_type) { case BRACED_CODE: handle_action_at (text, loc); return; case PERCENT_INITIAL_ACTION: case PERCENT_DESTRUCTOR: case PERCENT_PRINTER: if (text[1] == '$') { obstack_sgrow (&obstack_for_string, "]b4_at_dollar["); return; } break; default: break; } complain_at (loc, _("invalid value: %s"), quote (text));}/*------------------------------------------------------.| Scan NUMBER for a base-BASE integer at location LOC. |`------------------------------------------------------*/static unsigned long intscan_integer (char const *number, int base, location loc){ unsigned long int num; set_errno (0); num = strtoul (number, 0, base); if (INT_MAX < num || get_errno ()) { complain_at (loc, _("integer out of range: %s"), quote (number)); num = INT_MAX; } return num;}/*------------------------------------------------------------------.| Convert universal character name UCN to a single-byte character, || and return that character. Return -1 if UCN does not correspond || to a single-byte character. |`------------------------------------------------------------------*/static intconvert_ucn_to_byte (char const *ucn){ unsigned long int code = strtoul (ucn + 2, 0, 16); /* FIXME: Currently we assume Unicode-compatible unibyte characters on ASCII hosts (i.e., Latin-1 on hosts with 8-bit bytes). On non-ASCII hosts we support only the portable C character set. These limitations should be removed once we add support for multibyte characters. */ if (UCHAR_MAX < code) return -1;#if ! ('$' == 0x24 && '@' == 0x40 && '`' == 0x60 && '~' == 0x7e) { /* A non-ASCII host. Use CODE to index into a table of the C basic execution character set, which is guaranteed to exist on all Standard C platforms. This table also includes '$', '@', and '`', which are not in the basic execution character set but which are unibyte characters on all the platforms that we know about. */ static signed char const table[] = { '\0', -1, -1, -1, -1, -1, -1, '\a', '\b', '\t', '\n', '\v', '\f', '\r', -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~' }; code = code < sizeof table ? table[code] : -1; }#endif return code;}/*----------------------------------------------------------------.| Handle `#line INT "FILE"'. ARGS has already skipped `#line '. |`----------------------------------------------------------------*/static voidhandle_syncline (char *args){ int lineno = strtol (args, &args, 10); const char *file = NULL; file = strchr (args, '"') + 1; *strchr (file, '"') = 0; scanner_cursor.file = current_file = uniqstr_new (file); scanner_cursor.line = lineno; scanner_cursor.column = 1;}/*----------------------------------------------------------------.| For a token or comment starting at START, report message MSGID, || which should say that an end marker was found before || the expected TOKEN_END. |`----------------------------------------------------------------*/static voidunexpected_end (boundary start, char const *msgid, char const *token_end){ location loc; loc.start = start; loc.end = scanner_cursor; complain_at (loc, _(msgid), token_end);}/*------------------------------------------------------------------------.| Report an unexpected EOF in a token or comment starting at START. || An end of file was encountered and the expected TOKEN_END was missing. |`------------------------------------------------------------------------*/static voidunexpected_eof (boundary start, char const *token_end){ unexpected_end (start, N_("missing `%s' at end of file"), token_end);}/*----------------------------------------.| Likewise, but for unexpected newlines. |`----------------------------------------*/static voidunexpected_newline (boundary start, char const *token_end){ unexpected_end (start, N_("missing `%s' at end of line"), token_end);}/*-------------------------.| Initialize the scanner. |`-------------------------*/voidscanner_initialize (void){ obstack_init (&obstack_for_string);}/*-----------------------------------------------.| Free all the memory allocated to the scanner. |`-----------------------------------------------*/voidscanner_free (void){ obstack_free (&obstack_for_string, 0); /* Reclaim Flex's buffers. */ yy_delete_buffer (YY_CURRENT_BUFFER);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -