Skip to content

Commit

Permalink
Fix implementation of logical operators in gdt expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
franko committed May 16, 2013
1 parent b8955d3 commit 925ef99
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 26 deletions.
37 changes: 20 additions & 17 deletions expr-lexer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ local lexer_mt = {

local literal_chars = {['('] = 1, [')'] = 1, ['~'] = 1, [','] = 1, ['|'] = 1, [':'] = 1}

local oper_table = {['+'] = 2, ['-'] = 2, ['*'] = 3, ['/'] = 3, ['^'] = 4, ['!='] = 1, ['='] = 1, ['>'] = 1, ['>='] = 1, ['<'] = 1, ['<='] = 1, ['AND'] = 0, ['OR'] = 0, ['%'] = -1}
local oper_table = {['+'] = 2, ['-'] = 2, ['*'] = 3, ['/'] = 3, ['^'] = 4, ['!='] = 1, ['='] = 1, ['>'] = 1, ['>='] = 1, ['<'] = 1, ['<='] = 1, ['and'] = 0, ['or'] = 0, ['%'] = -1}
local word_operators = {'and', 'or'}
local multi_char_operators = {'!=', '>=', '<='}

expr_lexer.operators = oper_table
expr_lexer.max_oper_prio = 4
Expand Down Expand Up @@ -65,22 +67,23 @@ end

local function consume_oper(lexer, c)
local op
if lexer:match('AND[^%l%u_]') then
lexer:consume('AND')
op = 'AND'
elseif lexer:match('OR[^%l%u_]') then
lexer:consume('OR')
op = 'OR'
elseif lexer:match('>=') then
lexer:consume('>=')
op = '>='
elseif lexer:match('<=') then
lexer:consume('<=')
op = '<='
elseif lexer:match('!=') then
lexer:consume('!=')
op = '!='
else
for i, ops in ipairs(word_operators) do
if lexer:match(ops .. '[^%l%u_]') then
lexer:consume(ops)
op = ops
break
end
end
if not op then
for i, ops in ipairs(multi_char_operators) do
if lexer:match(ops) then
lexer:consume(ops)
op = ops
break
end
end
end
if not op then
op = oper_table[c] and c
if op then
lexer:incr()
Expand Down
20 changes: 11 additions & 9 deletions expr-print.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,20 @@ local function exlist_print(e)
return concat(t, ', ')
end

local high_prio = expr_lexer.max_oper_prio + 1

ex_print = function(e)
if type(e) == 'number' then
return e, 3
return e, high_prio
elseif type(e) == 'string' then
local s = e
if not is_ident_simple(s) then s = format('[%s]', s) end
return s, 3
return s, high_prio
elseif e.literal then
return format('%q', e.literal)
return format('%q', e.literal), high_prio
elseif e.func then
local arg_str = ex_print(e.arg)
return format('%s(%s)', e.func, arg_str), 3
return format('%s(%s)', e.func, arg_str), high_prio
else
local prio = oper_table[e.operator]
local s = op_print(e, prio)
Expand All @@ -64,14 +66,14 @@ local function eval_operator(op, a, b)
elseif op == '/' then return a / b
elseif op == '^' then return a ^ b
elseif op == '=' then return (a == b and 1 or 0)
elseif op == '>' then return (a > b and 1 or 0)
elseif op == '<' then return (a < b and 1 or 0)
elseif op == '>' then return (a > b and 1 or 0)
elseif op == '<' then return (a < b and 1 or 0)
elseif op == '!=' then return (a ~= b and 1 or 0)
elseif op == '>=' then return (a >= b and 1 or 0)
elseif op == '<=' then return (a <= b and 1 or 0)
elseif op == 'AND' then return ((a ~= 0 and b ~= 0) and 1 or 0)
elseif op == 'OR' then return ((a ~= 0 or b ~= 0) and 1 or 0)
else error('unkown operation: ' .. op) end
elseif op == 'and' then return ((a ~= 0 and b ~= 0) and 1 or 0)
elseif op == 'or' then return ((a ~= 0 or b ~= 0) and 1 or 0)
else error('unknown operation: ' .. op) end
end

local function eval(expr, scope, ...)
Expand Down

0 comments on commit 925ef99

Please sign in to comment.