Rascal插值字符串美化器空格保留问题及语法优化求助
问题诊断
- 词法匹配逻辑错误:原
IntStringCharacter规则会将${中的$识别为字符串常量的一部分,导致${foobar}被整体纳入InterpolatedStringConstant,无法触发InterpolatedPart的语法匹配。 - 美化器代码问题:存在重复的
toString(interpolatedPart)方法,且interpolatedString方法参数与语法定义的Interpolation结构不匹配,直接导致空格丢失。
修正方案
1. 调整词法规则,优先识别插值标记${
修改词法规则,确保$仅在后续不是{时才被纳入字符串常量,让${能被语法分析器识别为插值起始标记:
lexical InterpolatedStringConstant = @category="Constant" IntStringCharacter* // 仅匹配插值前后的纯字符串内容(不含s"和结尾") ; lexical IntStringCharacter = "\\" [" \\ b f n r t] // 处理转义序列 | UnicodeEscape // Unicode转义 | ![" \\ $] // 匹配非 "、\、$ 的普通字符 | "$" !>> "{" // 匹配独立$,后续是{则不纳入字符串 ; lexical Id = ([a-zA-Z] [a-zA-Z0-9_]* !>> [a-zA-Z0-9]) | `[^`]*` // 简化并修正标识符规则 ; syntax InterpolatedPart = "${" Id variable "}"; // 明确插值字符串的整体结构:s" + 前缀 + 插值 + 后缀 + " syntax Interpolation = "s\"" InterpolatedStringConstant? InterpolatedPart InterpolatedStringConstant? "\""; syntax Expr = Interpolation;
- 将
s"和结尾"从InterpolatedStringConstant中拆分到Interpolation规则,确保空格能被完整保留在前后字符串部分。 - 修正了原
Id规则中的语法错误,简化为标准的标识符匹配逻辑。
2. 修复美化器代码
删除重复方法,调整参数与语法结构对应,确保空格被正确拼接:
public str toString(interpolatedPart(str variable)){ return "${<variable>}"; } public str toString(interpolation(str prefix, InterpolatedPart intpart, str suffix)){ // 处理前缀/后缀为空的情况(比如插值在字符串首尾) str pre = prefix != null ? prefix : ""; str suf = suffix != null ? suffix : ""; return "s\"<pre><toString(intpart)><suf>\""; }
验证效果
输入:let x = s" ${foobar} "
解析后结构:
- 前缀:
" " - 插值部分:
${foobar} - 后缀:
" "
输出:let x = s" ${foobar} ",与预期完全一致。
扩展说明
如果需要支持多插值场景(如s"a${x}b${y}c"),可将Interpolation规则修改为:
syntax Interpolation = "s\"" (InterpolatedStringConstant | InterpolatedPart)+ "\"";
同时对应的美化器方法需要遍历处理所有字符串和插值部分。
内容的提问来源于stack exchange,提问作者Onyedika Ekwe CHRISxx
相关产品推荐
相关产品推荐

