Skip to content

Commit

Permalink
Implement ISCHAR function
Browse files Browse the repository at this point in the history
  • Loading branch information
Rangi42 committed Oct 28, 2023
1 parent 84f3cb4 commit 79746ae
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 1 deletion.
2 changes: 2 additions & 0 deletions include/asm/charmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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_IsChar(char const *input);
size_t charmap_Convert(char const *input, uint8_t *output);
size_t charmap_ConvertNext(char const **input, uint8_t **output);

Expand Down
1 change: 1 addition & 0 deletions man/rgbasm.5
Original file line number Diff line number Diff line change
Expand Up @@ -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 ISCHAR str Ta Returns 1 if Ar str No is a single 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
Expand Down
15 changes: 15 additions & 0 deletions src/asm/charmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,21 @@ void charmap_Add(char *mapping, uint8_t value)
node->value = value;
}

bool charmap_IsChar(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;
Expand Down
3 changes: 2 additions & 1 deletion src/asm/lexer.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ static struct KeywordMapping {

{"CHARLEN", T_OP_CHARLEN},
{"CHARSUB", T_OP_CHARSUB},
{"ISCHAR", T_OP_ISCHAR},

{"INCLUDE", T_POP_INCLUDE},
{"PRINT", T_POP_PRINT},
Expand Down Expand Up @@ -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[367] = {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)
Expand Down
4 changes: 4 additions & 0 deletions src/asm/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ enum {

%token T_OP_CHARLEN "CHARLEN"
%token T_OP_CHARSUB "CHARSUB"
%token T_OP_ISCHAR "ISCHAR"

%token <symName> T_LABEL "label"
%token <symName> T_ID "identifier"
Expand Down Expand Up @@ -1579,6 +1580,9 @@ relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); }
| T_OP_CHARLEN T_LPAREN string T_RPAREN {
rpn_Number(&$$, charlenUTF8($3));
}
| T_OP_ISCHAR T_LPAREN string T_RPAREN {
rpn_Number(&$$, charmap_IsChar($3));
}
| T_LPAREN relocexpr T_RPAREN { $$ = $2; }
;

Expand Down
28 changes: 28 additions & 0 deletions test/asm/ischar.asm
Original file line number Diff line number Diff line change
@@ -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 ischar("a")
assert ischar("ab")
assert ischar(strcat("ab", "c"))

assert !ischar("") ; empty
assert !ischar("A") ; case sensitive
assert !ischar("aa") ; multiple chars "a" "a"
assert !ischar("d") ; unmapped char "d"
assert !ischar("bc") ; unmapped chars "b" "c"

setcharmap second

assert ischar("d") ; now "d" is mapped
assert !ischar("a") ; only in 'main'
assert !ischar("bc") ; still unmapped chars
assert ischar({__ISO_8601_UTC__})
Empty file added test/asm/ischar.err
Empty file.
Empty file added test/asm/ischar.out
Empty file.

0 comments on commit 79746ae

Please sign in to comment.