Skip to content

Commit 752e2b3

Browse files
committed
Symbol names with more than two '.'s could be defined as constants
Dot-only names could also trip an assertion in `make develop` when used as labels
1 parent ad3188f commit 752e2b3

File tree

13 files changed

+78
-7
lines changed

13 files changed

+78
-7
lines changed

include/asm/symbol.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ struct Symbol {
6868
uint32_t getConstantValue() const;
6969
};
7070

71+
bool sym_IsDotScope(std::string const &symName);
72+
7173
void sym_ForEach(void (*callback)(Symbol &));
7274

7375
Symbol *sym_AddLocalLabel(std::string const &symName);

src/asm/lexer.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,7 +1295,7 @@ static Token readIdentifier(char firstChar, bool raw) {
12951295
}
12961296

12971297
// Label scopes `.` and `..` are the only nonlocal identifiers that start with a dot
1298-
if (identifier.find_first_not_of('.') == identifier.npos) {
1298+
if (sym_IsDotScope(identifier)) {
12991299
tokenType = T_(SYMBOL);
13001300
}
13011301

@@ -1939,11 +1939,12 @@ static Token yylex_NORMAL() {
19391939

19401940
// `token` is either a `SYMBOL` or a `LOCAL`, and both have a `std::string` value.
19411941
assume(std::holds_alternative<std::string>(token.value));
1942+
std::string const &identifier = std::get<std::string>(token.value);
19421943

19431944
// Raw symbols and local symbols cannot be string expansions
19441945
if (!raw && token.type == T_(SYMBOL) && lexerState->expandStrings) {
19451946
// Attempt string expansion
1946-
if (Symbol const *sym = sym_FindExactSymbol(std::get<std::string>(token.value));
1947+
if (Symbol const *sym = sym_FindExactSymbol(identifier);
19471948
sym && sym->type == SYM_EQUS) {
19481949
beginExpansion(sym->getEqus(), sym->name);
19491950
continue; // Restart, reading from the new buffer
@@ -1954,6 +1955,7 @@ static Token yylex_NORMAL() {
19541955
// - label definitions (which are followed by a ':' and use the token `LABEL`)
19551956
// - quiet macro invocations (which are followed by a '?' and use the token `QMACRO`)
19561957
// - regular macro invocations (which use the token `SYMBOL`)
1958+
// - label scopes "." and ".." (which use the token `SYMBOL` no matter what)
19571959
//
19581960
// If we had one `IDENTIFIER` token, the parser would need to perform "lookahead" to
19591961
// determine which rule applies. But since macros need to enter "raw" mode to parse
@@ -1964,7 +1966,7 @@ static Token yylex_NORMAL() {
19641966
// one to lex depending on the character *immediately* following the identifier.
19651967
// Thus "name:" is a label definition, and "name?" is a quiet macro invocation, but
19661968
// "name :" and "name ?" and just "name" are all regular macro invocations.
1967-
if (token.type == T_(SYMBOL)) {
1969+
if (token.type == T_(SYMBOL) && !sym_IsDotScope(identifier)) {
19681970
c = peek();
19691971
token.type = c == ':' ? T_(LABEL) : c == '?' ? T_(QMACRO) : T_(SYMBOL);
19701972
}

src/asm/symbol.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ bool sym_IsPC(Symbol const *sym) {
5353
return sym == PCSymbol;
5454
}
5555

56+
bool sym_IsDotScope(std::string const &symName) {
57+
// Label scopes `.` and `..` are the only nonlocal identifiers that start with a dot.
58+
// Three or more dots are considered a nonsensical local label.
59+
return symName == "." || symName == "..";
60+
}
61+
5662
void sym_ForEach(void (*callback)(Symbol &)) {
5763
for (auto &it : symbols) {
5864
callback(it.second);
@@ -215,8 +221,8 @@ static void redefinedError(Symbol const &sym) {
215221

216222
static void assumeAlreadyExpanded(std::string const &symName) {
217223
// Either the symbol name is `Global.local` or entirely '.'s (for scopes `.` and `..`),
218-
// but cannot be unqualified `.local`
219-
assume(!symName.starts_with('.') || symName.find_first_not_of('.') == symName.npos);
224+
// but cannot be unqualified `.local` or more than two '.'s
225+
assume(!symName.starts_with('.') || sym_IsDotScope(symName));
220226
}
221227

222228
static Symbol &createSymbol(std::string const &symName) {
@@ -253,7 +259,7 @@ static bool isAutoScoped(std::string const &symName) {
253259
}
254260

255261
// Label scopes `.` and `..` are the only nonlocal identifiers that start with a dot
256-
if (dotPos == 0 && symName.find_first_not_of('.') == symName.npos) {
262+
if (sym_IsDotScope(symName)) {
257263
return false;
258264
}
259265

test/asm/dots-constant.asm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
section "test", rom0
2+
def #... equs "sublocal"

test/asm/dots-constant.err

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
error: syntax error, unexpected local label, expecting symbol
2+
at dots-constant.asm(2)
3+
Assembly aborted with 1 error!

test/asm/dots-interpolate.asm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
section "test", rom0
2+
println "{...}"

test/asm/dots-interpolate.err

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
FATAL: `...` is a nonsensical reference to a nested local label
2+
at dots-interpolate.asm(2)

test/asm/dots-label.asm

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
section "test", rom0
2+
#...:

test/asm/dots-label.err

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
FATAL: `...` is a nonsensical reference to a nested local label
2+
at dots-label.asm(2)

test/asm/dots-macro-arg.asm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
MACRO test
2+
println "\<...>"
3+
ENDM
4+
test 1, 2, 3, 4

0 commit comments

Comments
 (0)