|
40 | 40 | import java.util.Map.Entry;
|
41 | 41 | import java.util.ServiceLoader;
|
42 | 42 | import java.util.logging.Level;
|
| 43 | +import java.util.regex.Matcher; |
| 44 | +import java.util.regex.Pattern; |
43 | 45 |
|
44 | 46 | import org.graalvm.nativeimage.ImageInfo;
|
45 | 47 |
|
@@ -209,6 +211,8 @@ public final class Python3Core implements PythonCore {
|
209 | 211 | private static final TruffleLogger LOGGER = PythonLanguage.getLogger(Python3Core.class);
|
210 | 212 | private final String[] coreFiles;
|
211 | 213 |
|
| 214 | + public static final Pattern MISSING_PARENTHESES_PATTERN = Pattern.compile("^(print|exec) +([^(][^;]*).*"); |
| 215 | + |
212 | 216 | private static final String[] initializeCoreFiles() {
|
213 | 217 | // Order matters!
|
214 | 218 | List<String> coreFiles = new ArrayList<>(Arrays.asList(
|
@@ -774,6 +778,22 @@ public RuntimeException raiseInvalidSyntax(PythonParser.ErrorType type, Node loc
|
774 | 778 | } else {
|
775 | 779 | msg = "invalid syntax";
|
776 | 780 | }
|
| 781 | + if (section.isAvailable() && type == PythonParser.ErrorType.Generic) { |
| 782 | + Matcher matcher = MISSING_PARENTHESES_PATTERN.matcher(source.getCharacters(section.getStartLine())); |
| 783 | + if (matcher.matches()) { |
| 784 | + String fn = matcher.group(1); |
| 785 | + if (fn.equals("print")) { |
| 786 | + String arg = matcher.group(2).trim(); |
| 787 | + String maybeEnd = ""; |
| 788 | + if (arg.endsWith(",")) { |
| 789 | + maybeEnd = " end=\" \""; |
| 790 | + } |
| 791 | + msg = (new ErrorMessageFormatter()).format("Missing parentheses in call to 'print'. Did you mean print(%s%s)?", arg, maybeEnd); |
| 792 | + } else { |
| 793 | + msg = "Missing parentheses in call to 'exec'"; |
| 794 | + } |
| 795 | + } |
| 796 | + } |
777 | 797 | instance.setAttribute("msg", msg);
|
778 | 798 | throw PException.fromObject(instance, location);
|
779 | 799 | }
|
|
0 commit comments