Config::INI in Perl 6

What better way to learn Perl 6 than to write software in it? I thought a nice, small project would be to write an INI file parser. Unfortunately, it turns out there there is no standard INI format. Or if there is, there it's pretty much ignored. As a result, I tried to write something which would handle something which is the least surprising to people. Thus, I trim whitespace, I allow comment lines starting with ';' and '#' and I ignore blank lines. It does not yet handle quoted strings, but I want to add that later.

I finally have a (clumsy) grammar which matches, but turning it into an AST and transforming it into a useful object has failed miserably. Tips? The code below runs on the latest version of Rakudo and the first parse shows that we match, but the second match generates errors such as:

Use of uninitialized value
Use of uninitialized value
Null PMC access in find_method('new')
in Main (file <unknown>, line <unknown>)

And the Perl 6:

grammar Config::INI::Grammar { token TOP { <config> {*} } token config { <root_section>? <section>+ {*} } token root_section { [ <property> | <ignore> ]* {*} } regex section { ^^ '[' <.ws> $<name>=<-[\n\]]>*? <.ws> ']' \h* \n [ <property> | <ignore> ]* {*} } regex property { ^^ <.ws> $<name>=[<.print>+?] <.ws> '=' <.ws> $<value>=[\N*?] \h* \n } token ignore { | ^^ <.ws> [';'|'#'] [\N*] \n | ^^ \h* \n } } class Config::INI { class Config::INI::Section { has $.name is rw; has %.properties is rw; } has $.root_section is rw; has Config::INI::Section @.sections is rw; } class Config::INI::Actions { method TOP ($/) { say 'TOP'; make ($<config>).ast; } method config ($/) { say 'config'; make Config::INI.new( root_section => ($<root_section>).ast, sections => ($<section>)>>.ast, ); } method root_section ($/) { my %property; for $<property> -> $p { %property{$<name>} = $<value>; } make Config::INI::Section.new( name => '_', properties => %property, ); } method section ($/) { my %property; for $<property> -> $p { %property{$<name>} = $<value>; } make Config::INI::Section.new( name => $<name>, properties => %property {*} ); } } my $text = Q{ uno=dos tres = quatro [ foo bar ] this=that one = two # ignore this ; and this }; my $config = Config::INI::Grammar.parse($text); say $config ?? 'yes' !! 'no'; say $config.perl; my $actions = Config::INI::Actions.new(); $config = Config::INI::Grammar.parse($text, :action($actions)).ast; say $config ?? 'yes' !! 'no'; say $config.perl;

Clearly the Config::INI classes are clumsy right now, but they're just a first pass for me trying to generate the AST.

2 Comments

In the RSS feed, your nicely formatted grammar shows up as a code blob.

Leave a comment

About Ovid

user-pic Have Perl; Will Travel. Freelance Perl/Testing/Agile consultant. Photo by http://www.circle23.com/. Warning: that site is not safe for work. The photographer is a good friend of mine, though, and it's appropriate to credit his work.