diff --git a/java/src/processing/mode/java/Compiler.java b/java/src/processing/mode/java/Compiler.java index 94448bf56..944ca442a 100644 --- a/java/src/processing/mode/java/Compiler.java +++ b/java/src/processing/mode/java/Compiler.java @@ -63,8 +63,8 @@ public class Compiler { "-g", "-Xemacs", //"-noExit", // not necessary for ecj - "-source", "11", - "-target", "11", + "-source", "11", // TODO: 17 if using new language features + "-target", "11", // TODO: 17 if using new language features "-encoding", "utf8", "-classpath", classpathEmptyRemoved, "-nowarn", // we're not currently interested in warnings (works in ecj) diff --git a/java/src/processing/mode/java/PreprocService.java b/java/src/processing/mode/java/PreprocService.java index 8678d410b..1d325e30f 100644 --- a/java/src/processing/mode/java/PreprocService.java +++ b/java/src/processing/mode/java/PreprocService.java @@ -957,6 +957,7 @@ public class PreprocService { static { Map compilerOptions = new HashMap<>(); + // TODO: VERSION_17 if using new language features compilerOptions.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_11); compilerOptions.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_11); compilerOptions.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_11); diff --git a/java/src/processing/mode/java/preproc/JavaLexer.g4 b/java/src/processing/mode/java/preproc/JavaLexer.g4 index 27b188cb3..13adc7dc9 100644 --- a/java/src/processing/mode/java/preproc/JavaLexer.g4 +++ b/java/src/processing/mode/java/preproc/JavaLexer.g4 @@ -9,7 +9,7 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -116,6 +116,8 @@ BOOL_LITERAL: 'true' CHAR_LITERAL: '\'' (~['\\\r\n] | EscapeSequence) '\''; STRING_LITERAL: '"' (~["\\\r\n] | EscapeSequence)* '"'; +MULTI_STRING_LIT: '"""' (~[\\] | EscapeSequence)* '"""'; + NULL_LITERAL: 'null'; // Separators LPAREN: '('; diff --git a/java/src/processing/mode/java/preproc/JavaParser.g4 b/java/src/processing/mode/java/preproc/JavaParser.g4 index 9974cb2bb..4157fcde7 100644 --- a/java/src/processing/mode/java/preproc/JavaParser.g4 +++ b/java/src/processing/mode/java/preproc/JavaParser.g4 @@ -294,11 +294,19 @@ literal : integerLiteral | floatLiteral | CHAR_LITERAL - | STRING_LITERAL + | stringLiteral | BOOL_LITERAL | NULL_LITERAL ; +baseStringLiteral: STRING_LITERAL; +multilineStringLiteral: MULTI_STRING_LIT; + +stringLiteral + : baseStringLiteral + | multilineStringLiteral + ; + integerLiteral : DECIMAL_LITERAL | HEX_LITERAL diff --git a/java/src/processing/mode/java/preproc/PdeParseTreeListener.java b/java/src/processing/mode/java/preproc/PdeParseTreeListener.java index ac15eaef1..ab2c2b8c6 100644 --- a/java/src/processing/mode/java/preproc/PdeParseTreeListener.java +++ b/java/src/processing/mode/java/preproc/PdeParseTreeListener.java @@ -55,6 +55,7 @@ public class PdeParseTreeListener extends ProcessingBaseListener { private static final String NO_SMOOTH_METHOD_NAME = "noSmooth"; private static final String PIXEL_DENSITY_METHOD_NAME = "pixelDensity"; private static final String FULLSCREEN_METHOD_NAME = "fullScreen"; + private static final boolean SIMULATE_MULTILINE_STRINGS = true; final private String sketchName; private boolean isTesting; @@ -452,6 +453,29 @@ public class PdeParseTreeListener extends ProcessingBaseListener { } } + /** + * Endpoint for ANTLR to call after parsing a String literal. + * + *

+ * Endpoint for ANTLR to call when finished parsing a string literal, simulating multiline + * strings if configured to do so. + *

+ * + * @param ctx ANTLR context for the literal. + */ + public void exitMultilineStringLiteral(ProcessingParser.MultilineStringLiteralContext ctx) { + String fullLiteral = ctx.getText(); + if (SIMULATE_MULTILINE_STRINGS) { + delete(ctx.start, ctx.stop); + int endIndex = fullLiteral.length() - 3; + String literalContents = fullLiteral.substring(3, endIndex); + String newLiteralContents = literalContents + .replace("\n", "\\n") + .replace("\"", "\\\""); + insertAfter(ctx.stop, "\"" + newLiteralContents + "\""); + } + } + /** * Endpoint for ANTLR to call after parsing a static processing sketch. * diff --git a/java/src/processing/mode/java/preproc/Processing.g4 b/java/src/processing/mode/java/preproc/Processing.g4 index 5e091aefa..ea7bb5696 100644 --- a/java/src/processing/mode/java/preproc/Processing.g4 +++ b/java/src/processing/mode/java/preproc/Processing.g4 @@ -107,7 +107,7 @@ literal : integerLiteral | floatLiteral | CHAR_LITERAL - | STRING_LITERAL + | stringLiteral | BOOL_LITERAL | NULL_LITERAL | hexColorLiteral diff --git a/java/test/processing/mode/java/ParserTests.java b/java/test/processing/mode/java/ParserTests.java index f57849129..ee80d7143 100644 --- a/java/test/processing/mode/java/ParserTests.java +++ b/java/test/processing/mode/java/ParserTests.java @@ -415,4 +415,9 @@ public class ParserTests { expectGood("sizeclass"); } + @Test + public void testMultlineString() { + expectGood("multilinestr"); + } + } diff --git a/java/test/resources/multilinestr.expected b/java/test/resources/multilinestr.expected new file mode 100644 index 000000000..830b12e39 --- /dev/null +++ b/java/test/resources/multilinestr.expected @@ -0,0 +1,35 @@ +import processing.core.*; +import processing.data.*; +import processing.event.*; +import processing.opengl.*; + +import java.util.HashMap; +import java.util.ArrayList; +import java.io.File; +import java.io.BufferedReader; +import java.io.PrintWriter; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public class multilinestr extends PApplet { + + public void setup() { +String testOldStyle = "line1\"\nline 2 \"\"\nline 3"; +String testMultiline = "\nline4 \"\nline 5 \"\"\nline 6\nline 7"; + +println(testOldStyle); +println(testMultiline); + + noLoop(); + } + + static public void main(String[] passedArgs) { + String[] appletArgs = new String[] { "multilinestr" }; + if (passedArgs != null) { + PApplet.main(concat(appletArgs, passedArgs)); + } else { + PApplet.main(appletArgs); + } + } +} diff --git a/java/test/resources/multilinestr.pde b/java/test/resources/multilinestr.pde new file mode 100644 index 000000000..4c4c8dbea --- /dev/null +++ b/java/test/resources/multilinestr.pde @@ -0,0 +1,9 @@ +String testOldStyle = "line1\"\nline 2 \"\"\nline 3"; +String testMultiline = """ +line4 " +line 5 "" +line 6 +line 7"""; + +println(testOldStyle); +println(testMultiline);