/* How many look-ahead tokens are available (0 - 4, or
more if parsing from pre-lexed tokens). */
unsigned int tokens_avail;
+ /* Raw look-ahead tokens, used only for checking in Objective-C
+ whether '[[' starts attributes. */
+ vec<c_token, va_gc> *raw_tokens;
+ /* The number of raw look-ahead tokens that have since been fully
+ lexed. */
+ unsigned int raw_tokens_used;
/* True if a syntax error is being recovered from; false otherwise.
c_parser_error sets this flag. It should clear this flag when
enough tokens have been consumed to recover from the error. */
static GTY (()) c_parser *the_parser;
-/* Read in and lex a single token, storing it in *TOKEN. */
+/* Read in and lex a single token, storing it in *TOKEN. If RAW,
+ context-sensitive postprocessing of the token is not done. */
static void
-c_lex_one_token (c_parser *parser, c_token *token)
+c_lex_one_token (c_parser *parser, c_token *token, bool raw = false)
{
timevar_push (TV_LEX);
- token->type = c_lex_with_flags (&token->value, &token->location,
- &token->flags,
- (parser->lex_joined_string
- ? 0 : C_LEX_STRING_NO_JOIN));
- token->id_kind = C_ID_NONE;
- token->keyword = RID_MAX;
- token->pragma_kind = PRAGMA_NONE;
+ if (raw || vec_safe_length (parser->raw_tokens) == 0)
+ {
+ token->type = c_lex_with_flags (&token->value, &token->location,
+ &token->flags,
+ (parser->lex_joined_string
+ ? 0 : C_LEX_STRING_NO_JOIN));
+ token->id_kind = C_ID_NONE;
+ token->keyword = RID_MAX;
+ token->pragma_kind = PRAGMA_NONE;
+ }
+ else
+ {
+ /* Use a token previously lexed as a raw look-ahead token, and
+ complete the processing on it. */
+ *token = (*parser->raw_tokens)[parser->raw_tokens_used];
+ ++parser->raw_tokens_used;
+ if (parser->raw_tokens_used == vec_safe_length (parser->raw_tokens))
+ {
+ vec_free (parser->raw_tokens);
+ parser->raw_tokens_used = 0;
+ }
+ }
+
+ if (raw)
+ goto out;
switch (token->type)
{
default:
break;
}
+ out:
timevar_pop (TV_LEX);
}
return &parser->tokens[n - 1];
}
+/* Return a pointer to the Nth token from PARSER, reading it in as a
+ raw look-ahead token if necessary. The N-1th token is already read
+ in. Raw look-ahead tokens remain available for when the non-raw
+ functions above are called. */
+
+c_token *
+c_parser_peek_nth_token_raw (c_parser *parser, unsigned int n)
+{
+ /* N is 1-based, not zero-based. */
+ gcc_assert (n > 0);
+
+ if (parser->tokens_avail >= n)
+ return &parser->tokens[n - 1];
+ unsigned int raw_len = vec_safe_length (parser->raw_tokens);
+ unsigned int raw_avail
+ = parser->tokens_avail + raw_len - parser->raw_tokens_used;
+ gcc_assert (raw_avail >= n - 1);
+ if (raw_avail >= n)
+ return &(*parser->raw_tokens)[parser->raw_tokens_used
+ + n - 1 - parser->tokens_avail];
+ vec_safe_reserve (parser->raw_tokens, 1);
+ parser->raw_tokens->quick_grow (raw_len + 1);
+ c_lex_one_token (parser, &(*parser->raw_tokens)[raw_len], true);
+ return &(*parser->raw_tokens)[raw_len];
+}
+
bool
c_keyword_starts_typename (enum rid keyword)
{
return nreverse (attributes);
}
+/* Look past an optional balanced token sequence of raw look-ahead
+ tokens starting with the *Nth token. *N is updated to point to the
+ following token. Return true if such a sequence was found, false
+ if the tokens parsed were not balanced. */
+
+static bool
+c_parser_check_balanced_raw_token_sequence (c_parser *parser, unsigned int *n)
+{
+ while (true)
+ {
+ c_token *token = c_parser_peek_nth_token_raw (parser, *n);
+ switch (token->type)
+ {
+ case CPP_OPEN_BRACE:
+ {
+ ++*n;
+ if (c_parser_check_balanced_raw_token_sequence (parser, n))
+ {
+ token = c_parser_peek_nth_token_raw (parser, *n);
+ if (token->type == CPP_CLOSE_BRACE)
+ ++*n;
+ else
+ return false;
+ }
+ else
+ return false;
+ break;
+ }
+
+ case CPP_OPEN_PAREN:
+ {
+ ++*n;
+ if (c_parser_check_balanced_raw_token_sequence (parser, n))
+ {
+ token = c_parser_peek_nth_token_raw (parser, *n);
+ if (token->type == CPP_CLOSE_PAREN)
+ ++*n;
+ else
+ return false;
+ }
+ else
+ return false;
+ break;
+ }
+
+ case CPP_OPEN_SQUARE:
+ {
+ ++*n;
+ if (c_parser_check_balanced_raw_token_sequence (parser, n))
+ {
+ token = c_parser_peek_nth_token_raw (parser, *n);
+ if (token->type == CPP_CLOSE_SQUARE)
+ ++*n;
+ else
+ return false;
+ }
+ else
+ return false;
+ break;
+ }
+
+ case CPP_CLOSE_BRACE:
+ case CPP_CLOSE_PAREN:
+ case CPP_CLOSE_SQUARE:
+ case CPP_EOF:
+ return true;
+
+ default:
+ ++*n;
+ break;
+ }
+ }
+}
+
/* Return whether standard attributes start with the Nth token. */
static bool
if (!(c_parser_peek_nth_token (parser, n)->type == CPP_OPEN_SQUARE
&& c_parser_peek_nth_token (parser, n + 1)->type == CPP_OPEN_SQUARE))
return false;
- /* In C, '[[' must start attributes. In Objective-C, identifying
- whether those tokens start attributes requires unbounded
- lookahead, which is not yet implemented. */
- return !c_dialect_objc ();
+ /* In C, '[[' must start attributes. In Objective-C, we need to
+ check whether '[[' is matched by ']]'. */
+ if (!c_dialect_objc ())
+ return true;
+ n += 2;
+ if (!c_parser_check_balanced_raw_token_sequence (parser, &n))
+ return false;
+ c_token *token = c_parser_peek_nth_token_raw (parser, n);
+ if (token->type != CPP_CLOSE_SQUARE)
+ return false;
+ token = c_parser_peek_nth_token_raw (parser, n + 1);
+ return token->type == CPP_CLOSE_SQUARE;
}
static tree