Signed-off-by: erick-alcachofa <erick@artichoke.dev>
Implement precedence capping in `parseExpression` for switch cases to
prevent the parser from misinterpreting the case arrow (`->`) as a
pointer member access operator.
Additionally, increased the binding power of `ModuleAccess` (::) to
ensure namespaced identifiers are correctly resolved within case
patterns before hitting the precedence limit.
- Use `PointerMemberAccess.right` as the precedence floor for cases.
- Update `ModuleAccess` binding power to {23, 24}.
116 lines
4.8 KiB
C++
116 lines
4.8 KiB
C++
//============================================================================//
|
|
// //
|
|
// artichoke programming language //
|
|
// //
|
|
// Copyright (C) 2025 Erick Saul Guzman Ramos, whoami.artichoke.dev //
|
|
// //
|
|
// //
|
|
// This program is free software: you can redistribute it and/or modify //
|
|
// it under the terms of the GNU Affero General Public License as published //
|
|
// by the Free Software Foundation, either version 3 of the License, or //
|
|
// (at your option) any later version. //
|
|
// //
|
|
// This program is distributed in the hope that it will be useful, //
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
|
// GNU Affero General Public License for more details. //
|
|
// //
|
|
// You should have received a copy of the GNU Affero General Public License //
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>. //
|
|
// //
|
|
//============================================================================//
|
|
|
|
#include <artichoke/Parser/Pratt.hpp>
|
|
|
|
namespace arti::lang::pratt {
|
|
|
|
std::uint16_t prefixBindingPower(ast::PrefixOperator op) {
|
|
switch (op) {
|
|
// Unary operators generally bind very tightly
|
|
case ast::PrefixOperator::Not:
|
|
case ast::PrefixOperator::Minus:
|
|
case ast::PrefixOperator::BitNot:
|
|
case ast::PrefixOperator::MemPtr:
|
|
case ast::PrefixOperator::DerefPtr:
|
|
return 17; // Should be higher than most infix but lower than postfix
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
BindingPower infixBindingPower(ast::InfixOperator op) {
|
|
switch (op) {
|
|
// Member Access (Highest)
|
|
case ast::InfixOperator::ModuleAccess: return { 23, 24 };
|
|
case ast::InfixOperator::MemberAccess:
|
|
case ast::InfixOperator::PointerMemberAccess: return { 21, 22 };
|
|
|
|
// Multiplicative
|
|
case ast::InfixOperator::Multiplication:
|
|
case ast::InfixOperator::Division:
|
|
case ast::InfixOperator::Modulo: return { 15, 16 };
|
|
|
|
// Additive
|
|
case ast::InfixOperator::Addition:
|
|
case ast::InfixOperator::Substraction: return { 13, 14 };
|
|
|
|
// Shift
|
|
case ast::InfixOperator::LeftShift:
|
|
case ast::InfixOperator::RightShift: return { 11, 12 };
|
|
|
|
// Relational
|
|
case ast::InfixOperator::LessThan:
|
|
case ast::InfixOperator::GreaterThan:
|
|
case ast::InfixOperator::LessEqual:
|
|
case ast::InfixOperator::GreaterEqual: return { 9, 10 };
|
|
|
|
// Equality
|
|
case ast::InfixOperator::Equal:
|
|
case ast::InfixOperator::NotEqual: return { 7, 8 };
|
|
|
|
// Bitwise
|
|
case ast::InfixOperator::BitAnd: return { 6, 7 };
|
|
case ast::InfixOperator::BitXor: return { 5, 6 };
|
|
case ast::InfixOperator::BitOr: return { 4, 5 };
|
|
|
|
// Logical
|
|
case ast::InfixOperator::BoolAnd: return { 3, 4 };
|
|
case ast::InfixOperator::BoolOr: return { 1, 2 };
|
|
|
|
// Assignment (Right-associative: left > right)
|
|
case ast::InfixOperator::Assignment:
|
|
case ast::InfixOperator::AdditionAssignment:
|
|
case ast::InfixOperator::SubstractionAssignment:
|
|
case ast::InfixOperator::MultiplicationAssignment:
|
|
case ast::InfixOperator::DivisionAssignment:
|
|
case ast::InfixOperator::ModuloAssignment:
|
|
case ast::InfixOperator::BitAndAssignment:
|
|
case ast::InfixOperator::BitOrAssignment:
|
|
case ast::InfixOperator::BoolAndAssignment:
|
|
case ast::InfixOperator::BoolOrAssignment:
|
|
case ast::InfixOperator::LShiftAssignment:
|
|
case ast::InfixOperator::RShiftAssignment:
|
|
return { 2, 1 };
|
|
default:
|
|
return { 0, 0 };
|
|
}
|
|
}
|
|
|
|
std::uint16_t postfixBindingPower(ast::PostfixOperator op) {
|
|
switch (op) {
|
|
// Postfix usually has the highest precedence (e.g., function calls,
|
|
// slicing)
|
|
case ast::PostfixOperator::FunctionCall:
|
|
case ast::PostfixOperator::SliceAccess:
|
|
case ast::PostfixOperator::SliceSize:
|
|
case ast::PostfixOperator::PtrToSlice:
|
|
case ast::PostfixOperator::SliceToPtr:
|
|
case ast::PostfixOperator::Reflect:
|
|
case ast::PostfixOperator::ObjectLiteral:
|
|
return 19;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
} // namespace arti::lang::pratt
|