最近,我一直试图在jQuery和JavaScript中模拟一种小语言,但我遇到了我认为是一个问题。我认为我可能正在解决一切完全错误的问题 在代码中:
@name Testing
@inputs
@outputs
@persist
@trigger
print("Test")
我分离和解析字符串的当前方法是将所有代码拆分为行,然后使用搜索和拆分读取此行数组。例如,我会使用类似的东西找到名称:
if(typeof lines[line] === 'undefined')
{
}
else
{
if(lines[line].search('@name') == 0)
{
name = lines[line].split(' ')[1];
}
}
但我认为我处理解析的方式可能大不相同 在阅读其他人如何处理这样的代码块解析的示例时,似乎人们解析了整个块,而不是像我一样将其拆分成行。我想问题是,解析这样的事情的正确和传统方式是什么,你怎么建议我用它来解析这样的东西?
答案 0 :(得分:0)
在这种简单的情况下,regular expressions是您的首选工具:
matches = code.match(/@name\s+(\w+)/)
name = matches[1]
要解析“真正的”编程语言,正则表达式不够强大,您需要一个解析器,可以手写或使用PEG等工具自动生成。
答案 1 :(得分:0)
解析的一般方法,我喜欢经常采用以下方法:
这是一个小例子:
var text = "@func(arg1,arg2)"
function parse(text) {
var i, max_i, ch, funcRes;
for (i = 0, max_i = text.length; i < max_i; i++) {
ch = text.charAt(i);
if (ch === "@") {
funcRes = parseFunction(text, i + 1);
i = funcRes.index;
}
}
console.log(funcRes);
}
function parseFunction(text, i) {
var max_i, ch, name, argsRes;
name = [];
for (max_i = text.length; i < max_i; i++) {
ch = text.charAt(i);
if (ch === "(") {
argsRes = parseArguments(text, i + 1);
return {
name: name.join(""),
args: argsRes.arr,
index: argsRes.index
};
}
name.push(ch);
}
}
function parseArguments(text, i) {
var max_i, ch, args, arg;
arg = [];
args = [];
for (max_i = text.length; i < max_i; i++) {
ch = text.charAt(i);
if (ch === ",") {
args.push(arg.join(""));
arg = [];
continue;
} else if (ch === ")") {
args.push(arg.join(""));
return {
arr: args,
index: i
};
}
arg.push(ch);
}
}
<强> FIDDLE 强>
这个例子只是解析函数表达式,它遵循语法“@functionName(argumentName1,argumentName2,...)”。一般的想法是完全访问每个字符一次而不需要保存当前状态,如“hasSeenAtCharacter”或“hasSeenOpeningParentheses”,这在解析大型结构时会变得相当混乱。
请注意,这是一个非常简单的示例,它错过了所有错误处理和类似的东西,但我希望可以看到一般的想法。还要注意,我并不是说你应该一直使用这种方法。这是一种非常通用的方法,可用于许多场景。但这并不意味着它不能与正则表达式结合,例如,如果它在文本的某些部分比解析每个单独的字符更有意义。
最后一句话:如果你把专门的解析函数放在主解析函数中,你可以省去麻烦,这样所有函数都可以访问同一个变量i
。