Skip to content

Commit 4b70d2a

Browse files
committed
more pre-processing
1 parent 7c1a91e commit 4b70d2a

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

basic

4 KB
Binary file not shown.

basic.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ static int is_ident_char(int c)
7979
return isalpha((unsigned char)c) || isdigit((unsigned char)c) || c == '$';
8080
}
8181

82+
static int is_name_char(int c)
83+
{
84+
return isalpha((unsigned char)c) || c == '$';
85+
}
86+
8287
static const TokenMap token_map[] = {
8388
{"WHITE", 5},
8489
{"RED", 28},
@@ -385,6 +390,40 @@ static char *normalize_keywords_line(const char *input)
385390
}
386391
}
387392

393+
/* FOR followed immediately by identifier/digit: FORI=1TO9 -> FOR I=1TO9 */
394+
if (c1 == 'F' && c2 == 'O' && c3 == 'R') {
395+
char next = input[i + 3];
396+
if (next != '\0' && !isspace((unsigned char)next) && next != ':' ) {
397+
if (out.len > 0) {
398+
char prev = out.buf[out.len - 1];
399+
if (!isspace((unsigned char)prev) && prev != ':' && prev != '(') {
400+
sb_append_char(&out, ' ');
401+
}
402+
}
403+
sb_append_str(&out, "FOR");
404+
i += 3;
405+
sb_append_char(&out, ' ');
406+
continue;
407+
}
408+
}
409+
410+
/* NEXT followed immediately by identifier: NEXTI -> NEXT I */
411+
if (c1 == 'N' && c2 == 'E' && c3 == 'X' && c4 == 'T') {
412+
char next = input[i + 4];
413+
if (out.len > 0) {
414+
char prev = out.buf[out.len - 1];
415+
if (!isspace((unsigned char)prev) && prev != ':' && prev != '(') {
416+
sb_append_char(&out, ' ');
417+
}
418+
}
419+
sb_append_str(&out, "NEXT");
420+
i += 4;
421+
if (next != '\0' && !isspace((unsigned char)next) && next != ':' ) {
422+
sb_append_char(&out, ' ');
423+
}
424+
continue;
425+
}
426+
388427
/* THEN */
389428
if (c1 == 'T' && c2 == 'H' && c3 == 'E' && c4 == 'N') {
390429
/* Insert space before THEN if needed */
@@ -407,6 +446,56 @@ static char *normalize_keywords_line(const char *input)
407446
continue;
408447
}
409448

449+
/* TO inside numeric ranges: 1TO9 -> 1 TO 9, but never split GOTO. */
450+
if (c1 == 'T' && c2 == 'O') {
451+
size_t j;
452+
char prev_ns = ' ';
453+
char next_ns = '\0';
454+
455+
/* Skip if this is the TO in GOTO (e.g. ...GOTO 100). */
456+
if (i >= 2) {
457+
char g = (char)toupper((unsigned char)input[i - 2]);
458+
char o = (char)toupper((unsigned char)input[i - 1]);
459+
if (g == 'G' && o == 'O') {
460+
/* fall through to normal character handling */
461+
} else {
462+
/* Find previous non-space character. */
463+
j = i;
464+
while (j > 0) {
465+
j--;
466+
if (!isspace((unsigned char)input[j])) {
467+
prev_ns = input[j];
468+
break;
469+
}
470+
}
471+
/* Find next non-space character after TO. */
472+
j = i + 2;
473+
while (input[j] != '\0' && isspace((unsigned char)input[j])) {
474+
j++;
475+
}
476+
next_ns = input[j];
477+
478+
/* Treat as TO only when between numeric-ish tokens, like 1TO9. */
479+
if ((isdigit((unsigned char)prev_ns) || prev_ns == ')') &&
480+
(isdigit((unsigned char)next_ns) || next_ns == '+' || next_ns == '-')) {
481+
if (out.len > 0) {
482+
char prev = out.buf[out.len - 1];
483+
if (!isspace((unsigned char)prev) && prev != '(') {
484+
sb_append_char(&out, ' ');
485+
}
486+
}
487+
sb_append_str(&out, "TO");
488+
i += 2;
489+
if (next_ns != '\0' && !isspace((unsigned char)next_ns) &&
490+
next_ns != ':' && next_ns != ')') {
491+
sb_append_char(&out, ' ');
492+
}
493+
continue;
494+
}
495+
}
496+
}
497+
}
498+
410499
/* AND / OR infix operators without spaces.
411500
* Only treat as operators when they are not embedded in identifiers
412501
* (e.g., avoid splitting FOR into F OR, or ORD into OR D).

0 commit comments

Comments
 (0)