diff --git a/source/parse.h b/source/parse.h index 909677e86e..e4c94a6963 100644 --- a/source/parse.h +++ b/source/parse.h @@ -3068,15 +3068,15 @@ class parser -> void { auto m = std::string{msg}; + auto i = done() ? -1 : 0; + assert (peek(i)); if (include_curr_token) { - m += std::string(" (at '") + curr().to_string(true) + "')"; + m += std::string(" (at '") + peek(i)->to_string(true) + "')"; } if ( err_pos == source_position{} - && peek(0) - ) - { - err_pos = peek(0)->position(); + ) { + err_pos = peek(i)->position(); } errors.emplace_back( err_pos, m, false, fallback ); } @@ -3225,6 +3225,12 @@ class parser next(); return {}; } + if ( // check if a single-expression function is followed by an extra second semicolon + decl->initializer && decl->initializer->is_expression() + && !done() && curr().type() == lexeme::Semicolon + ) { + error("a single-expression function should end with a single semicolon"); + } if (!(*func)->contracts.empty()) { error("an unnamed function at expression scope currently cannot have contracts"); next(); @@ -4423,6 +4429,10 @@ class parser if (!handle_logical_expression ()) { return {}; } if (!handle_optional_next_clause()) { return {}; } if (!handle_compound_statement ()) { return {}; } + if (!done() && curr().type() == lexeme::Semicolon) { + error("a loop body may not be followed by a semicolon (empty statements are not allowed)"); + return {}; + } return n; } @@ -4485,6 +4495,11 @@ class parser n->for_with_in = true; } + if (!done() && curr().type() == lexeme::Semicolon) { + error("a loop body may not be followed by a semicolon (empty statements are not allowed)"); + return {}; + } + return n; } @@ -4707,6 +4722,11 @@ class parser ) -> std::unique_ptr { + if (!done() && curr().type() == lexeme::Semicolon) { + error("empty statement is not allowed - remove extra semicolon"); + return {}; + } + auto n = std::make_unique(); // Now handle the rest of the statement @@ -5073,7 +5093,8 @@ class parser // If there's no [ [ then this isn't a contract if ( - curr().type() != lexeme::LeftBracket + done() + || curr().type() != lexeme::LeftBracket || !peek(1) || peek(1)->type() != lexeme::LeftBracket ) @@ -5690,6 +5711,21 @@ class parser return {}; } + if ( + n->is_function() + && n->initializer + && !done() && curr().type() == lexeme::Semicolon + ) + { + if (n->initializer->is_compound() && n->has_name()) { + error("a braced function body may not be followed by a semicolon (empty statements are not allowed)"); + return {}; + } else if (n->initializer->is_expression()) { + error("a single-expression function should end with a single semicolon"); + return {}; + } + } + // If this is an implicit constructor, it must have two parameters if (n->is_constructor()) {