json-format.pl: make it a streaming formatter

Always pretty-print.
This commit is contained in:
Přemysl Eric Janouch 2017-01-25 20:42:32 +01:00
parent 17331073a4
commit 18c25e8bff
Signed by: p
GPG Key ID: B715679E3A361BE6
1 changed files with 24 additions and 17 deletions

View File

@ -56,9 +56,15 @@ my $any_token = qr/\G(${\join '|', @all_pats})/;
my $indent = 0; my $indent = 0;
sub nexttoken ($) { sub nexttoken ($) {
my $ref = shift; my $json = shift;
return unless @$ref; if (!@$json) {
my $text = shift @$ref; return unless defined (my $line = <>);
push @$json, $line =~ /$any_token/gsc;
push @$json, substr $line, pos $line
if pos $line != length $line;
}
my $text = shift @$json;
if (my $s = $lookup{$text}) { if (my $s = $lookup{$text}) {
return $s, $text; return $s, $text;
} }
@ -68,6 +74,15 @@ sub nexttoken ($) {
return 'ERROR', $text; return 'ERROR', $text;
} }
sub skip_ws ($) {
my $json = shift;
while (my ($token, $text) = nexttoken $json) {
next if $token eq 'WS';
return $token, $text;
}
return;
}
sub printindent () { sub printindent () {
print "\n"; print "\n";
print ' ' x $indent; print ' ' x $indent;
@ -78,7 +93,7 @@ sub do_object ($) {
my $json = shift; my $json = shift;
my $in_field_name = 1; my $in_field_name = 1;
my $first = 1; my $first = 1;
while (my ($token, $text) = nexttoken $json) { while (my ($token, $text) = skip_ws $json) {
if ($token eq 'COLON') { if ($token eq 'COLON') {
$in_field_name = 0; $in_field_name = 0;
} elsif ($token eq 'COMMA') { } elsif ($token eq 'COMMA') {
@ -101,7 +116,7 @@ sub do_object ($) {
sub do_array ($) { sub do_array ($) {
my $json = shift; my $json = shift;
my $first = 1; my $first = 1;
while (my ($token, $text) = nexttoken $json) { while (my ($token, $text) = skip_ws $json) {
if ($token eq 'RBRACKET') { if ($token eq 'RBRACKET') {
$indent--; $indent--;
printindent; printindent;
@ -134,16 +149,8 @@ sub do_value ($$$) {
} }
} }
while (<>) { my @buffer;
# FIXME: this way it doesn't work with pre-formatted JSON while (my ($token, $text) = skip_ws \@buffer) {
my $json = $_; do_value $token, $text, \@buffer;
my @matches = $json =~ /$any_token/gsc;
push @matches, substr $json, pos $json
if pos $json != length $json;
while (my ($token, $text) = nexttoken \@matches) {
next if $token eq 'WS';
do_value $token, $text, \@matches;
}
print "\n";
} }
print "\n";