婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > 深入探究Lua中的解析表達(dá)式

深入探究Lua中的解析表達(dá)式

熱門標(biāo)簽:艾比利外呼系統(tǒng) 杞縣地圖標(biāo)注app 免費(fèi)門店地圖標(biāo)注注冊入駐 電話機(jī)器人每天搜索多少次 陜西便宜電銷機(jī)器人軟件 海口智能語音電銷機(jī)器人好用嗎 衡水外呼線路解決 昆明電話外呼系統(tǒng)好么 外呼系統(tǒng)一天耗費(fèi)多少流量

 使用一個模式

這個例子顯示了一個建立和使用模式的程序,它非常簡單但很完整:

復(fù)制代碼 代碼如下:
local lpeg = require "lpeg"

-- matches a word followed by end-of-string
p = lpeg.R"az"^1 * -1

print(p:match("hello"))        --> 6
print(lpeg.match(p, "hello"))  --> 6
print(p:match("1 hello"))      --> nil

模式是簡單的一個或多個小寫字符并在尾端以(-1)結(jié)束的序列。該程序調(diào)用match來當(dāng)作一個方法和函數(shù)。在以上成功案例,匹配函數(shù)返回成功 匹配的第一個字符的索引,為其字符串長度加1。

復(fù)制代碼 代碼如下:
Name-value lists

這個例子解析一個名稱 - 值配對的列表,并返回那些配對的表:

復(fù)制代碼 代碼如下:
lpeg.locale(lpeg)   -- adds locale entries into 'lpeg' table

local space = lpeg.space^0
local name = lpeg.C(lpeg.alpha^1) * space
local sep = lpeg.S(",;") * space
local pair = lpeg.Cg(name * "=" * space * name) * sep^-1
local list = lpeg.Cf(lpeg.Ct("") * pair^0, rawset)
t = list:match("a=b, c = hi; next = pi")  --> { a = "b", c = "hi", next = "pi" }

每一配對都有  formatname =namefollowed 的一個可選的分離器(用逗號或分號)。  配對模式(Thepairpattern)在一個組模式里形成閉包,那么那些名稱就可以成為單個捕獲的值。 列表模式 (Thelistpattern)然后折疊這些捕獲。 它以空列表開始,通過創(chuàng)建列表捕獲匹配一個空字符串,然后為每個捕獲(一名稱對)appliesrawsetover累加器(表)和捕捉值(對名稱)。rawsetreturns((未初始化的集合)返回表本身,所以累加器總是表中執(zhí)行。


以下代碼創(chuàng)建了一個模式,該模式使用給定的分隔模式sep作為分隔器來來拆分字符串:

復(fù)制代碼 代碼如下:
function split (s, sep)
  sep = lpeg.P(sep)
  local elem = lpeg.C((1 - sep)^0)
  local p = elem * (sep * elem)^0
  return lpeg.match(p, s)
end

首先,該函數(shù)確保sep一個合適的模式。只要沒有匹配分隔器,該模式的elem 是重復(fù)的零個或多個任意字符。它還捕捉其匹配值。模式p匹配由sep拆分的一組元素.

如果拆分產(chǎn)生的結(jié)果值太多,可能會溢出由一個Lua函數(shù)返回的最大數(shù)目的值。在這種情況下,我們可以將這些值放到一個表中:

復(fù)制代碼 代碼如下:
function split (s, sep)
  sep = lpeg.P(sep)
  local elem = lpeg.C((1 - sep)^0)
  local p = lpeg.Ct(elem * (sep * elem)^0)   -- make a table capture
  return lpeg.match(p, s)
end

模式搜索

基本的匹配僅僅工作在錨定模式下。如果我們打算查找匹配字符串中任何地方的模式,那么我們必須寫一個匹配任何地方的模式。

因?yàn)槟J绞强梢跃帉懙模晕覀兛梢跃帉懸粋€函數(shù),它給定一個任意的模式p,返回一個搜索p的新模式,以匹配字符串的任何位置。執(zhí)行這種搜索有幾種方法。一種方法如下:

復(fù)制代碼 代碼如下:
function anywhere (p)
  return lpeg.P{ p + 1 * lpeg.V(1) }
end

這個語法的直接解讀:匹配p或者跳過一個字符,然后試圖再次匹配。

如果我們想知道這個模式在字符串的所有匹配位置(而不僅僅知道它在字符串的某個位置),那么我們可以給這個模式添加位置捕捉:

復(fù)制代碼 代碼如下:
local I = lpeg.Cp()
function anywhere (p)
  return lpeg.P{ I * p * I + 1 * lpeg.V(1) }
end

print(anywhere("world"):match("hello world!"))   -> 7   12

這種搜索的另一個方法如下:

復(fù)制代碼 代碼如下:
local I = lpeg.Cp()
function anywhere (p)
  return (1 - lpeg.P(p))^0 * I * p * I
end

再次說明,這個模式的直接解讀:當(dāng)不匹配p時,它跳過盡可能多的字符,然后對p進(jìn)行匹配(外加正確的位置捕捉)。

如果我們打算查找僅僅匹配單詞邊界的模式的話,那么我們可以使用以下轉(zhuǎn)換:

復(fù)制代碼 代碼如下:
local t = lpeg.locale()

function atwordboundary (p)
  return lpeg.P{
    [1] = p + t.alpha^0 * (1 - t.alpha)^1 * lpeg.V(1)
  }
end

平衡的括號

以下模式只匹配帶有平衡括號的字符串::

復(fù)制代碼 代碼如下:
b = lpeg.P{ "(" * ((1 - lpeg.S"()") + lpeg.V(1))^0 * ")" }

閱讀第一個(也是唯一的)所給語法規(guī)則,所謂平衡字符串,就是一個開括號,后跟零個或多個非括號字符或者平衡字符串(LPFG.V(1)),最后跟著與開括號能夠閉合的結(jié)束括號。
全局替換

下面的例子和tostring.gsub所做工作類似。它接收一個母串和一個模式以及一個替換值,然后替代所傳入的母串中所有與指定模式匹配的子串為指定的替換值::

復(fù)制代碼 代碼如下:
function gsub (s, patt, repl)
  patt = lpeg.P(patt)
  patt = lpeg.Cs((patt / repl + 1)^0)
  return lpeg.match(patt, s)
end

作為instring.gsub,替換值可以是一個字串、函數(shù),或者一個表.

逗號分隔值(CSV)

下面的例子將字符串轉(zhuǎn)換成逗號分隔的值,并返回所有的字段:

復(fù)制代碼 代碼如下:
local field = '"' * lpeg.Cs(((lpeg.P(1) - '"') + lpeg.P'""' / '"')^0) * '"' +
                    lpeg.C((1 - lpeg.S',\n"')^0)

local record = field * (',' * field)^0 * (lpeg.P'\n' + -1)

function csv (s)
  return lpeg.match(record, s)
end

一個字段或是一個引用的字段(一族可能包含任何字符除單引號,或雙引號)或是一個未被引用的字段(不包含逗號,換行符或引號)。一個記錄就是一個用逗號分隔的字段列表(以換行符或以字符串結(jié)尾)。

就像這樣,前面的匹配返回的每個字段都是獨(dú)立返回的。若我們添加一個列表截取定義的記錄。返回的將不再是一個獨(dú)立的包含所有字段的列表。

復(fù)制代碼 代碼如下:
local record = lpeg.Ct(field * (',' * field)^0) * (lpeg.P'\n' + -1)


UTF-8 和 Latin 1

使用LPeg來將一字符串從UTF-8編碼轉(zhuǎn)換成Latin 1(ISO 88590-1),這并不困難:

復(fù)制代碼 代碼如下:
-- convert a two-byte UTF-8 sequence to a Latin 1 character
local function f2 (s)
  local c1, c2 = string.byte(s, 1, 2)
  return string.char(c1 * 64 + c2 - 12416)
end

local utf8 = lpeg.R("\0\127")
           + lpeg.R("\194\195") * lpeg.R("\128\191") / f2

local decode_pattern = lpeg.Cs(utf8^0) * -1

這些代碼中,UTF-8定義已經(jīng)為Latin 1的編碼范圍(從0到255)。所有不在該范圍內(nèi)的編碼(以及任何無效的編碼)將不匹配該模式。

正如decode_pattern所要求的,這個模式匹配所有的輸入(因?yàn)?1在它的結(jié)尾處),任何無效字符串會匹配失敗,而無任何關(guān)于此問題的有用信息。我們可以通過重定義如下decode_pattern來改善這種情況:

復(fù)制代碼 代碼如下:
local function er (_, i) error("invalid encoding at position " .. i) end

local decode_pattern = lpeg.Cs(utf8^0) * (-1 + lpeg.P(er))

現(xiàn)在,如果模式utf8^0  在字符串尾部之前停止,會調(diào)用一個適用的出錯函數(shù)。

UTF-8 和 Unicode

我們可以擴(kuò)展以前的模式來處理所有的Unicdoe代碼片段,當(dāng)然, 我們不能把它們翻譯阿拉伯?dāng)?shù)字1或其他任何一個字節(jié)編碼。相反,我們的翻譯序列結(jié)果中的數(shù)字表示的代碼片段。這里完整的代碼:
 

復(fù)制代碼 代碼如下:
-- decode a two-byte UTF-8 sequence
local function f2 (s)
  local c1, c2 = string.byte(s, 1, 2)
  return c1 * 64 + c2 - 12416
end
 
-- decode a three-byte UTF-8 sequence
local function f3 (s)
  local c1, c2, c3 = string.byte(s, 1, 3)
  return (c1 * 64 + c2) * 64 + c3 - 925824
end
 
-- decode a four-byte UTF-8 sequence
local function f4 (s)
  local c1, c2, c3, c4 = string.byte(s, 1, 4)
  return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168
end
 
local cont = lpeg.R("\128\191")   -- continuation byte
 
local utf8 = lpeg.R("\0\127") / string.byte
           + lpeg.R("\194\223") * cont / f2

 
-- decode a two-byte UTF-8 sequence
local function f2 (s)
  local c1, c2 = string.byte(s, 1, 2)
  return c1 * 64 + c2 - 12416
end
 
-- decode a three-byte UTF-8 sequence
local function f3 (s)
  local c1, c2, c3 = string.byte(s, 1, 3)
  return (c1 * 64 + c2) * 64 + c3 - 925824
end
 
-- decode a four-byte UTF-8 sequence
local function f4 (s)
  local c1, c2, c3, c4 = string.byte(s, 1, 4)
  return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168
end
 
local cont = lpeg.R("\128\191")   -- continuation byte
 
local utf8 = lpeg.R("\0\127") / string.byte
           + lpeg.R("\194\223") * cont / f2

Lua的長字符串

Lua中的長字符串由模式 [= *[ 開始,到第一次出現(xiàn)的帶有完全相同數(shù)量的等號的 ] =*] 結(jié)束。如果開括號后跟一個換行符,換行符將被丟棄(即,不會把它當(dāng)作字符串的一部分)。

在Lua中想要匹配一個長字符串,模式必須捕捉第一次重復(fù)的等號,然后,只需找到有關(guān)閉字符串的候選項(xiàng),檢查其是否具有相同數(shù)量的等號。

復(fù)制代碼 代碼如下:
equals = lpeg.P"="^0
open = "[" * lpeg.Cg(equals, "init") * "[" * lpeg.P"\n"^-1
close = "]" * lpeg.C(equals) * "]"
closeeq = lpeg.Cmt(close * lpeg.Cb("init"), function (s, i, a, b) return a == b end)
string = open * lpeg.C((lpeg.P(1) - closeeq)^0) * close / 1

open 模式匹配 [=*[,在一個名為 init 的組中捕獲重復(fù)的等號;它也會丟棄一個可選的換行符(如果它存在的話)。close 模式匹配 ]= *],也是捕捉重復(fù)的等號。closeeq模式首先匹配 close,然后它采用逆向捕捉來恢復(fù)先前由 open 捕捉并命名為 init 的內(nèi)容,最后,用 match-time 捕捉來檢查兩個捕獲是否相同。字符串模式從 open 開始之后,它會一直包含到匹配了 closeeq 為止,然后匹配最終的 close。最后的數(shù)字捕獲簡單地丟棄由 close 產(chǎn)生的捕獲。

算術(shù)表達(dá)式

本例對簡單的算術(shù)表達(dá)式進(jìn)行完整的解析和求值。而且我們用兩種風(fēng)格來書寫。

第一種途徑首先建立一個語法樹,然后遍歷這棵樹來計算表達(dá)式的值:

復(fù)制代碼 代碼如下:
-- 詞典元素
[code]local Space = lpeg.S(" \n\t")^0
local Number = lpeg.C(lpeg.P"-"^-1 * lpeg.R("09")^1) * Space
local TermOp = lpeg.C(lpeg.S("+-")) * Space
local FactorOp = lpeg.C(lpeg.S("*/")) * Space
local Open = "(" * Space
local Close = ")" * Space

-- 語法
local Exp, Term, Factor = lpeg.V"Exp", lpeg.V"Term", lpeg.V"Factor"
G = lpeg.P{ Exp,
  Exp = lpeg.Ct(Term * (TermOp * Term)^0);
  Term = lpeg.Ct(Factor * (FactorOp * Factor)^0);
  Factor = Number + Open * Exp * Close;
}

G = Space * G * -1

-- 求值器
function eval (x)
  if type(x) == "string" then
    return tonumber(x)
  else
    local op1 = eval(x[1])
    for i = 2, #x, 2 do
      local op = x[i]
      local op2 = eval(x[i + 1])
      if (op == "+") then op1 = op1 + op2
      elseif (op == "-") then op1 = op1 - op2
      elseif (op == "*") then op1 = op1 * op2
      elseif (op == "/") then op1 = op1 / op2
      end
    end
    return op1
  end
end

-- 解析/求值
function evalExp (s)
  local t = lpeg.match(G, s)
  if not t then error("syntax error", 2) end
  return eval(t)
end

-- 使用例子
print(evalExp"3 + 5*9 / (1+1) - 12")   --> 13.5

第二種風(fēng)格不用建立語法樹,直接求值。下面代碼就按此種途徑(假定和上面有相同的詞典元素):

復(fù)制代碼 代碼如下:
-- 輔助函數(shù)
function eval (v1, op, v2)
  if (op == "+") then return v1 + v2
  elseif (op == "-") then return v1 - v2
  elseif (op == "*") then return v1 * v2
  elseif (op == "/") then return v1 / v2
  end
end

-- 語法
local V = lpeg.V
G = lpeg.P{ "Exp",
  Exp = lpeg.Cf(V"Term" * lpeg.Cg(TermOp * V"Term")^0, eval);
  Term = lpeg.Cf(V"Factor" * lpeg.Cg(FactorOp * V"Factor")^0, eval);
  Factor = Number / tonumber + Open * V"Exp" * Close;
}

-- 使用例子
print(lpeg.match(G, "3 + 5*9 / (1+1) - 12"))   --> 13.5

注意 fold (收集器) 捕獲的用法。 要計算一個表達(dá)式的值,收集器從第一個術(shù)語的值開始,為每個副本應(yīng)用進(jìn)化收集器,操作符,和新術(shù)語。

您可能感興趣的文章:
  • 詳解Lua中的數(shù)據(jù)類型
  • Lua判斷數(shù)據(jù)類型的方法
  • 實(shí)現(xiàn)Lua中數(shù)據(jù)類型的源碼分享
  • Lua數(shù)據(jù)類型介紹
  • Lua中的基本數(shù)據(jù)類型詳細(xì)介紹
  • Lua學(xué)習(xí)筆記之?dāng)?shù)據(jù)類型
  • Lua教程(三):表達(dá)式和語句
  • Lua學(xué)習(xí)筆記之表達(dá)式
  • Lua表達(dá)式和控制結(jié)構(gòu)學(xué)習(xí)筆記
  • Lua中的操作符和表達(dá)式總結(jié)
  • Lua基礎(chǔ)教程之賦值語句、表達(dá)式、流程控制、函數(shù)學(xué)習(xí)筆記
  • Lua學(xué)習(xí)筆記之運(yùn)算符和表達(dá)式
  • Lua中基本的數(shù)據(jù)類型、表達(dá)式與流程控制語句講解

標(biāo)簽:臨滄 南京 營口 西寧 宿遷 海口 泰安 昌都

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《深入探究Lua中的解析表達(dá)式》,本文關(guān)鍵詞  深入,探究,Lua,中的,解析,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《深入探究Lua中的解析表達(dá)式》相關(guān)的同類信息!
  • 本頁收集關(guān)于深入探究Lua中的解析表達(dá)式的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    亚洲视频一区在线观看| 国产人伦精品一区二区| 亚洲成年人网站在线观看| 91在线你懂得| 欧美日本一区二区在线观看| 这里只有精品免费| 日本一区二区三区在线观看| 国产亚洲短视频| 欧美国产97人人爽人人喊| 亚洲成国产人片在线观看| 毛片av一区二区| eeuss国产一区二区三区| 日本欧美韩国一区三区| 国产成人精品亚洲日本在线桃色| 成人一二三区视频| 欧美日韩日日摸| 日本在线不卡视频| 欧美乱妇一区二区三区不卡视频| 欧美电影免费观看完整版| 久久午夜国产精品| 3atv一区二区三区| 欧美三级中文字幕在线观看| 秋霞电影一区二区| 精品美女一区二区| 国产v综合v亚洲欧| 一级特黄大欧美久久久| 日韩一区二区免费视频| 国产夫妻精品视频| 亚洲大片在线观看| 国产欧美视频一区二区| 在线精品视频一区二区| 亚洲品质自拍视频| 久久久国产精品午夜一区ai换脸| 极品少妇xxxx精品少妇偷拍| 精品久久国产老人久久综合| 国产精品主播直播| 欧美激情一区二区三区不卡| 欧美日韩视频一区二区| 久久综合色婷婷| 色狠狠桃花综合| 亚洲二区在线视频| 欧美女孩性生活视频| 日本乱人伦aⅴ精品| 亚洲一区二区成人在线观看| 国产麻豆午夜三级精品| 国产精品免费人成网站| 91丨九色丨黑人外教| 午夜视频一区二区三区| 91福利视频在线| 国产又黄又大久久| 欧美午夜精品一区二区三区| 精品一区二区在线免费观看| 欧美一区二区三区视频免费| 6080日韩午夜伦伦午夜伦| 久久久久久久久久久电影| 国产欧美日韩精品在线| 日韩经典一区二区| 日韩欧美你懂的| 久久精品人人爽人人爽| 欧美老年两性高潮| 色吧成人激情小说| 成人激情小说乱人伦| 国产大陆a不卡| 日韩和欧美的一区| 国产精品成人免费精品自在线观看 | 91福利社在线观看| 日韩欧美一区二区三区在线| 成人国产电影网| 亚洲欧美在线视频| 在线视频欧美精品| 亚洲一区av在线| 成人永久aaa| 一本色道综合亚洲| 99视频精品免费视频| 国产盗摄女厕一区二区三区| 毛片不卡一区二区| 国模娜娜一区二区三区| 久久国产尿小便嘘嘘| 国产一区二区三区免费看| 激情偷乱视频一区二区三区| 久久爱www久久做| 国精产品一区一区三区mba视频| 麻豆精品视频在线观看| 日韩电影在线看| 日韩成人dvd| 黄色日韩三级电影| 国产精品资源在线| 99久久久精品免费观看国产蜜| 成人avav影音| 99re成人精品视频| 欧美精品久久99久久在免费线 | 欧美高清在线精品一区| 91精品免费观看| 国产99久久精品| 色综合天天综合网天天看片| 国产suv精品一区二区883| 99精品热视频| 欧美高清视频一二三区 | 91福利国产成人精品照片| 国产福利一区在线| 不卡一区二区中文字幕| 在线观看av不卡| 夜夜亚洲天天久久| 亚洲高清视频的网址| 午夜激情一区二区| 亚洲成人免费在线观看| 视频一区二区不卡| 国产91精品露脸国语对白| 欧美亚洲精品一区| 久久影院午夜片一区| 一区二区三区视频在线看| 另类的小说在线视频另类成人小视频在线| 国内精品伊人久久久久av影院 | 日韩电影免费在线观看网站| 激情五月激情综合网| 丁香六月久久综合狠狠色| 欧美日韩一区二区三区四区 | 欧美日韩电影在线播放| 欧美成人午夜电影| 夜夜嗨av一区二区三区中文字幕 | 国产成人免费在线| 91国偷自产一区二区开放时间| 久久夜色精品国产噜噜av| 亚洲午夜久久久| 国产一区二区日韩精品| 91成人网在线| 国产精品午夜免费| 日本中文字幕一区二区有限公司| 黑人巨大精品欧美一区| 欧美日韩高清在线播放| 亚洲日本护士毛茸茸| 国产成人精品1024| 久久精品网站免费观看| 国产一区二区三区免费观看| 日韩视频一区二区在线观看| 亚洲国产成人午夜在线一区| 日本一区二区三区电影| 亚洲精品视频在线观看免费| av电影在线观看一区| 久久久久久久免费视频了| 国产精品一二三在| 亚洲精品在线三区| 亚洲日穴在线视频| 亚洲天堂福利av| 欧美一级专区免费大片| 欧美亚洲动漫精品| 亚洲老司机在线| 成人一区二区三区在线观看| 综合久久国产九一剧情麻豆| av不卡免费在线观看| 在线观看日韩毛片| 99久久精品免费看国产| 亚洲图片欧美综合| 一区二区激情小说| 国产91精品在线观看| 精品久久久久香蕉网| 日韩国产欧美在线视频| aaa欧美日韩| 91麻豆国产香蕉久久精品| 亚洲成精国产精品女| 欧美一区二视频| 欧美一三区三区四区免费在线看| 欧美日韩久久久久久| 一区二区三区欧美| 亚洲男女毛片无遮挡| 麻豆专区一区二区三区四区五区| 日韩精品成人一区二区三区 | 五月激情丁香一区二区三区| 色综合久久久久综合| av影院午夜一区| 91精选在线观看| 亚洲精品视频一区| 亚洲一区二区三区自拍| 亚洲天堂免费看| 国产高清不卡二三区| 欧美三级午夜理伦三级中视频| 国产精品不卡在线观看| 国产精品激情偷乱一区二区∴| 免费成人你懂的| 亚洲国产精品精华液网站| 狠狠色狠狠色合久久伊人| 91精品蜜臀在线一区尤物| 欧美韩国日本一区| 色综合久久九月婷婷色综合| 亚洲国产精品激情在线观看| 国产在线观看一区二区| 91麻豆精品国产91久久久使用方法 | 国产精品一区三区| 国产成人免费xxxxxxxx| 蜜臀av性久久久久蜜臀aⅴ流畅| 亚洲国产视频一区二区| 日韩一区二区不卡| 国产成a人亚洲精| 视频一区免费在线观看| 久久久电影一区二区三区| av电影天堂一区二区在线| 国产在线国偷精品免费看| 精品国产露脸精彩对白| 国产电影一区二区三区| 亚洲天堂精品视频|