Handle string literals within macro arguments (#685)

Fixes #683 and #691

The lexer's raw mode for reading macro args already attempted
to handle semicolons inside string literals, versus outside ones
which start comments. This change reuses the same function for
reading string literals in normal and raw modes, also handling:

- Commas in strings versus between macro args
- Character escapes
- {Interpolations} and \1-\9 args inside vs. outside strings
- Multi-line string literals

Macro args now allow escaping '\', '"', and '\\'.

A consistent model for expanding macro args and interpolations,
within macro args, string literals, and normal context:

- "{S}" should always equal the contents of S
- "\1" should always act like quoting the value of \1
This commit is contained in:
Rangi
2021-02-16 19:44:25 -08:00
committed by GitHub
parent 8c0275480c
commit d049ffc0f0
17 changed files with 360 additions and 79 deletions

View File

@@ -1,9 +1,12 @@
print1: MACRO
if _NARG == 2
assert !STRCMP("\1", \2)
endc
PRINTLN "\1"
ENDM
print1 John "Danger" Smith
print1 \\A\nB
print1 \\\\A\\nB\n, "\\\\A\\nB\n"
print1 C\
D
print1 E\!F ; illegal character escape
@@ -15,3 +18,10 @@ ENDM
s EQUS "hello"
iprint s
symprint: MACRO
PRINTLN {\1}
ENDM
hello EQUS "\"goodbye\""
symprint s

View File

@@ -1,3 +1,3 @@
ERROR: macro-arg-in-string.asm(9) -> macro-arg-in-string.asm::print1(2):
ERROR: macro-arg-in-string.asm(12):
Illegal character escape '!'
error: Assembly aborted (1 errors)!

View File

@@ -1,6 +1,7 @@
John "Danger" Smith
\A
B
\\A\nB
CD
E\F
E!F
hello
goodbye

View File

@@ -21,7 +21,8 @@ printarg: MACRO
ENDM
printarg "
printarg """
printarg """multi-line
string argument"""
EMPTY1 EQUS ""
EMPTY2 EQUS "\ ; comment

View File

@@ -1,2 +1,5 @@
warning: multi-line-strings.asm(34): [-Wuser]
ERROR: multi-line-strings.asm(23):
Unterminated string
warning: multi-line-strings.asm(35): [-Wuser]
check the line number
error: Assembly aborted (1 errors)!

View File

@@ -8,6 +8,8 @@ The multi-line string can contain:
!
arg <">
arg (")
arg <""">
arg (""")
arg <"""multi-line
string argument""">
arg ("""multi-line
string argument""")
()

14
test/asm/quine.asm Normal file
View File

@@ -0,0 +1,14 @@
R:MACRO
REPT _NARG
PRINT STRSUB("\n\"\\ ENRST1ABCDFGHIMOPU_n#()+,:>",\1+1,1)
SHIFT
ENDR
ENDM
N:MACRO
R \#
REPT _NARG
PRINT"\1",STRSUB("\n,",(_NARG>1)+1,1)
SHIFT
ENDR
ENDM
N 6,29,18,10,12,6,19,0,6,4,20,8,3,22,5,10,6,15,0,20,6,17,5,8,3,7,8,6,7,21,11,25,1,2,23,2,1,2,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,1,28,2,9,27,9,28,9,26,0,7,16,17,14,8,0,4,5,13,6,0,4,5,13,18,0,5,29,18,10,12,6,19,0,3,6,3,2,24,0,6,4,20,8,3,22,5,10,6,15,0,20,6,17,5,8,1,2,9,1,28,7,8,6,7,21,11,25,1,2,23,28,1,28,25,22,5,10,6,15,30,9,26,27,9,28,9,26,0,7,16,17,14,8,0,4,5,13,6,0,4,5,13,18,0,3,5,3

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

14
test/asm/quine.out Normal file
View File

@@ -0,0 +1,14 @@
R:MACRO
REPT _NARG
PRINT STRSUB("\n\"\\ ENRST1ABCDFGHIMOPU_n#()+,:>",\1+1,1)
SHIFT
ENDR
ENDM
N:MACRO
R \#
REPT _NARG
PRINT"\1",STRSUB("\n,",(_NARG>1)+1,1)
SHIFT
ENDR
ENDM
N 6,29,18,10,12,6,19,0,6,4,20,8,3,22,5,10,6,15,0,20,6,17,5,8,3,7,8,6,7,21,11,25,1,2,23,2,1,2,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,1,28,2,9,27,9,28,9,26,0,7,16,17,14,8,0,4,5,13,6,0,4,5,13,18,0,5,29,18,10,12,6,19,0,3,6,3,2,24,0,6,4,20,8,3,22,5,10,6,15,0,20,6,17,5,8,1,2,9,1,28,7,8,6,7,21,11,25,1,2,23,28,1,28,25,22,5,10,6,15,30,9,26,27,9,28,9,26,0,7,16,17,14,8,0,4,5,13,6,0,4,5,13,18,0,3,5,3

4
test/asm/quine2.asm Normal file
View File

@@ -0,0 +1,4 @@
q: macro
println \1,"\1"
endm
q "q: macro\n\tprintln \\1,\"\\1\"\nendm\n\tq "

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

4
test/asm/quine2.out Normal file
View File

@@ -0,0 +1,4 @@
q: macro
println \1,"\1"
endm
q "q: macro\n\tprintln \\1,\"\\1\"\nendm\n\tq "

View File

@@ -0,0 +1,38 @@
printargs: MACRO
rept _NARG
println \1
shift
endr
ENDM
printlit: MACRO
rept _NARG
println "\1"
shift
endr
ENDM
NUM EQU 42
STR EQUS "str\"ing"
printargs NUM
printargs "{d:NUM}"
printargs "{STR}", 16 ; comment 1
printargs "\"literal \\\"\\\\\\\"\""
printargs "literal \"\\\"", \ ; comment 2
"""multi-"line"
""string"" arg"""
printargs MUL(2.0\, 3.0)
printargs "unclosed
printlit NUM
printlit "{d:NUM}"
printlit "{STR}", 16 ; comment 3
printlit "\"literal \\\"\\\\\\\"\""
printlit "literal \"\\\"", \ ; comment 4
"""multi-"line"
""string"" arg"""
printlit MUL(2.0\, 3.0)
printlit this\n is\, \{not\} a\\n syntax\" error
printlit "unclosed
printlit """EOF

View File

@@ -0,0 +1,9 @@
ERROR: raw-macro-args.asm(26):
Unterminated string
ERROR: raw-macro-args.asm(26) -> raw-macro-args.asm::printargs(2) -> raw-macro-args.asm::printargs::REPT~1(3):
Unterminated string
ERROR: raw-macro-args.asm(37):
Unterminated string
ERROR: raw-macro-args.asm(38):
Unterminated string
error: Assembly aborted (4 errors)!

View File

@@ -0,0 +1,23 @@
$2A
42
str"ing
$10
"literal \"\\\""
literal "\"
multi-"line"
""string"" arg
$60000
unclosed
NUM
"42"
"str\"ing"
16
"\"literal \\\"\\\\\\\"\""
"literal \"\\\""
"""multi-"line"
""string"" arg"""
MUL(2.0, 3.0)
this
is, {not} a\n syntax" error
"unclosed
"""EOF