Fix five defects the port uncovered in the reference parser and scanner
Chained subtraction and exponentiation fold left instead of abandoning the rest of the line -- `1 - 2 - 3` gave -1 and dropped the `- 3`. A unary leaf's operand moves to .left, so a negative literal is one argument again and a second argument no longer overwrites it. An operator in a line's final column survives. Hex literals reach the parser whole. A leading zero is padding, not a radix. Item 16 stays pinned: the fix works and costs an upstream golden case, which is a decision rather than a defect. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
36
src/parser.c
36
src/parser.c
@@ -349,10 +349,15 @@ akerr_ErrorContext *akbasic_parser_relation(akbasic_Parser *obj, akbasic_ASTLeaf
|
||||
}
|
||||
|
||||
/*
|
||||
* subtraction and exponent return after one operator where addition,
|
||||
* multiplication and division loop. That asymmetry is the reference's, not a
|
||||
* transcription slip: `1 - 2 - 3` parses as `1 - (2 - 3)` there. Reproduced,
|
||||
* because the golden corpus encodes the observed associativity.
|
||||
* Loops, where the reference returns after one operator (basicparser.go:329).
|
||||
* That asymmetry was reproduced faithfully at first and is TODO.md section 6
|
||||
* item 12: `1 - 2 - 3` computed `1 - 2` and abandoned the rest of the line,
|
||||
* which the statement loop then picked up as a second statement and discarded.
|
||||
* A wrong answer, silently -- the highest-impact item on that list.
|
||||
*
|
||||
* Left-associative, matching addition, multiplication and division here and
|
||||
* matching a C128, which evaluates a run of same-precedence operators left to
|
||||
* right.
|
||||
*/
|
||||
static akerr_ErrorContext *subtraction(akbasic_Parser *obj, akbasic_ASTLeaf **dest)
|
||||
{
|
||||
@@ -363,15 +368,16 @@ static akerr_ErrorContext *subtraction(akbasic_Parser *obj, akbasic_ASTLeaf **de
|
||||
akbasic_Token *operator_ = NULL;
|
||||
|
||||
PASS(errctx, addition(obj, &left));
|
||||
if ( akbasic_parser_match1(obj, AKBASIC_TOK_MINUS) ) {
|
||||
while ( akbasic_parser_match1(obj, AKBASIC_TOK_MINUS) ) {
|
||||
PASS(errctx, akbasic_parser_previous(obj, &operator_));
|
||||
PASS(errctx, addition(obj, &right));
|
||||
if ( expr != NULL ) {
|
||||
left = expr;
|
||||
}
|
||||
PASS(errctx, akbasic_parser_new_leaf(obj, &expr));
|
||||
PASS(errctx, akbasic_leaf_new_binary(expr, left, operator_->tokentype, right));
|
||||
*dest = expr;
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
*dest = left;
|
||||
*dest = (expr != NULL ? expr : left);
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
@@ -469,15 +475,21 @@ static akerr_ErrorContext *exponent(akbasic_Parser *obj, akbasic_ASTLeaf **dest)
|
||||
akbasic_Token *operator_ = NULL;
|
||||
|
||||
PASS(errctx, function_call(obj, &left));
|
||||
if ( akbasic_parser_match1(obj, AKBASIC_TOK_CARAT) ) {
|
||||
/*
|
||||
* Loops for the same reason subtraction does -- `2 ^ 3 ^ 2` abandoned the
|
||||
* second operator before this. Left-associative, which is a C128: 2^3^2 is
|
||||
* 64 there, not the 512 a right-associative reading gives.
|
||||
*/
|
||||
while ( akbasic_parser_match1(obj, AKBASIC_TOK_CARAT) ) {
|
||||
PASS(errctx, akbasic_parser_previous(obj, &operator_));
|
||||
PASS(errctx, function_call(obj, &right));
|
||||
if ( expr != NULL ) {
|
||||
left = expr;
|
||||
}
|
||||
PASS(errctx, akbasic_parser_new_leaf(obj, &expr));
|
||||
PASS(errctx, akbasic_leaf_new_binary(expr, left, operator_->tokentype, right));
|
||||
*dest = expr;
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
*dest = left;
|
||||
*dest = (expr != NULL ? expr : left);
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user