public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Improve syntax error
@ 2019-01-04 20:25 Daniel Marjamäki
  2019-01-05  8:50 ` Segher Boessenkool
  0 siblings, 1 reply; 7+ messages in thread
From: Daniel Marjamäki @ 2019-01-04 20:25 UTC (permalink / raw)
  To: gcc

Hello!

I just chose the word "unmatched" for now.. let me know if "stray" or
some other word is better. :-)

I have a work in progress patch that as far as I can tell works.

I wonder if you see some problems with my design. What do I need to
do..? Basically I have chosen to add a nesting_depth to the c_parser
struct. That is updated in the consume_token. I first tried to add
such variable in c_parser_declaration_or_fndef() but that was much
more difficult.

I wanted to warn about unmatched }. It is however more complicated
than I thought. For two reasons:

The first reason is the hard problem, but maybe we can ignore this now also:

void f()
{
    }  // <- looking at the indentation, it seems preferable to warn about this
}

The second reason is easier.. I just don't want to get into too deep
water too quickly. To warn about that also I can't just have a
nesting_depth anymore. I need to have a stack that track the nesting.
I have experimented with a linked list like this and made it work:

    struct nesting {
        cpp_ttype type;
        struct nesting *next;
    };

but well here I run into memory management and I also wonder if you
like the design decision to put a linked list in the c_parser struct.

Here is my current patch...

diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 972b629c092..eabc5ffa15e 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -171,6 +171,8 @@ struct GTY(()) c_parser {
   /* How many look-ahead tokens are available (0 - 4, or
      more if parsing from pre-lexed tokens).  */
   unsigned int tokens_avail;
+  /* nesting depth in expression (parentheses / squares) */
+  unsigned int nesting_depth;
   /* 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.  */
@@ -763,6 +765,22 @@ c_parser_next_tokens_start_declaration (c_parser *parser)
   return false;
 }

+/* Nesting start token */
+
+static bool c_parser_is_nesting_start (c_parser *parser)
+{
+    return c_parser_next_token_is (parser, CPP_OPEN_PAREN) ||
+           c_parser_next_token_is (parser, CPP_OPEN_SQUARE);
+}
+
+/* Nesting end token */
+
+static bool c_parser_is_nesting_end (c_parser *parser)
+{
+    return c_parser_next_token_is (parser, CPP_CLOSE_PAREN) ||
+           c_parser_next_token_is (parser, CPP_CLOSE_SQUARE);
+}
+
 /* Consume the next token from PARSER.  */

 void
@@ -772,6 +790,10 @@ c_parser_consume_token (c_parser *parser)
   gcc_assert (parser->tokens[0].type != CPP_EOF);
   gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
   gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
+  if (c_parser_is_nesting_start (parser))
+    parser->nesting_depth++;
+  else if (parser->nesting_depth > 0 && c_parser_is_nesting_end (parser))
+    parser->nesting_depth--;
   parser->last_token_location = parser->tokens[0].location;
   if (parser->tokens != &parser->tokens_buf[0])
     parser->tokens++;
@@ -1673,6 +1695,20 @@ add_debug_begin_stmt (location_t loc)
   add_stmt (stmt);
 }

+static bool c_parser_unmatched_p (c_parser *parser)
+{
+  if (c_parser_is_nesting_end (parser))
+    return parser->nesting_depth == 0;
+  return false;
+}
+
+static void complain_about_unmatched_token (c_parser *parser)
+{
+  c_token *token = c_parser_peek_token(parser);
+  error_at (token->location, "unmatched %<%s%>",
+            cpp_type2name(token->type, token->flags));
+}
+
 /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
    6.7, 6.9.1, C11 6.7, 6.9.1).  If FNDEF_OK is true, a function definition
    is accepted; otherwise (old-style parameter declarations) only other
@@ -2228,7 +2264,10 @@ c_parser_declaration_or_fndef (c_parser
*parser, bool fndef_ok,
         }
       else
         {
-          c_parser_error (parser, "expected %<,%> or %<;%>");
+          if (c_parser_unmatched_p (parser))
+            complain_about_unmatched_token (parser);
+          else
+            c_parser_error (parser, "expected %<,%> or %<;%>");
           c_parser_skip_to_end_of_block_or_statement (parser);
           return;
         }
diff --git a/gcc/testsuite/gcc.dg/unmatched.c b/gcc/testsuite/gcc.dg/unmatched.c
new file mode 100644
index 00000000000..bd458a01109
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/unmatched.c
@@ -0,0 +1,19 @@
+
+/* { dg-do compile } */
+
+void f1() {
+  int a = 0)+3; /* { dg-error "unmatched" } */
+}
+
+void f2() {
+  int b = (1]+3; /* { dg-error "expected" } */
+}
+
+void f3() {
+  int b = 1]+3; /* { dg-error "unmatched" } */
+}
+
+void f4() {
+  int c = (1))+3; /* { dg-error "unmatched" } */
+}
+

Best regards,
Daniel Marjamäki

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-01-10 10:39 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-04 20:25 Improve syntax error Daniel Marjamäki
2019-01-05  8:50 ` Segher Boessenkool
2019-01-05 17:02   ` Daniel Marjamäki
2019-01-05 19:44     ` Daniel Marjamäki
2019-01-08 20:29       ` Daniel Marjamäki
2019-01-08 20:44         ` Joseph Myers
2019-01-10 10:39     ` Segher Boessenkool

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).