gsl-shell.git - gsl-shell

index : gsl-shell.git
gsl-shell
summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat
-rw-r--r--expr-lexer.lua 57
-rw-r--r--expr-print.lua 5
2 files changed, 56 insertions, 6 deletions
diff --git a/expr-lexer.lua b/expr-lexer.lua
index c13b1c38..f464cff1 100644
--- a/expr-lexer.lua
+++ b/expr-lexer.lua
@@ -8,10 +8,25 @@ local lexer_mt = {
local literal_chars = {['('] = 1, [')'] = 1, ['~'] = 1, [','] = 1, ['|'] = 1, [':'] = 1}
-local oper_table = {['+'] = 0, ['-'] = 0, ['*'] = 1, ['/'] = 1, ['^'] = 2, ['='] = 3, ['>'] = 3, ['<'] = 3, ['%'] = -1}
+local oper_table = {['+'] = 2, ['-'] = 2, ['*'] = 3, ['/'] = 3, ['^'] = 4, ['!='] = 1, ['='] = 1, ['>'] = 1, ['>='] = 1, ['<'] = 1, ['<='] = 1, ['AND'] = 0, ['OR'] = 0, ['%'] = -1}
expr_lexer.operators = oper_table
-expr_lexer.max_oper_prio = 3
+expr_lexer.max_oper_prio = 4
+
+local oper_start_sym
+local function compile_oper_pattern()
+ local oper_start_set = {}
+ for k in pairs(oper_table) do
+ oper_start_set[k:sub(1,1)] = true
+ end
+
+ oper_start_sym = '['
+ for k in pairs(oper_start_set) do
+ local str = (k == '-' or k == '%' or k == '^') and ('%' .. k) or k
+ oper_start_sym = oper_start_sym .. str
+ end
+ oper_start_sym = oper_start_sym .. ']'
+end
function expr_lexer.new(src)
local lexer = {n = 1, src= src}
@@ -48,6 +63,35 @@ function expr_lexer.skip(lexer, pattern)
if m then lexer.n = lexer.n + len(m) end
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
+ op = oper_table[c] and c
+ if op then
+ lexer:incr()
+ end
+ end
+ if op then
+ local prio = oper_table[op]
+ return {type= 'operator', symbol= op, priority = prio}
+ end
+end
+
function expr_lexer.next_token(lexer)
lexer:skip('%s*')
if lexer.n > len(lexer.src) then return {type= 'EOF'} end
@@ -60,10 +104,9 @@ function expr_lexer.next_token(lexer)
local str = lexer:consume('%b[]')
return {type= 'ident', value= str:sub(2,-2)}
end
- if oper_table[c] then
- local prio = oper_table[c]
- lexer:incr()
- return {type= 'operator', symbol= c, priority = prio}
+ if lexer:match(oper_start_sym) then
+ local elt = consume_oper(lexer, c)
+ if elt then return elt end
end
if literal_chars[c] then
lexer:incr()
@@ -94,4 +137,6 @@ function expr_lexer.local_error(lexer, msg, n_pos)
error(string.format("%s\n%s\n%s", msg, line, pos))
end
+compile_oper_pattern()
+
return expr_lexer
diff --git a/expr-print.lua b/expr-print.lua
index 4c73f44d..543ee58a 100644
--- a/expr-print.lua
+++ b/expr-print.lua
@@ -66,6 +66,11 @@ local function eval_operator(op, 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 == '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
end
generated by cgit v1.2.3 (git 2.39.1) at 2025年10月04日 02:44:33 +0000

AltStyle によって変換されたページ (->オリジナル) /