📄 lex.cc
字号:
const char *name = nm.contents(); if (!get_delimited()) return; token_buffer += '\0'; macro_table.define(name, strsave(token_buffer.contents()));}void do_undef(){ int t = get_token(0); // do not expand what we are undefining if (t != VARIABLE && t != LABEL) { lex_error("can only define variable or placename"); return; } token_buffer += '\0'; macro_table.define(token_buffer.contents(), 0);}class for_input : public input { char *var; char *body; double to; int by_is_multiplicative; double by; const char *p; int done_newline;public: for_input(char *, double, int, double, char *); ~for_input(); int get(); int peek();};for_input::for_input(char *vr, double t, int bim, double b, char *bd): var(vr), to(t), by_is_multiplicative(bim), by(b), body(bd), p(body), done_newline(0){}for_input::~for_input(){ a_delete var; a_delete body;}int for_input::get(){ if (p == 0) return EOF; for (;;) { if (*p != '\0') return (unsigned char)*p++; if (!done_newline) { done_newline = 1; return '\n'; } double val; if (!lookup_variable(var, &val)) { lex_error("body of `for' terminated enclosing block"); return EOF; } if (by_is_multiplicative) val *= by; else val += by; define_variable(var, val); if (val > to) { p = 0; return EOF; } p = body; done_newline = 0; }}int for_input::peek(){ if (p == 0) return EOF; if (*p != '\0') return (unsigned char)*p; if (!done_newline) return '\n'; double val; if (!lookup_variable(var, &val)) return EOF; if (by_is_multiplicative) { if (val * by > to) return EOF; } else { if (val + by > to) return EOF; } if (*body == '\0') return EOF; return (unsigned char)*body;}void do_for(char *var, double from, double to, int by_is_multiplicative, double by, char *body){ define_variable(var, from); if (from <= to) input_stack::push(new for_input(var, to, by_is_multiplicative, by, body));}void do_copy(const char *filename){ errno = 0; FILE *fp = fopen(filename, "r"); if (fp == 0) { lex_error("can't open `%1': %2", filename, strerror(errno)); return; } input_stack::push(new file_input(fp, filename));}class copy_thru_input : public input { int done; char *body; char *until; const char *p; const char *ap; int argv[9]; int argc; string line; int get_line(); virtual int inget() = 0;public: copy_thru_input(const char *b, const char *u); ~copy_thru_input(); int get(); int peek();};class copy_file_thru_input : public copy_thru_input { input *in;public: copy_file_thru_input(input *, const char *b, const char *u); ~copy_file_thru_input(); int inget();};copy_file_thru_input::copy_file_thru_input(input *i, const char *b, const char *u): in(i), copy_thru_input(b, u){}copy_file_thru_input::~copy_file_thru_input(){ delete in;}int copy_file_thru_input::inget(){ if (!in) return EOF; else return in->get();}class copy_rest_thru_input : public copy_thru_input {public: copy_rest_thru_input(const char *, const char *u); int inget();};copy_rest_thru_input::copy_rest_thru_input(const char *b, const char *u): copy_thru_input(b, u){}int copy_rest_thru_input::inget(){ while (next != 0) { int c = next->get(); if (c != EOF) return c; if (next->next == 0) return EOF; input *tem = next; next = next->next; delete tem; } return EOF;}copy_thru_input::copy_thru_input(const char *b, const char *u): done(0){ ap = 0; body = process_body(b); p = 0; until = strsave(u);}copy_thru_input::~copy_thru_input(){ a_delete body; a_delete until;}int copy_thru_input::get(){ if (ap) { if (*ap != '\0') return (unsigned char)*ap++; ap = 0; } for (;;) { if (p == 0) { if (!get_line()) break; p = body; } if (*p == '\0') { p = 0; return '\n'; } while (*p >= ARG1 && *p <= ARG1 + 8) { int i = *p++ - ARG1; if (i < argc && line[argv[i]] != '\0') { ap = line.contents() + argv[i]; return (unsigned char)*ap++; } } if (*p != '\0') return (unsigned char)*p++; } return EOF;}int copy_thru_input::peek(){ if (ap) { if (*ap != '\0') return (unsigned char)*ap; ap = 0; } for (;;) { if (p == 0) { if (!get_line()) break; p = body; } if (*p == '\0') return '\n'; while (*p >= ARG1 && *p <= ARG1 + 8) { int i = *p++ - ARG1; if (i < argc && line[argv[i]] != '\0') { ap = line.contents() + argv[i]; return (unsigned char)*ap; } } if (*p != '\0') return (unsigned char)*p; } return EOF;}int copy_thru_input::get_line(){ if (done) return 0; line.clear(); argc = 0; int c = inget(); for (;;) { while (c == ' ') c = inget(); if (c == EOF || c == '\n') break; if (argc == 9) { do { c = inget(); } while (c != '\n' && c != EOF); break; } argv[argc++] = line.length(); do { line += char(c); c = inget(); } while (c != ' ' && c != '\n'); line += '\0'; } if (until != 0 && argc > 0 && strcmp(&line[argv[0]], until) == 0) { done = 1; return 0; } return argc > 0 || c == '\n';}class simple_file_input : public input { const char *filename; int lineno; FILE *fp;public: simple_file_input(FILE *, const char *); ~simple_file_input(); int get(); int peek(); int get_location(const char **, int *);};simple_file_input::simple_file_input(FILE *p, const char *s): filename(s), fp(p), lineno(1){}simple_file_input::~simple_file_input(){ // don't delete the filename fclose(fp);}int simple_file_input::get(){ int c = getc(fp); while (illegal_input_char(c)) { error("illegal input character code %1", c); c = getc(fp); } if (c == '\n') lineno++; return c;}int simple_file_input::peek(){ int c = getc(fp); while (illegal_input_char(c)) { error("illegal input character code %1", c); c = getc(fp); } if (c != EOF) ungetc(c, fp); return c;}int simple_file_input::get_location(const char **fnp, int *lnp){ *fnp = filename; *lnp = lineno; return 1;}void copy_file_thru(const char *filename, const char *body, const char *until){ errno = 0; FILE *fp = fopen(filename, "r"); if (fp == 0) { lex_error("can't open `%1': %2", filename, strerror(errno)); return; } input *in = new copy_file_thru_input(new simple_file_input(fp, filename), body, until); input_stack::push(in);}void copy_rest_thru(const char *body, const char *until){ input_stack::push(new copy_rest_thru_input(body, until));}void push_body(const char *s){ input_stack::push(new char_input('\n')); input_stack::push(new macro_input(s));}int delim_flag = 0;char *get_thru_arg(){ int c = input_stack::peek_char(); while (c == ' ') { input_stack::get_char(); c = input_stack::peek_char(); } if (c != EOF && csalpha(c)) { // looks like a macro input_stack::get_char(); token_buffer = c; for (;;) { c = input_stack::peek_char(); if (c == EOF || (!csalnum(c) && c != '_')) break; input_stack::get_char(); token_buffer += char(c); } context_buffer = token_buffer; token_buffer += '\0'; char *def = macro_table.lookup(token_buffer.contents()); if (def) return strsave(def); // I guess it wasn't a macro after all; so push the macro name back. // -2 because we added a '\0' for (int i = token_buffer.length() - 2; i >= 0; i--) input_stack::push_back(token_buffer[i]); } if (get_delimited()) { token_buffer += '\0'; return strsave(token_buffer.contents()); } else return 0;}int lookahead_token = -1;string old_context_buffer;void do_lookahead(){ if (lookahead_token == -1) { old_context_buffer = context_buffer; lookahead_token = get_token(1); }}int yylex(){ if (delim_flag) { assert(lookahead_token == -1); if (delim_flag == 2) { if ((yylval.str = get_thru_arg()) != 0) return DELIMITED; else return 0; } else { if (get_delimited()) { token_buffer += '\0'; yylval.str = strsave(token_buffer.contents()); return DELIMITED; } else return 0; } } for (;;) { int t; if (lookahead_token >= 0) { t = lookahead_token; lookahead_token = -1; } else t = get_token(1); switch (t) { case '\n': return ';'; case EOF: return 0; case DEFINE: do_define(); break; case UNDEF: do_undef(); break; case ORDINAL: yylval.n = token_int; return t; case NUMBER: yylval.x = token_double; return t; case COMMAND_LINE: case TEXT: token_buffer += '\0'; if (!input_stack::get_location(&yylval.lstr.filename, &yylval.lstr.lineno)) { yylval.lstr.filename = 0; yylval.lstr.lineno = -1; } yylval.lstr.str = strsave(token_buffer.contents()); return t; case LABEL: case VARIABLE: token_buffer += '\0'; yylval.str = strsave(token_buffer.contents()); return t; case LEFT: // change LEFT to LEFT_CORNER when followed by OF old_context_buffer = context_buffer; lookahead_token = get_token(1); if (lookahead_token == OF) return LEFT_CORNER; else return t; case RIGHT: // change RIGHT to RIGHT_CORNER when followed by OF old_context_buffer = context_buffer; lookahead_token = get_token(1); if (lookahead_token == OF) return RIGHT_CORNER; else return t; case UPPER: // recognise UPPER only before LEFT or RIGHT old_context_buffer = context_buffer; lookahead_token = get_token(1); if (lookahead_token != LEFT && lookahead_token != RIGHT) { yylval.str = strsave("upper"); return VARIABLE; } else return t; case LOWER: // recognise LOWER only before LEFT or RIGHT old_context_buffer = context_buffer; lookahead_token = get_token(1); if (lookahead_token != LEFT && lookahead_token != RIGHT) { yylval.str = strsave("lower"); return VARIABLE; } else return t; case TOP: // recognise TOP only before OF old_context_buffer = context_buffer; lookahead_token = get_token(1); if (lookahead_token != OF) { yylval.str = strsave("top"); return VARIABLE; } else return t; case BOTTOM: // recognise BOTTOM only before OF old_context_buffer = context_buffer; lookahead_token = get_token(1); if (lookahead_token != OF) { yylval.str = strsave("bottom"); return VARIABLE; } else return t; case CENTER: // recognise CENTER only before OF old_context_buffer = context_buffer; lookahead_token = get_token(1); if (lookahead_token != OF) { yylval.str = strsave("center"); return VARIABLE; } else return t; case START: // recognise START only before OF old_context_buffer = context_buffer; lookahead_token = get_token(1); if (lookahead_token != OF) { yylval.str = strsave("start"); return VARIABLE; } else return t; case END: // recognise END only before OF old_context_buffer = context_buffer; lookahead_token = get_token(1); if (lookahead_token != OF) { yylval.str = strsave("end"); return VARIABLE; } else return t; default: return t; } }}void lex_error(const char *message, const errarg &arg1, const errarg &arg2, const errarg &arg3){ const char *filename; int lineno; if (!input_stack::get_location(&filename, &lineno)) error(message, arg1, arg2, arg3); else error_with_file_and_line(filename, lineno, message, arg1, arg2, arg3);}void lex_warning(const char *message, const errarg &arg1, const errarg &arg2, const errarg &arg3){ const char *filename; int lineno; if (!input_stack::get_location(&filename, &lineno)) warning(message, arg1, arg2, arg3); else warning_with_file_and_line(filename, lineno, message, arg1, arg2, arg3);}void yyerror(const char *s){ const char *filename; int lineno; const char *context = 0; if (lookahead_token == -1) { if (context_buffer.length() > 0) { context_buffer += '\0'; context = context_buffer.contents(); } } else { if (old_context_buffer.length() > 0) { old_context_buffer += '\0'; context = old_context_buffer.contents(); } } if (!input_stack::get_location(&filename, &lineno)) { if (context) { if (context[0] == '\n' && context[1] == '\0') error("%1 before newline", s); else error("%1 before `%2'", s, context); } else error("%1 at end of picture", s); } else { if (context) { if (context[0] == '\n' && context[1] == '\0') error_with_file_and_line(filename, lineno, "%1 before newline", s); else error_with_file_and_line(filename, lineno, "%1 before `%2'", s, context); } else error_with_file_and_line(filename, lineno, "%1 at end of picture", s); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -