2017-10-14 1 views
1

Ich versuche, Lua 5.3 Strings zu parsen. Ich habe jedoch ein Problem festgestellt. Zum BeispielParsing Lua Strings, genauer gesagt Zeilenumbrüche

$ 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"' 

Diese beiden Fehler in Zeile 6, und die Logik dahinter ist recht einfach: Zeilenumbrüche essen (\ r oder \ n), wenn sie von der aktuellen anders sind (ich glauben um eine genaue Beschreibung zu sein, wie der Lua Lexer funktioniert, aber ich kann falsch liegen).

Ich habe diesen Code, die es tun soll:

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 

, ob Zeilenumbrüche auf dem vorherigen Zeichen basierend zu essen entscheidet. Nun, von dem, was ich sagen kann, das sollte funktionieren, aber egal was ich tue es scheint nicht zu funktionieren. Andere Versuche haben es 5 Zeilen gemeldet, während dieser Bericht 9 (!) Meldet. Was fehlt mir hier? Ich betreibe dies auf Lua 5.2.4.

Dies ist Teil einer Routine \z zum Parsen:

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' ist immer 'nil' weil' appeared: gmatch ('() [\ r \ n]') 'gibt nur EINE Aufnahme zurück. Wahrscheinlich willst du, dass dein Muster '() ([\ r \ n])' 'ist? –

+0

@EgorSriptunoff Das löst es, aber ich kann einen Kommentar nicht als Antwort akzeptieren. – SoniEx2

+0

Ja, das ist ein berüchtigter Fehler der SO: Kommentare dürfen nicht akzeptiert werden, obwohl sie eine Antwort enthalten könnten :-) –

Antwort

0

Compact-Code für Linien von Lua Skript iteriert:

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 

Effizienter Code für Linien von Lua Skript iteriert:

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

Das ist für kompakt, aber wie wäre es effizient? Ich wiederhole nicht die Zeilen eines Lua-Skripts, sondern analysiere Strings. – SoniEx2

+0

Ich mag deine Lösung. Das heißt, es ist nicht die beste Lösung für meinen Anwendungsfall. Siehe meine aktualisierte Frage. – SoniEx2

Verwandte Themen