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:
@@ -103,6 +103,15 @@ static bool match_next_char(akbasic_Runtime *obj, char cm, akbasic_TokenType tru
|
||||
char nc = '\0';
|
||||
|
||||
if ( !peek(obj, &nc) ) {
|
||||
/*
|
||||
* Nothing left to peek at, so the operator is whatever it is on its
|
||||
* own. The reference returns here *without* setting a type
|
||||
* (basicscanner.go:272), which silently drops a comparison operator in
|
||||
* the final column of a line: `A# =` produced one token, not two, and
|
||||
* the parse error that followed pointed somewhere else entirely.
|
||||
* TODO.md section 6 item 14.
|
||||
*/
|
||||
obj->tokentype = falsetype;
|
||||
return false;
|
||||
}
|
||||
if ( nc == cm ) {
|
||||
@@ -144,6 +153,7 @@ static akerr_ErrorContext *match_number(akbasic_Runtime *obj)
|
||||
char nc = '\0';
|
||||
int64_t lineno = 0;
|
||||
long long converted = 0;
|
||||
bool hex = false;
|
||||
|
||||
obj->tokentype = AKBASIC_TOK_LITERAL_INT;
|
||||
while ( !is_at_end(obj) ) {
|
||||
@@ -156,8 +166,27 @@ static akerr_ErrorContext *match_number(akbasic_Runtime *obj)
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
obj->tokentype = AKBASIC_TOK_LITERAL_FLOAT;
|
||||
} else if ( !isdigit((unsigned char)c) && c != 'x' ) {
|
||||
/* 'x' is allowed through so 0x-prefixed hex reaches the parser. */
|
||||
} else if ( c == 'x' && !hex ) {
|
||||
/*
|
||||
* An 'x' in a number run. The reference lets it through and then
|
||||
* stops at the first hex digit after it (basicscanner.go:318), so
|
||||
* `0xff` lexed as `0x` followed by an identifier `ff`, the parser's
|
||||
* base-16 branch was unreachable, and the README's hex support did
|
||||
* not exist. TODO.md section 6 item 15. Once the 'x' is seen, keep
|
||||
* going over hex digits.
|
||||
*
|
||||
* Accepted anywhere in the run rather than only after a leading `0`,
|
||||
* which is the reference's rule and is worth keeping: it is what
|
||||
* makes `1x2` one malformed token that the line-number conversion
|
||||
* then diagnoses by name, instead of two tokens that fail somewhere
|
||||
* less helpful.
|
||||
*/
|
||||
hex = true;
|
||||
} else if ( hex ) {
|
||||
if ( !isxdigit((unsigned char)c) ) {
|
||||
break;
|
||||
}
|
||||
} else if ( !isdigit((unsigned char)c) ) {
|
||||
break;
|
||||
}
|
||||
obj->current += 1;
|
||||
@@ -231,6 +260,12 @@ static akerr_ErrorContext *match_identifier(akbasic_Runtime *obj)
|
||||
}
|
||||
|
||||
PASS(errctx, get_lexeme(obj, lexeme, sizeof(lexeme)));
|
||||
/*
|
||||
* Searched with the type suffix still attached, which is the reference's
|
||||
* rule (basicscanner.go:349) and is why the "Reserved word in variable name"
|
||||
* branch below is unreachable -- TODO.md section 6 item 16, which explains
|
||||
* why it is still here rather than fixed.
|
||||
*/
|
||||
PASS(errctx, akbasic_verb_lookup(lexeme, &verb));
|
||||
|
||||
ATTEMPT {
|
||||
|
||||
Reference in New Issue
Block a user