lua 標籤解析器

2021-06-27 00:57:33 字數 4449 閱讀 6296

乙個類xml標籤解析函式,將標籤解析成lua中的表結構

它可以用來解析簡單xml結構,可以作為richlabel控制項的字串解析元件(其實它現在就是這麼用的;-))

使用lua的模式匹配, 使用了模式串%b%26lt;%26gt;

%b用來匹配對稱的字元。常寫為%26nbsp;%bxy,x和y是任意兩個不同的字元。 x作為匹配的開始,y作為匹配的結束。

比如,%b%26lt;%26gt;%26nbsp;匹配以%26nbsp;%26lt;%26nbsp;開始,以%26nbsp;%26gt;%26nbsp;結束的字串

要解析的字串

hello world

%26lt;

div%26gt;hello world%26lt;/

div%26gt;

你好%26lt;

div

fontname

='nihao'

fontcolor

=#ffccdd

%26gt;hello,world%26lt;/

div%26gt;

%26lt;

div%26gt;%26lt;/

div%26gt;

**基本結構

--

迭代所有格式為%26lt;***%26gt;的標籤(包含了標籤頭和標籤尾)

local beginindex, endindex = string.find(text, "

%b%26lt;%26gt;

", 1

)while beginindex do

--獲得下乙個標籤的位置

beginindex, endindex = string.find(text, "

%b%26lt;%26gt;

", endindex)

end

上面獲得的beginindex和endindex分別是標籤的在字串中開始和結束的index值 但並不區分標籤頭和標籤尾,

還得判斷標籤到底是標籤頭還是標籤尾。

--

獲得當前標籤,字串擷取出來

local label = string.sub

(text, beginindex, endindex)

--判斷當前標籤是不是以'%26lt;/'開頭,若是以'%26lt;/'開頭則代表為標籤尾巴,否則為標籤頭

ifstring.find(label, "

^%26lt;/

") then

else

end

至此已經可以在正確的從字串中提取所有的標籤,並且區分出標籤頭和標籤尾了

處理標籤匹配問題

為了支援標籤巢狀包含,我們得用乙個棧記錄標籤頭,要不然巢狀好幾層標籤不好判斷內容被哪個標籤修飾。

具體做法:

+ 若當前標籤是標籤頭則將棧頂標籤,到新標籤頭之間內容用棧頂標籤修飾,並且將當前標籤入棧

+ 若當前標籤是標籤尾則將棧頂標籤,到新標籤尾之間內容用棧頂標籤修飾,並將棧頂標籤出棧

簡單來說:

棧頂標籤修飾當前的內容(新標籤和棧頂標籤之間的內容) ,然後根據新標籤是頭還是尾決定入棧或出棧

我們沒有考慮特殊情況,若字串最完成不是標籤那最外層處理會存在點問題。

好吧,那我們可以直接在字串外層加上一組標籤就好了,很簡單吧。

現在我們解析出了內容和修飾內容的標籤,離成功不遠了!!

解析標籤頭

這應該是最簡單的一部,但又是最繁瑣的一步。

因為標籤頭內容很少了,格式也確定了,只要提取出標籤名和屬性的key-value對就可以了

不過提取屬性key-value對比較繁瑣,要考慮value的種種可能,當然我考慮的並不全面也沒打算那麼全面,只要功能夠用就可以了

第一步解析出標籤名,簡單的模式匹配

local labelnameindex1, labelnameindex2 = string.find(label, "

%w+")

因為我們要解析的串大多是手寫,為了減小書寫難度,標籤名屬性名最好不區分大小寫

--

獲得標籤名稱

local labelname = string.sub

(label, labelnameindex1, labelnameindex2)

labelname = string.lower(labelname)

第二步獲取屬性,還是模式匹配,匹配形式為 propertyname=propertyvalue(等號兩邊不能存在空格)

propertyname%26nbsp;要求就是字母或者數字的組合

propertyvalue%26nbsp;要求就比較多, 因為顏色使用的是web的標記形式#ff33aa, 而且字串也可能是'括起來表示。

%w: 與任何字母/數字配對

%s: 與空白字元配對

--

value要求非空白字元並且不含有'%26gt;'字元的乙個單詞

string.gmatch(labelhead, "

%w+%=[^%s%%26gt;]+

")

gmatch會返回乙個迭代器,每次執行都返回乙個匹配串,所以我們這麼寫

for property in

string.gmatch(labelhead, "

%w+%=[^%s%%26gt;]+

") do

end

在迴圈中我們可以處理每個屬性對字串無非就是根據=位置分離出屬性名和屬性值,屬性名不需要處理,

把屬性值做一下處理然後放到乙個table中就好了,處理如下:

local equalmarkpos = string.find(property, "="

)--分離屬性名和屬性值

local propertyname = string.sub(property, 1, equalmarkpos-1

)local propertyvalue = string.sub(property, equalmarkpos+1, string.len

(property))

--屬性名轉為小寫

propertyname = string.lower

(propertyname)

--屬性值處理

local continue = false

--1.檢測是否為字串(單引號或者雙引號括起來)

local beginindex, endindex = string.find(propertyvalue, "

['\"].+['

\"]")

if beginindex then

propertyvalue = string.sub(propertyvalue, beginindex+1, endindex-1

) continue = true

end--

2.檢測是否為布林值

ifnot continue then

local propertyvalue_lower = string.lower

(propertyvalue)

if propertyvalue_lower == boolean_true then

propertyvalue = true

continue = true

elseif propertyvalue_lower == boolean_false then

propertyvalue = false

continue = true

endend

--3.檢測是否為數字

ifnot continue then

local propertyvalue_number = tonumber

(propertyvalue)

if propertyvalue_number then

propertyvalue =propertyvalue_number

continue = true

endend

--若以上都不是,則預設直接為字串

labelparams[propertyname] = propertyvalue

順便吐槽一下lua沒有關鍵字continue,造成程式巢狀層次變深

最後完整**在我的github上面叫labelparser,lua5.1解析器可以直接執行,無需任何依賴

Lua解析器Read指令碼內容

你知道c語言是怎麼read一整個檔案嗎?如果你知道了,那麼請忽略本文,如果你不知道,你可以花五分鐘來閱讀本文。在我開始閱讀lua 之前,我好像從來沒有用c語言寫過一次性read整個檔案的字元的 以往都是一句句的讀取。以至於我對這樣的 失去了敏感性。在開始閱讀lua 的時候,花了兩個小時來尋找lua解...

使用解析器

使用解析器 使用解析器是非常簡單,可以使用它自己的詞法分析器,但是,用fsyacc.exe 產生的解析器總是要求詞法分析器。在這一小節,我們將討論如何使用自己的詞法分析器,以及與解析器聯合。警告記住f 編譯器不能直接使用.fsl 和 fsy 檔案,需要用fslex.exe 和 fsyacc.exe ...

指令碼解析器

指令碼解析器 命令指令碼解析器,自建立一種指令碼語法,解釋執行它。目前指令碼形式類似於命令,沒有變數型別的概念,關鍵字為 if else while break continue 解釋與c語言一樣。上傳 型別 無型別,全為字串看待。作用域 當前大括號中,以及所有子大括號中,退出當前大括號則清除變數。...