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; } } } }
int get_token(int lookup_flag) { context_buffer.clear(); for (;;) { int n = 0; int bol = input_stack::bol(); int c = input_stack::get_char(); if (bol && c == command_char) { token_buffer.clear(); token_buffer += c; // the newline is not part of the token for (;;) { c = input_stack::peek_char(); if (c == EOF || c == '\n') break; input_stack::get_char(); token_buffer += char(c); } context_buffer = token_buffer; return COMMAND_LINE; } switch (c) { case EOF: return EOF; case ' ': case '\t': break; case '\\': { int d = input_stack::peek_char(); if (d != '\n') { context_buffer = '\\'; return '\\'; } input_stack::get_char(); break; } case '#': do { c = input_stack::get_char(); } while (c != '\n' && c != EOF); if (c == '\n') context_buffer = '\n'; return c; case '"': context_buffer = '"'; token_buffer.clear(); for (;;) { c = input_stack::get_char(); if (c == '\\') { context_buffer += '\\'; c = input_stack::peek_char(); if (c == '"') { input_stack::get_char(); token_buffer += '"'; context_buffer += '"'; } else token_buffer += '\\'; } else if (c == '\n') { error("newline in string"); break; } else if (c == EOF) { error("missing `\"'"); break; } else if (c == '"') { context_buffer += '"'; break; } else { context_buffer += char(c); token_buffer += char(c); } } return TEXT; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int overflow = 0; n = 0; for (;;) { if (n > (INT_MAX - 9)/10) { overflow = 1; break; } n *= 10; n += c - '0'; context_buffer += char(c); c = input_stack::peek_char(); if (c == EOF || !csdigit(c)) break; c = input_stack::get_char(); } token_double = n; if (overflow) { for (;;) { token_double *= 10.0; token_double += c - '0'; context_buffer += char(c); c = input_stack::peek_char(); if (c == EOF || !csdigit(c)) break; c = input_stack::get_char(); } // if somebody asks for 1000000000000th, we will silently // give them INT_MAXth double temp = token_double; // work around gas 1.34/sparc bug if (token_double > INT_MAX) n = INT_MAX; else n = int(temp); } } switch (c) { case 'i': case 'I': context_buffer += char(c); input_stack::get_char(); return NUMBER; case '.': { context_buffer += '.'; input_stack::get_char(); got_dot: double factor = 1.0; for (;;) { c = input_stack::peek_char(); if (c == EOF || !csdigit(c)) break; input_stack::get_char(); context_buffer += char(c); factor /= 10.0; if (c != '0') token_double += factor*(c - '0'); } if (c != 'e' && c != 'E') { if (c == 'i' || c == 'I') { context_buffer += char(c); input_stack::get_char(); } return NUMBER; } } // fall through case 'e': case 'E': { int echar = c; input_stack::get_char(); c = input_stack::peek_char(); int sign = '+'; if (c == '+' || c == '-') { sign = c; input_stack::get_char(); c = input_stack::peek_char(); if (c == EOF || !csdigit(c)) { input_stack::push_back(sign); input_stack::push_back(echar); return NUMBER; } context_buffer += char(echar); context_buffer += char(sign); } else { if (c == EOF || !csdigit(c)) { input_stack::push_back(echar); return NUMBER; } context_buffer += char(echar); } input_stack::get_char(); context_buffer += char(c); n = c - '0'; for (;;) { c = input_stack::peek_char(); if (c == EOF || !csdigit(c)) break; input_stack::get_char(); context_buffer += char(c); n = n*10 + (c - '0'); } if (sign == '-') n = -n; if (c == 'i' || c == 'I') { context_buffer += char(c); input_stack::get_char(); } token_double *= pow(10.0, n); return NUMBER; } case 'n': input_stack::get_char(); c = input_stack::peek_char(); if (c == 'd') { input_stack::get_char(); token_int = n; context_buffer += "nd"; return ORDINAL; } input_stack::push_back('n'); return NUMBER; case 'r': input_stack::get_char(); c = input_stack::peek_char(); if (c == 'd') { input_stack::get_char(); token_int = n; context_buffer += "rd"; return ORDINAL; } input_stack::push_back('r'); return NUMBER; case 't': input_stack::get_char(); c = input_stack::peek_char(); if (c == 'h') { input_stack::get_char(); token_int = n; context_buffer += "th"; return ORDINAL; } input_stack::push_back('t'); return NUMBER; case 's': input_stack::get_char(); c = input_stack::peek_char(); if (c == 't') { input_stack::get_char(); token_int = n; context_buffer += "st"; return ORDINAL; } input_stack::push_back('s'); return NUMBER; default: return NUMBER; } break; case '\'': { c = input_stack::peek_char(); if (c == 't') { input_stack::get_char(); c = input_stack::peek_char(); if (c == 'h') { input_stack::get_char(); context_buffer = "'th"; return TH; } else input_stack::push_back('t'); } context_buffer = "'"; return '\''; } case '.': { c = input_stack::peek_char(); if (c != EOF && csdigit(c)) { n = 0; token_double = 0.0; context_buffer = '.'; goto got_dot; } return get_token_after_dot(c); } case '<': c = input_stack::peek_char(); if (c == '-') { input_stack::get_char(); c = input_stack::peek_char(); if (c == '>') { input_stack::get_char(); context_buffer = "<->"; return DOUBLE_ARROW_HEAD; } context_buffer = "<-"; return LEFT_ARROW_HEAD; } else if (c == '=') { input_stack::get_char(); context_buffer = "<="; return LESSEQUAL; } context_buffer = "<"; return '<'; case '-': c = input_stack::peek_char(); if (c == '>') { input_stack::get_char(); context_buffer = "->"; return RIGHT_ARROW_HEAD; } context_buffer = "-"; return '-'; case '!': c = input_stack::peek_char(); if (c == '=') { input_stack::get_char(); context_buffer = "!="; return NOTEQUAL; } context_buffer = "!"; return '!'; case '>': c = input_stack::peek_char(); if (c == '=') { input_stack::get_char(); context_buffer = ">="; return GREATEREQUAL; } context_buffer = ">"; return '>'; case '=': c = input_stack::peek_char(); if (c == '=') { input_stack::get_char(); context_buffer = "=="; return EQUALEQUAL; } context_buffer = "="; return '='; case '&': c = input_stack::peek_char(); if (c == '&') { input_stack::get_char(); context_buffer = "&&"; return ANDAND; } context_buffer = "&"; return '&'; case '|': c = input_stack::peek_char(); if (c == '|') { input_stack::get_char(); context_buffer = "||"; return OROR; } context_buffer = "|"; return '|'; default: if (c != EOF && csalpha(c)) { token_buffer.clear(); token_buffer = c; for (;;) { c = input_stack::peek_char(); if (c == EOF || (!csalnum(c) && c != '_')) break; input_stack::get_char(); token_buffer += char(c); } int tok = lookup_keyword(token_buffer.contents(), token_buffer.length()); if (tok != 0) { context_buffer = token_buffer; return tok; } char *def = 0; if (lookup_flag) { token_buffer += '\0'; def = macro_table.lookup(token_buffer.contents()); token_buffer.set_length(token_buffer.length() - 1); if (def) { if (c == '(') { input_stack::get_char(); interpolate_macro_with_args(def); } else input_stack::push(new macro_input(def)); } } if (!def) { context_buffer = token_buffer; if (csupper(token_buffer[0])) return LABEL; else return VARIABLE; } } else { context_buffer = char(c); return (unsigned char)c; } break; } } }