diff --git a/mlir/lib/Tools/PDLL/Parser/Parser.cpp b/mlir/lib/Tools/PDLL/Parser/Parser.cpp index 6d3080c8f694167..ef471e5a2edc109 100644 --- a/mlir/lib/Tools/PDLL/Parser/Parser.cpp +++ b/mlir/lib/Tools/PDLL/Parser/Parser.cpp @@ -323,6 +323,14 @@ class Parser { // Exprs FailureOr parseExpr(); + FailureOr parseLogicalOrExpr(); + FailureOr parseLogicalAndExpr(); + FailureOr parseEqualityExpr(); + FailureOr parseRelationExpr(); + FailureOr parseAddSubExpr(); + FailureOr parseMulDivExpr(); + FailureOr parseLogicalNotExpr(); + FailureOr parseOtherExpr(); /// Identifier expressions. FailureOr parseArrayAttrExpr(); @@ -1859,7 +1867,53 @@ FailureOr Parser::parseArgOrResultConstraint() { //===----------------------------------------------------------------------===// // Exprs -FailureOr Parser::parseExpr() { +// Operator precedence follows C++: +// When parsing an expression, an operator which is listed on some row below with a precedence will be bound tighter (as if by parentheses) to +// its arguments than any operator that is listed on a row further below it with +// a lower precedence. Operators that have the same precedence are bound to +// their arguments left-to-right. +// Highest precedence first: +// - call, member access +// - logical not +// - multipication, division, remainder +// - addition, subtraction +// - relation operators +// - equality operators +// - logical and +// - logical or +FailureOr Parser::parseExpr() { return parseLogicalOrExpr(); } + +FailureOr Parser::parseLogicalOrExpr() { + return parseLogicalAndExpr(); +} + +FailureOr Parser::parseLogicalAndExpr() { + return parseEqualityExpr(); +} + +FailureOr Parser::parseEqualityExpr() { + return parseRelationExpr(); +} + +FailureOr Parser::parseRelationExpr() { return parseAddSubExpr(); } + +FailureOr Parser::parseAddSubExpr() { return parseMulDivExpr(); } + +FailureOr Parser::parseMulDivExpr() { + return parseLogicalNotExpr(); +} + +FailureOr Parser::parseLogicalNotExpr() { + switch (curToken.getKind()) { + case Token::exclam: + return parseNegatedExpr(); + break; + default: + return parseOtherExpr(); + } +} + +FailureOr Parser::parseOtherExpr() { if (curToken.is(Token::underscore)) return parseUnderscoreExpr(); @@ -1893,9 +1947,6 @@ FailureOr Parser::parseExpr() { case Token::l_square: lhsExpr = parseArrayAttrExpr(); break; - case Token::exclam: - lhsExpr = parseNegatedExpr(); - break; case Token::string_block: return emitError("expected expression. If you are trying to create an " "ArrayAttr, use a space between `[` and `{`."); @@ -2136,6 +2187,8 @@ FailureOr Parser::parseNegatedExpr() { FailureOr identifierExpr = parseIdentifierExpr(); if (failed(identifierExpr)) return failure(); + if (!curToken.is(Token::l_paren)) + return emitError("expected `(` after function name"); return parseCallExpr(*identifierExpr, /*isNegated = */ true); } diff --git a/mlir/test/mlir-pdll/Parser/expr-failure.pdll b/mlir/test/mlir-pdll/Parser/expr-failure.pdll index b0430abbf02adbd..9c1982a85cd876f 100644 --- a/mlir/test/mlir-pdll/Parser/expr-failure.pdll +++ b/mlir/test/mlir-pdll/Parser/expr-failure.pdll @@ -195,6 +195,23 @@ Pattern { // ----- +Pattern { + // CHECK: expected native constraint + !attr<"0 : i1"> + erase _; +} + +// ----- + +Pattern { + let tuple = (attr<"3 : i34">); + // CHECK: expected `(` after function name + !tuple.0; + erase _; +} + +// ----- + Pattern { // CHECK: expected expression let tuple = (10 = _: Value);