2014-06-07 15:00:07 +02:00
|
|
|
#!/usr/bin/perl
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
|
|
|
|
use Parse::RecDescent;
|
|
|
|
use Getopt::Std;
|
|
|
|
use Data::Dumper;
|
|
|
|
|
|
|
|
# todo: 1. the entire syntax for pointers to functions.
|
|
|
|
# 2. preprocessor directives. (getting there)
|
|
|
|
# So, the problem with handling CPP directives is when they
|
|
|
|
# interrupt something. I'm open to ideas.
|
|
|
|
# 4. functions to handle the nesting levels (ordinal number generator and CPP stack)
|
|
|
|
# 6. change returns to prints where appropriate.
|
|
|
|
|
2014-06-15 06:28:54 +02:00
|
|
|
our ($opt_T, $opt_t, $opt_o, $opt_P);
|
|
|
|
getopts('TPto:');
|
2014-06-07 15:00:07 +02:00
|
|
|
|
|
|
|
if ($opt_T ) {
|
|
|
|
$::RD_TRACE = 1;
|
|
|
|
} else {
|
|
|
|
undef $::RD_TRACE ;
|
|
|
|
}
|
|
|
|
|
|
|
|
$::RD_HINT = 1;
|
|
|
|
$Parse::RecDescent::skip = '\s*';
|
|
|
|
|
|
|
|
# This may be necessary..
|
|
|
|
# $::RD_AUTOACTION = q { [@item] };
|
|
|
|
|
2014-06-15 06:28:54 +02:00
|
|
|
my $parser;
|
|
|
|
|
2014-06-15 17:42:20 +02:00
|
|
|
if($opt_P or !eval { require PCGrammar }) {
|
2014-06-15 06:28:54 +02:00
|
|
|
precompile_grammar();
|
|
|
|
require PCGrammar;
|
|
|
|
}
|
2014-06-07 15:00:07 +02:00
|
|
|
|
2014-06-15 17:42:20 +02:00
|
|
|
$parser = PCGrammar->new() or die "Bad grammar!\n";
|
|
|
|
|
2014-06-07 15:00:07 +02:00
|
|
|
if ($opt_o) {
|
|
|
|
open(OUTFILE, ">>$opt_o");
|
|
|
|
*STDOUT = *OUTFILE{IO};
|
|
|
|
}
|
|
|
|
|
|
|
|
my $text = "";
|
|
|
|
foreach my $arg (@ARGV) {
|
|
|
|
print STDERR "Opening file $arg\n";
|
|
|
|
|
|
|
|
open(CFILE, "$arg") or die "Could not open $arg.\n";
|
|
|
|
local $/;
|
|
|
|
$text = <CFILE>;
|
|
|
|
close(CFILE);
|
|
|
|
|
|
|
|
print STDERR "parsing...\n";
|
|
|
|
|
|
|
|
# for debugging...
|
|
|
|
if ($opt_t) {
|
|
|
|
$::RD_TRACE = 1;
|
|
|
|
} else {
|
|
|
|
undef $::RD_TRACE;
|
|
|
|
}
|
|
|
|
|
2014-06-22 08:08:01 +02:00
|
|
|
my $result = $parser->startrule(\$text) or die "Bad text!\n$text\n";
|
|
|
|
|
|
|
|
$text =~ s/^\s+//g;
|
|
|
|
$text =~ s/\s+$//g;
|
|
|
|
|
|
|
|
if(length $text) {
|
2014-06-22 08:11:11 +02:00
|
|
|
print "Bad parse at: $text";
|
2014-06-22 08:08:01 +02:00
|
|
|
} else {
|
2014-06-28 16:41:50 +02:00
|
|
|
my $output = join('', flatten($result));
|
|
|
|
|
|
|
|
# beautification
|
|
|
|
my @quotes;
|
|
|
|
$output =~ s/(?:\"((?:\\\"|(?!\").)*)\")/push @quotes, $1; '"' . ('-' x length $1) . '"'/ge;
|
|
|
|
|
|
|
|
$output =~ s/the value the expression/the value of the expression/g;
|
|
|
|
$output =~ s/the value the member/the value of the member/g;
|
|
|
|
$output =~ s/the value the/the/g;
|
|
|
|
$output =~ s/of evaluate/of/g;
|
2014-07-01 18:16:40 +02:00
|
|
|
$output =~ s/the evaluate the/the/g;
|
|
|
|
$output =~ s/by evaluate the/by the/g;
|
2014-07-01 21:07:44 +02:00
|
|
|
$output =~ s/the a /the /g;
|
2014-06-28 16:41:50 +02:00
|
|
|
|
|
|
|
foreach my $quote (@quotes) {
|
2014-06-28 16:49:59 +02:00
|
|
|
next unless $quote;
|
|
|
|
$output =~ s/"-+"/"$quote"/;
|
2014-06-28 16:41:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
print $output;
|
2014-06-22 08:08:01 +02:00
|
|
|
}
|
2014-06-07 15:00:07 +02:00
|
|
|
}
|
|
|
|
|
2014-06-15 06:28:54 +02:00
|
|
|
|
|
|
|
sub precompile_grammar {
|
|
|
|
print STDERR "Precompiling grammar...\n";
|
|
|
|
open GRAMMAR, 'CGrammar.pm' or die "Could not open CGrammar.pm: $!";
|
|
|
|
local $/;
|
|
|
|
my $grammar = <GRAMMAR>;
|
|
|
|
close GRAMMAR;
|
|
|
|
|
|
|
|
Parse::RecDescent->Precompile($grammar, "PCGrammar") or die "Could not precompile: $!";
|
|
|
|
}
|
2014-06-20 09:43:06 +02:00
|
|
|
|
|
|
|
sub flatten {
|
|
|
|
map { ref eq 'ARRAY' ? flatten(@$_) : $_ } @_
|
|
|
|
}
|
2014-06-24 07:34:54 +02:00
|
|
|
|
|
|
|
sub istrue {
|
2014-07-03 23:33:20 +02:00
|
|
|
my @parts = split /(?<!,) and /, $_[0];
|
2014-06-24 07:34:54 +02:00
|
|
|
my ($result, $and) = ('', '');
|
|
|
|
foreach my $part (@parts) {
|
|
|
|
$result .= $and;
|
2014-06-28 12:18:28 +02:00
|
|
|
if($part !~ /(discard the result|result discarded|greater|less|equal|false$)/) {
|
2014-06-24 07:38:59 +02:00
|
|
|
$result .= "$part is nonzero";
|
2014-06-24 07:34:54 +02:00
|
|
|
} else {
|
|
|
|
$result .= $part;
|
|
|
|
}
|
|
|
|
$and = ' and ';
|
|
|
|
}
|
2014-06-28 12:18:28 +02:00
|
|
|
$result =~ s/is nonzero and the result discarded/is evaluated and the result discarded/g;
|
|
|
|
$result =~ s/is ((?:(?!evaluated).)+) and the result discarded/is evaluated to be $1 and the result discarded/g;
|
2014-06-24 07:34:54 +02:00
|
|
|
return $result;
|
|
|
|
}
|