Example #1
0
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;
      }
    }
  }
}
Example #2
0
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;
    }
  }
}