Update precedence rules to match design. (#3081)

- Only allow assignment at the top level in an expression statement.
- Allow both negation and complement as subexpressions of both bitwise
  and numeric operators.
- Remove parsing support for postincrement and postdecrement.
- Add parsing support for `as` operator.
- Use the same ambient precedence for types and non-type expressions.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
This commit is contained in:
Richard Smith
2023-08-10 18:39:37 +00:00
committed by GitHub
co-authored by Chandler Carruth
parent 3cca175a57
commit fc5a9541ce
18 changed files with 634 additions and 99 deletions
+34 -11
View File
@@ -6,6 +6,15 @@
namespace Carbon {
static auto DiagnoseStatementOperatorAsSubexpression(ParserContext& context)
-> void {
CARBON_DIAGNOSTIC(StatementOperatorAsSubexpression, Error,
"Operator `{0}` can only be used as a complete statement.",
TokenKind);
context.emitter().Emit(*context.position(), StatementOperatorAsSubexpression,
context.PositionKind());
}
auto ParserHandleExpression(ParserContext& context) -> void {
auto state = context.PopState();
@@ -17,13 +26,20 @@ auto ParserHandleExpression(ParserContext& context) -> void {
OperatorPriority::RightFirst) {
// The precedence rules don't permit this prefix operator in this
// context. Diagnose this, but carry on and parse it anyway.
CARBON_DIAGNOSTIC(
UnaryOperatorRequiresParentheses, Error,
"Parentheses are required around this unary `{0}` operator.",
TokenKind);
context.emitter().Emit(*context.position(),
UnaryOperatorRequiresParentheses,
context.PositionKind());
if (PrecedenceGroup::GetPriority(PrecedenceGroup::ForTopLevelExpression(),
*operator_precedence) ==
OperatorPriority::RightFirst) {
CARBON_DIAGNOSTIC(
UnaryOperatorRequiresParentheses, Error,
"Parentheses are required around this unary `{0}` operator.",
TokenKind);
context.emitter().Emit(*context.position(),
UnaryOperatorRequiresParentheses,
context.PositionKind());
} else {
// This operator wouldn't be allowed even if parenthesized.
DiagnoseStatementOperatorAsSubexpression(context);
}
} else {
// Check that this operator follows the proper whitespace rules.
context.DiagnoseOperatorFixity(ParserContext::OperatorFixity::Prefix);
@@ -188,10 +204,17 @@ auto ParserHandleExpressionLoop(ParserContext& context) -> void {
// Either the LHS operator and this operator are ambiguous, or the
// LHS operator is a unary operator that can't be nested within
// this operator. Either way, parentheses are required.
CARBON_DIAGNOSTIC(
OperatorRequiresParentheses, Error,
"Parentheses are required to disambiguate operator precedence.");
context.emitter().Emit(*context.position(), OperatorRequiresParentheses);
if (PrecedenceGroup::GetPriority(PrecedenceGroup::ForTopLevelExpression(),
operator_precedence) ==
OperatorPriority::RightFirst) {
CARBON_DIAGNOSTIC(
OperatorRequiresParentheses, Error,
"Parentheses are required to disambiguate operator precedence.");
context.emitter().Emit(*context.position(), OperatorRequiresParentheses);
} else {
// This operator wouldn't be allowed even if parenthesized.
DiagnoseStatementOperatorAsSubexpression(context);
}
state.has_error = true;
} else {
context.DiagnoseOperatorFixity(