Esempio n. 1
0
/* Returns nonzero if a space should be inserted to avoid an
   accidental token paste for output.  For simplicity, it is
   conservative, and occasionally advises a space where one is not
   needed, e.g. "." and ".2".  */
int
cpp_avoid_paste (cpp_reader *pfile, const cpp_token *token1,
		 const cpp_token *token2)
{
  enum cpp_ttype a = token1->type, b = token2->type;
  cppchar_t c;

  if (token1->flags & NAMED_OP)
    a = CPP_NAME;
  if (token2->flags & NAMED_OP)
    b = CPP_NAME;

  c = EOF;
  if (token2->flags & DIGRAPH)
    c = digraph_spellings[(int) b - (int) CPP_FIRST_DIGRAPH][0];
  else if (token_spellings[b].category == SPELL_OPERATOR)
    c = token_spellings[b].name[0];

  /* Quickly get everything that can paste with an '='.  */
  if ((int) a <= (int) CPP_LAST_EQ && c == '=')
    return 1;

  switch (a)
    {
    case CPP_GREATER:	return c == '>' || c == '?';
    case CPP_LESS:	return c == '<' || c == '?' || c == '%' || c == ':';
    case CPP_PLUS:	return c == '+';
    case CPP_MINUS:	return c == '-' || c == '>';
    case CPP_DIV:	return c == '/' || c == '*'; /* Comments.  */
    case CPP_MOD:	return c == ':' || c == '>';
    case CPP_AND:	return c == '&';
    case CPP_OR:	return c == '|';
    case CPP_COLON:	return c == ':' || c == '>';
    case CPP_DEREF:	return c == '*';
    case CPP_DOT:	return c == '.' || c == '%' || b == CPP_NUMBER;
    case CPP_HASH:	return c == '#' || c == '%'; /* Digraph form.  */
    case CPP_NAME:	return ((b == CPP_NUMBER
				 && name_p (pfile, &token2->val.str))
				|| b == CPP_NAME
				|| b == CPP_CHAR || b == CPP_STRING); /* L */
    case CPP_NUMBER:	return (b == CPP_NUMBER || b == CPP_NAME
				|| c == '.' || c == '+' || c == '-');
				      /* UCNs */
    case CPP_OTHER:	return ((token1->val.str.text[0] == '\\'
				 && b == CPP_NAME)
				|| (CPP_OPTION (pfile, objc)
				    && token1->val.str.text[0] == '@'
				    && (b == CPP_NAME || b == CPP_STRING)));
    default:		break;
    }

  return 0;
}
Esempio n. 2
0
File: lexer.c Progetto: nathan/logo
static void logo_Lexer_advance(logo_Lexer *self) {
#define opv(_name, _value) do { self->token = (logo_Token) { .type = logo_Token_ ## _name, .value = _value, .start = start, .end = logo_Stream_position(self->stream) }; return; } while (0)
#define op(_name) opv(_name, NULL)

    long start = logo_Stream_position(self->stream);
    int c = logo_Stream_next(self->stream);

    bool whitespace = false;
trim:
    if (whitespace_p(c) || ((self->list_level || self->in_proc) && newline_p(c))) {
        start = logo_Stream_position(self->stream);
        c = logo_Stream_next(self->stream);
        whitespace = true;
        goto trim;
    }
    if (c == '#') {
        if (logo_Stream_next(self->stream) == '!') {
            do {
                c = logo_Stream_next(self->stream);
            } while (!newline_p(c) && c != logo_Stream_END);
            start = logo_Stream_position(self->stream) - 1;
            goto trim;
        }
        logo_Stream_skip(self->stream, -1);
    }
    if (c == ';' && self->list_level == 0) {
        do {
            c = logo_Stream_next(self->stream);
        } while (!newline_p(c) && c != logo_Stream_END);
        start = logo_Stream_position(self->stream) - 1;
        goto trim;
    }

    switch (c) {
        case logo_Stream_END:
            op(END);
        case '[':
            ++self->list_level;
            op(LBRACKET);
        case ']':
            if (self->list_level > 0) --self->list_level;
            op(RBRACKET);
    }
    if (newline_p(c)) {
        do {
            c = logo_Stream_next(self->stream);
        } while (newline_p(c));
        logo_Stream_skip(self->stream, -1);
        op(NEWLINE);
    }

    if (self->list_level || self->in_proc) {
        size_t size = 0;
        do {
            ++size;
            c = logo_Stream_next(self->stream);
        } while (lword_p(c));

        logo_Stream_skip(self->stream, -size - 1);

        char *s = malloc(size + 1), *p;
        for (p = s; p < s + size; ++p) {
            *p = logo_Stream_next(self->stream);
        }
        *p = 0;

        if (self->in_proc && strcmp(s, "end") == 0) {
            free(s);
            op(PROCEND);
        }

        opv(WORD, s);
    }

    switch (c) {
        case '(': op(LPAREN);
        case ')': op(RPAREN);
        case ':': op(COLON);
        case '?': op(QUESTION);
        case '+': op(ADD);
        case '-':
            if (whitespace && !whitespace_p(logo_Stream_peek(self->stream))) {
                op(INVERSE);
            }
            op(SUB);
        case '*': op(MUL);
        case '/': op(DIV);
        case '=': op(EQUAL);
        case '>':
            if (logo_Stream_peek(self->stream) == '=') {
                logo_Stream_next(self->stream);
                op(GTE);
            }
            op(GT);
        case '<':
            if (logo_Stream_peek(self->stream) == '=') {
                logo_Stream_next(self->stream);
                op(LTE);
            }
            if (logo_Stream_peek(self->stream) == '>') {
                logo_Stream_next(self->stream);
                op(NOTEQUAL);
            }
            op(LT);
    }

    if (c == '"') {
        size_t size = 0;
        c = logo_Stream_next(self->stream);
        while (word_p(c)) {
            ++size;
            c = logo_Stream_next(self->stream);
        }

        logo_Stream_skip(self->stream, -size - 1);

        char *s = malloc(size + 1), *p;
        for (p = s; p < s + size; ++p) {
            *p = logo_Stream_next(self->stream);
        }
        *p = 0;

        opv(WORD, s);
    }
    if (digit_p(c)) {
        size_t size = 0;
#define next do { ++size; c = logo_Stream_next(self->stream); } while (0)

        do {
            do next; while (digit_p(c));

            if (c == '.') {
                next;
                if (!digit_p(c)) break;
                do next; while (digit_p(c));
            }
            if (c == 'e' || c == 'E') {
                next;
                if (c == '+' || c == '-') next;
                if (!digit_p(c)) break;
                do next; while (digit_p(c));
            }

            if (name_p(c)) break;

            logo_Stream_skip(self->stream, -size - 1);

            char *s = malloc(size + 1), *p;
            for (p = s; p < s + size; ++p) {
                *p = logo_Stream_next(self->stream);
            }
            *p = 0;

            opv(NUMBER, s);
        } while (false);
#undef next

        logo_Stream_skip(self->stream, -size - 1);
        c = logo_Stream_next(self->stream);
    }
    if (name_p(c)) {
        size_t size = 0;
        do {
            ++size;
            c = logo_Stream_next(self->stream);
        } while (name_p(c));

        logo_Stream_skip(self->stream, -size - 1);

        char *s = malloc(size), *p;
        for (p = s; p < s + size; ++p) {
            *p = logo_Stream_next(self->stream);
        }
        *p = 0;

        opv(NAME, s);
    }
#undef op
}