mirror of
https://forge.sourceware.org/marek/gcc.git
synced 2026-02-22 20:01:31 -05:00
253 lines
6.8 KiB
C++
253 lines
6.8 KiB
C++
// Copyright (C) 2025-2026 Free Software Foundation, Inc.
|
|
|
|
// This file is part of GCC.
|
|
|
|
// GCC is free software; you can redistribute it and/or modify it under
|
|
// the terms of the GNU General Public License as published by the Free
|
|
// Software Foundation; either version 3, or (at your option) any later
|
|
// version.
|
|
|
|
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
// for more details.
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with GCC; see the file COPYING3. If not see
|
|
// <http://www.gnu.org/licenses/>.
|
|
|
|
/* DO NOT INCLUDE ANYWHERE - this is automatically included
|
|
* by rust-parse-impl.h
|
|
* This is also the reason why there are no include guards. */
|
|
|
|
#include "rust-parse.h"
|
|
|
|
namespace Rust {
|
|
|
|
// "Unexpected token" panic mode - flags gcc error at unexpected token
|
|
// TODO: seems to be unused, remove?
|
|
template <typename ManagedTokenSource>
|
|
void
|
|
Parser<ManagedTokenSource>::unexpected_token (const_TokenPtr t)
|
|
{
|
|
Error error (t->get_locus (), "unexpected token %qs",
|
|
t->get_token_description ());
|
|
add_error (std::move (error));
|
|
}
|
|
|
|
/* Crappy "error recovery" performed after error by skipping tokens until a
|
|
* semi-colon is found */
|
|
template <typename ManagedTokenSource>
|
|
void
|
|
Parser<ManagedTokenSource>::skip_after_semicolon ()
|
|
{
|
|
const_TokenPtr t = lexer.peek_token ();
|
|
|
|
while (t->get_id () != END_OF_FILE && t->get_id () != SEMICOLON)
|
|
{
|
|
lexer.skip_token ();
|
|
t = lexer.peek_token ();
|
|
}
|
|
|
|
if (t->get_id () == SEMICOLON)
|
|
lexer.skip_token ();
|
|
}
|
|
|
|
/* Skips the current token */
|
|
template <typename ManagedTokenSource>
|
|
void
|
|
Parser<ManagedTokenSource>::skip_token ()
|
|
{
|
|
lexer.skip_token ();
|
|
}
|
|
|
|
/* Checks if current token has inputted id - skips it and returns true if so,
|
|
* diagnoses an error and returns false otherwise. */
|
|
template <typename ManagedTokenSource>
|
|
bool
|
|
Parser<ManagedTokenSource>::skip_token (TokenId token_id)
|
|
{
|
|
return expect_token (token_id) != const_TokenPtr ();
|
|
}
|
|
|
|
/* Checks if current token is similar to inputted token - skips it and returns
|
|
* true if so, diagnoses an error and returns false otherwise. */
|
|
template <typename ManagedTokenSource>
|
|
bool
|
|
Parser<ManagedTokenSource>::skip_token (const_TokenPtr token)
|
|
{
|
|
return expect_token (token) != const_TokenPtr ();
|
|
}
|
|
|
|
/* Checks if current token has inputted id - skips it and returns true if so,
|
|
* returns false otherwise without diagnosing an error */
|
|
template <typename ManagedTokenSource>
|
|
bool
|
|
Parser<ManagedTokenSource>::maybe_skip_token (TokenId token_id)
|
|
{
|
|
if (lexer.peek_token ()->get_id () != token_id)
|
|
return false;
|
|
else
|
|
return skip_token (token_id);
|
|
}
|
|
|
|
/* Checks the current token - if id is same as expected, skips and returns it,
|
|
* otherwise diagnoses error and returns null. */
|
|
template <typename ManagedTokenSource>
|
|
const_TokenPtr
|
|
Parser<ManagedTokenSource>::expect_token (TokenId token_id)
|
|
{
|
|
const_TokenPtr t = lexer.peek_token ();
|
|
if (t->get_id () == token_id)
|
|
{
|
|
lexer.skip_token ();
|
|
return t;
|
|
}
|
|
else
|
|
{
|
|
Error error (t->get_locus (), "expecting %qs but %qs found",
|
|
get_token_description (token_id),
|
|
t->get_token_description ());
|
|
add_error (std::move (error));
|
|
|
|
return const_TokenPtr ();
|
|
}
|
|
}
|
|
|
|
/* Checks the current token - if same as expected, skips and returns it,
|
|
* otherwise diagnoses error and returns null. */
|
|
template <typename ManagedTokenSource>
|
|
const_TokenPtr
|
|
Parser<ManagedTokenSource>::expect_token (const_TokenPtr token_expect)
|
|
{
|
|
const_TokenPtr t = lexer.peek_token ();
|
|
if (t->get_id () == token_expect->get_id ()
|
|
&& (!t->should_have_str () || t->get_str () == token_expect->get_str ()))
|
|
{
|
|
lexer.skip_token ();
|
|
return t;
|
|
}
|
|
else
|
|
{
|
|
Error error (t->get_locus (), "expecting %qs but %qs found",
|
|
token_expect->get_token_description (),
|
|
t->get_token_description ());
|
|
add_error (std::move (error));
|
|
|
|
return const_TokenPtr ();
|
|
}
|
|
}
|
|
|
|
// Skips all tokens until EOF or }. Don't use.
|
|
template <typename ManagedTokenSource>
|
|
void
|
|
Parser<ManagedTokenSource>::skip_after_end ()
|
|
{
|
|
const_TokenPtr t = lexer.peek_token ();
|
|
|
|
while (t->get_id () != END_OF_FILE && t->get_id () != RIGHT_CURLY)
|
|
{
|
|
lexer.skip_token ();
|
|
t = lexer.peek_token ();
|
|
}
|
|
|
|
if (t->get_id () == RIGHT_CURLY)
|
|
{
|
|
lexer.skip_token ();
|
|
}
|
|
}
|
|
|
|
/* A slightly more aware error-handler that skips all tokens until it reaches
|
|
* the end of the block scope (i.e. when left curly brackets = right curly
|
|
* brackets). Note: assumes currently in the middle of a block. Use
|
|
* skip_after_next_block to skip based on the assumption that the block
|
|
* has not been entered yet. */
|
|
template <typename ManagedTokenSource>
|
|
void
|
|
Parser<ManagedTokenSource>::skip_after_end_block ()
|
|
{
|
|
const_TokenPtr t = lexer.peek_token ();
|
|
int curly_count = 1;
|
|
|
|
while (curly_count > 0 && t->get_id () != END_OF_FILE)
|
|
{
|
|
switch (t->get_id ())
|
|
{
|
|
case LEFT_CURLY:
|
|
curly_count++;
|
|
break;
|
|
case RIGHT_CURLY:
|
|
curly_count--;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
lexer.skip_token ();
|
|
t = lexer.peek_token ();
|
|
}
|
|
}
|
|
|
|
/* Skips tokens until the end of the next block. i.e. assumes that the block
|
|
* has not been entered yet. */
|
|
template <typename ManagedTokenSource>
|
|
void
|
|
Parser<ManagedTokenSource>::skip_after_next_block ()
|
|
{
|
|
const_TokenPtr t = lexer.peek_token ();
|
|
|
|
// initial loop - skip until EOF if no left curlies encountered
|
|
while (t->get_id () != END_OF_FILE && t->get_id () != LEFT_CURLY)
|
|
{
|
|
lexer.skip_token ();
|
|
|
|
t = lexer.peek_token ();
|
|
}
|
|
|
|
// if next token is left, skip it and then skip after the block ends
|
|
if (t->get_id () == LEFT_CURLY)
|
|
{
|
|
lexer.skip_token ();
|
|
|
|
skip_after_end_block ();
|
|
}
|
|
// otherwise, do nothing as EOF
|
|
}
|
|
|
|
/* Skips all tokens until ] (the end of an attribute) - does not skip the ]
|
|
* (as designed for attribute body use) */
|
|
template <typename ManagedTokenSource>
|
|
void
|
|
Parser<ManagedTokenSource>::skip_after_end_attribute ()
|
|
{
|
|
const_TokenPtr t = lexer.peek_token ();
|
|
|
|
while (t->get_id () != RIGHT_SQUARE && t->get_id () != END_OF_FILE)
|
|
{
|
|
lexer.skip_token ();
|
|
t = lexer.peek_token ();
|
|
}
|
|
|
|
// Don't skip the RIGHT_SQUARE token
|
|
}
|
|
|
|
// Returns true if the next token is END, ELSE, or EOF;
|
|
template <typename ManagedTokenSource>
|
|
bool
|
|
Parser<ManagedTokenSource>::done_end_or_else ()
|
|
{
|
|
const_TokenPtr t = lexer.peek_token ();
|
|
return (t->get_id () == RIGHT_CURLY || t->get_id () == ELSE
|
|
|| t->get_id () == END_OF_FILE);
|
|
}
|
|
|
|
// Returns true if the next token is END or EOF.
|
|
template <typename ManagedTokenSource>
|
|
bool
|
|
Parser<ManagedTokenSource>::done_end ()
|
|
{
|
|
const_TokenPtr t = lexer.peek_token ();
|
|
return (t->get_id () == RIGHT_CURLY || t->get_id () == END_OF_FILE);
|
|
}
|
|
|
|
} // namespace Rust
|