乙個類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 instring.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語言一樣。上傳 型別 無型別,全為字串看待。作用域 當前大括號中,以及所有子大括號中,退出當前大括號則清除變數。...