
本文介绍如何修改现有 JavaScript 转换器,使其支持多行源代码输入(如换行符 \n),并通过 textarea 获取完整文本,正确分词、解析并生成格式清晰的等效 JavaScript 代码。
本文介绍如何修改现有 javascript 转换器,使其支持多行源代码输入(如换行符 `\n`),并通过 `textarea` 获取完整文本,正确分词、解析并生成格式清晰的等效 javascript 代码。
默认情况下,原代码使用 document.getElementById("sparkText").value 获取输入值,但若该元素是 ,则无法接收换行符(\n),导致多行输入被截断为单行。根本解决方法是将输入控件替换为 —— 它天然支持多行文本输入,并完整保留 \n(或 \r\n)换行符。
在此基础上,需重构核心处理逻辑:原 convert() 函数仅对整个字符串做一次词法分析,未考虑按行划分语义单元。而实际需求中,每行通常对应一条独立语句(如 new dog is "dog"),应逐行处理,避免跨行误匹配(例如引号跨越多行时引发正则异常)。
以下是关键改进点:
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
✅ 1. 使用 textarea 替代 input
<textarea id="sparkText" placeholder="请输入自定义语言代码(支持多行)"></textarea><pre class="brush:php;toolbar:false;" id="jsText">
确保 DOM 元素支持换行输入。
✅ 2. 按行分割输入,逐行处理
在 convert() 中先用正则 /\r?\n/ 统一匹配 Windows/macOS/Linux 换行符,再对每行调用 lexer → parse → out 流程:
function convert(input) {
const lines = input.split(/\r?\n/);
let result = '';
for (const line of lines) {
if (line.trim() === '') continue; // 跳过空行
const tokens = lexer(line);
result += out(tokens) + '\n';
}
return result.trim(); // 去除末尾多余换行
}
✅ 3. 优化辅助函数(提升健壮性)
- parse() 可链式调用,避免重复赋值;
- out() 中统一使用模板字符串或 +=,并注意奇偶索引逻辑(偶数位为代码主体,奇数位为字符串字面量);
- lexer() 的正则 /".*?"/g 对简单字符串有效,但不支持嵌套引号或转义引号;生产环境建议改用状态机或成熟 parser(如 acorn),此处为教学简化保留。
✅ 4. 完整可运行示例
function lexer(code) {
const regex = /"(.*?)"/g;
return code.split(regex);
}
function parse(input) {
return input
.replace(/new/g, 'let')
.replace(/is/g, '=')
.replace(/say/g, 'console.log')
.replace(/shout/g, 'alert');
}
function out(arr) {
return arr.map((part, i) =>
i % 2 === 0 ? parse(part) : `"${parse(part)}"`
).join('');
}
function convert(input) {
return input
.split(/\r?\n/)
.filter(line => line.trim())
.map(line => out(lexer(line)))
.join('\n');
}
// 绑定到页面事件
function update() {
const input = document.getElementById('sparkText').value;
const output = convert(input);
document.getElementById('jsText').textContent = output;
}
// 示例调用
console.log(convert(`new dog is "dog"
new cat is "cat"`));
// 输出:
// let dog = "dog"
// let cat = "cat"
⚠️ 注意事项
- 正则局限性:当前 /"(.*?)"/g 无法处理含转义引号(如 "He said \"Hi\"")的字符串,如需增强,请改用更鲁棒的字符串解析逻辑。
- 全局替换风险:replace(/new/g, 'let') 可能误替换变量名中的 new(如 known → klet)。建议使用单词边界 /\bnew\b/g。
- 性能考量:对于大文件,逐行处理已足够高效;若需高亮、错误定位等功能,应引入 AST 解析。
通过以上改造,你的转换器即可无缝支持多行输入,真正实现类 DSL 的基础编译体验。










