Implement INCHARMAP function (#1184)

This commit is contained in:
Rangi
2023-11-02 15:14:54 -04:00
committed by GitHub
parent 5a25c547ab
commit 181512ad9d
8 changed files with 53 additions and 1 deletions

View File

@@ -9,6 +9,7 @@
#ifndef RGBDS_ASM_CHARMAP_H
#define RGBDS_ASM_CHARMAP_H
#include <stdbool.h>
#include <stdint.h>
#define DEFAULT_CHARMAP_NAME "main"
@@ -19,6 +20,7 @@ void charmap_Set(char const *name);
void charmap_Push(void);
void charmap_Pop(void);
void charmap_Add(char *mapping, uint8_t value);
bool charmap_HasChar(char const *input);
size_t charmap_Convert(char const *input, uint8_t *output);
size_t charmap_ConvertNext(char const **input, uint8_t **output);

View File

@@ -425,6 +425,7 @@ pattern replaced by interpolating the format
with its corresponding argument in
.Ar args
.Pq So %% Sc is replaced by the So % Sc character .
.It Fn INCHARMAP str Ta Returns 1 if Ar str No has an entry in the current charmap, and 0 otherwise.
.It Fn CHARLEN str Ta Returns the number of charmap entries in Ar str No with the current charmap.
.It Fn CHARSUB str pos Ta Returns the substring for the charmap entry at Ar pos No in Ar str No (first character is position 1, last is position -1) with the current charmap.
.El

View File

@@ -187,6 +187,22 @@ void charmap_Add(char *mapping, uint8_t value)
node->value = value;
}
bool charmap_HasChar(char const *input)
{
struct Charmap const *charmap = *currentCharmap;
struct Charnode const *node = &charmap->nodes[0];
for (; *input; input++) {
size_t next = node->next[*input - 1];
if (!next)
return false;
node = &charmap->nodes[next];
}
return node->isTerminal;
}
size_t charmap_Convert(char const *input, uint8_t *output)
{
uint8_t *start = output;

View File

@@ -206,6 +206,7 @@ static struct KeywordMapping {
{"CHARLEN", T_OP_CHARLEN},
{"CHARSUB", T_OP_CHARSUB},
{"INCHARMAP", T_OP_INCHARMAP},
{"INCLUDE", T_POP_INCLUDE},
{"PRINT", T_POP_PRINT},
@@ -571,7 +572,7 @@ struct KeywordDictNode {
uint16_t children[0x60 - ' '];
struct KeywordMapping const *keyword;
// Since the keyword structure is invariant, the min number of nodes is known at compile time
} keywordDict[365] = {0}; // Make sure to keep this correct when adding keywords!
} keywordDict[370] = {0}; // Make sure to keep this correct when adding keywords!
// Convert a char into its index into the dict
static uint8_t dictIndex(char c)

View File

@@ -606,6 +606,7 @@ enum {
%token T_OP_CHARLEN "CHARLEN"
%token T_OP_CHARSUB "CHARSUB"
%token T_OP_INCHARMAP "INCHARMAP"
%token <symName> T_LABEL "label"
%token <symName> T_ID "identifier"
@@ -1608,6 +1609,9 @@ relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); }
| T_OP_CHARLEN T_LPAREN string T_RPAREN {
rpn_Number(&$$, charlenUTF8($3));
}
| T_OP_INCHARMAP T_LPAREN string T_RPAREN {
rpn_Number(&$$, charmap_HasChar($3));
}
| T_LPAREN relocexpr T_RPAREN { $$ = $2; }
;

28
test/asm/incharmap.asm Normal file
View File

@@ -0,0 +1,28 @@
; default charmap 'main'
charmap "a", 1
charmap "ab", 2
charmap "abc", 3
newcharmap second
charmap "d", 4
charmap "e", 5
charmap {__ISO_8601_UTC__}, 6 ; expands with quotes
setcharmap main
assert incharmap("a")
assert incharmap("ab")
assert incharmap(strcat("ab", "c"))
assert !incharmap("") ; empty
assert !incharmap("A") ; case sensitive
assert !incharmap("aa") ; multiple chars "a" "a"
assert !incharmap("d") ; unmapped char "d"
assert !incharmap("bc") ; unmapped chars "b" "c"
setcharmap second
assert incharmap("d") ; now "d" is mapped
assert !incharmap("a") ; only in 'main'
assert !incharmap("bc") ; still unmapped chars
assert incharmap({__ISO_8601_UTC__})

0
test/asm/incharmap.err Normal file
View File

0
test/asm/incharmap.out Normal file
View File