--[[
è§£æç®åçæ ç¾ç»æå¯ææ¬è½¬å为Luaä¸çè¡¨ç»æ
ä½è
ï¼Luwei
è§åï¼
* 被解æçå¯ææ¬æ¾ç¤ºå
容ä¸è½å«æ""è¿ç§æ ·å¼çå符串, åç¬ç'<', '>'æ¯å¯ä»¥æ¯æçï¼ä½æ¯ä¸ºäºé¿å
è§£æé误æå¥½ä¸è¦ä½¿ç¨
* æ ç¾ä¸å¯ä»¥åå¨å±æ§ï¼ä½æ¯å±æ§å¿
é¡»ä»¥ç©ºæ ¼åéï¼å¦ï¼hello,world
* æ ç¾ä¸ç屿§å¼é»è®¤å¯ä»¥æ¯åç¬¦ä¸²ãæ°åãå¸å°å¼(true,false)ï¼è¥æ¯å符串å¯ä»¥å åå¼å·ï¼ä¹å¯ä»¥ä¸å ï¼ä¸ºäºé¿å
è§£æé误æå¥½æ·»å åå¼å·
* 屿§åå屿§å¼ä¹é´ç¨â=âè¿æ¥ï¼ä½æ¯ä¸è½åå¨ç©ºæ ¼
* æ ç¾åå屿§åä¸åºå大å°åï¼å
¨é¨è½¬å为å°å(ä¸»è¦æ¯ä¸ºäºé¿å
大å°åé æç书åé误ï¼åå°å¯ææ¬ä¸²çç¼åé¾åº¦)
* æ ç¾å±æ§å¼ä¸å
许åå¨ç©ºç½å符ï¼ä¾å¦ï¼
* 屿§ä¿çå'content', ä¸å¯éåï¼å³ä¸å¯ä½¿ç¨å±æ§åcontentï¼å¦åè§£æåºæ¥æ²¡æææ¬å
容åå¨
* è¥å¼å¤´åç»å°¾æ²¡ææ ç¾çè¯ï¼å
é¨ä¼èªå¨å¨æå¤å±å
ä¸ä¸å±(å¯ä»¥ä¿®æ¹LABEL_DIV_BEGINä»èå
ä¸å
¶ä»æ ç¾)
* æ¯æèªéåæ ç¾
* æ ç¾èå´ä¸å¯äº¤åï¼ä½æ¯å¯ä»¥åµå¥å
å«
* 空çéèªéåæ ç¾æ²¡æä»»ä½æä¹ï¼ä¸ä¼è¢«è§£æï¼ç´æ¥å¿½ç¥
* èªéåæ ç¾ç'/>'ä¸å±æ§å¼ä¹é´æå¥½åå¨ç©ºæ ¼,å¦åè¿ç§æ
åµåºé
示ä¾ï¼
local labelparser = require("labelparser")
local text1 = "hello worldd hello world
ä½ å¥½ hello,world
"
local parsedtable = labelparser.parse(text1)
-- output:
= {
{
content = "hello worldd ",
labelname = "div",
},
{
content = "hello world",
labelname = "div",
},
{
content = " ä½ å¥½ ",
labelname = "div",
},
{
content = "hello,world",
fontname = "nihao",
fontsize = "#123456",
labelname = "div",
},
}
å½åçæ¬ï¼v1.01
v1.0 - æ¯ææåºæ¬åè½
v1.01 - æ·»å èªéåæ ç¾æ¯æï¼ä¿®å¤è¥å¹²BUG
]]--
local print = print
local table = table
local string = string
local _M = {}
local LABEL_DIV_BEGIN = ""
local LABEL_DIV_END = "
"
local BOOLEAN_TRUE = "true"
local BOOLEAN_FALSE = "false"
function _M.parse(text)
-- ç¨äºåå¨è§£æç»æ
local parsedtable = {}
-- æ£æµå¼å¤´åç»å°¾æ¯å¦ä¸ºæ ç¾ å³ä¸ºæ ç¾
if not string.find(text, "^%b<>.+%b<>$") then
-- 卿å¤å±å
è£
ä¸ä¸ªæ ç¾ï¼ä¾¿äºè§£ææ¶çç»ä¸å¤çï¼ä¸ç¨å¤ç没æå
è£
æ ç¾çæ
åµ
text = table.concat({LABEL_DIV_BEGIN, text, LABEL_DIV_END})
end
-- æ ç¾å¤´æ ï¼ç¨äºå卿 ç¾å¤´(æ¯æ ç¾å¤´ï¼
æ¯æ ç¾å°¾)
-- æ ç¾å¤´åå¨äºæ ¼å¼ä¿¡æ¯ï¼ç¢°å°æ ç¾æ¶å¯ä»¥ç´æ¥ä½¿ç¨å½åæ é¡¶çæ ç¾å¤´æ ¼å¼ä¿¡æ¯ï¼åºç¨å°æ ç¾ä¹é´çå
容ä¸
local labelheadstack = {}
-- è¿ä»£æææ ¼å¼ä¸ºçæ ç¾(å
å«äºæ ç¾å¤´åæ ç¾å°¾å·´)
local index = 0
for beginindex, endindex in function() return string.find(text, "%b<>", index) end do
local label = string.sub(text, beginindex, endindex)
-- æ£æµå符串æ¯å¦ä»¥""å¼å¤´
if string.find(label, "^") then
-- æ ç¾å°¾
_M.disposeLabelTail(labelheadstack, parsedtable, text, label, beginindex, endindex)
elseif string.find(label, "/>$") then -- æ£æµä»¥'/>'ç»å°¾
-- èªéåæ ç¾
_M.disposeLabelSelfClosing(labelheadstack, parsedtable, text, label, beginindex, endindex)
else-- æ£æµå°æ ç¾å¤´
_M.disposeLabelHead(labelheadstack, parsedtable, text, label, beginindex, endindex)
end
index = endindex + 1
end
return parsedtable
end
-- å¤çæ ç¾å¤´
function _M.disposeLabelHead(labelheadstack, parsedtable, text, labelhead, beginindex, endindex)
-- ååºå½åæ é¡¶ä½ç½®çæ ç¾ä¿¡æ¯
local labelinfo = _M.peekstack(labelheadstack)
if labelinfo then
-- è·å¾å½åæ ç¾å¤´åä¸ä¸ä¸ªæ ç¾å¤´ä¹é´å
容(æ ç¾åµå¥é æ)
local content = string.sub(text, labelinfo.endindex+1, beginindex-1)
-- è§£æä¸¤ä¸ªæ ç¾å¤´ä¹é´çå
容
local labelparams = _M.parseLabelWithContent(labelinfo.labelhead, content)
table.insert(parsedtable, labelparams)
end
-- å°å½åæ ç¾å¤´åä½ç½®ä¿¡æ¯ï¼æ¾å
¥æ é¡¶ä½ç½®
_M.pushstack(labelheadstack, {["labelhead"]=labelhead, ["beginindex"]=beginindex, ["endindex"]=endindex})
end
-- å¤çæ ç¾å°¾
function _M.disposeLabelTail(labelheadstack, parsedtable, text, labeltail, beginindex, endindex, selfclosing)
-- æ£æµå°æ ç¾å°¾ï¼å¯ä»¥è§£æå½åæ ç¾èå´å
çä¸²ï¼æ ç¾å¤´å¨æ é¡¶ä½ç½®
-- å°ä¸æ ç¾å°¾å¯¹åºçæ ç¾å¤´åºæ (æ é¡¶)
local labelinfo = _M.popstack(labelheadstack)
-- è§£ææ é¡¶æ ç¾å¤´åå½åæ ç¾å°¾ä¹é´çå
容
if labelinfo then
-- æ£æµæ ç¾æ¯å¦å¹é
if not _M.checkLabelMatch(labelinfo.labelhead, labeltail) then
return print(string.format("labelparser # error: label can not match(%s, %s)",
labelinfo.labelhead, labeltail))
end
-- è·å¾å½åæ ç¾å°¾åå¯¹åºæ ç¾å¤´ä¹é´å
容
local content = string.sub(text, labelinfo.endindex+1, beginindex-1)
local labelparams = _M.parseLabelWithContent(labelinfo.labelhead, content, selfclosing)
table.insert(parsedtable, labelparams)
-- å 为æ¤åå
容é½è§£æè¿äºï¼æä»¥ä¿®æ¹æ é¡¶æ ç¾å¤´ä¿¡æ¯ï¼è®©å
¶ä¿®é¥°èå´æ¹å为æ£ç¡®ç
-- ä¿®æ¹å½åæ é¡¶æ ç¾å¤´ä½ç½®å°å½åæ ç¾å°¾çèå´
local labelinfo_unused = _M.peekstack(labelheadstack)
if labelinfo_unused then
labelinfo_unused.beginindex = beginindex
labelinfo_unused.endindex = endindex
end
end
end
-- å¤çèªéåæ ç¾
function _M.disposeLabelSelfClosing(labelheadstack, parsedtable, text, label, beginindex, endindex)
_M.disposeLabelHead(labelheadstack, parsedtable, text, label, beginindex, endindex)
_M.disposeLabelTail(labelheadstack, parsedtable, text, label, beginindex, endindex, true)
end
-- æ£æµæ ç¾å¤´åæ ç¾å°¾æ¯å¦é
对ï¼å³æ ç¾åæ¯å¦ç¸å
function _M.checkLabelMatch(labelhead, labeltail)
local labelheadname = _M.parseLabelname(labelhead)
local labeltailname = _M.parseLabelname(labeltail)
return labeltailname == labelheadname
end
-- æ´åæ ç¾å¤´å±æ§åå
容
function _M.parseLabelWithContent(labelhead, content, selfclosing)
-- 䏿¯èªéåæ ç¾åï¼åæ£æµå
容ï¼å
容为空åç´æ¥è¿å
if not selfclosing then
if content == nil or content == "" then return
end
else
-- æ¯èªéåæ ç¾
content = nil
end
-- è·å¾æ ç¾åç§°
local labelname = _M.parseLabelname(labelhead)
-- è§£ææ ç¾å±æ§
local labelparams = _M.parseLabelHead(labelhead)
labelparams.labelname = labelname
labelparams.content = content
return labelparams
end
-- 仿 ç¾å¤´æè
æ ç¾å°¾è§£æåºæ ç¾åç§°
function _M.parseLabelname(label)
-- è§£ææ ç¾å
local labelnameindex1, labelnameindex2 = string.find(label, "%w+")
if not labelnameindex1 then
return print ("labelparser # error: label name not found") and nil
end
-- è·å¾æ ç¾åç§°
local labelname = string.sub(label, labelnameindex1, labelnameindex2)
local labelname = string.lower(labelname)
return labelname
end
-- è§£ææ ç¾å¤´å±æ§
function _M.parseLabelHead(labelhead)
local labelparams = {}
-- å¹é
æ ¼å¼ï¼property=value
-- valueè¦æ±é空ç½å符并ä¸ä¸å«æâ>â
for property in string.gmatch(labelhead, "[%w%_]+%=[^%s%>]+") do
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.æ£æµæ¯å¦ä¸ºå¸å°å¼
if not 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
end
end
-- 3.æ£æµæ¯å¦ä¸ºæ°å
if not continue then
local propertyvalue_number = tonumber(propertyvalue)
if propertyvalue_number then
propertyvalue = propertyvalue_number
continue = true
end
end
-- è¥ä»¥ä¸é½ä¸æ¯ï¼åé»è®¤ç´æ¥ä¸ºå符串
labelparams[propertyname] = propertyvalue
end
return labelparams
end
--
-- utils-stack
--
function _M.peekstack(stacktable)
return stacktable[#stacktable]
end
function _M.pushstack(stacktable, elem)
table.insert(stacktable, elem)
end
function _M.popstack(stacktable)
local elem = stacktable[#stacktable]
stacktable[#stacktable] = nil
return elem
end
return _M