寻找Lua中括号的算法?

我正在制作一个 JSON 解析器,我正在寻找一种算法,可以找到所有匹配的方括号([])和大括号({}),并将它们放入一个表格中,记录它们的位置。

返回值的示例:

table[x][firstPos][secondPos] = type

table[x] = {firstPos, secondPos, bracketType}

编辑:让parse()函数返回一对括号的位置。让table成为parse()函数返回的值。让codeString为包含要检测的括号的字符串。让firstPos为第N对括号中第一个括号的位置。让secondPos为第N对括号中第二个括号的位置。让bracketType为一对括号的类型(“括号”或“大括号”)。

示例:

如果调用:

table = parse(codeString)

table[N][firstPos][secondPos]将等于type

点赞
用户513763
用户513763

嗯,在普通的 Lua 中,你可以像这样做,同时考虑到嵌套的括号:

function bm(s)
    local res ={}
    if not s:match('%[') then
            return s
    end
    for k in s:gmatch('%b[]') do
            res[#res+1] = bm(k:sub(2,-2))
    end
    return res
end

当然,你可以将此通常化为花括号、括号等(记得在模式中需要转义 [],除了 %b 模式之后)。

如果你不仅需要查找括号中的内容,还需要查找位置,那么递归的方法就难以实现了,因为你需要追踪记录你所处的位置。更容易的方法是直接遍历字符串并在过程中寻找匹配:

function bm(s,i)
    local res={}
    res.par=res      -- Root
    local lev = 0
    for loc=1,#s do
        if s:sub(loc,loc) == '[' then
            lev = lev+1
            local t={par=res,start=loc,lev=lev}   -- keep track of the parent
            res[#res+1] = t                       -- Add to the parent
            res = t                               -- make this the current working table
            print('[',lev,loc)
        elseif s:sub(loc,loc) == ']' then
            lev = lev-1
            if lev<0 then error('too many ]') end -- more closing than opening.
            print(']',lev,loc)
            res.stop=loc                          -- save bracket closing position
            res = res.par                         -- revert to the parent.
        end
    end
    return res
end

现在你有了所有匹配的括号,你可以遍历这个表并提取所有位置。

2013-10-15 11:23:53
用户2694431
用户2694431

我想出了自己的算法。

function string:findAll(query)
    local firstSub = 1
    local lastSub = #query
    local result = {}
    while lastSub <= #self do
        if self:sub(firstSub, lastSub) == query then
            result[#result + 1] = firstSub
        end
        firstSub = firstSub + 1
        lastSub = lastSub + 1
    end
    return result
end

function string:findPair(openPos, openChar, closeChar)
    local counter = 1
    local closePos = openPos
    while closePos <= #self do
        closePos = closePos + 1
        if self:sub(closePos, closePos) == openChar then
            counter = counter + 1
        elseif self:sub(closePos, closePos) == closeChar then
            counter = counter - 1
        end
        if counter == 0 then
            return closePos
        end
    end
    return -1
end

function string:findBrackets(bracketType)
    local openBracket = ""
    local closeBracket = ""
    local openBrackets = {}
    local result = {}
    if bracketType == "[]" then
        openBracket = "["
        closeBracket = "]"
    elseif bracketType == "{}" then
        openBracket = "{"
        closeBracket = "}"
    elseif bracketType == "()" then
        openBracket = "("
        closeBracket = ")"
    elseif bracketType == "<>" then
        openBracket = "<"
        closeBracket = ">"
    else
        error("IllegalArgumentException: Invalid or unrecognized bracket type "..bracketType.."\nFunction: findBrackets()")
    end
    local openBrackets = self:findAll(openBracket)
    if not openBrackets[1] then
        return {}
    end
    for i, j in pairs(openBrackets) do
        result[#result + 1] = {j, self:findPair(j, openBracket, closeBracket)}
    end
    return result
end

将输出:

5   14
6   13
7   12
8   11
9   10
2013-11-04 00:38:20