/** * 将一行字符串切割为(str,quoted)[]的形式 * @param str * @returns */ export function splitStr2Objs(str: string) { // console.log(`splitStr2Objs: ${str}`); let res: { str: string; isQuoted?: boolean; isSquared?: boolean, isRounded?: boolean }[] = []; let len = str.length; let p = 0; while (p < len) { while (p < len && str[p] === " ") ++p; // find first not space if (p === len) return res; if (str[p] === '"') { // find next `"` let q = p + 1; while (q < len && str[q] !== '"') { if (str[q] === "\\") q += 2; else ++q; } if (q >= len) throw "Quote not completed"; let resstr = str.slice(p + 1, q); // console.log(`Transformed[${res.length}]:\n${transformStr(resstr)}`); let transformedStr: string = "error"; try { transformedStr = transformStr(resstr); } catch (e) { throw "该字符串中的转义字符有错误:" + resstr; } res.push({ str: transformedStr!, isQuoted: true }); p = q + 1; } else if (str[p] === "[") { // find next `]` let q = p + 1; while (q < len && str[q] !== "]") { // if (str[q] === "\\") q += 2; // else ++q; ++q; } if (q >= len) throw "square brackets not completed"; let resstr = str.slice(p + 1, q); res.push({ str: resstr, isSquared: true }); p = q + 1; } else if (str[p] === "(") { // find next `)` let q = p + 1; while (q < len && str[q] !== ")") { // if (str[q] === "\\") q += 2; // else ++q; ++q; } if (q >= len) throw "round brackets not completed"; let resstr = str.slice(p + 1, q); res.push({ str: resstr, isRounded: true }); p = q + 1; } else { let q = p + 1; while (q < len && str[q] !== " " && str[q] !== '"' && str[q] !== "(" && str[q] !== "[") ++q; // find first space/quote after this let resstr = str.slice(p, q); // console.log(transformStr(resstr)); res.push({ str: resstr, isQuoted: false }); p = q; } } return res; } export function mergeObjs2Str( objs: { str: string; isQuoted?: boolean; isSquared?: boolean, isRounded?: boolean }[] ) { return objs .map((obj) => obj.isQuoted ? `"${obj.str}"` : obj.isSquared ? `[${obj.str}]` : obj.isRounded ? `(${obj.str})` : obj.str ) .join(" "); } export function splitStr2Strs(str: string) { return splitStr2Objs(str).map((obj) => obj.isQuoted ? `"${obj.str}"` : obj.str ); } /** * 转义一遍字符串,使其中\n等变成对应字符(可能报错) * @param str * @returns */ export function transformStr(str: string) { return JSON.parse(`"${str}"`); } // 翻译hzengine script插值字符串 // 语法:"...[expression]..." // 如果希望在字符串中显示`[`,请使用两个`[`,如`"[[正常显示而不被当作表达式的文字]]"` export function parseInterpolatedStr(str: string): ParsedInterpolationItem[] { let len = str.length; let p = 0; let expr_record: [l: number, r: number][] = []; while (p < len) { // 寻找第一个`[` while (p < len && str[p] !== "[") ++p; if (p >= len) break; // 判断是否是两个`[` if (str[p] === "[" && str[p + 1] === "[") { p += 2; continue; } // 寻找第一个`]` let q = p + 1; while (q < len && str[q] !== "]") { ++q; // 判断是否是两个`]` while (q < len && str[q] === "]" && str[q + 1] === "]") { q += 2; } } if (q >= len) { // 没有找到`]`,报错 throw `Interpolated string lose closing bracket: ${str}`; } expr_record.push([p, q]); p = q + 1; } let left = 0, right = len; let res: ParsedInterpolationItem[] = []; for (let i = 0; i < expr_record.length; ++i) { let [l, r] = expr_record[i]; if (l > left) res.push({ str: str.slice(left, l), isExpression: false }); res.push({ str: str.slice(l + 1, r), isExpression: true }); left = r + 1; } if (left < right) res.push({ str: str.slice(left, right), isExpression: false }); return res; } export function removeComment(str: string) { let quoteNotClosed = false; let len = str.length; for (let i = 0; i < len; ++i) { if (quoteNotClosed && str[i] === `\\`) { ++i; } else if (str[i] === `"`) { quoteNotClosed = !quoteNotClosed; } else if (str[i] === "#" && !quoteNotClosed) { return str.slice(0, i); } } return str; } type ParsedInterpolationItem = { str: string; isExpression: boolean; };