%%{
machine params_tree; action H { @head = p } action T { @tail = p } action inject_key { inject_key } action push { push } action pop { pop } DELIMITER = ',' >H@T @{ log(:delimiter) }; LEVEL = '(' >H@T @{ log(:level) }; END_LEVEL = ')'+ >H@T @{ log(:end_level); }; INPUT = (any - LEVEL - END_LEVEL - DELIMITER)+ >H@T @{ log(:input); memo_key; }; main := ( INPUT ( DELIMITER @inject_key @{ fnext main; } | END_LEVEL DELIMITER? @inject_key @pop @{ fret; } | LEVEL @inject_key @push @{ fcall main; } ) )*;
}%%
module ParamsTree
class Parser attr_accessor :data def initialize %% write data; end def parse(input) input = input.to_s.gsub(/\s*/, '') return {} if input.size == 0 @data = input.unpack('c*') stack = [] @log = [] @hash = {} @hash_stack = [] @key = nil %% write init; %% write exec; inject_key # FIXME @hash_stack.first || @hash end def chars @data[@head..@tail] end def strokes chars.pack('c*') end def log(token) @log << { token => strokes } end def memo_key @key = chars end def key @key.pack('c*') end def inject_key if @hash.key?(key) @hash[key][ParamsTree::DEFAULT] = {} else @hash[key] = {} end end def push @hash_stack.push(@hash) @hash = @hash[key] end def pop @hash = @hash_stack.pop end def self.parse(string) self.new.parse(string) end end
end