diff --git a/modules/compiler/src/main/antlr/ScriptLexer.g4 b/modules/compiler/src/main/antlr/ScriptLexer.g4 index a9d2e18..f0a6be2 100644 --- a/modules/compiler/src/main/antlr/ScriptLexer.g4 +++ b/modules/compiler/src/main/antlr/ScriptLexer.g4 @@ -139,6 +139,9 @@ GStringBegin TdqGStringBegin : TdqStringQuotationMark -> pushMode(TDQ_GSTRING_MODE) ; +SlashyGStringBegin + : Slash { this.isRegexAllowed() && _input.LA(1) != '*' }? SlashyStringCharacter* Dollar { isFollowedByJavaLetterInGString(_input) }? -> pushMode(SLASHY_GSTRING_MODE) + ; mode DQ_GSTRING_MODE; GStringEnd @@ -174,6 +177,23 @@ TdqGStringExprStart : '${' -> pushMode(DEFAULT_MODE) ; +mode SLASHY_GSTRING_MODE; +SlashyGStringEnd + : Dollar? Slash -> popMode + ; + +SlashyGStringPath + : Dollar IdentifierInGString (Dot IdentifierInGString)* + ; + +SlashyGStringText + : SlashyStringCharacter+ + ; + +SlashyGStringExprStart + : '${' -> pushMode(DEFAULT_MODE) + ; + mode DEFAULT_MODE; // character in the double quotation string. e.g. "a" fragment diff --git a/modules/compiler/src/main/antlr/ScriptParser.g4 b/modules/compiler/src/main/antlr/ScriptParser.g4 index 09591a4..e6f95d0 100644 --- a/modules/compiler/src/main/antlr/ScriptParser.g4 +++ b/modules/compiler/src/main/antlr/ScriptParser.g4 @@ -522,6 +522,7 @@ stringLiteral gstring : GStringBegin gstringDqPart* GStringEnd | TdqGStringBegin gstringTdqPart* TdqGStringEnd + | SlashyGStringBegin gstringSlashyPart* SlashyGStringEnd ; gstringDqPart @@ -536,6 +537,12 @@ gstringTdqPart | TdqGStringExprStart expression RBRACE #gstringTdqExprAlt ; +gstringSlashyPart + : SlashyGStringText #gstringSlashyTextAlt + | SlashyGStringPath #gstringSlashyPathAlt + | SlashyGStringExprStart expression RBRACE #gstringSlashyExprAlt + ; + // -- constructor method call creator : createdName arguments diff --git a/modules/compiler/src/main/java/script/parser/ScriptAstBuilder.java b/modules/compiler/src/main/java/script/parser/ScriptAstBuilder.java index 0e9cb54..6d1d95b 100644 --- a/modules/compiler/src/main/java/script/parser/ScriptAstBuilder.java +++ b/modules/compiler/src/main/java/script/parser/ScriptAstBuilder.java @@ -1222,9 +1222,6 @@ private String stringLiteral(String text) { text = StringUtils.trimQuotations(text, 3); } else if( text.startsWith(SQ_STR) || text.startsWith(DQ_STR) || startsWithSlash ) { - // the slashy string can span rows, so we have to remove CR for it - if( startsWithSlash ) - text = StringUtils.removeCR(text); text = StringUtils.trimQuotations(text, 1); } @@ -1264,6 +1261,17 @@ private Expression gstring(GstringContext ctx) { values.add(expression(eac.expression())); } + for( var part : ctx.gstringSlashyPart() ) { + if( part instanceof GstringSlashyTextAltContext tac ) + strings.add(ast( gstringText(tac, beginQuotation), tac )); + + if( part instanceof GstringSlashyPathAltContext pac ) + values.add(ast( gstringPath(pac), pac )); + + if( part instanceof GstringSlashyExprAltContext eac ) + values.add(expression(eac.expression())); + } + var result = new GStringExpression(verbatimText, strings, values); result.putNodeMetaData(QUOTE_CHAR, beginQuotation); return result; @@ -1274,6 +1282,8 @@ private String beginQuotation(String text) { return TDQ_STR; if( text.startsWith(DQ_STR) ) return DQ_STR; + if( text.startsWith(SLASH_STR) ) + return SLASH_STR; throw new IllegalStateException(); }