2017-10-14 9 views
1

私はLua 5.3文字列を解析しようとしています。しかし、問題が発生しました。例えば、ルア文字列、より具体的には改行の解析

$ lua 
Lua 5.3.4 Copyright (C) 1994-2017 Lua.org, PUC-Rio 
> print(load('return "\\z \n\r \n\r \r\n \n \n \\x"', "@test")) 
nil test:6: hexadecimal digit expected near '"\x"' 
> 
> print(load('return "\\z\n\r\n\r\r\n\n\n\\x"', "@test")) 
nil test:6: hexadecimal digit expected near '"\x"' 

6行目のこれらのエラーのいずれも、その背後にあるロジックは非常に単純です:彼らは現在のものと異なるなら(私はこれを信じる改行文字(\ Rまたは\ n)を食べますルア・レクサーがどのように動作するかを正確に記述することができますが、私は間違っているかもしれません)。

私はそれを行う必要があり、このコードを、持っている:

local ln = 1 
local skip = false 
local mode = 0 
local prev 
for at, crlf in eaten:gmatch('()[\r\n]') do 
    local last = eaten:sub(at-1, at-1) 
    if skip and prev == last and last ~= crlf then 
    skip = false 
    else 
    skip = true 
    ln = ln + 1 
    end 
    prev = crlf 
end 

それは、前の文字に基づいて改行を食べるかどうかを決定します。今、私が言うことができるから、このでなければなりませんが、私が何をしても動作しないようです。それ以外の試みでは5行が報告され、一方で9行(!)になりました。私はここで何が欠けていますか?私はこれをLua 5.2.4で実行しています。

これは\zを解析するためのルーチンの一部である:

local function parse52(s) 
    local startChar = string.sub(s,1,1) 
    if startChar~="'" and startChar~='"' then 
    error("not a string", 0) 
    end 
    local c = 0 
    local ln = 1 
    local t = {} 
    local nj = 1 
    local eos = #s 
    local pat = "^(.-)([\\" .. startChar .. "\r\n])" 
    local mkerr = function(emsg, ...) 
    error(string.format('[%s]:%d: ' .. emsg, s, ln, ...), 0) 
    end 
    local lnj 
    repeat 
    lnj = nj 
    local i, j, part, k = string.find(s, pat, nj + 1, false) 
    if i then 
     c = c + 1 
     t[c] = part 
     if simpleEscapes[v] then 
     --[[ some code, some elseifs, some more code ]] 
     elseif v == "z" then 
     local eaten, np = s:match("^([\t\n\v\f\r ]*)%f[^\t\n\v\f\r ]()", nj+1) 
     local p=np 
     nj = p-1 
     --[[ the newline counting routine above ]] 
     --[[ some other elseifs ]] 
     end 
    else 
     nj = nil 
    end 
    until not nj 
    if s:sub(-1, -1) ~= startChar then 
    mkerr("unfinished string near <eof>") 
    end 
    return table.concat(t) 
end 
+0

'crlf' is is 'eaten:gmatch( '()[\ r \ n]')'は1つのキャプチャだけを返すので、常に 'nil'になります。おそらく、パターンを '()([\ r \ n])'にしたいでしょうか? –

+0

@EgorSkriptunoffそれはそれを解決しますが、答えとしてコメントを受け入れることはできません。 – SoniEx2

+0

はい、これは悪名高いことですので、コメントは受け入れることができませんが、回答は含まれています:-) –

答えて

0

Luaのスクリプトのラインを反復するためのコンパクトなコード:Luaのスクリプトのラインを繰り返すため

local text = "First\n\r\n\r\r\n\n\nSixth" 
local ln = 1 
for line, newline in text:gmatch"([^\r\n]*)([\r\n]*)" do 
    print(ln, line) 
    ln = ln + #newline:gsub("\n+", "\0%0\0"):gsub(".%z.", "."):gsub("%z", "") 
end 

効率的なコード:

local text = "First\n\r\n\r\r\n\n\nSixth" 
local sub = string.sub 
local ln = 1 
for line, newline in text:gmatch'([^\r\n]*)([\r\n]*)' do 
    print(ln, line) 
    local pos, max_pos = 1, #newline 
    while pos <= max_pos do 
     local crlf = sub(newline, pos, pos + 1) 
     if crlf == "\r\n" or crlf == "\n\r" then 
     pos = pos + 2 
     else 
     pos = pos + 1 
     end 
     ln = ln + 1 
    end 
end 
+0

コンパクトですが効率はどうですか?私はLuaスクリプトの行を繰り返すのではなく、むしろ文字列を解析しています。 – SoniEx2

+0

私はあなたのソリューションが好きです。つまり、私のユースケースには最適なソリューションではありません。更新された質問を参照してください。 – SoniEx2