Skip to content

Commit 0df45cd

Browse files
committed
Add checking for missing parentheses for print/exec
1 parent effdb6e commit 0df45cd

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
import java.util.Map.Entry;
4141
import java.util.ServiceLoader;
4242
import java.util.logging.Level;
43+
import java.util.regex.Matcher;
44+
import java.util.regex.Pattern;
4345

4446
import org.graalvm.nativeimage.ImageInfo;
4547

@@ -209,6 +211,8 @@ public final class Python3Core implements PythonCore {
209211
private static final TruffleLogger LOGGER = PythonLanguage.getLogger(Python3Core.class);
210212
private final String[] coreFiles;
211213

214+
public static final Pattern MISSING_PARENTHESES_PATTERN = Pattern.compile("^(print|exec) +([^(][^;]*).*");
215+
212216
private static final String[] initializeCoreFiles() {
213217
// Order matters!
214218
List<String> coreFiles = new ArrayList<>(Arrays.asList(
@@ -774,6 +778,22 @@ public RuntimeException raiseInvalidSyntax(PythonParser.ErrorType type, Node loc
774778
} else {
775779
msg = "invalid syntax";
776780
}
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+
}
777797
instance.setAttribute("msg", msg);
778798
throw PException.fromObject(instance, location);
779799
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/antlr/DescriptiveBailErrorListener.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ public class DescriptiveBailErrorListener extends BaseErrorListener {
6565
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol,
6666
int line, int charPositionInLine,
6767
String msg, RecognitionException e) {
68-
68+
// If we already constructed the error, keep it, it should be the most specific one
69+
if (e instanceof EmptyRecognitionException) {
70+
throw e;
71+
}
6972
String entireMessage = e == null || e.getMessage() == null ? "invalid syntax" : e.getMessage();
7073

7174
IntervalSet expectedTokens = null;

0 commit comments

Comments
 (0)