Skip to content

Commit 20daac9

Browse files
committed
fix sprintf WIP
1 parent 246a2f0 commit 20daac9

File tree

1 file changed

+70
-10
lines changed

1 file changed

+70
-10
lines changed

src/main/java/org/perlonjava/operators/sprintf/SprintfFormatParser.java

Lines changed: 70 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -193,28 +193,58 @@ FormatSpecifier parseSpecifier() {
193193
spec.widthFromArg = true; // Means "has custom separator"
194194
advance(); // consume 'v'
195195

196+
System.err.println("DEBUG Parser: Parsed %*v, next char: '" + current() + "'");
197+
196198
// Now check for width after %*v
197199
if (match('*')) {
200+
System.err.println("DEBUG Parser: Found * after %*v");
198201
// Check for invalid positional after %*v*
199202
checkpoint = pos;
200203
Integer posParam = parseNumber();
201-
if (posParam != null && peek(0) == '$') {
204+
System.err.println("DEBUG Parser: After %*v*, number=" + posParam + ", current='" + current() + "'");
205+
206+
if (posParam != null && match('$')) {
207+
System.err.println("DEBUG Parser: Detected invalid %*v*N$ pattern");
202208
// %*v*999$ is invalid
203-
advance(); // consume $
204-
while (!isAtEnd() && !Character.isLetter(current())) {
205-
advance();
206-
}
209+
210+
// Continue parsing to get the conversion character
207211
if (!isAtEnd()) {
208212
spec.conversionChar = current();
209213
advance();
210214
}
215+
216+
spec.isValid = false;
217+
spec.errorMessage = "INVALID";
218+
spec.endPos = pos;
219+
spec.raw = input.substring(spec.startPos, spec.endPos);
220+
System.err.println("DEBUG Parser: Returning invalid spec: " + spec.raw);
221+
return spec;
222+
} else if (posParam != null) {
223+
// ADDITIONAL CHANGE: Handle case where we have number but no $
224+
// This is still invalid - don't reset position
225+
System.err.println("DEBUG Parser: Found number after %*v* but no $ - treating as invalid");
226+
227+
// The number is part of the format, continue to find conversion char
228+
// Current position is after the number
229+
if (!isAtEnd()) {
230+
// Skip any backslashes or other characters until we find a letter
231+
while (!isAtEnd() && !Character.isLetter(current())) {
232+
advance();
233+
}
234+
if (!isAtEnd()) {
235+
spec.conversionChar = current();
236+
advance();
237+
}
238+
}
239+
211240
spec.isValid = false;
212241
spec.errorMessage = "INVALID";
213242
spec.endPos = pos;
214243
spec.raw = input.substring(spec.startPos, spec.endPos);
244+
System.err.println("DEBUG Parser: Returning invalid spec: " + spec.raw);
215245
return spec;
216246
} else {
217-
pos = checkpoint; // Reset
247+
pos = checkpoint; // Reset only if no number was found
218248
spec.precisionFromArg = true; // HACK: means second *
219249
}
220250
} else {
@@ -311,14 +341,44 @@ FormatSpecifier parseSpecifier() {
311341
}
312342
}
313343

314-
// 7. Parse conversion character
344+
// 7. Parse conversion character
315345
if (isAtEnd()) {
316346
spec.isValid = false;
317347
spec.errorMessage = "MISSING";
318348
} else {
319-
spec.conversionChar = current();
349+
char firstChar = current();
320350
advance();
321-
// System.err.println("DEBUG: Parsed conversion char '" + spec.conversionChar + "'");
351+
352+
// Check if this might be part of a positional parameter
353+
if (Character.isDigit(firstChar) && !isAtEnd()) {
354+
// Look ahead to see if we have more digits and a $
355+
int checkPos = pos;
356+
while (!isAtEnd() && Character.isDigit(current())) {
357+
advance();
358+
}
359+
360+
if (!isAtEnd() && current() == '$') {
361+
// This is an invalid positional parameter at the conversion position
362+
advance(); // consume $
363+
364+
// Get the actual conversion character
365+
if (!isAtEnd()) {
366+
spec.conversionChar = current();
367+
advance();
368+
} else {
369+
spec.conversionChar = firstChar; // Use the first digit if nothing follows
370+
}
371+
372+
spec.isValid = false;
373+
spec.errorMessage = "INVALID";
374+
} else {
375+
// Not a positional parameter, just use the first character
376+
pos = checkPos; // Reset to after first char
377+
spec.conversionChar = firstChar;
378+
}
379+
} else {
380+
spec.conversionChar = firstChar;
381+
}
322382
}
323383

324384
spec.endPos = pos;
@@ -500,4 +560,4 @@ void validateFlags(FormatSpecifier spec) {
500560
}
501561
}
502562
}
503-
}
563+
}

0 commit comments

Comments
 (0)