jQuery / JavaScript以正确的方式解析字符串

时间:2013-07-13 21:09:23

标签: javascript jquery string parsing

最近,我一直试图在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];
    }
}

但我认为我处理解析的方式可能大不相同 在阅读其他人如何处理这样的代码块解析的示例时,似乎人们解析了整个块,而不是像我一样将其拆分成行。我想问题是,解析这样的事情的正确和传统方式是什么,你怎么建议我用它来解析这样的东西?

2 个答案:

答案 0 :(得分:0)

在这种简单的情况下,regular expressions是您的首选工具:

matches = code.match(/@name\s+(\w+)/)
name = matches[1]

要解析“真正的”编程语言,正则表达式不够强大,您需要一个解析器,可以手写或使用PEG等工具自动生成。

答案 1 :(得分:0)

解析的一般方法,我喜欢经常采用以下方法:

  1. 逐个字符地循环遍历完整的文本块。
  2. 如果找到一个表示一个单位开头的字符,请调用一个专门的子函数来解析下一个字符。
  3. 在每个子功能中,如果找到某些字符,则调用其他子功能
  4. 当找到一个角色时,从每个子功能返回,表示该装置已经结束。
  5. 这是一个小例子:

    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