Chinaunix首页 | 论坛 | 博客
  • 博客访问: 219688
  • 博文数量: 42
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 420
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-09 10:55
个人简介

每天改变一点点,生活充满了惊喜。

文章分类

全部博文(42)

文章存档

2016年(8)

2015年(29)

2014年(5)

我的朋友

分类: LINUX

2016-02-28 18:56:52

有些事件,处理之后的结果为真值,然后需要获取多个事情的逻辑关系结果,
但是事件的逻辑关系是动态的,可以是从入参传入,通过字符串类型的逻辑表达式来表示
类似 'even01&!(enent02|event03)' ,字符串里的 ! & | 分别表示取反,与,或逻辑关系,
本文要讲述的怎样获取这个表达式的逻辑结果。

我们重点是解析逻辑表达式,所以把问题简化为求  'true&!(false|false)' 表达式的值,
整体思路是,将整个表达式,按照括号的层级递归求值,在每一层,通过 & 和 |来划分表达式为子表达式,
如果是元表达式(类似 true,false,!false,!true这样的形式),直接求出结果,
如果使非元表达式,将该子表达式再次划分。实际上这里利用的动态规划的思想。

我用Lua写了下代码的实现过程:

  1. local str_find = string.find
  2. local str_sub = string.sub
  3. local table_sort = table.sort

  4. local function trim(str, substr)
  5.     local strRet = str
  6.     local s, e = str_find(strRet, '^' .. substr .. '+', 1)
  7.     if s then
  8.         strRet = str_sub(strRet, e + 1)
  9.     end
  10.     s, e = str_find(strRet, substr .. '+$', 1)
  11.     if s then
  12.         strRet = str_sub(strRet, 1, e - 1)
  13.     end
  14.     return strRet
  15. end

  16. local function ipairsBySortedKey(t)
  17.     local t_tmp = {}
  18.     for k in pairs(t) do
  19.         if type(k) == 'number' then
  20.             t_tmp[#t_tmp + 1] = k
  21.         end
  22.     end
  23.     table.sort(t_tmp)
  24.     local i = 0
  25.     return function()
  26.         i = i + 1
  27.         return t_tmp[i], t[t_tmp[i]]
  28.     end
  29. end

  30. local function parseStrExpress(strExpress)
  31.     -- 删除表达式两端没有意义的空格
  32.     local strExpress = trim(strExpress, ' ')
  33.     -- 先检查表达式开始是 ! 开头,且 取反操作是针对整个表达式的
  34.     local wholeNotFlag = false
  35.     local checkRet = strExpress:find('^![ ]*[(].*[)]$', 1)
  36.     if checkRet ~= nil then
  37.         -- 如果是,置取反标识,在求出真个表达式值时取反
  38.         wholeNotFlag = true
  39.         -- 删除开头的 取反 符号
  40.         strExpress = strExpress:sub(2)
  41.     end
  42.     strExpress = trim(strExpress, ' ')
  43.     -- 删除表达式两段开头和结尾 成对的 括号
  44.     while strExpress:sub(1, 1) == '(' do
  45.         if strExpress:sub(-1) == ')' then
  46.             strExpress = strExpress:sub(2, -2)
  47.         else
  48.             error('logic express format invalid.')
  49.         end
  50.     end
  51.     strExpress = trim(strExpress, ' ')
  52.     -- 找到当前表达式 第一层级 的 '|' '&' 操作符
  53.     local braceCout = 0
  54.     local arrIndexList = {}
  55.     for index = 1, #strExpress, 1 do
  56.         if strExpress:sub(index, index) == '(' then
  57.             braceCout = braceCout + 1
  58.         elseif strExpress:sub(index, index) == ')' then
  59.             braceCout = braceCout - 1
  60.         elseif strExpress:sub(index, index) == '|' or strExpress:sub(index, index) == '&' then
  61.             if braceCout == 0 then
  62.                 -- print("index : " .. index .. ' Char : ' .. strExpress:sub(index, index))
  63.                 arrIndexList[index] = strExpress:sub(index, index)
  64.             end
  65.         end
  66.     end
  67.     -- 如果括号不成对,表达式不合法
  68.     if braceCout ~= 0 then error('logic express format invalid.') end
  69.     -- 如果当前表达式中不包含 '|' '&', 也不为空(为空表达式不合法),
  70.     -- 则 表达式为 true, false, !true, !false, !(false), !(true), !(!true) 中的一种,称之为元表达式(可以直接求出值)
  71.     if next(arrIndexList) == nil then
  72.         if strExpress == '' then error('logic express format invalid.') end
  73.         local notFlag = false
  74.         if strExpress:sub(1, 1) == '!' then
  75.             notFlag = true;
  76.             strExpress = strExpress:sub(2)
  77.         end
  78.         strExpress = trim(strExpress, ' ')
  79.         local strExpressValue = nil
  80.         if strExpress == 'false' then
  81.             strExpressValue = false
  82.         elseif strExpress == 'true' then
  83.             strExpressValue = true
  84.         else
  85.             error('logic express format invalid. has value not false or true : ' .. strExpress)
  86.         end
  87.         if notFlag then strExpressValue = not strExpressValue end
  88.         if wholeNotFlag then strExpressValue = not strExpressValue end
  89.         return strExpressValue
  90.     end
  91.     -- 如果当前表达式不是元表达式,变量当前层级的 '|''&',按照它们来划分子表达式
  92.     local boolRet = nil
  93.     local k_prev, v_prev = nil, nil
  94.     for k, v in ipairsBySortedKey(arrIndexList) do
  95.         -- 求出第一个子表达式的 值
  96.         if boolRet == nil then
  97.             k_prev = k
  98.             v_prev = v
  99.             boolRet = parseStrExpress(strExpress:sub(1, k_prev - 1))
  100.         else
  101.             -- 根据前一个表达式的值 和 接下来的 逻辑运算符号,来计算 这两个表达式组成的表达式的值
  102.             if (v_prev == '&' and boolRet == true) or (v_prev == '|' and boolRet == false) then
  103.                 -- print(strExpress .. ' : ' .. strExpress:sub(k_prev + 1, k - 1))
  104.                 boolRet = parseStrExpress(strExpress:sub(k_prev + 1, k - 1))
  105.             end
  106.             k_prev = k
  107.             v_prev = v
  108.         end
  109.     end
  110.     -- 求出最后一个表达式
  111.     if (v_prev == '&' and boolRet == true) or (v_prev == '|' and boolRet == false) then
  112.         boolRet = parseStrExpress(strExpress:sub(k_prev + 1))
  113.     end
  114.     if wholeNotFlag then boolRet = not boolRet end
  115.     return boolRet
  116. end

  117. -- Test
  118. local Test = {
  119.     [1] = 'true',
  120.     [2] = '!true',
  121.     [3] = 'true|false',
  122.     [4] = 'true|true',
  123.     [5] = 'true&false',
  124.     [6] = 'true&true',
  125.     [7] = '!false&true',
  126.     [8] = 'true&!false',
  127.     [9] = 'true&!(false|false)',
  128.     [10] = 'true&(false|!false)',
  129.     [11] = 'true&!(false|!false)&true',
  130.     [12] = '!false&! ( true )',
  131.     [13] = 'false|(true&(!false))',
  132.     [14] = 'false|(true&(!false))|!(false)',
  133.     [15] = 'false|(true&(!false))|!(false)&(false|!true)',
  134.     [16] = 'true&(true|true|true|true)',
  135. }

  136. function Test:run()
  137.     for k, v in ipairsBySortedKey(self) do
  138.         local callRet = parseStrExpress(v)
  139.         print('Test ' .. k .. ' : ' .. v .. ' = ' .. tostring(callRet))
  140.     end
  141. end

代码下面的部分为测试代码,执行并输出:

  1. $lua parseStrExp.lua
  2. Test 1 : true = true
  3. Test 2 : !true = false
  4. Test 3 : true|false = true
  5. Test 4 : true|true = true
  6. Test 5 : true&false = false
  7. Test 6 : true&true = true
  8. Test 7 : !false&true = true
  9. Test 8 : true&!false = true
  10. Test 9 : true&!(false|false) = true
  11. Test 10 : true&(false|!false) = true
  12. Test 11 : true&!(false|!false)&true = false
  13. Test 12 : !false&! ( true ) = false
  14. Test 13 : false|(true&(!false)) = true
  15. Test 14 : false|(true&(!false))|!(false) = true
  16. Test 15 : false|(true&(!false))|!(false)&(false|!true) = false
  17. Test 16 : true&(true|true|true|true) = true


阅读(3791) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~