mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Implement ++ operator for string concatenation (#1698)
This commit is contained in:
13
man/rgbasm.5
13
man/rgbasm.5
@@ -548,7 +548,7 @@ There are a number of escape sequences you can use within a string:
|
||||
.El
|
||||
.Pp
|
||||
Multi-line strings are contained in triple quotes
|
||||
.Pq Ql \&"\&"\&"for instance\&"\&"\&" .
|
||||
.Pq Ql \&"\&"\&"for instance""" .
|
||||
Escape sequences work the same way in multi-line strings; however, literal newline characters will be included as-is, without needing to escape them with
|
||||
.Ql \er
|
||||
or
|
||||
@@ -560,10 +560,19 @@ Inside them, backslashes and braces are treated like regular characters, so they
|
||||
For example, the raw string
|
||||
.Ql #"\et\e1{s}\e"
|
||||
is equivalent to the regular string
|
||||
.Ql "\e\et\e\e1\e{s}\e\e" .
|
||||
.Ql \&"\e\et\e\e1\e{s}\e\e" .
|
||||
(Note that this prevents raw strings from including the double quote character.)
|
||||
Raw strings also may be contained in triple quotes for them to be multi-line, so they can include literal newline or quote characters (although still not three quotes in a row).
|
||||
.Pp
|
||||
You can use the
|
||||
.Sq ++
|
||||
operator to concatenate two strings.
|
||||
.Ql \&"str" ++ \&"ing"
|
||||
is equivalent to
|
||||
.Ql \&"string" ,
|
||||
or to
|
||||
.Ql STRCAT("str", \&"ing") .
|
||||
.Pp
|
||||
The following functions operate on string expressions, and return strings themselves.
|
||||
.Bl -column "STRSLICE(str, start, stop)"
|
||||
.It Sy Name Ta Sy Operation
|
||||
|
||||
@@ -1774,12 +1774,17 @@ static Token yylex_NORMAL() {
|
||||
|
||||
// Handle ambiguous 1- or 2-char tokens
|
||||
|
||||
case '+': // Either += or ADD
|
||||
if (peek() == '=') {
|
||||
case '+': // Either +=, ADD, or CAT
|
||||
switch (peek()) {
|
||||
case '=':
|
||||
shiftChar();
|
||||
return Token(T_(POP_ADDEQ));
|
||||
}
|
||||
case '+':
|
||||
shiftChar();
|
||||
return Token(T_(OP_CAT));
|
||||
default:
|
||||
return Token(T_(OP_ADD));
|
||||
}
|
||||
|
||||
case '-': // Either -= or SUB
|
||||
if (peek() == '=') {
|
||||
|
||||
@@ -125,6 +125,9 @@
|
||||
%token OP_MUL "*" OP_DIV "/" OP_MOD "%"
|
||||
%token OP_EXP "**"
|
||||
|
||||
// String operators
|
||||
%token OP_CAT "++"
|
||||
|
||||
// Comparison operators
|
||||
%token OP_LOGICEQU "==" OP_LOGICNE "!="
|
||||
%token OP_LOGICLT "<" OP_LOGICGT ">"
|
||||
@@ -147,6 +150,7 @@
|
||||
%left OP_AND OP_OR OP_XOR
|
||||
%left OP_SHL OP_SHR OP_USHR
|
||||
%left OP_MUL OP_DIV OP_MOD
|
||||
%left OP_CAT
|
||||
%precedence NEG // applies to unary OP_LOGICNOT, OP_ADD, OP_SUB, OP_NOT
|
||||
%right OP_EXP
|
||||
|
||||
@@ -1613,6 +1617,10 @@ string_literal:
|
||||
STRING {
|
||||
$$ = std::move($1);
|
||||
}
|
||||
| string OP_CAT string {
|
||||
$$ = std::move($1);
|
||||
$$.append($3);
|
||||
}
|
||||
| OP_STRSLICE LPAREN string COMMA iconst COMMA iconst RPAREN {
|
||||
size_t len = strlenUTF8($3, false);
|
||||
uint32_t start = adjustNegativeIndex($5, len, "STRSLICE");
|
||||
|
||||
@@ -3,6 +3,5 @@ warning: equs-newline.asm(3): [-Wuser]
|
||||
while expanding symbol "ACT"
|
||||
warning: equs-newline.asm(3): [-Wuser]
|
||||
Second
|
||||
while expanding symbol "ACT"
|
||||
warning: equs-newline.asm(4): [-Wuser]
|
||||
Third
|
||||
|
||||
26
test/asm/string-concat.asm
Normal file
26
test/asm/string-concat.asm
Normal file
@@ -0,0 +1,26 @@
|
||||
SECTION "test", ROM0
|
||||
|
||||
MACRO test
|
||||
assert !strcmp(\1, \2)
|
||||
ENDM
|
||||
|
||||
test "a"++"b", "ab"
|
||||
test "a"++""++"b", "ab"
|
||||
test "a"++"b", strcat("a", "b")
|
||||
test "a"++"b"++"c", strcat("a","b","c")
|
||||
test "" ++ "", ""
|
||||
test strupr("a") ++ strlwr("B"), "Ab"
|
||||
|
||||
def str equs "hi"
|
||||
test #str ++ strupr(#str), "hiHI"
|
||||
test "a" ++ """b""" ++ strupr("c") ++ strslice(#str, 0, 0), "abC"
|
||||
|
||||
charmap "a", 1
|
||||
charmap "b", 2
|
||||
charmap "ab", 12
|
||||
assert "a" + "b" == 3
|
||||
assert "a" ++ "b" == 12
|
||||
|
||||
; errors
|
||||
assert 2 ++ 2 == 4
|
||||
ld a, [hl++]
|
||||
5
test/asm/string-concat.err
Normal file
5
test/asm/string-concat.err
Normal file
@@ -0,0 +1,5 @@
|
||||
error: string-concat.asm(25):
|
||||
syntax error, unexpected ++
|
||||
error: string-concat.asm(26):
|
||||
syntax error, unexpected ++, expecting ] or + or -
|
||||
error: Assembly aborted (2 errors)!
|
||||
@@ -3,41 +3,30 @@ error: unique-id.asm(11):
|
||||
while expanding symbol "warn_unique"
|
||||
warning: unique-id.asm(11): [-Wuser]
|
||||
!
|
||||
while expanding symbol "warn_unique"
|
||||
warning: unique-id.asm(12) -> unique-id.asm::m(4): [-Wuser]
|
||||
_u1!
|
||||
while expanding symbol "warn_unique"
|
||||
warning: unique-id.asm(12) -> unique-id.asm::m(5) -> unique-id.asm::m::REPT~1(6): [-Wuser]
|
||||
_u2!
|
||||
while expanding symbol "warn_unique"
|
||||
warning: unique-id.asm(12) -> unique-id.asm::m(5) -> unique-id.asm::m::REPT~2(6): [-Wuser]
|
||||
_u3!
|
||||
while expanding symbol "warn_unique"
|
||||
warning: unique-id.asm(12) -> unique-id.asm::m(8): [-Wuser]
|
||||
_u1!
|
||||
while expanding symbol "warn_unique"
|
||||
error: unique-id.asm(13):
|
||||
'\@' cannot be used outside of a macro or REPT/FOR block
|
||||
while expanding symbol "warn_unique"
|
||||
warning: unique-id.asm(13): [-Wuser]
|
||||
!
|
||||
while expanding symbol "warn_unique"
|
||||
warning: unique-id.asm(14) -> unique-id.asm::m(4): [-Wuser]
|
||||
_u4!
|
||||
while expanding symbol "warn_unique"
|
||||
warning: unique-id.asm(14) -> unique-id.asm::m(5) -> unique-id.asm::m::REPT~1(6): [-Wuser]
|
||||
_u5!
|
||||
while expanding symbol "warn_unique"
|
||||
warning: unique-id.asm(14) -> unique-id.asm::m(5) -> unique-id.asm::m::REPT~2(6): [-Wuser]
|
||||
_u6!
|
||||
while expanding symbol "warn_unique"
|
||||
warning: unique-id.asm(14) -> unique-id.asm::m(8): [-Wuser]
|
||||
_u4!
|
||||
while expanding symbol "warn_unique"
|
||||
error: unique-id.asm(15):
|
||||
'\@' cannot be used outside of a macro or REPT/FOR block
|
||||
while expanding symbol "warn_unique"
|
||||
warning: unique-id.asm(15): [-Wuser]
|
||||
!
|
||||
while expanding symbol "warn_unique"
|
||||
error: Assembly aborted (3 errors)!
|
||||
|
||||
Reference in New Issue
Block a user