CGrammar improvements:

- show return type if _Noreturn function has type other than void
  - improve translation of function body
  - replace "Let `i` be an int" with "Declare `i` as an int"
This commit is contained in:
Pragmatic Software 2014-07-04 12:18:59 +00:00
parent 1f3533bf76
commit 9b93a33acf
3 changed files with 42 additions and 18 deletions

View File

@ -13,7 +13,7 @@ use warnings;
# These are set automatically by the build/commit script # These are set automatically by the build/commit script
use constant { use constant {
BUILD_NAME => "PBot", BUILD_NAME => "PBot",
BUILD_REVISION => 702, BUILD_REVISION => 703,
BUILD_DATE => "2014-07-04", BUILD_DATE => "2014-07-04",
}; };

View File

@ -19,7 +19,7 @@ if($code =~ s/^-f\s+//) {
} }
my ($has_function, $has_main, $got_nomain); my ($has_function, $has_main, $got_nomain);
my $prelude_base = "#define _XOPEN_SOURCE 9001\n#define __USE_XOPEN\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <math.h>\n#include <limits.h>\n#include <sys/types.h>\n#include <stdint.h>\n#include <errno.h>\n#include <ctype.h>\n#include <assert.h>\n\n"; my $prelude_base = "#define _XOPEN_SOURCE 9001\n#define __USE_XOPEN\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <math.h>\n#include <limits.h>\n#include <sys/types.h>\n#include <stdint.h>\n#include <errno.h>\n#include <ctype.h>\n#include <assert.h>\n#include <stdnoreturn.h>\n#include <stdbool.h>\n\n";
my $prelude = $prelude_base; my $prelude = $prelude_base;
print "code before: [$code]\n" if $debug; print "code before: [$code]\n" if $debug;
@ -275,7 +275,7 @@ if($lang eq 'C89' or $lang eq 'C99' or $lang eq 'C11' or $lang eq 'C++') {
$precode =~ s/^{(.*)}$/$1/s; $precode =~ s/^{(.*)}$/$1/s;
if(not $has_main and not $got_nomain) { if(not $has_main and not $got_nomain) {
$code = "$prelude\n$code" . "int main(void) {\n$precode\n;\nreturn 0;\n}\n"; $code = "$prelude\n$code" . "int main(void) {\n$precode\n;\n}\n";
} else { } else {
print "code: [$code]; precode: [$precode]\n" if $debug; print "code: [$code]; precode: [$precode]\n" if $debug;
$code = "$prelude\n$precode\n\n$code\n"; $code = "$prelude\n$precode\n\n$code\n";
@ -389,14 +389,17 @@ close $fh;
$output = `./c2eng.pl code2eng.c` if not defined $output; $output = `./c2eng.pl code2eng.c` if not defined $output;
if(not $has_function and not $has_main) { if(not $has_function and not $has_main) {
$output =~ s/Let .main. be a function taking no arguments and returning int.\s*To perform the function.\s*(return 0.)?//i; $output =~ s/Let .main. be a function taking no arguments and returning int.\s*When called, the function will.\s*(return 0.)?//i;
$output =~ s/\s*Return 0.\s*End of function .main..\s*//; $output =~ s/\s*Return 0.\s*End of function .main..\s*//;
$output =~ s/\s*Return 0.$//; $output =~ s/\s*Finally, return 0.$//;
$output =~ s/\s*and then return 0.$/./;
$output =~ s/\s*Do nothing.\s*$//; $output =~ s/\s*Do nothing.\s*$//;
$output =~ s/^\s*(.)/\U$1/; $output =~ s/^\s*(.)/\U$1/;
$output =~ s/\.\s+(\S)/. \U$1/g; $output =~ s/\.\s+(\S)/. \U$1/g;
} elsif($has_function and not $has_main) { } elsif($has_function and not $has_main) {
$output =~ s/\s*Let `main` be a function taking no arguments and returning int.\s*To perform the function, return 0.//; $output =~ s/\s*Let `main` be a function taking no arguments and returning int.\s*When called, the function will return 0.//;
$output =~ s/\s*Finally, return 0.$//;
$output =~ s/\s*and then return 0.$/./;
} }
$output =~ s/\s+/ /; $output =~ s/\s+/ /;

View File

@ -162,20 +162,37 @@ function_definition:
$parameter_list =~ s/function/function with suggestion to be as fast as possible$and/; $parameter_list =~ s/function/function with suggestion to be as fast as possible$and/;
} }
if ($declaration_specifiers =~ /_Noreturn/) { if ($return_type =~ s/_Noreturn//g) {
$return_type = join(' ', split(' ', $return_type));
$parameter_list =~ s/ returning$//; $parameter_list =~ s/ returning$//;
$return_type = "which doesn't return to its caller"; if ($return_type eq 'void') {
$return_type = "which doesn't return to its caller";
} else {
$return_type = "which shouldn't return to its caller yet does mysteriously return $return_type";
}
} }
$return = "\nLet $name be a "; $return = "\nLet $name be a $parameter_list $return_type.\n";
$return .= $parameter_list;
$return .= " $return_type.\nTo perform the function, ^L"; my $statements = join('', @{$item{'compound_statement(?)'}});
$return .= join('', @{$item{'compound_statement(?)'}}); $return .= "When called, the function will ^L$statements";
} }
block_item_list: block_item_list:
block_item(s) block_item(s)
{ $return = join('', @{$item{'block_item(s)'}}); } {
if (@{$item{'block_item(s)'}} == 1) {
$return = $item{'block_item(s)'}->[0];
} elsif (@{$item{'block_item(s)'}} == 2) {
my $first = $item{'block_item(s)'}->[0];
my $second = $item{'block_item(s)'}->[1];
$first =~ s/\.?\s*$//;
$return = "$first and then ^L$second";
} else {
my $last = pop @{$item{'block_item(s)'}};
$return = join('Then ^L', @{$item{'block_item(s)'}}) . "Finally, ^L$last";
}
}
block_item: block_item:
declaration declaration
@ -629,7 +646,11 @@ declaration:
$item{declaration_specifiers} = join(' ', split(' ', $item{declaration_specifiers})); $item{declaration_specifiers} = join(' ', split(' ', $item{declaration_specifiers}));
if ($noreturn) { if ($noreturn) {
$item{declaration_specifiers} = "which doesn't return to its caller"; if($item{declaration_specifiers} eq 'void') {
$item{declaration_specifiers} = "which doesn't return to its caller";
} else {
$item{declaration_specifiers} = "which shouldn't return to its caller yet does mysteriously return $item{declaration_specifiers}";
}
} }
my $inits = 0; my $inits = 0;
@ -637,9 +658,9 @@ declaration:
$inits++; $inits++;
if (not $arg{context} eq 'struct member') { if (not $arg{context} eq 'struct member') {
if ($arg{context} eq 'for init') { if ($arg{context} eq 'for init') {
$return .= "letting "; $return .= "declaring ";
} else { } else {
$return .= "Let "; $return .= "Declare ";
} }
} }
@ -753,10 +774,10 @@ declaration:
if ($typedef) { if ($typedef) {
$return .= ' each' if @identifiers > 1; $return .= ' each' if @identifiers > 1;
$return .= ' be another name for '; $return .= ' as another name for ';
push @typedefs, @identifiers; push @typedefs, @identifiers;
} else { } else {
$return .= ' be '; $return .= ' as ';
} }
if ($first_qualifier) { if ($first_qualifier) {