📄 lex.cc
字号:
const int NCONTEXT = 4;string context_ring[NCONTEXT];int context_index = 0;void flush_context(){ for (int i = 0; i < NCONTEXT; i++) context_ring[i] = ""; context_index = 0;}void show_context(){ int i = context_index; fputs(" context is\n\t", stderr); for (;;) { int j = (i + 1) % NCONTEXT; if (j == context_index) { fputs(">>> ", stderr); put_string(context_ring[i], stderr); fputs(" <<<", stderr); break; } else if (context_ring[i].length() > 0) { put_string(context_ring[i], stderr); putc(' ', stderr); } i = j; } putc('\n', stderr);}void add_context(const string &s){ context_ring[context_index] = s; context_index = (context_index + 1) % NCONTEXT;}void add_context(char c){ context_ring[context_index] = c; context_index = (context_index + 1) % NCONTEXT;}void add_quoted_context(const string &s){ string &r = context_ring[context_index]; r = '"'; for (int i = 0; i < s.length(); i++) if (s[i] == '"') r += "\\\""; else r += s[i]; r += '"'; context_index = (context_index + 1) % NCONTEXT;}void init_lex(const char *str, const char *filename, int lineno){ while (current_input != 0) { input *tem = current_input; current_input = current_input->next; delete tem; } current_input = new top_input(str, filename, lineno, 0); flush_context();}void get_delimited_text(){ char *filename; int lineno; int got_location = get_location(&filename, &lineno); int start = get_char(); while (start == ' ' || start == '\t' || start == '\n') start = get_char(); token_buffer.clear(); if (start == EOF) { if (got_location) error_with_file_and_line(filename, lineno, "end of input while defining macro"); else error("end of input while defining macro"); return; } for (;;) { int c = get_char(); if (c == EOF) { if (got_location) error_with_file_and_line(filename, lineno, "end of input while defining macro"); else error("end of input while defining macro"); add_context(start + token_buffer); return; } if (c == start) break; token_buffer += char(c); } add_context(start + token_buffer + start);}void interpolate_macro_with_args(const char *body){ char *argv[9]; int argc = 0; for (int i = 0; i < 9; i++) argv[i] = 0; int level = 0; int c; do { token_buffer.clear(); for (;;) { c = get_char(); if (c == EOF) { lex_error("end of input while scanning macro arguments"); break; } if (level == 0 && (c == ',' || c == ')')) { if (token_buffer.length() > 0) { token_buffer += '\0'; argv[argc] = strsave(token_buffer.contents()); } // for `foo()', argc = 0 if (argc > 0 || c != ')' || i > 0) argc++; break; } token_buffer += char(c); if (c == '(') level++; else if (c == ')') level--; } } while (c != ')' && c != EOF); current_input = new argument_macro_input(body, argc, argv, current_input);}/* If lookup flag is non-zero the token will be looked up to seeif it is macro. If it's 1, it will looked up to see if it's a token.*/int get_token(int lookup_flag = 0){ for (;;) { int c = get_char(); while (c == ' ' || c == '\n') c = get_char(); switch (c) { case EOF: add_context("end of input"); return 0; case '"': { int quoted = 0; token_buffer.clear(); for (;;) { c = get_char(); if (c == EOF) { lex_error("missing \""); break; } else if (c == '\n') { lex_error("newline before end of quoted text"); break; } else if (c == '"') { if (!quoted) break; token_buffer[token_buffer.length() - 1] = '"'; quoted = 0; } else { token_buffer += c; quoted = quoted ? 0 : c == '\\'; } } } add_quoted_context(token_buffer); return QUOTED_TEXT; case '{': case '}': case '^': case '~': case '\t': add_context(c); return c; default: { int break_flag = 0; int quoted = 0; token_buffer.clear(); if (c == '\\') quoted = 1; else token_buffer += c; int done = 0; while (!done) { c = peek_char(); if (!quoted && lookup_flag != 0 && c == '(') { token_buffer += '\0'; definition *def = macro_table.lookup(token_buffer.contents()); if (def && def->is_macro && !def->is_simple) { (void)get_char(); // skip initial '(' interpolate_macro_with_args(def->contents); break_flag = 1; break; } token_buffer.set_length(token_buffer.length() - 1); } if (quoted) { quoted = 0; switch (c) { case EOF: lex_error("`\\' ignored at end of equation"); done = 1; break; case '\n': lex_error("`\\' ignored because followed by newline"); done = 1; break; case '\t': lex_error("`\\' ignored because followed by tab"); done = 1; break; case '"': (void)get_char(); token_buffer += '"'; break; default: (void)get_char(); token_buffer += '\\'; token_buffer += c; break; } } else { switch (c) { case EOF: case '{': case '}': case '^': case '~': case '"': case ' ': case '\t': case '\n': done = 1; break; case '\\': (void)get_char(); quoted = 1; break; default: (void)get_char(); token_buffer += char(c); break; } } } if (break_flag || token_buffer.length() == 0) break; if (lookup_flag != 0) { token_buffer += '\0'; definition *def = macro_table.lookup(token_buffer.contents()); token_buffer.set_length(token_buffer.length() - 1); if (def) { if (def->is_macro) { current_input = new macro_input(def->contents, current_input); break; } else if (lookup_flag == 1) { add_context(token_buffer); return def->tok; } } } add_context(token_buffer); return TEXT; } } }}void do_include(){ int t = get_token(2); if (t != TEXT && t != QUOTED_TEXT) { lex_error("bad filename for include"); return; } token_buffer += '\0'; const char *filename = token_buffer.contents(); errno = 0; FILE *fp = fopen(filename, "r"); if (fp == 0) { lex_error("can't open included file `%1'", filename); return; } current_input = new file_input(fp, filename, current_input);}void ignore_definition(){ int t = get_token(); if (t != TEXT) { lex_error("bad definition"); return; } get_delimited_text();}void do_definition(int is_simple){ int t = get_token(); if (t != TEXT) { lex_error("bad definition"); return; } token_buffer += '\0'; const char *name = token_buffer.contents(); definition *def = macro_table.lookup(name); if (def == 0) { def = new definition; macro_table.define(name, def); } else if (def->is_macro) { a_delete def->contents; } get_delimited_text(); token_buffer += '\0'; def->is_macro = 1; def->contents = strsave(token_buffer.contents()); def->is_simple = is_simple;}void do_undef(){ int t = get_token(); if (t != TEXT) { lex_error("bad undef command"); return; } token_buffer += '\0'; macro_table.define(token_buffer.contents(), 0);}void do_gsize(){ int t = get_token(2); if (t != TEXT && t != QUOTED_TEXT) { lex_error("bad argument to gsize command"); return; } token_buffer += '\0'; if (!set_gsize(token_buffer.contents())) lex_error("invalid size `%1'", token_buffer.contents());}void do_gfont(){ int t = get_token(2); if (t != TEXT && t != QUOTED_TEXT) { lex_error("bad argument to gfont command"); return; } token_buffer += '\0'; set_gfont(token_buffer.contents());}void do_grfont(){ int t = get_token(2); if (t != TEXT && t != QUOTED_TEXT) { lex_error("bad argument to grfont command"); return; } token_buffer += '\0'; set_grfont(token_buffer.contents());}void do_gbfont(){ int t = get_token(2); if (t != TEXT && t != QUOTED_TEXT) { lex_error("bad argument to gbfont command"); return; } token_buffer += '\0'; set_gbfont(token_buffer.contents());}void do_space(){ int t = get_token(2); if (t != TEXT && t != QUOTED_TEXT) { lex_error("bad argument to space command"); return; } token_buffer += '\0'; char *ptr; long n = strtol(token_buffer.contents(), &ptr, 10); if (n == 0 && ptr == token_buffer.contents()) lex_error("bad argument `%1' to space command"); else set_space(int(n));}void do_ifdef(){ int t = get_token(); if (t != TEXT) { lex_error("bad ifdef"); return; } token_buffer += '\0'; definition *def = macro_table.lookup(token_buffer.contents()); int result = def && def->is_macro && !def->is_simple; get_delimited_text(); if (result) { token_buffer += '\0'; current_input = new macro_input(token_buffer.contents(), current_input); }}void do_delim(){ int c = get_char(); while (c == ' ' || c == '\n') c = get_char(); int d; if (c == EOF || (d = get_char()) == EOF) lex_error("end of file while reading argument to `delim'"); else { if (c == 'o' && d == 'f' && peek_char() == 'f') { (void)get_char(); start_delim = end_delim = '\0'; } else { start_delim = c; end_delim = d; } }}void do_chartype(){ int t = get_token(2); if (t != TEXT && t != QUOTED_TEXT) { lex_error("bad chartype"); return; } token_buffer += '\0'; string type = token_buffer; t = get_token(); if (t != TEXT && t != QUOTED_TEXT) { lex_error("bad chartype"); return; } token_buffer += '\0'; set_char_type(type.contents(), strsave(token_buffer.contents()));}void do_set(){ int t = get_token(2); if (t != TEXT && t != QUOTED_TEXT) { lex_error("bad set"); return; } token_buffer += '\0'; string param = token_buffer; t = get_token(); if (t != TEXT && t != QUOTED_TEXT) { lex_error("bad set"); return; } token_buffer += '\0'; int n; if (sscanf(&token_buffer[0], "%d", &n) != 1) { lex_error("bad number `%1'", token_buffer.contents()); return; } set_param(param.contents(), n);}int yylex(){ for (;;) { int tk = get_token(1); switch(tk) { case UNDEF: do_undef(); break; case SDEFINE: do_definition(1); break; case DEFINE: do_definition(0); break; case TDEFINE: if (!nroff) do_definition(0); else ignore_definition(); break; case NDEFINE: if (nroff) do_definition(0); else ignore_definition(); break; case GSIZE: do_gsize(); break; case GFONT: do_gfont(); break; case GRFONT: do_grfont(); break; case GBFONT: do_gbfont(); break; case SPACE: do_space(); break; case INCLUDE: do_include(); break; case IFDEF: do_ifdef(); break; case DELIM: do_delim(); break; case CHARTYPE: do_chartype(); break; case SET: do_set(); break; case QUOTED_TEXT: case TEXT: token_buffer += '\0'; yylval.str = strsave(token_buffer.contents()); // fall through default: return tk; } }}void lex_error(const char *message, const errarg &arg1, const errarg &arg2, const errarg &arg3){ char *filename; int lineno; if (!get_location(&filename, &lineno)) error(message, arg1, arg2, arg3); else error_with_file_and_line(filename, lineno, message, arg1, arg2, arg3);}void yyerror(const char *s){ char *filename; int lineno; if (!get_location(&filename, &lineno)) error(s); else error_with_file_and_line(filename, lineno, s); show_context();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -