I wrote a SavedVariable parser a while ago for a project of mine (and after trying to write a recursive decent parser that took over an hour to parse some files :/ ), unfortunately I lost the version that had my commented/whitespaced out regular expression, but this should still work (perl):
It takes a string of raw lua dumped from the SV file and returns a multi level hash of all the variables

use Regexp::Common qw /delimited balanced/;
sub parseLuaBlock
{
my $lua = shift;
$lua =~ s/\s*--.+?$//mg; # Strip comments
my %varhash;
my @refstack;
my $pos;
my $arpos = 0;
my %arindex;
$arindex{$arpos} = 1;
push(@refstack, \%varhash);
use re 'eval';
while(1)
{
if( $lua =~ /\G\s*(?:($RE{balanced}{-parens=>'[]'}|[-+a-z0-9_.]+)\s*=\s*($RE{delimited}{-delim=>'"'}{-esc=>'\\'}|[-+a-z0-9_.]+|\{)|(}|{|$RE{delimited}{-delim=>'"'}{-esc=>'\\'}|[-+a-z0-9_.]+)),?/isg)
{
$pos = pos;
my $lhs = (defined($1)) ? $1 : "";
my $rhs = (defined($2)) ? $2 : "";
my $bracket = (defined($3)) ? $3 : "";
if($rhs eq '{')
{
$arpos++;
$arindex{$arpos} = 1;
}
if($bracket eq '}' && $arpos > 0)
{
$arpos--;
} elsif($bracket eq '}')
{
$arindex{$arpos} = 1;
}
if($bracket =~ /['"]/)
{
$lhs = "[$arindex{$arpos}]";
$arindex{$arpos}++;
$rhs = $bracket;
$bracket = '';
}
if($bracket eq '{')
{
$lhs = "[$arindex{$arpos}]";
$arindex{$arpos}++;
$arpos++;
$arindex{$arpos} = 1;
$rhs = $bracket;
$bracket = '';
}
if($lhs =~ s/^\[(.+)\]$/$1/s)
{
$lhs =~ s/\\([\cM\cJ]+|[\\\[\]"])/$1/sg if $lhs =~ s/^"(.*)"$/$1/s;
}
$rhs =~ s/^"(true|false|(?:\d*\.)?\d+)"$/'$1'/s;
$rhs =~ s/\\([\cM\cJ]+|[\\"])/$1/sg if $rhs =~ s/^"(.*)"$/$1/s;
if($bracket eq '}')
{
die "Malformed config file, more closed then open brackets!" if $#refstack <= 0;
pop(@refstack);
} elsif( $rhs eq '{' )
{
push(@refstack, \%{$refstack[$#refstack]{$lhs}});
} else {
$refstack[$#refstack]{$lhs} = $rhs;
}
} else {
last;
}
pos($pos);
}
return %varhash;
}
I was fairly proud of myself at the time for it, and am pretty sure it can handle most things that the SV files will throw at it.