fix(parser): support optional start and end indices in slice ranges
Signed-off-by: erick-alcachofa <erick@artichoke.dev> Update the SliceAccess postfix operator logic to handle the full variety of slice range syntaxes. This allows for open-ended slices by making the start and end expressions optional within the brackets. - Add logic to detect a leading colon for `[:end]` and `[:]` forms. - Support trailing colons for `[start:]` forms. - Differentiate between a single index access and a slice range based on the presence of the colon operator. - Update SliceRangeExprNode construction to handle optional boundaries.
This commit is contained in:
parent
c2f37d5702
commit
25486fbace
@ -632,6 +632,28 @@ namespace arti::lang {
|
|||||||
node = std::move(newNode);
|
node = std::move(newNode);
|
||||||
}
|
}
|
||||||
else if (op == ast::PostfixOperator::SliceAccess) {
|
else if (op == ast::PostfixOperator::SliceAccess) {
|
||||||
|
bool isSlice = false;
|
||||||
|
bool skipSliceEnd = false;
|
||||||
|
bool skipSliceStart = false;
|
||||||
|
|
||||||
|
if (auto skipLeft = matchAndConsume(TokenV::opColon); ! skipLeft) {
|
||||||
|
return Unexpected<>{ std::move(skipLeft).error() };
|
||||||
|
}
|
||||||
|
else if (skipLeft.value()) {
|
||||||
|
isSlice = true;
|
||||||
|
skipSliceStart = true;
|
||||||
|
|
||||||
|
if (auto close = matchAndConsume(TokenV::opRBracket); ! close) {
|
||||||
|
return Unexpected<>{ std::move(close).error() };
|
||||||
|
}
|
||||||
|
else if (close.value()) {
|
||||||
|
skipSliceEnd = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto idxExpr = ast::Optional<ast::ExpressionNode>{};
|
||||||
|
|
||||||
|
if (! skipSliceStart) {
|
||||||
auto idx = parseExpression();
|
auto idx = parseExpression();
|
||||||
|
|
||||||
if (! idx) {
|
if (! idx) {
|
||||||
@ -642,6 +664,20 @@ namespace arti::lang {
|
|||||||
return Unexpected<>{ std::move(range).error() };
|
return Unexpected<>{ std::move(range).error() };
|
||||||
}
|
}
|
||||||
else if (range.value()) {
|
else if (range.value()) {
|
||||||
|
isSlice = true;
|
||||||
|
|
||||||
|
if (auto close = matchAndConsume(TokenV::opRBracket); ! close) {
|
||||||
|
return Unexpected<>{ std::move(close).error() };
|
||||||
|
}
|
||||||
|
else if (close.value()) {
|
||||||
|
skipSliceEnd = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
idxExpr = std::move(idx).value();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSlice) {
|
||||||
auto newNode = ast::MakeNode<ast::SliceRangeExprNode>();
|
auto newNode = ast::MakeNode<ast::SliceRangeExprNode>();
|
||||||
|
|
||||||
newNode->location = {
|
newNode->location = {
|
||||||
@ -649,8 +685,11 @@ namespace arti::lang {
|
|||||||
.column = peekToken->column
|
.column = peekToken->column
|
||||||
};
|
};
|
||||||
|
|
||||||
newNode->start = std::move(idx).value();
|
if (! skipSliceStart) {
|
||||||
|
newNode->start = std::move(idxExpr).value();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! skipSliceEnd) {
|
||||||
auto endIdx = parseExpression();
|
auto endIdx = parseExpression();
|
||||||
|
|
||||||
if (! endIdx) {
|
if (! endIdx) {
|
||||||
@ -662,6 +701,7 @@ namespace arti::lang {
|
|||||||
if (auto close = consume(TokenV::opRBracket, "']'"); ! close) {
|
if (auto close = consume(TokenV::opRBracket, "']'"); ! close) {
|
||||||
return Unexpected<>{ std::move(close).error() };
|
return Unexpected<>{ std::move(close).error() };
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
newNode->slice = std::move(lhs);
|
newNode->slice = std::move(lhs);
|
||||||
|
|
||||||
@ -675,7 +715,7 @@ namespace arti::lang {
|
|||||||
.column = peekToken->column
|
.column = peekToken->column
|
||||||
};
|
};
|
||||||
|
|
||||||
newNode->index = std::move(idx).value();
|
newNode->index = std::move(idxExpr).value();
|
||||||
|
|
||||||
if (auto close = consume(TokenV::opRBracket, "']'"); ! close) {
|
if (auto close = consume(TokenV::opRBracket, "']'"); ! close) {
|
||||||
return Unexpected<>{ std::move(close).error() };
|
return Unexpected<>{ std::move(close).error() };
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user