Skip to content

Commit

Permalink
[slang][parser] Fix timeless constraint expression parsing (#1128)
Browse files Browse the repository at this point in the history
  • Loading branch information
likeamahoney authored Sep 18, 2024
1 parent b2cf6ae commit 6e18236
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 5 deletions.
5 changes: 5 additions & 0 deletions source/parsing/Parser_members.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2206,10 +2206,15 @@ ConstraintItemSyntax* Parser::parseConstraintItem(bool allowBlock, bool isTopLev
if (!isPossibleExpression(peek().kind) && !allowBlock)
return nullptr;

Token curr = peek();
// at this point we either have an expression with optional distribution or
// we have an implication constraint
auto expr =
&parseSubExpression(ExpressionOptions::ConstraintContext | ExpressionOptions::AllowDist, 0);
// checking that tokens were extracted during expression parsing
if (curr == peek() && !allowBlock)
return nullptr;

if (peek(TokenKind::MinusArrow)) {
auto arrow = consume();
return &factory.implicationConstraint(*expr, arrow, *parseConstraintItem(true, false));
Expand Down
15 changes: 10 additions & 5 deletions source/parsing/Parser_statements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -762,14 +762,14 @@ RandCaseStatementSyntax& Parser::parseRandCaseStatement(NamedLabelSyntax* label,
SmallVector<RandCaseItemSyntax*> itemBuffer;

while (isPossibleExpression(peek().kind)) {
Token curr = peek();
auto& expr = parseExpression();
auto colon = expect(TokenKind::Colon);
const auto loc = peek().location();
auto& stmt = parseStatement();
if (stmt.kind == SyntaxKind::EmptyStatement &&
stmt.as<EmptyStatementSyntax>().semicolon.isMissing() && loc == peek().location()) {
// If there is no consumed tokens then expression and statement were not parsed
if (curr == peek())
skipToken(std::nullopt);
}

itemBuffer.push_back(&factory.randCaseItem(expr, colon, stmt));
}

Expand Down Expand Up @@ -995,8 +995,13 @@ StatementSyntax& Parser::parseRandSequenceStatement(NamedLabelSyntax* label, Att
auto closeParen = expect(TokenKind::CloseParenthesis);

SmallVector<ProductionSyntax*> productions;
while (isPossibleDataType(peek().kind))
while (isPossibleDataType(peek().kind)) {
Token curr = peek();
productions.push_back(&parseProduction());
// If there is no consumed tokens then production was not parsed
if (curr == peek())
skipToken(std::nullopt);
}

if (productions.empty())
addDiag(diag::ExpectedRsRule, peek().location());
Expand Down
19 changes: 19 additions & 0 deletions tests/unittests/parsing/MemberParsingTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1489,3 +1489,22 @@ endmodule
REQUIRE(diagnostics.size() == 1);
CHECK(diagnostics[0].code == diag::UnexpectedEndDelim);
}

TEST_CASE("Bad top level constraints") {
auto& text = R"(
constraint A :: A { &&& }

constraint A :: A { matches }

constraint A :: A { soft *) 0 ; }

program A ; final randsequence ( const ) A : A ; endsequence endprogram

constraint A :: A { foreach ( &&& A [ ] ) 0 ; }

program A ; final randcase 0 : matches A = # 0 0 ; endcase endprogram
)";
parseCompilationUnit(text);

REQUIRE(diagnostics.size() == 16);
}

0 comments on commit 6e18236

Please sign in to comment.