- more work-in-progress implementing the config parser into logstash.

This commit is contained in:
Jordan Sissel 2013-06-07 23:50:15 -07:00
parent a3e072c253
commit 0a13127fd6
6 changed files with 2878 additions and 593 deletions

View file

@ -56,7 +56,7 @@ endif
# Compile config grammar (ragel -> ruby)
.PHONY: compile-grammar
compile-grammar: lib/logstash/config/grammar.rb
lib/logstash/config/grammar.rb: lib/logstash/config/grammar.rl
lib/logstash/config/grammar.rb: lib/logstash/config/grammar.treetop
$(QUIET)$(MAKE) -C lib/logstash/config grammar.rb
.PHONY: clean

View file

@ -1,3 +1,4 @@
grammar.rb: grammar.rl
ragel -R grammar.rl
#ragel -R grammar.rl
grammar.rb: grammar.treetop
tt grammar.treetop

View file

@ -0,0 +1,151 @@
require "treetop"
class Treetop::Runtime::SyntaxNode
def generate_config
return "" if elements.nil?
return elements.collect(&:generate_config).reject(&:empty?).join("")
end
def compile
return "" if elements.nil?
return elements.collect(&:compile).reject(&:empty?).join("")
end
def recursive_select(results=[], &block)
if !elements.nil?
elements.each do |e|
if block.call(e)
results << e
else
e.recursive_select(results, &block)
end
end
end
return results
end
def recursive_select_parent(results=[], &block)
if !parent.nil?
if block.call(parent)
results << parent
else
parent.recursive_select_parent(results, &block)
end
end
return results
end
end
module LogStash; module Config; module AST
class Node < Treetop::Runtime::SyntaxNode; end
class Config < Node; end
class Comment < Node; end
class Whitespace < Node; end
class PluginSection < Node
def generate_config
return "#{plugin_type.text_value} {\n" << super << "}\n"
end
end
class Plugins < Node; end
class Plugin < Node
def generate_config
return "#{name.text_value} {\n" << attributes.elements.collect(&:generate_config).join("") << "}\n"
end
def compile
# Search up the stack for the PluginSection we're in
plugin_type = recursive_select_parent { |e| e.is_a?(PluginSection) }.first.plugin_type.text_value.inspect
# Unless we're inside a Plugin, then any 'plugin object is actually a
# codec.
is_codec = recursive_select_parent { |e| e.is_a?(Plugin) }.any?
plugin_type = "codec".inspect if is_codec
if attributes.elements.nil?
return "plugin(#{plugin_type}, #{name.text_value.inspect})" << (is_codec ? "" : "\n")
else
return "plugin(#{plugin_type}, #{name.text_value.inspect}, " << attributes.recursive_select { |e| e.is_a?(Attribute) }.collect(&:compile).reject(&:empty?).join(", ") << ")" << (is_codec ? "" : "\n")
end
end
end
class Name < Node
def generate_config
return text_value
end
def compile
return text_value.inspect
end
end
class Attribute < Node
def generate_config
return %Q(#{name.generate_config} => #{value.generate_config}\n)
end
def compile
return %Q(#{name.compile} => #{value.compile})
end
end
class Value < Node; end
class Bareword < Value
def generate_config
return text_value.inspect
end
def compile
return text_value.inspect
end
end
class String < Value
def generate_config
return text_value[1...-1].inspect
end
def compile
return text_value[1...-1].inspect
end
end
class Number < Value
def generate_config
return text_value
end
def compile
return text_value
end
end
class Array < Value
def generate_config
return "[" << recursive_select { |e| e.is_a?(Value) }.collect(&:generate_config).join(", ") << "]"
end
def compile
return "[" << recursive_select { |e| e.is_a?(Value) }.collect(&:compile).reject(&:empty?).join(", ") << "]"
end
end
class Hash < Value
def generate_config
return "{" << recursive_select { |e| e.is_a?(HashEntry) }.collect(&:generate_config).join(" ") << "}"
end
def compile
return "{" << recursive_select { |e| e.is_a?(HashEntry) }.collect(&:compile).reject(&:empty?).join(", ") << "}"
end
end
class HashEntries < Node; end
class HashEntry < Node
def generate_config
return %Q(#{name.generate_config} => #{value.generate_config}\n)
end
def compile
return %Q(#{name.compile} => #{value.compile})
end
end
class Branch < Node; end
class If < Node; end
class Elsif < Node; end
class Else < Node; end
class Condition < Node; end
class Expression < Node; end
class Rvalue < Node; end
class ComparisonOperator < Node; end
class BooleanOperator < Node; end
class Selector < Node; end
class SelectorElement < Node; end
end; end; end

View file

@ -1,5 +1,6 @@
require "logstash/namespace"
require "logstash/config/grammar"
require "logstash/config/config_ast"
require "logstash/config/registry"
require "logger"
@ -26,15 +27,22 @@ class LogStash::Config::File
end
def _get_config(data)
grammar = LogStash::Config::Grammar.new
grammar.parse(data)
grammar.config
#grammar = LogStash::Config::Grammar.new
grammar = LogStashConfigParser.new
result = grammar.parse(data)
if result.nil?
raise grammar.failure_reason
end
return result
end
public
def parse
@config = _get_config(_get_config_data);
require "pry"
binding.pry
registry = LogStash::Config::Registry::registry
each do |o|
# Load the base class for the type given (like inputs/base, or filters/base)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,177 @@
require "treetop"
grammar LogStashConfig
rule config
_ plugin_section _ (_ plugin_section)* _ <LogStash::Config::AST::Config>
end
rule comment
(_ "#" [^\r\n]+ "\r"? "\n")+ <LogStash::Config::AST::Comment>
end
rule _
(whitespace)? <LogStash::Config::AST::Whitespace>
end
rule whitespace
[ \t\r\n]+ <LogStash::Config::AST::Whitespace>
end
rule plugin_section
comment?
plugin_type _ "{"
comment?
_
(branch / plugins)
_
comment?
"}"
<LogStash::Config::AST::PluginSection>
end
rule plugin_type
("input" / "filter" / "output")
end
rule plugins
(plugin (_ plugin)*)?
<LogStash::Config::AST::Plugins>
end
rule plugin
comment?
name _ "{"
comment? _
attributes:( attribute (whitespace attribute)*)?
comment? _
"}"
comment?
<LogStash::Config::AST::Plugin>
end
rule name
[A-Za-z0-9_-]+
<LogStash::Config::AST::Name>
end
rule attribute
comment?
name _ "=>" _ value
comment?
<LogStash::Config::AST::Attribute>
end
rule value
plugin / bareword / string / number / array / hash
#<LogStash::Config::AST::Value>
end
rule bareword
[A-Za-z_] [A-Za-z0-9_]+
<LogStash::Config::AST::Bareword>
end
rule string
'"'
('\"' / !'"' .)*
'"'
<LogStash::Config::AST::String>
#/ ("'" (("'" / !"'" .)*) "'")
end
rule number
"-"? [0-9]+ ("." [0-9]*)?
<LogStash::Config::AST::Number>
end
rule array
"["
comment?
_
(
value (_ "," comment? _ value)*
)?
comment?
_
"]"
<LogStash::Config::AST::Array>
end
rule hash
"{"
comment?
_
hashentries?
comment?
_
"}"
<LogStash::Config::AST::Hash>
end
rule hashentries
hashentry (comment? whitespace hashentry)*
<LogStash::Config::AST::HashEntries>
end
rule hashentry
name:(number / bareword / string) _ "=>" _ value
<LogStash::Config::AST::HashEntry>
end
# Conditions
rule branch
if (_ elsif)* (_ else)?
<LogStash::Config::AST::Branch>
end
rule if
"if" _ condition _ "{" _ plugins _ "}"
<LogStash::Config::AST::If>
end
rule elsif
"elsif" _ condition _ "{" _ plugins _ "}"
<LogStash::Config::AST::Elsif>
end
rule else
"else" _ "{" _ plugins _ "}"
<LogStash::Config::AST::Else>
end
rule condition
expression (_ boolean_operator _ expression)*
<LogStash::Config::AST::Condition>
end
rule expression
"(" _ condition _ ")"
/ "!" _ condition
/ rvalue _ comparison _ rvalue
<LogStash::Config::AST::Expression>
end
rule rvalue
string / number / array
end
rule comparison
"==" / "!=" / "<" / ">" / "<=" / ">=" / "=~" / "!~" / "in"
<LogStash::Config::AST::Comparison>
end
rule boolean_operator
"and" / "or" / "xor" / "nand"
<LogStash::Config::AST::Boolean_operator>
end
rule selector
selector_element+
<LogStash::Config::AST::Selector>
end
rule selector_element
"[" (!"]")+ "]"
<LogStash::Config::AST::SelectorElement>
end
end