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
if (node.value.type == "Macro") then
if (defs[node.value.value] == nil) then
tostring = require 'ml'.tstring
error("Undefined macro '".. node.value.value .. "' used in filter.")
end
node.value = defs[node.value.value]
@@ -445,7 +444,7 @@ function print_ast(node, level)
elseif t == "MacroDef" then
-- don't print for now
else
error ("Unexpected type: "..t)
error ("Unexpected type in print_ast: "..t)
end
end
compiler.parser.print_ast = print_ast
@@ -463,22 +462,9 @@ end
--[[
Sets up compiler state and returns it.
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.
Compiles a single line from a digwatch ruleset and updates the passed-in macros table. Returns the AST of the line.
--]]
function compiler.init()
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)
function compiler.compile_line(line, macro_defs)
local ast, error_msg = compiler.parser.parse_line(line)
if (error_msg) then
@@ -504,7 +490,7 @@ function compiler.compile_line(line, state)
end
for m, _ in pairs(macros) do
if state.macros[m] == nil then
if macros[m] == nil then
error ("Undefined macro '"..m.."' used in '"..line.."'")
end
end
@@ -512,7 +498,7 @@ function compiler.compile_line(line, state)
if (ast.type == "MacroDef") then
-- Parsed line is a macro definition, so update our dictionary of macros and
-- return
state.macros[ast.name] = ast.value
macro_defs[ast.name] = ast.value
return ast
elseif (ast.type == "Rule") then
@@ -522,14 +508,9 @@ function compiler.compile_line(line, state)
expand_in(ast.filter)
repeat
expanded = expand_macros(ast, state.macros, false)
expanded = expand_macros(ast, macro_defs, 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
error("Unexpected top-level AST type: "..ast.type)
end

View File

@@ -32,7 +32,7 @@ local function install_filter(node)
--io.write(node.argument.value.." "..node.operator)
else
error ("Unexpected type: "..t)
error ("Unexpected type in install_filter: "..t)
end
end
@@ -49,12 +49,34 @@ end
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)
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
compiler.compile_line(r, state)
end
function on_done()

View File

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