Move compiler state and AST grafting to rule_loader.lua

This is needed so that rule_loader (which should be renamed in a later pass..) can tag
filters with their index.
This commit is contained in:
Henri DF
2016-02-22 17:03:34 -08:00
parent 5ba821aaef
commit 426097241d
3 changed files with 36 additions and 32 deletions

View File

@@ -341,7 +341,6 @@ function expand_macros(node, defs, changed)
elseif node.type == "Filter" then elseif node.type == "Filter" then
if (node.value.type == "Macro") then if (node.value.type == "Macro") then
if (defs[node.value.value] == nil) then if (defs[node.value.value] == nil) then
tostring = require 'ml'.tstring
error("Undefined macro '".. node.value.value .. "' used in filter.") error("Undefined macro '".. node.value.value .. "' used in filter.")
end end
node.value = defs[node.value.value] node.value = defs[node.value.value]
@@ -445,7 +444,7 @@ function print_ast(node, level)
elseif t == "MacroDef" then elseif t == "MacroDef" then
-- don't print for now -- don't print for now
else else
error ("Unexpected type: "..t) error ("Unexpected type in print_ast: "..t)
end end
end end
compiler.parser.print_ast = print_ast compiler.parser.print_ast = print_ast
@@ -463,22 +462,9 @@ end
--[[ --[[
Sets up compiler state and returns it. Compiles a single line from a digwatch ruleset and updates the passed-in macros table. Returns the AST of the line.
This is an opaque blob that is passed into subsequent compiler calls and
should not be modified by the client.
It holds state such as macro definitions that must be kept across calls
to the line-oriented compiler.
--]] --]]
function compiler.init() function compiler.compile_line(line, macro_defs)
return {macros={}, filter_ast=nil}
end
--[[
Compiles a single line from a digwatch ruleset and updates the passed-in state object. Returns the AST of the line.
--]]
function compiler.compile_line(line, state)
local ast, error_msg = compiler.parser.parse_line(line) local ast, error_msg = compiler.parser.parse_line(line)
if (error_msg) then if (error_msg) then
@@ -504,7 +490,7 @@ function compiler.compile_line(line, state)
end end
for m, _ in pairs(macros) do for m, _ in pairs(macros) do
if state.macros[m] == nil then if macros[m] == nil then
error ("Undefined macro '"..m.."' used in '"..line.."'") error ("Undefined macro '"..m.."' used in '"..line.."'")
end end
end end
@@ -512,7 +498,7 @@ function compiler.compile_line(line, state)
if (ast.type == "MacroDef") then if (ast.type == "MacroDef") then
-- Parsed line is a macro definition, so update our dictionary of macros and -- Parsed line is a macro definition, so update our dictionary of macros and
-- return -- return
state.macros[ast.name] = ast.value macro_defs[ast.name] = ast.value
return ast return ast
elseif (ast.type == "Rule") then elseif (ast.type == "Rule") then
@@ -522,14 +508,9 @@ function compiler.compile_line(line, state)
expand_in(ast.filter) expand_in(ast.filter)
repeat repeat
expanded = expand_macros(ast, state.macros, false) expanded = expand_macros(ast, macro_defs, false)
until expanded == false until expanded == false
if (state.filter_ast == nil) then
state.filter_ast = ast.filter.value
else
state.filter_ast = { type = "BinaryBoolOp", operator = "or", left = state.filter_ast, right = ast.filter.value }
end
else else
error("Unexpected top-level AST type: "..ast.type) error("Unexpected top-level AST type: "..ast.type)
end end

View File

@@ -32,7 +32,7 @@ local function install_filter(node)
--io.write(node.argument.value.." "..node.operator) --io.write(node.argument.value.." "..node.operator)
else else
error ("Unexpected type: "..t) error ("Unexpected type in install_filter: "..t)
end end
end end
@@ -49,12 +49,34 @@ end
local state local state
--[[
Sets up compiler state and returns it.
It holds state such as macro definitions that must be kept across calls
to the line-oriented compiler.
--]]
local function init()
return {macros={}, filter_ast=nil}
end
function load_rule(r) function load_rule(r)
if (state == nil) then if (state == nil) then
state = compiler.init() state = init()
end
local line_ast = compiler.compile_line(r, state.macros)
if (line_ast.type == "MacroDef") then
return
elseif (not (line_ast.type == "Rule")) then
error ("Unexpected type in load_rule: "..line_ast.type)
end
if (state.filter_ast == nil) then
state.filter_ast = line_ast.filter.value
else
state.filter_ast = { type = "BinaryBoolOp", operator = "or", left = state.filter_ast, right = line_ast.filter.value }
end end
compiler.compile_line(r, state)
end end
function on_done() function on_done()

View File

@@ -5,10 +5,11 @@ if #arg ~= 1 then
os.exit(1) os.exit(1)
end end
local state = compiler.init() local macros = {}
local ast
local function doit(line) local function doit(line)
local ast = compiler.compile_line(line, state) ast = compiler.compile_line(line, macros)
if not ast then if not ast then
print("error", error_msg) print("error", error_msg)
@@ -20,8 +21,8 @@ for str in string.gmatch(arg[1], "([^;]+)") do
doit(str) doit(str)
end end
if not (state.ast == nil) then -- can be nil if only macros if not (ast) then
compiler.parser.print_ast(state.ast) compiler.parser.print_ast(ast)
end end
os.exit(0) os.exit(0)