Report prescan errors on their source lines
Some checks failed
akbasic CI Build / coverage (push) Failing after 27s
akbasic CI Build / cmake_build (push) Failing after 33s
akbasic CI Build / akgl_build (push) Failing after 18s
akbasic CI Build / sanitizers (push) Failing after 1m7s
akbasic CI Build / mutation_test (push) Failing after 39s

This commit is contained in:
2026-08-05 06:40:14 -04:00
parent 350deb3a45
commit d715bc0625
8 changed files with 98 additions and 4 deletions

View File

@@ -16,6 +16,8 @@
* below.
*/
#include <stdio.h>
#include "harness.h"
/**
@@ -341,6 +343,28 @@ static akerr_ErrorContext AKERR_NOIGNORE *test_prescan_boundaries(void)
SUCCEED_RETURN(errctx);
}
/** @brief A full label table reports the line whose label could not be filed. */
static void test_label_prescan_error_line(void)
{
char source[4096] = "";
size_t used = 0;
int i = 0;
for ( i = 1; i <= AKBASIC_MAX_LABELS + 1; i++ ) {
used += (size_t)snprintf(source + used, sizeof(source) - used,
"%d LABEL L%d\n", i, i);
}
(void)snprintf(source + used, sizeof(source) - used, "100 PRINT 1\n");
TEST_REQUIRE_OK(harness_start(NULL));
TEST_REQUIRE_OK(akbasic_runtime_load(&HARNESS_RUNTIME, source));
TEST_REQUIRE_OK(akbasic_runtime_start(&HARNESS_RUNTIME, AKBASIC_MODE_RUN));
TEST_REQUIRE(strstr(HARNESS_OUTPUT, "? 65 : PARSE ERROR") != NULL,
"a full label table should report its source line, got \"%s\"",
HARNESS_OUTPUT);
harness_stop();
}
int main(void)
{
PREPARE_ERROR(errctx);
@@ -355,6 +379,7 @@ int main(void)
CATCH(errctx, test_undefined_label_is_reported());
CATCH(errctx, test_arm_refusals());
CATCH(errctx, test_prescan_boundaries());
test_label_prescan_error_line();
} CLEANUP {
} PROCESS(errctx) {
} HANDLE_DEFAULT(errctx) {

View File

@@ -1,2 +1,2 @@
? 90 : PARSE ERROR TYPE POINT: POINT is a reserved word and cannot name a type
? 60 : PARSE ERROR TYPE POINT: POINT is a reserved word and cannot name a type

View File

@@ -8,6 +8,7 @@
* TODO.md section 6.
*/
#include <stdio.h>
#include <string.h>
#include <akbasic/error.h>
@@ -174,6 +175,34 @@ static void test_colon_ends_data(void)
harness_stop();
}
/** @brief DATA overflow reports the line where the item limit was crossed. */
static void test_data_prescan_error_line(void)
{
char source[4096] = "";
size_t used = 0;
int line = 0;
int item = 0;
for ( line = 1; line <= 34; line++ ) {
used += (size_t)snprintf(source + used, sizeof(source) - used, "%d DATA ", line);
for ( item = 0; item < 15; item++ ) {
used += (size_t)snprintf(source + used, sizeof(source) - used,
"%s1", (item == 0 ? "" : ","));
}
used += (size_t)snprintf(source + used, sizeof(source) - used, "\n");
}
used += (size_t)snprintf(source + used, sizeof(source) - used, "100 DATA 1,1\n");
(void)snprintf(source + used, sizeof(source) - used, "101 DATA 1\n200 PRINT 1\n");
TEST_REQUIRE_OK(harness_start(NULL));
TEST_REQUIRE_OK(akbasic_runtime_load(&HARNESS_RUNTIME, source));
TEST_REQUIRE_OK(akbasic_runtime_start(&HARNESS_RUNTIME, AKBASIC_MODE_RUN));
TEST_REQUIRE(strstr(HARNESS_OUTPUT, "? 101 : PARSE ERROR") != NULL,
"DATA overflow should report its source line, got \"%s\"",
HARNESS_OUTPUT);
harness_stop();
}
/** @brief A float item fills a float variable with its fractional part intact. */
static void test_float_items(void)
{
@@ -227,6 +256,7 @@ int main(void)
test_type_mismatch();
test_quoted_items();
test_colon_ends_data();
test_data_prescan_error_line();
test_float_items();
test_negative_items();
return akbasic_test_failures;

View File

@@ -218,6 +218,22 @@ static void test_declaration_errors_are_basic_errors(void)
}
}
/** @brief A field declaration error reports the field's source line. */
static void test_type_prescan_error_line(void)
{
TEST_REQUIRE_OK(harness_start(NULL));
TEST_REQUIRE_OK(akbasic_runtime_load(&HARNESS_RUNTIME,
"10 TYPE RECT\n"
"20 W# EXTRA\n"
"30 END TYPE\n"
"40 PRINT 1\n"));
TEST_REQUIRE_OK(akbasic_runtime_start(&HARNESS_RUNTIME, AKBASIC_MODE_RUN));
TEST_REQUIRE(strstr(HARNESS_OUTPUT, "? 20 : PARSE ERROR") != NULL,
"TYPE prescan should report its source line, got \"%s\"",
HARNESS_OUTPUT);
harness_stop();
}
/**
* @brief An over-long type or field name is refused, not silently trimmed.
*
@@ -270,6 +286,7 @@ int main(void)
test_missing_field_lists_the_others();
test_self_by_value_refused();
test_declaration_errors_are_basic_errors();
test_type_prescan_error_line();
test_long_names_are_refused();
return akbasic_test_failures;