Skip to content

Instantly share code, notes, and snippets.

@pstuifzand
Last active December 10, 2015 14:38
Show Gist options
  • Save pstuifzand/4448957 to your computer and use it in GitHub Desktop.
Save pstuifzand/4448957 to your computer and use it in GitHub Desktop.
Completely incomplete parser for Makefiles
package Demo::MarpaX::Makefile;
use strict;
use Marpa::R2;
sub new {
my ($class) = @_;
my $self = bless {}, $class;
$self->{grammar} = Marpa::R2::Scanless::G->new(
{
action_object => 'Demo::MarpaX::Makefile::Actions',
default_action => 'do_first_arg',
source => \(<<'END_OF_SOURCE'),
:start ::= makefile
makefile ::= recipes
recipes ::= recipe+ action => do_list
recipe ::= target_line command_lines possible_newlines action => do_recipe separator => ws proper => 0
target_line ::= target target_sep dependencies newline action => do_targetline
command_lines ::= commands
possible_newlines ::= newline*
target ::= filename
dependencies ::= filename* action => do_list separator => ws proper => 0
commands ::= command+ action => do_list separator => newline proper => 0
target_sep ::= (':' ws)
command ~ tab commandline
filename ~ [^:\s]+
tab ~ [\x09]
commandline ~ [^\n]+
newline ~ [\n]
ws ~ [ ]*
END_OF_SOURCE
}
);
return $self;
}
sub parse {
my ($self, $string) = @_;
my $re = Marpa::R2::Scanless::R->new( { grammar => $self->{grammar} } );
$re->read(\$string);
my $value_ref = $re->value();
return ${$value_ref};
}
sub parse_makefile {
my ($string) = @_;
my $parser = MarpaX::Makefile->new();
return $parser->parse($string);
}
package Demo::MarpaX::Makefile::Actions;
use strict;
use Data::Dumper;
sub new {
my ($class) = @_;
return bless {}, $class;
}
sub do_first_arg {
shift;
return $_[0];
}
sub do_list {
shift;
return \@_;
}
sub do_recipe {
shift;
my $commands = $_[1];
for (@$commands) {
s/^\s+//;
s/\s+$//;
}
return { %{$_[0]}, commands => $commands };
}
sub do_targetline {
shift;
return { target => $_[0], deps => $_[2] };
}
1;
use lib 'lib';
use MarpaX::Makefile;
use Data::Dumper;
my $p = MarpaX::Makefile->new;
my $out = $p->parse(<<"MAKEFILE");
target.o: target.c
gcc -c target.c -o target.o
target.o: target.c
gcc -c target.c -o target.o
gcc -c target.c -o target.o
gcc -c target.c -o target.o
MAKEFILE
print Dumper($out);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment