If you can't find a module to parse your config format, write your own parser.
Marpa::R2 can help you in the task:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
use Marpa::R2;
my $input = << '__INPUT__';
# This is a comment
feed_realtime_processor_pool = ( 11, 12 ) ;
dropout_detection_time_start = "17:00";
# Sometimes the config can have sub-structures
named_clients = (
{
name = "thread1";
user_threads = (
{ name = "realtime1"; cpu = 11; } # more comments
{ name = "realtime2"; cpu = 12; } # more comments
);
}
);
__INPUT__
my $dsl = << '__DSL__';
lexeme default = latm => 1
:default ::= action => ::first
Config ::= Elements
Elements ::= Element+ action => grep_def
+ined
Element ::= (Comment) action => empty
| Name (s eq s) Value action => [values]
| Name (s eq s) Value (semicolon s) action => [values]
Comment ::= (hash nonnl nl) action => empty
Name ::= alpha
Value ::= List
| String
| Num
| Struct
List ::= (lpar) Nums (rpar s semicolon s)
Nums ::= Num+ separator => comma action => listify
Num ::= (s) digits (s)
| (s) digits
| digits (s)
| digits
String ::= (qq) nqq (qq semicolon s) action => quote
Struct ::= (lpar s) InStructs (rpar semicolon s)
InStructs ::= InStruct+ action => grep_def
+ined
InStruct ::= (lcurl s) Elements (rcurl s)
| (Comment s) action => empty
| Element
s ~ [\s]*
eq ~ '='
hash ~ '#'
nonnl ~ [^\n]*
nl ~ [\n]
alpha ~ [a-z_]+
lpar ~ '('
rpar ~ ')'
lcurl ~ '{'
rcurl ~ '}'
semicolon ~ ';'
comma ~ ','
digits ~ [\d]+
qq ~ '"'
nqq ~ [^"]+
__DSL__
sub listify { shift; [ @_ ] }
sub quote { qq("$_[1]") }
sub empty {}
sub grep_defined { shift; [ grep defined, @_ ] }
my $id = 1;
sub show {
my ($parent, $name, $elems) = @_;
if (ref $elems->[0]) {
show($parent, $name, $_) for @$elems;
} elsif (ref $elems->[1]) {
if (ref $elems->[1][0]) {
say join ', ', $id, $parent, $elems->[0], 'null';
show($id++, $elems->[0], $elems->[1]);
} else {
for my $e (@{ $elems->[1] }) {
say join ', ', $id++, $parent, $elems->[0], $e;
}
}
} else {
say join ', ', $id++, $parent, @$elems;
}
}
my $grammar = 'Marpa::R2::Scanless::G'->new({ source => \$dsl });
show('null', q(), ${ $grammar->parse(\$input, 'main') });
Output:
1, null, feed_realtime_processor_pool, 11
2, null, feed_realtime_processor_pool, 12
3, null, dropout_detection_time_start, "17:00"
4, null, named_clients, null
5, 4, name, "thread1"
6, 4, user_threads, null
7, 6, name, "realtime1"
8, 6, cpu, 11
9, 6, name, "realtime2"
10, 6, cpu, 12
Note that the id of the last line is 10, not 9 as in your sample. Adding leading zeroes and aligning the columns left as an exercise for the OP.
($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord
}map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,