Skip to content

Commit b41b0cb

Browse files
committed
Only splitting assembler arguments along commas that are not nested within "" () [] {}.
1 parent 322472f commit b41b0cb

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

Source/DFPSR/implementation/machine/VirtualMachine.h

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,47 @@ struct VirtualMachine {
324324
}
325325
return nullptr;
326326
}
327+
// Instead of tokenizing, the assembler simply splits everything after colon along commas to get the arguments.
328+
// To avoid splitting with commas inside of text used to create immediate values, only the commas outside of "" () [] {} are used to split.
329+
List<String> nestedCommaSplit(const ReadableString& source) {
330+
List<String> result;
331+
intptr_t sectionStart = 0;
332+
bool quoted = false;
333+
intptr_t depth = 0;
334+
for (intptr_t i = 0; i < string_length(source); i++) {
335+
DsrChar c = source[i];
336+
if (quoted) {
337+
if (c == U'"') {
338+
quoted = false;
339+
} else if (c == U'\\') {
340+
// Skip one character after escape.
341+
i++;
342+
}
343+
} else {
344+
if (c == U'"') {
345+
quoted = true;
346+
} else if (c == U',' and depth == 0) {
347+
ReadableString element = string_exclusiveRange(source, sectionStart, i);
348+
result.push(string_removeOuterWhiteSpace(element));
349+
sectionStart = i + 1;
350+
} else if (c == U'(' || c == U'[' || c == U'{') {
351+
depth++;
352+
} else if (c == U')' || c == U']' || c == U'}') {
353+
depth--;
354+
}
355+
}
356+
}
357+
if (string_length(source) > sectionStart) {
358+
result.push(string_removeOuterWhiteSpace(string_exclusiveRange(source, sectionStart, string_length(source))));
359+
}
360+
if (quoted) {
361+
throwError(U"Quotes may not contain unmangled line-breaks in virtual machine assembler code!\n");
362+
}
363+
if (depth != 0) {
364+
throwError(U"Immediate constants must balance expressions containing () [] {}, because otherwise parsing of virtual machine assembler code can not know which commas are used to separate arguments!\n");
365+
}
366+
return result;
367+
}
327368
// Constructor
328369
VirtualMachine(const ReadableString& code, const Handle<PlanarMemory<TYPE_COUNT>>& memory,
329370
const InsSig<TYPE_COUNT>* machineInstructions, int32_t machineInstructionCount,
@@ -348,7 +389,7 @@ struct VirtualMachine {
348389
if (colonIndex > -1) {
349390
ReadableString command = string_removeOuterWhiteSpace(string_before(currentLine, colonIndex));
350391
ReadableString argumentLine = string_after(currentLine, colonIndex);
351-
List<String> arguments = string_split(argumentLine, U',', true);
392+
List<String> arguments = nestedCommaSplit(argumentLine);
352393
this->interpretMachineWord(command, arguments);
353394
} else if (string_length(currentLine) > 0) {
354395
throwError(U"Unexpected line \"", currentLine, U"\".\n");

0 commit comments

Comments
 (0)