Version 1.0;
GlobalPList plist1 [option1] [option2] {
#base=111
# this is a full line comment
Pat n1000000g0000001; # this is a partial line comment
Pat n2000000g0000002; #HOT#
LocalPList plist2 {
Pat n5000000g0000005;
GlobalPList plist4 { Pat n8000000g0000008; #KEEP# } }
Pat n3000000g0000003; #HOT,COLD#
Pat n4000000g0000004;
PList plist2;
PList file1.plist:plist3;
}
GlobalPList plist2 [option3] {
PList plist1;
Pattern n6000000g0000006;
Pattern n7000000g0000007;
}
####
use strict;
use warnings;
my $file = $ARGV[0];
my $s;
if (defined $file) {
# parse data from file argument
open my $fh, '<', $file
or die "Failed to open file ($file):$!\n";
# for processing speed, tossing out full line comments and empty lines now
while (<$fh>) {
next if /^\s*#.*$/ and !/^\s*#\s*base\s*=/;
next if /^\s*$/;
$s .= $_
}
}
else {
# parse data from DATA
while () {
next if /^\s*#.*$/ and !/^\s*#\s*base\s*=/;
next if /^\s*$/;
$s .= $_
}
}
close $fh or die "Failed to close file ($file): $!\n";
#print STDERR "DATA :\n$s\n";
use Regexp::Grammars;
my $parser = qr/
#
#
\d+(\.\d+)?
GlobalPList|LocalPList
PList
\w+
\[[\w \.,]*\]
\d+
\#[^\n]*
Pat|Pattern
\w+
\w+
\{
\}
[\w\.]+
<[global_plist]>+
Version \;
\#\s*base\s*=\s*<[base_number]>+ % ,\s*\n
\#<[tag]>+ % ,\#
<.global_plist_declare>
<[plist_option]>* % \s*
<.plist_open>
?
(<[data_node]> | <.comment>)+
<.plist_close>
| |
<.reference_plist_declare>
( :
|
)
;
<.pat_declare> ; ?
/xms;
$s =~ $parser;
use Data::Dumper;
open $fh, '>', 'C:\tmp\tmp' or die "FAILED!\n";
print $fh "RESULTS:".Dumper(\%/);
print STDERR "RESULTS:".Dumper(\%/);
__DATA__
Version 1.0;
# Plist SVN Url: $HeadURL: https://XXXXXX...
# Plist SVN Revision: $Id: gt.plist 2555 2014-02-06 16:16:26Z vsgatcha $
# RunDir: /XXXXXX...
GlobalPList plist1 [option1] [option2] {
#base=111
# this is a full line comment
Pat n1000000g0000001; # this is a partial line comment
Pat n2000000g0000002; #HOT#
LocalPList plist2 {
Pat n5000000g0000005;
GlobalPList plist4 { Pat n8000000g0000008; #KEEP# } }
Pat n3000000g0000003; #HOT,COLD#
Pat n4000000g0000004;
PList plist2;
PList file1:plist3;
}
GlobalPList plist2 [option3] {
PList plist1;
Pattern n6000000g0000006;
Pattern n7000000g0000007;
}
####
use strict;
use warnings;
use Data::Dumper;
my $file = $ARGV[0];
my $s;
if (defined $file) {
# parse data from file if given
open my $fh, '<', $file
or die "Failed to open file ($file):$!\n";
# for processing speed, tossing out full line comments and empty lines now
while (<$fh>) {
next if /^\s*#.*$/ and !/^\s*#\s*base\s*=/;
next if /^\s*$/;
$s .= $_
}
close $fh or die "Failed to close file ($file): $!\n";
}
else {
# parse data from DATA
while () {
next if /^\s*#.*$/ and !/^\s*#\s*base\s*=/;
next if /^\s*$/;
$s .= $_
}
}
#print STDERR "DATA :\n$s\n";
use Marpa::R2;
my $grammar_str = <<'END_GRAMMAR';
inaccessible is fatal by default
lexeme default = latm => 1
:start ::= plist_file
plist_file ::= version_data ows global_plists
version_data ::= 'Version' mws float ows ';'
global_plists ::= global_plist+
global_plist ::= global_pl_declare mws pl_name ows opt_pl_options ows '{' ows opt_embedded_base ows nodes '}'
pl_name ::= [\w]+
opt_pl_options ::= option*
option ::= '[' ows option_data ows ']' ows
nodes ::= node+
node ::= pattern | comment | global_plist || reference_plist
pattern ::= pat_declare mws pat_name ows opt_pat_option ';' ows opt_tag_str ows
opt_pat_option ::= option*
comment ::= '#' comment_chars newline ows
reference_plist ::= 'PList' mws ref_pl_name ows ';' ows
ref_pl_name ::= opt_ref_file pl_name
opt_ref_file ::= ref_file*
ref_file ::= file_name ':'
file_name ::= [\w\.]+
opt_tag_str ::= tag_str*
tag_str ::= '#' ows tag_list ows '#'
tag_list ::= tag* separator => comma
opt_embedded_base ::= embedded_base*
embedded_base ::= '#' ows 'base' ows '=' ows base_numbers
base_numbers ::= base_number+ separator => comma
comma ::= ','
pat_name ::= [\w]+
pat_declare ::= 'Pat'|'Pattern'
comment_chars ::= [^\n]*
newline ::= [\n]
int ::= [\d]+
tag ::= [\w]+
global_pl_declare ::= 'GlobalPList'|'LocalPList'|'PatternList'
option_data ::= [\w \.,]*
base_number ::= [\d]+
float ::= int opt_fractional
opt_fractional ::= fractional*
fractional ::= '.' int
# optional whitespace
ows ::= [\s]*
# mandatory whitespace
mws ::= [\s]+
END_GRAMMAR
my $grammar = Marpa::R2::Scanless::G->new({
source => \$grammar_str,
});
my $parser = Marpa::R2::Scanless::R->new({
grammar => $grammar,
# trace_values => 2,
# trace_terminals => 1,
});
eval {
$parser->read( \$s );
};
if ($@) {
print "PARSE ERROR:$@\n";
die "EXITING\n";
# die $parser->show_progress(0, -1);
}
else {
print "SUCCESSFUL PARSE!\n"; ;
}
print STDERR Dumper( $parser->value );
__DATA__
Version 1.0;
# Plist SVN Url: $HeadURL: https://XXXXXX...
# Plist SVN Revision: $Id: gt.plist 2555 2014-02-06 16:16:26Z vsgatcha $
# RunDir: /XXXXXX...
GlobalPList plist1 [option1] [option2] {
#base=111
# this is a full line comment
Pat n1000000g0000001; # this is a partial line comment
Pat n2000000g0000002; #HOT#
LocalPList plist2 {
Pat n5000000g0000005;
GlobalPList plist4 { Pat n8000000g0000008; #KEEP# } }
Pat n3000000g0000003; #HOT,COLD#
Pat n4000000g0000004;
PList plist2;
PList file1.plist:plist3;
}
GlobalPList plist2 [option3] {
PList plist1;
Pattern n6000000g0000006;
Pattern n7000000g0000007;
}