Как бы я отменить действия string.gmatch для определенного раздела строки в lua - PullRequest
0 голосов
/ 19 марта 2019

Так что я использую lua и разбиваю строку на пробелы для написания своего рода языка. И я пытаюсь, чтобы это ничего не разделяло внутри скобок, я уже на стадии, где я могу определить, есть ли скобки. Но я хочу обратить вспять соответствие строки в круглых скобках, поскольку я хочу сохранить строку, содержащуюся внутри.

local function split(strng)
    local __s={}
    local all_included={}
    local flag_table={}
    local uncompiled={}
    local flagged=false
    local flagnum=0

    local c=0
    for i in string.gmatch(strng,'%S+') do
        c=c+1
        table.insert(all_included,i)
        if(flagged==false)then
            if(string.find(i,'%('or'%['or'%{'))then
                flagged=true
                flag_table[tostring(c)]=1
                table.insert(uncompiled,i)
                print'flagged'
            else 
                table.insert(__s,i)
            end
        elseif(flagged==true)then
            table.insert(uncompiled,i)
            if(string.find(i,'%)' or '%]' or '%}'))then
                flagged=false
                local __=''
                for i=1,#uncompiled do
                    __=__ .. uncompiled[i]
                end
                table.insert(__s,__)
                print'unflagged'
            end
        end
    end

    return __s;
end

Это мой код расщепления

Ответы [ 2 ]

2 голосов
/ 19 марта 2019

Я бы просто не использовал gmatch для этого вообще.

local input = " this is a string (containg some (well, many) annoying) parentheses and should be split. The string contains  double   spaces. What should be done? And what about trailing spaces? "

local pos = 1
local words = {}
local last_start = pos
while pos <= #input do
    local char = string.byte(input, pos)

    if char == string.byte(" ") then
        table.insert(words, string.sub(input, last_start, pos - 1))
        last_start = pos + 1
    elseif char == string.byte("(") then
        local depth = 1
        while depth ~= 0 and pos + 1 < #input do
            local char = string.byte(input, pos + 1)
            if char == string.byte(")") then
                depth = depth - 1
            elseif char == string.byte("(") then
                depth = depth + 1
            end
            pos = pos + 1
        end
    end
    pos = pos + 1
end
table.insert(words, string.sub(input, last_start))

for k, v in pairs(words) do
    print(k, "'" .. v .. "'")
end

Выход:

1   ''
2   'this'
3   'is'
4   'a'
5   'string'
6   '(containg some (well, many) annoying)'
7   'parentheses'
8   'and'
9   'should'
10  'be'
11  'split.'
12  'The'
13  'string'
14  'contains'
15  ''
16  'double'
17  ''
18  ''
19  'spaces.'
20  'What'
21  'should'
22  'be'
23  'done?'
24  'And'
25  'what'
26  'about'
27  'trailing'
28  'spaces?'
29  ''

Думая о пробелах и других подобных проблемах, мы оставляем читателю упражнение Я попытался выделить некоторые из возможных проблем с примером, который я использовал. Кроме того, я рассмотрел только один вид скобок, так как я не хочу думать, как this (string} should be ]parsed.

Да, и если вложенные скобки не имеют значения: большую часть кода выше можно заменить вызовом string.find(input, ")", pos, true), чтобы найти закрывающую скобку.

Обратите внимание, что вы не можете использовать шаблоны or или and, как это делается в вашем коде.

"%(" or "%[" равно "%("

Луа будет интерпретировать это выражение слева направо. "%( - это истинное значение, Lua уменьшит выражение до "%(", что логически совпадает с полным выражением.

Так что string.find(i,'%('or'%['or'%{') найдет только ( в i.

1 голос
/ 19 марта 2019

Как похожий, но немного другой подход к ответу Ули, я бы сначала разделил его на круглые скобки.Затем вы можете разделить поля с номерами odd на пробел:

split = require("split") -- https://luarocks.org/modules/telemachus/split

split__by_parentheses = function(input)
    local fields = {}
    local level = 0
    local field = ""

    for i = 1, #input do
        local char = input:sub(i, i)

        if char == "(" then
            if level == 0 then 
                -- add non-parenthesized field to list
                fields[#fields+1] = field 
                field = ""
            end
            level = level + 1
        end

        field = field .. char

        if char == ")" then
            level = level - 1
            assert(level >= 0, 'Mismatched parentheses')
            if level == 0 then 
                -- add parenthesized field to list
                fields[#fields+1] = field 
                field = ""
            end
        end
    end

    assert(level == 0, 'Mismatched parentheses')
    fields[#fields+1] = field
    return fields
end

input = " this is a string (containg some (well, many) annoying) parentheses and should be split. The string contains  double   spaces. What should be done? And what about trailing spaces? "

fields = split__by_parentheses(input)

for i, field in ipairs(fields) do
    print(("%d\t'%s'"):format(i, field))
    if i % 2 == 1 then
        for j, word in ipairs(split.split(field)) do
            print(("\t%d\t%s"):format(j, word))
        end
    end
end

output

1       ' this is a string '
        1
        2       this
        3       is
        4       a
        5       string
        6
2       '(containg some (well, many) annoying)'
3       ' parentheses and should be split. The string contains  double   spaces. What should be done? And what about trailing spaces? '
        1
        2       parentheses
        3       and
        4       should
        5       be
        6       split.
        7       The
        8       string
        9       contains
        10      double
        11      spaces.
        12      What
        13      should
        14      be
        15      done?
        16      And
        17      what
        18      about
        19      trailing
        20      spaces?
        21
...