OK, I got a little bored at work, so I thought I'd code it up in Marpa just as an example. There's a minor bug in it, but I'll leave it in there. Source code:
#!/usr/bin/env perl
#
# parse_config_file.pl - a quickie parser for <tag>: <value> config
+files
#
use strict;
use warnings;
use Marpa::R2;
use Data::Dump qw(pp);
my $stuff = <<'EOGrammar';
:default ::= action => [ values ]
lexeme default = latm => 1
ConfigFile ::= Line ConfigFile action => return_result
ConfigFile ::= action => return_result
Line ::= Tag COLON Value EOL action => add_config_value
| EOL
Tag ::= START_CHAR Tag_remainder action => add_remainder
Tag_remainder ::=
TAG_CHAR Tag_remainder action => add_remainder
| TAG_CHAR action => ::first
Value ::= START_CHAR Value_remainder action => add_remainder
Value_remainder ::=
VAL_CHAR Value_remainder action => add_remainder
| VAL_CHAR action => ::first
####
# Token definitions
####
:discard ~ WHITESPACE
WHITESPACE ~ [\r\t ]+
# Delimiter between the tag and the value
COLON ~ [:]
# End of line marker
EOL ~ [\n]
# Starting character of a tag/value
START_CHAR ~ [^:\s]
# Legal characters in a tag after the starting character
TAG_CHAR ~ [^:\n]
# After the starting character, a value can have any character but lin
+e end
VAL_CHAR ~ [^\n]
EOGrammar
my $grammar = Marpa::R2::Scanless::G->new({ source=> \$stuff });
my $input = join("", <DATA>);
# Note: Right-hand-side is wrapped in ${...} because we're returning a
# reference to a hash reference. (Not as useful as a plain hashref)
my $config = ${$grammar->parse( \$input, 'ConfigFileActions' )};
print "Daily mission: ", $config->{'What are we doing today Brain'}, "
+\n";
print "Location: ", $config->{where}, "\n\n";
print "All configuration data: ", pp($config), "\n";
sub ConfigFileActions::add_config_value {
# Add the tag / value combination to the result hash
my ($result, $tag, $colon, $val) = @_;
$result->{$tag} = $val;
return $result;
}
sub ConfigFileActions::add_remainder {
# Append character to the tag/val string
my ($context, $char, $rest) = @_;
return join("", $char, $rest);
}
sub ConfigFileActions::return_result {
# Final result of a top-level production is to return the
# hash reference we've been building
my ($context, undef) = @_;
return $context;
}
__DATA__
where: October
foo: bar
baz: 1234+54q - bar bar
who: bob
Some other parameter: 42
What are we doing today Brain: Same thing we do every day Pinky
When I run it, I get:
$ perl parse_cfg_file.pl
Daily mission: Same thing we do every day Pinky
Location: October
All configuration data: {
"baz" => "1234+54q - bar bar",
"foo" => "bar",
"Some other parameter" => 42,
"What are we doing today Brain" => "Same thing we do every day Pinky
+",
"where" => "October",
"who" => "bob",
}
...roboticus
When your only tool is a hammer, all problems look like your thumb.