3
0
mirror of https://github.com/pragma-/pbot.git synced 2024-10-07 03:49:04 +02:00

CGrammar: Significantly improve indentation; minor textual improvements

This commit is contained in:
Pragmatic Software 2014-06-08 06:34:55 +00:00
parent 8e818baa52
commit ca91e34a25
2 changed files with 1170 additions and 1071 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 => 618, BUILD_REVISION => 619,
BUILD_DATE => "2014-06-07", BUILD_DATE => "2014-06-07",
}; };

View File

@ -1,3 +1,5 @@
# C-to-English Grammar
#
# Warning: work-in-progress. Many things are incomplete or non-functional. # Warning: work-in-progress. Many things are incomplete or non-functional.
# #
# todo: # todo:
@ -12,10 +14,11 @@
{ {
my @defined_types = ('FILE'); my @defined_types = ('FILE');
my ($basic, $add_on, @basics, $rule_context, $rule_name, $nonsyntactic, @macros, $array_size); my ($basic, $add_on, @basics, $rule_context, $rule_name, @macros, $array_size);
} }
startrule : translation_unit startrule:
translation_unit
{ {
my $output = $item[-1]; my $output = $item[-1];
$output =~ s/\^L(\s*.)/\L$1/g; # lowercase specified characters $output =~ s/\^L(\s*.)/\L$1/g; # lowercase specified characters
@ -24,13 +27,15 @@ startrule : translation_unit
} }
startrule(?) startrule(?)
translation_unit : (comment translation_unit:
(comment
| external_declaration | external_declaration
| function_definition | function_definition
| function_prototype | function_prototype
| preproc[matchrule => 'translation_unit']) | preproc[matchrule => 'translation_unit'])
preproc : <skip: '[ \t]*'> definition preproc:
<skip: '[ \t]*'> definition
| undefinition | undefinition
| <skip: '[ \t]*'> inclusion | <skip: '[ \t]*'> inclusion
| line | line
@ -41,7 +46,8 @@ preproc : <skip: '[ \t]*'> definition
| '#' /^.*\n/ | '#' /^.*\n/
{ print STDERR "Unknown CPP directive $item[-1]\n"; $return = ""; } { print STDERR "Unknown CPP directive $item[-1]\n"; $return = ""; }
definition : <skip: '[ \t]*'> /\n*/ macro_definition definition:
<skip: '[ \t]*'> /\n*/ macro_definition
| <skip: '[ \t]*'> /\s*?\n*#/ 'define' identifier token_sequence(?) .../\s*?\n/ | <skip: '[ \t]*'> /\s*?\n*#/ 'define' identifier token_sequence(?) .../\s*?\n/
{ {
my $token_sequence = join('',@{$item{'token_sequence(?)'}}); my $token_sequence = join('',@{$item{'token_sequence(?)'}});
@ -50,7 +56,8 @@ definition : <skip: '[ \t]*'> /\n*/ macro_definition
$return .= ".\n"; $return .= ".\n";
} }
macro_definition : '#' 'define' identifier '(' <leftop: identifier ',' identifier > ')' token_sequence "\n" macro_definition:
'#' 'define' identifier '(' <leftop: identifier ',' identifier > ')' token_sequence "\n"
{ {
my @symbols = @{$item[-4]}; my @symbols = @{$item[-4]};
my $last; my $last;
@ -67,32 +74,41 @@ macro_definition : '#' 'define' identifier '(' <leftop: identifier ',' identifie
$return .= "to use the token sequence \'$item{token_sequence}\'.\n"; $return .= "to use the token sequence \'$item{token_sequence}\'.\n";
} }
undefinition : <skip: '[ \t]*'> ("\n")(s?) '#' 'undef' identifier undefinition:
<skip: '[ \t]*'> ("\n")(s?) '#' 'undef' identifier
{ $return = "\nAnnul the definition of $item{identifier}.\n"; } { $return = "\nAnnul the definition of $item{identifier}.\n"; }
inclusion : <skip: '[ \t]*'> /\s*?\n*#/ 'include' '<' filename '>' .../\s*?\n/ inclusion:
{ $return = "\nInclude the contents of the system file $item{filename}.\n"; } <skip: '[ \t]*'> /\s*?\n*#/ 'include' '<' filename '>' .../\s*?\n/
{ $return = "\nInclude system file $item{filename}.\n"; }
| <skip: '[ \t]*'> /\s*?\n*#/ 'include' '"' filename '"' .../\s*?\n/ | <skip: '[ \t]*'> /\s*?\n*#/ 'include' '"' filename '"' .../\s*?\n/
{ $return = "\nInclude the contents of the user file $item{filename}.\n"; } { $return = "\nInclude user file $item{filename}.\n"; }
| <skip: '[ \t]*'> /\s*?\n*#/ 'include' token | <skip: '[ \t]*'> /\s*?\n*#/ 'include' token
{ $return = "\nImport code noted by the token $item{token}.\n"; } { $return = "\nImport code noted by the token $item{token}.\n"; }
filename : /[_\.\-\w\/]+/ filename:
/[_\.\-\w\/]+/
line : '#' 'line' constant ('"' filename '"' { $return = "and filename $item{filename}"; } )(?) /\n+/ line:
{ $return = "\nNote: for debugging, this is line number $item{constant}" . join('', @{$item[-1]}) . ".\n"; } '#' 'line' constant ('"' filename '"'
{ $return = "and filename $item{filename}"; }
)(?) /\n+/
{ $return = "\nThis is line number $item{constant}" . join('', @{$item[-1]}) . ".\n"; }
error : '#' 'error' token_sequence(?) error:
{ $return = "\nNote: compilation should stop here.\n" . "The message is \"" . join('', @{$item{'token_sequence(?)'}}) . "\".\n"; } '#' 'error' token_sequence(?)
{ $return = "Stop compilation with error \"" . join('', @{$item{'token_sequence(?)'}}) . "\".\n"; }
pragma : '#' 'pragma' token_sequence(?) pragma:
'#' 'pragma' token_sequence(?)
{ {
my $pragma = join('',@{$item[-1]}); my $pragma = join('',@{$item[-1]});
if ($pragma) { $pragma = ' "' . $pragma . '"'; } if ($pragma) { $pragma = ' "' . $pragma . '"'; }
$return = "\nNote: a compiler-dependent pragma$pragma is added here.\n"; $return = "\nNote: a compiler-dependent pragma$pragma is added here.\n";
} }
preproc_conditional : <skip: '[ \t]*'> /\n*/ if_line[matchrule => $arg{matchrule}] preproc_conditional:
<skip: '[ \t]*'> /\n*/ if_line[matchrule => $arg{matchrule}]
{ $rule_name = $arg{matchrule}; } { $rule_name = $arg{matchrule}; }
<matchrule: $rule_name>(s?) <matchrule: $rule_name>(s?)
{ $return = $item{if_line} . join('',@{$item[-1]}); } { $return = $item{if_line} . join('',@{$item[-1]}); }
@ -102,7 +118,8 @@ preproc_conditional : <skip: '[ \t]*'> /\n*/ if_line[matchrule => $arg{matchrule
/\n*/ '#' 'endif' /\n*/ '#' 'endif'
{ $return .= "\nNote: This ends a conditional inclusion section.\n"; } { $return .= "\nNote: This ends a conditional inclusion section.\n"; }
if_line : <skip: '[ \t]*'> '#' 'ifdef' identifier .../\n+/ if_line:
<skip: '[ \t]*'> '#' 'ifdef' identifier .../\n+/
{ {
$return = "\nNote: The current context is interrupted.\n"; $return = "\nNote: The current context is interrupted.\n";
$return .= "The next section is used only if $item{identifier} is defined.\n"; $return .= "The next section is used only if $item{identifier} is defined.\n";
@ -119,7 +136,8 @@ if_line : <skip: '[ \t]*'> '#' 'ifdef' identifier .../\n+/
$return .= "\"$item{constant_expression}\".\n"; $return .= "\"$item{constant_expression}\".\n";
} }
elif_parts : ('#' 'elif' constant_expression elif_parts:
('#' 'elif' constant_expression
{ {
$return = "\nNote: we interrupt the current context again.\n"; $return = "\nNote: we interrupt the current context again.\n";
$return .= "Instead of the previous precondition, we include "; $return .= "Instead of the previous precondition, we include ";
@ -130,24 +148,31 @@ elif_parts : ('#' 'elif' constant_expression
{ $return .= join('',@{$item[-1]}); } { $return .= join('',@{$item[-1]}); }
)(s) )(s)
else_parts : (/\n+/)(?) '#' 'else' { $rule_name = $arg{matchrule}; } (<matchrule: $rule_name>)[matchrule => $arg{matchrule}](s?) else_parts:
(/\n+/)(?) '#' 'else'
{ $rule_name = $arg{matchrule}; }
(<matchrule: $rule_name>)[matchrule => $arg{matchrule}](s?)
{ {
$return = "\nNote: we interrupt the current context once more.\n" . "The following section gets included if the previous precondition fails.\n"; $return = "\nNote: we interrupt the current context once more.\n" . "The following section gets included if the previous precondition fails.\n";
$return .= join('',@{$item[-1]}); $return .= join('',@{$item[-1]});
} }
token_sequence : token(s) token_sequence:
token(s)
{ $return = join(' ', @{$item[1]}); } { $return = join(' ', @{$item[1]}); }
token : <skip: '[ \t]*'> /\S+/ token:
<skip: '[ \t]*'> /\S+/
{ {
$return = $item[-1]; $return = $item[-1];
$return =~ s/"/\\"/; # escaping all quotes. $return =~ s/"/\\"/; # escaping all quotes.
} }
external_declaration : declaration external_declaration:
declaration
function_definition : <skip: '\s*'> declaration_specifiers(?) declarator[context => 'function_definition'] function_definition:
<skip: '\s*'> declaration_specifiers(?) declarator[context => 'function_definition']
'(' parameter_type_list(?) ')' '{' declaration_list(?) statement_list(?) '}' '(' parameter_type_list(?) ')' '{' declaration_list(?) statement_list(?) '}'
{ {
my $declaration_specifiers = join('', @{$item{'declaration_specifiers(?)'}}); my $declaration_specifiers = join('', @{$item{'declaration_specifiers(?)'}});
@ -186,9 +211,11 @@ function_definition : <skip: '\s*'> declaration_specifiers(?) declarator[context
# $return .= "End of function $name.\n"; # $return .= "End of function $name.\n";
# $return .= $item{compound_statement}; # $return .= $item{compound_statement};
1;
} }
function_prototype : declaration_specifiers(?) declarator[context => 'function_prototype'] function_prototype:
declaration_specifiers(?) declarator[context => 'function_prototype']
'(' parameter_type_list(?) ')' ';' '(' parameter_type_list(?) ')' ';'
{ {
my $declaration_specifiers = join('', @{$item{'declaration_specifiers(?)'}}); my $declaration_specifiers = join('', @{$item{'declaration_specifiers(?)'}});
@ -216,7 +243,8 @@ function_prototype : declaration_specifiers(?) declarator[context => 'function_p
$return .= " and returning $return_type.\n"; $return .= " and returning $return_type.\n";
} }
compound_statement : '{' declaration_list(?) statement_list(?) '}' compound_statement:
'{' declaration_list(?) statement_list(?) '}'
{ {
my $declaration_list = join('',@{$item{'declaration_list(?)'}}); my $declaration_list = join('',@{$item{'declaration_list(?)'}});
my $statement_list = join('',@{$item{'statement_list(?)'}}); my $statement_list = join('',@{$item{'statement_list(?)'}});
@ -241,7 +269,8 @@ compound_statement : '{' declaration_list(?) statement_list(?) '}'
1; 1;
} }
statement_list : comment(?) preproc[matchrule => 'statement'](?) statement statement_list:
comment(?) preproc[matchrule => 'statement'](?) statement
{ {
my $preproc = join('',@{$item{'preproc(?)'}}); my $preproc = join('',@{$item{'preproc(?)'}});
my $comment = join('',@{$item{'comment(?)'}}); my $comment = join('',@{$item{'comment(?)'}});
@ -254,7 +283,8 @@ statement_list : comment(?) preproc[matchrule => 'statement'](?) statement
statement_list(?) statement_list(?)
{ $return .= join('',@{$item{'statement_list(?)'}}); } { $return .= join('',@{$item{'statement_list(?)'}}); }
statement : jump_statement statement:
jump_statement
{ $return = $item{jump_statement}; } { $return = $item{jump_statement}; }
| compound_statement[context => $arg{context}, name => $arg{context} ] | compound_statement[context => $arg{context}, name => $arg{context} ]
| iteration_statement | iteration_statement
@ -262,7 +292,8 @@ statement : jump_statement
| labeled_statement | labeled_statement
| expression_statement | expression_statement
iteration_statement : 'for' '(' <commit> for_initialization(?) ';' for_expression(?) ';' for_increment(?) ')' iteration_statement:
'for' '(' <commit> for_initialization(?) ';' for_expression(?) ';' for_increment(?) ')'
statement[context => 'for loop'] statement[context => 'for loop']
{ {
my $initialization = join('', @{$item{'for_initialization(?)'}}); my $initialization = join('', @{$item{'for_initialization(?)'}});
@ -301,16 +332,28 @@ iteration_statement : 'for' '(' <commit> for_initialization(?) ';' for_expressio
| 'do' statement[context => 'do loop'] 'while' '(' expression ')' ';' | 'do' statement[context => 'do loop'] 'while' '(' expression ')' ';'
{ $return = "Do the following:\n$item{statement}\nDo this as long as '$item{expression}' evaluates to a positive number.\n"; } { $return = "Do the following:\n$item{statement}\nDo this as long as '$item{expression}' evaluates to a positive number.\n"; }
selection_statement : 'if' <commit> '(' expression[context => 'if block'] ')' statement[context => 'if block'] for_initialization:
expression[context => 'statement']
for_expression:
expression[context => 'for_expression']
for_increment:
expression[context => 'statement']
selection_statement:
'if' <commit> '(' expression[context => 'if block'] ')' statement[context => 'if block']
{ $return = "If $item{expression}, then ^L$item{statement}"; } { $return = "If $item{expression}, then ^L$item{statement}"; }
('else' statement[context => 'else block'] ('else' statement[context => 'else block']
{ $return = "Otherwise, ^L$item{statement}"; })(?) { $return = "Otherwise, ^L$item{statement}"; }
)(?)
{ $return .= join('',@{$item[-1]}); } { $return .= join('',@{$item[-1]}); }
| 'switch' '(' expression ')' statement[context => 'switch'] | 'switch' '(' expression ')' statement[context => 'switch']
{ $return = "This section is controlled by a switch based on the expression \'$item{expression}\':\n$item{statement}"; } { $return = "This section is controlled by a switch based on the expression \'$item{expression}\':\n$item{statement}"; }
jump_statement : <skip:'\s*'> 'break' ';' jump_statement:
<skip:'\s*'> 'break' ';'
{ $return = "Break from the current block.\n"; } { $return = "Break from the current block.\n"; }
| 'continue' ';' | 'continue' ';'
{ $return = "Return to the top of the current loop and continue it.\n"; } { $return = "Return to the top of the current loop and continue it.\n"; }
@ -332,7 +375,8 @@ jump_statement : <skip:'\s*'> 'break' ';'
} }
} }
expression_statement : expression[context => 'statement'](?) ';' expression_statement:
expression[context => 'statement'](?) ';'
{ {
my $item_expression = join('',@{$item[1]}); my $item_expression = join('',@{$item[1]});
if (!$item_expression) { if (!$item_expression) {
@ -342,23 +386,22 @@ expression_statement : expression[context => 'statement'](?) ';'
} }
} }
labeled_statement : identifier ':' statement labeled_statement:
identifier ':' statement
{ $return = "The following statement is preceded by the label $item{identifier}.\n$item{statement}"; } { $return = "The following statement is preceded by the label $item{identifier}.\n$item{statement}"; }
| 'case' constant_expression ':' statement[context => 'case'] | 'case' constant_expression ':' statement[context => 'case']
{ $return = "In the case it has the value $item{constant_expression}, do this:\n$item{statement}"; } { $return = "In the case it has the value $item{constant_expression}, do this:\n$item{statement}"; }
| 'default' ':' statement | 'default' ':' statement
{ $return = "In the default case, do this:\n$item{statement}"; } { $return = "In the default case, do this:\n$item{statement}"; }
for_initialization : expression[context => 'statement'] expression:
for_expression : expression[context => 'for_expression'] <leftop: assignment_expression[context => $arg{context}] ',' assignment_expression[context => $arg{context}]>
for_increment : expression[context => 'statement']
expression : <leftop: assignment_expression[context => $arg{context}] ',' assignment_expression[context => $arg{context}]>
{ {
$return = join(". We're not done yet. ",@{$item[-1]}); $return = join(". We're not done yet. ",@{$item[-1]});
} }
assignment_expression : unary_expression[context => 'assignment_expression'] assignment_expression:
unary_expression[context => 'assignment_expression']
assignment_operator[context => $arg{context}] assignment_operator[context => $arg{context}]
assignment_expression[context => 'assignment_expression'] assignment_expression[context => 'assignment_expression']
{ {
@ -370,22 +413,21 @@ assignment_expression : unary_expression[context => 'assignment_expression']
} else { } else {
$return = "$item{unary_expression}, $assignment_operator $assignment_expression"; $return = "$item{unary_expression}, $assignment_operator $assignment_expression";
} }
$nonsyntactic = '';
} }
| conditional_expression[context => $arg{context}] | conditional_expression[context => $arg{context}]
conditional_expression : logical_OR_AND_expression[context => $arg{context}] conditional_expression:
logical_OR_AND_expression[context => $arg{context}]
| logical_OR_AND_expression[context => $arg{context}] | logical_OR_AND_expression[context => $arg{context}]
'?' expression[context => 'conditional_expression1'] '?' expression[context => 'conditional_expression1']
':' conditional_expression[context => 'conditional_expression2'] ':' conditional_expression[context => 'conditional_expression2']
{ {
print "foo2\n";
$return = "the choice dependent on the value of $item{logical_OR_expression}" . $return = "the choice dependent on the value of $item{logical_OR_expression}" .
" comprising of $item{expression} or $item{conditional_expression}"; " comprising of $item{expression} or $item{conditional_expression}";
} }
assignment_operator : '=' assignment_operator:
'='
{ {
if ($arg{context} eq 'statement') { if ($arg{context} eq 'statement') {
$return = ['Assign to', ' the value' ] ; $return = ['Assign to', ' the value' ] ;
@ -474,9 +516,11 @@ assignment_operator : '='
} }
} }
constant_expression : conditional_expression constant_expression:
conditional_expression
logical_OR_AND_expression : <leftop: logical_OR_AND_expression:
<leftop:
rel_add_mul_shift_expression[context => $arg{context}] rel_add_mul_shift_expression[context => $arg{context}]
log_OR_AND_bit_or_and_eq log_OR_AND_bit_or_and_eq
rel_add_mul_shift_expression[context => 'logical_OR_AND_expression'] > rel_add_mul_shift_expression[context => 'logical_OR_AND_expression'] >
@ -486,7 +530,8 @@ logical_OR_AND_expression : <leftop:
$return = join ('' , @ands); $return = join ('' , @ands);
} }
log_OR_AND_bit_or_and_eq : '||' { $return = ' logically orred by '; } log_OR_AND_bit_or_and_eq:
'||' { $return = ' logically orred by '; }
| '&&' { $return = ' logically anded by '; } | '&&' { $return = ' logically anded by '; }
| '|' { $return = ' bitwise orred by '; } | '|' { $return = ' bitwise orred by '; }
| '&' { $return = ' bitwise anded by '; } | '&' { $return = ' bitwise anded by '; }
@ -494,7 +539,8 @@ log_OR_AND_bit_or_and_eq : '||' { $return = ' logically orred by '; }
| '==' { $return = ' is equal to ' ; } | '==' { $return = ' is equal to ' ; }
| '!=' { $return = ' is not equal to ' ; } | '!=' { $return = ' is not equal to ' ; }
rel_mul_add_ex_op : '+' { $return = ' plus '; } rel_mul_add_ex_op:
'+' { $return = ' plus '; }
| '-' { $return = ' minus '; } | '-' { $return = ' minus '; }
| '*' { $return = ' times '; } | '*' { $return = ' times '; }
| '/' { $return = ' divided by '; } | '/' { $return = ' divided by '; }
@ -506,9 +552,21 @@ rel_mul_add_ex_op : '+' { $return = ' plus '; }
| '>' { $return = ' is greater than '; } | '>' { $return = ' is greater than '; }
| '<' { $return = ' is less than '; } | '<' { $return = ' is less than '; }
rel_add_mul_shift_expression : cast_expression[context => $arg{context}] ...';' unary_operator:
'&' { $return = 'the address of '; }
| '*' { $return = 'the contents of '; }
| '+' { $return = 'the value of '; }
| '-' ...constant { $return = 'negative '; }
| '-' { $return = 'minus '; }
| '~' { $return = "the one's complement of "; }
| '!' { $return = 'the logical negation of '; }
rel_add_mul_shift_expression:
cast_expression[context => $arg{context}] ...';'
{ $return = $item{cast_expression}; } { $return = $item{cast_expression}; }
| <leftop: cast_expression[context => $arg{context}] | <leftop:
cast_expression[context => $arg{context}]
rel_mul_add_ex_op rel_mul_add_ex_op
cast_expression[context => 'add_mul_shift_expression'] > cast_expression[context => 'add_mul_shift_expression'] >
{ {
@ -516,30 +574,34 @@ rel_add_mul_shift_expression : cast_expression[context => $arg{context}] ...';'
$return = join ('' , @ands); $return = join ('' , @ands);
} }
cast_expression : '(' type_name ')' cast_expression[context => 'recast'] closure:
',' | ';' | ')'
cast_expression:
'(' type_name ')' cast_expression[context => 'recast']
{ $return = "a casting into the type \'$item{type_name}\' of $item{cast_expression}"; } { $return = "a casting into the type \'$item{type_name}\' of $item{cast_expression}"; }
| unary_expression[context => $arg{context}] | unary_expression[context => $arg{context}]
{ $return = $item{unary_expression}; } { $return = $item{unary_expression}; }
#( ...closure )(?) #( ...closure )(?)
# { # {
# if ($arg{context} eq 'statement' #&& !($return =~ /^Perform/) # if ($arg{context} eq 'statement' #&& !($return =~ /^Perform/)
# ) { # )
# {
# if (${$item[-1]}[0]) { # if (${$item[-1]}[0]) {
# $return .= ".\n"; # $return .= ".\n";
# } # }
# } # }
#} #}
closure : ',' | ';' | ')' declaration_list:
# <skip: '\s*'>
declaration_list : # <skip: '\s*'>
declaration(s) declaration(s)
{ { $return = join('', @{$item{'declaration(s)'}}); }
$return = join('', @{$item{'declaration(s)'}});
}
declaration : declaration_specifiers init_declarator_list(?) ';' declaration:
declaration_specifiers init_declarator_list(?) ';'
{ {
# This whole thing needs to be re-written to parse declarations inside-out.
my @init_list = @{$item{'init_declarator_list(?)'}->[0]}; my @init_list = @{$item{'init_declarator_list(?)'}->[0]};
my $init_declaration_list; my $init_declaration_list;
@ -601,9 +663,11 @@ declaration : declaration_specifiers init_declarator_list(?) ';'
$return .= $item{'comment(?)'}; $return .= $item{'comment(?)'};
} }
init_declarator_list : <leftop: init_declarator ',' init_declarator> init_declarator_list:
<leftop: init_declarator ',' init_declarator>
init_declarator : declarator[context => 'init_declarator'] init_declarator:
declarator[context => 'init_declarator']
{ {
$return = $item{declarator}; $return = $item{declarator};
} }
@ -621,7 +685,8 @@ init_declarator : declarator[context => 'init_declarator']
$return .= $item{declarator}; $return .= $item{declarator};
} }
initializer : comment(?) assignment_expression comment(?) initializer:
comment(?) assignment_expression comment(?)
{ {
$return = $item[2]; $return = $item[2];
@ -636,7 +701,8 @@ initializer : comment(?) assignment_expression comment(?)
| '{' comment(?) initializer_list (',' )(?) '}' | '{' comment(?) initializer_list (',' )(?) '}'
{ $return = 'the set ' . join('', @{$item{'initializer_list(?)'}}); } { $return = 'the set ' . join('', @{$item{'initializer_list(?)'}}); }
initializer_list : <leftop: initializer ',' initializer > initializer_list:
<leftop: initializer ',' initializer >
{ {
my @inits = @{$item[1]}; my @inits = @{$item[1]};
@ -650,40 +716,34 @@ initializer_list : <leftop: initializer ',' initializer >
} }
} }
unary_expression : postfix_expression[context => $arg{context}] unary_expression:
postfix_expression[context => $arg{context}]
{ $return = $item{postfix_expression}; } { $return = $item{postfix_expression}; }
| '++' unary_expression | '++' unary_expression
{ {
if ($arg{context} eq 'statement' ) { if ($arg{context} eq 'statement' ) {
$return = "Uptick $item{unary_expression}"; $return = "pre-increment $item{unary_expression}";
} else { } else {
$return = "the now upticked $item{unary_expression}"; $return = "the pre-incremented $item{unary_expression}";
} }
} }
| '--' unary_expression | '--' unary_expression
{ {
if ($arg{context} eq 'statement' ) { if ($arg{context} eq 'statement' ) {
$return = "Downtick $item{unary_expression}"; $return = "Pre-decrement $item{unary_expression}";
} else { } else {
$return = "the now downticked $item{unary_expression}"; $return = "the pre-decremented $item{unary_expression}";
} }
} }
| unary_operator cast_expression[context => $arg{context}] | unary_operator cast_expression[context => $arg{context}]
{ $return = $item{unary_operator} . $item{cast_expression}; } { $return = $item{unary_operator} . $item{cast_expression}; }
|'sizeof' unary_expression |'sizeof' unary_expression
{ $return = "the memory size of $item{unary_expression}"; } { $return = "the size of $item{unary_expression}"; }
|'sizeof' '(' type_name ')' |'sizeof' '(' type_name ')'
{ $return = "the memory size of the datatype $item{type_name}"; } { $return = "the size of the datatype $item{type_name}"; }
unary_operator : '&' { $return = 'the memory location of '; } postfix_expression:
| '*' { $return = 'the memory contents of '; } primary_expression[context => $arg{context}]
| '+' { $return = 'the value of '; }
| '-' ...constant {$return = 'negative '; }
| '-' { $return = 'minus '; }
| '~' { $return = "the one's complement of "; }
| '!' { $return = 'the logical negation of '; }
postfix_expression : primary_expression[context => $arg{context}]
{ {
# must be global. use stack to prevent disasters. # must be global. use stack to prevent disasters.
# Todo: this is just a Bad Idea, TM. $return needs to be turned to an hash with the # Todo: this is just a Bad Idea, TM. $return needs to be turned to an hash with the
@ -698,7 +758,6 @@ postfix_expression : primary_expression[context => $arg{context}]
( # function call ( # function call
'(' argument_expression_list(?) ')' '(' argument_expression_list(?) ')'
{ {
# we're in an un-named sub rule. This is where things get hard.
my $arg_exp_list = join('',@{$item{'argument_expression_list(?)'}}); my $arg_exp_list = join('',@{$item{'argument_expression_list(?)'}});
if ($arg_exp_list) { if ($arg_exp_list) {
$return = " with argument$arg_exp_list"; $return = " with argument$arg_exp_list";
@ -713,6 +772,7 @@ postfix_expression : primary_expression[context => $arg{context}]
if ($arg{context} eq 'statement') { if ($arg{context} eq 'statement') {
$return = "Perform "; $return = "Perform ";
} }
# is this function call involving a pointer to a function? # is this function call involving a pointer to a function?
if ($basic =~ /parenthetical/) { if ($basic =~ /parenthetical/) {
$return .= "the function pointed by $basic"; $return .= "the function pointed by $basic";
@ -722,7 +782,6 @@ postfix_expression : primary_expression[context => $arg{context}]
} }
# To discriminate between macros and functions. # To discriminate between macros and functions.
foreach (@macros) { foreach (@macros) {
if ($basic eq "'$_'") { if ($basic eq "'$_'") {
$return =~ s/Call/Insert/; $return =~ s/Call/Insert/;
@ -819,13 +878,15 @@ postfix_expression : primary_expression[context => $arg{context}]
$return = $item{primary_expression} . "'s " . join('',@{$item{'postfix_suffix(s)'}}); $return = $item{primary_expression} . "'s " . join('',@{$item{'postfix_suffix(s)'}});
} }
postfix_suffix : ('[' expression ']')(s) postfix_suffix:
('[' expression ']')(s)
| '.' identifier | '.' identifier
| '->' identifier | '->' identifier
| '++' | '++'
| '--' | '--'
argument_expression_list : <leftop: assignment_expression ',' assignment_expression > argument_expression_list:
<leftop: assignment_expression ',' assignment_expression >
{ {
my @arg_exp_list = @{$item[1]}; my @arg_exp_list = @{$item[1]};
my $last = ''; my $last = '';
@ -839,13 +900,16 @@ argument_expression_list : <leftop: assignment_expression ',' assignment_express
} }
} }
narrow_closure : ';' | ',' | '->' narrow_closure:
';' | ',' | '->'
primary_expression : '(' expression ')' (...narrow_closure)(?) primary_expression:
'(' expression ')' (...narrow_closure)(?)
{ {
my $expression = $item{expression} ; my $expression = $item{expression} ;
my $repeats = 1; my $repeats = 1;
my $ending = 1; my $ending = 1;
if ($expression =~ /^the (\d+)-layered parenthetical expression/) { if ($expression =~ /^the (\d+)-layered parenthetical expression/) {
$repeats = $1 + 1; $repeats = $1 + 1;
$expression =~ s/^the \d+-layered parenthetical expression //; $expression =~ s/^the \d+-layered parenthetical expression //;
@ -875,45 +939,17 @@ primary_expression : '(' expression ')' (...narrow_closure)(?)
| constant | constant
| string | string
| identifier | identifier
{ # todo: is this where the quotation marks belong? {
$return = "'$item{identifier}'"; $return = "`$item{identifier}`";
} }
string : m{".*?[^\"]"} declarator:
direct_declarator
constant : /-?[0-9]*\.[0-9]+f?/
{
if ($item[1] =~ /\D/) {
$return = "the floating point number $item[1]";
} else {
$return = $item[1];
}
}
| /0x[0-9a-fA-F]+/ ('L')(?)
{
if ($item[-1]) {
$return = 'the long ' ."hexadecimal number $item[1]";
} else {
$return = 'the ' . "hexadecimal number $item[1]";
}
}
| /0\d+/
{ $return = "the octal number $item[1]"; }
|/-?[0-9]+[lu]?/i # integer constant
{
$return = $item[-1];
$return =~ s/[Uu]$/(unsigned)/;
$return =~ s/[Ll]$/(long)/;
}
| m{'.*?[^\']'} # character constant
# | enumeration_constant
# needs more.
declarator : direct_declarator
| pointer direct_declarator | pointer direct_declarator
{ $return = "$item{pointer} $item{direct_declarator}"; } { $return = "$item{pointer} $item{direct_declarator}"; }
direct_declarator : identifier[context => 'direct_declarator'] array_declarator(s?) direct_declarator:
identifier[context => 'direct_declarator'] array_declarator(s?)
{ {
if(@{$item{'array_declarator(s?)'}}) { if(@{$item{'array_declarator(s?)'}}) {
$return = join('', @{$item{'array_declarator(s?)'}}) . "'$item{identifier}'"; $return = join('', @{$item{'array_declarator(s?)'}}) . "'$item{identifier}'";
@ -938,7 +974,8 @@ direct_declarator : identifier[context => 'direct_declarator'] array_declarator(
| '(' declarator ')' | '(' declarator ')'
{ $return = $item{declarator}; } { $return = $item{declarator}; }
array_declarator: ( '[' assignment_expression(?) ']' array_declarator:
( '[' assignment_expression(?) ']'
{ {
if (@{$item{'assignment_expression(?)'}}) { if (@{$item{'assignment_expression(?)'}}) {
$array_size = 'size '. join('',@{$item{'assignment_expression(?)'}}) . ' '; $array_size = 'size '. join('',@{$item{'assignment_expression(?)'}}) . ' ';
@ -956,7 +993,8 @@ array_declarator: ( '[' assignment_expression(?) ']'
} }
} }
identifier_list : (identifier ',')(s?) identifier identifier_list:
(identifier ',')(s?) identifier
{ {
my @identifier_list = @{$item[1]}; my @identifier_list = @{$item[1]};
if ($#identifier_list > 1) { if ($#identifier_list > 1) {
@ -968,10 +1006,13 @@ identifier_list : (identifier ',')(s?) identifier
} }
} }
parameter_type_list : <skip: '[ \t]*'> parameter_list | parameter_list ',' '...' parameter_type_list:
<skip: '[ \t]*'> parameter_list
| parameter_list ',' '...' # FIXME: never reached
{ $return = $item{parameter_list} . ', and possibly other arguments'; } { $return = $item{parameter_list} . ', and possibly other arguments'; }
parameter_list : <leftop: parameter_declaration ',' parameter_declaration > parameter_list:
<leftop: parameter_declaration ',' parameter_declaration>
{ {
my @parameter_list = @{$item[1]}; my @parameter_list = @{$item[1]};
if ($#parameter_list > 1) { if ($#parameter_list > 1) {
@ -993,7 +1034,8 @@ parameter_list : <leftop: parameter_declaration ',' parameter_declaration >
} }
} }
parameter_declaration : declaration_specifiers declarator parameter_declaration:
declaration_specifiers declarator
{ $return = $item{declaration_specifiers} . ' ' . $item{declarator}; } { $return = $item{declaration_specifiers} . ' ' . $item{declarator}; }
| /,?\.\.\./ | /,?\.\.\./
{ $return = "variadic parameters"; } { $return = "variadic parameters"; }
@ -1001,13 +1043,13 @@ parameter_declaration : declaration_specifiers declarator
| '' | ''
{ $return = "unspecified parameters"; } { $return = "unspecified parameters"; }
abstract_declarator : pointer abstract_declarator:
pointer
| pointer(?) direct_abstract_declarator | pointer(?) direct_abstract_declarator
{ $return = join('',@{$item{'pointer(?)'}}) . $item{direct_abstract_declarator}; } { $return = join('',@{$item{'pointer(?)'}}) . $item{direct_abstract_declarator}; }
# This is going to require some work handling correctly. direct_abstract_declarator:
'(' abstract_declarator ')'
direct_abstract_declarator : '(' abstract_declarator ')'
| '[' ']' | '[' ']'
| '[' constant_expression ']' | '[' constant_expression ']'
| DAD '[' ']' | DAD '[' ']'
@ -1024,10 +1066,12 @@ DAD : #macro for direct_abstract_declarator
( '(' ')' )(s?) ( '(' ')' )(s?)
( '(' parameter_type_list ')' )(s?) ( '(' parameter_type_list ')' )(s?)
identifier : ...!reserved identifier_word identifier:
...!reserved identifier_word
{ $return = $item{identifier_word}; } { $return = $item{identifier_word}; }
pointer : '*' type_qualifier_list(s) pointer(?) pointer:
'*' type_qualifier_list(s) pointer(?)
{ {
$return = 'a pointer to a ' . join('', @{$item{'type_qualifier_list(s)'}}); $return = 'a pointer to a ' . join('', @{$item{'type_qualifier_list(s)'}});
$return .= ' ' . join('', @{$item{'pointer(?)'}}) if @{$item{'pointer(?)'}}; $return .= ' ' . join('', @{$item{'pointer(?)'}}) if @{$item{'pointer(?)'}};
@ -1043,13 +1087,13 @@ pointer : '*' type_qualifier_list(s) pointer(?)
$return .= 'pointer to'; $return .= 'pointer to';
} }
integer_constant : /[0-9]+/ type_qualifier_list:
type_qualifier(s)
type_qualifier_list : type_qualifier(s)
{ $return = join(' ', @{$item{'type_qualifier(s)'}}); } { $return = join(' ', @{$item{'type_qualifier(s)'}}); }
declaration_specifiers : comment(?) type_specifier ...identifier declaration_specifiers:
comment(?) type_specifier ...identifier
{ $return = join('', @{$item{'comment(?)'}}) . $item{type_specifier}; } { $return = join('', @{$item{'comment(?)'}}) . $item{type_specifier}; }
| comment(?) storage_class_specifier declaration_specifiers(?) | comment(?) storage_class_specifier declaration_specifiers(?)
{ {
@ -1068,27 +1112,30 @@ declaration_specifiers : comment(?) type_specifier ...identifier
my $decl_spec = $return = join('',@{$item{'comment(?)'}}) . $item{type_qualifier} . ' ' . join(' ',@{$item{'declaration_specifiers(?)'}}); my $decl_spec = $return = join('',@{$item{'comment(?)'}}) . $item{type_qualifier} . ' ' . join(' ',@{$item{'declaration_specifiers(?)'}});
} }
storage_class_specifier : auto | 'extern' storage_class_specifier:
'auto'
{ $return = "(auto)"; }
| 'extern'
{ $return = "(declared elsewhere)"; } { $return = "(declared elsewhere)"; }
| 'static' | 'static'
{ $return = "(this declaration is not to be shared)"; } { $return = "(this declaration is not to be shared)"; }
| register | 'typedef' | 'register'
{ $return = "(suggestion to be as fast as possible)"; }
| 'typedef'
{ $return = 'type definition of'; } { $return = 'type definition of'; }
type_qualifier : const | 'volatile' type_qualifier:
'const'
const : 'const'
{ $return = "constant"; } { $return = "constant"; }
| 'volatile'
type_specifier : 'double' type_specifier:
{ $return = 'double'; } 'double'
| short | 'short'
| long | 'long'
| 'char' | 'char'
{ $return = 'char'; }
| 'int' | 'int'
{ $return = 'int'; } | 'float'
| float
| 'void' | 'void'
| 'signed' | 'signed'
| 'unsigned' | 'unsigned'
@ -1096,13 +1143,8 @@ type_specifier : 'double'
| enum_specifier | enum_specifier
| typedef_name | typedef_name
short : 'short' { $return = 'short'; } typedef_name:
long : 'long' { $return = 'long'; } identifier
auto : 'auto' { $return = "(auto)"; }
register : 'register' { $return = "(suggestion to be as fast as possible)"; }
float : 'float' { $return = 'float'; }
typedef_name : identifier
{ {
my $answer = 0; my $answer = 0;
foreach (@defined_types) { foreach (@defined_types) {
@ -1115,7 +1157,8 @@ typedef_name : identifier
$answer; $answer;
} }
struct_or_union_specifier : comment(?) struct_or_union identifier(?) '{' struct_declaration_list '}' struct_or_union_specifier:
comment(?) struct_or_union identifier(?) '{' struct_declaration_list '}'
{ {
my $identifier = join('',@{$item{'identifier(?)'}}); my $identifier = join('',@{$item{'identifier(?)'}});
$return = join('',@{$item{'comment(?)'}}) . $item{struct_or_union} ; $return = join('',@{$item{'comment(?)'}}) . $item{struct_or_union} ;
@ -1127,7 +1170,8 @@ struct_or_union_specifier : comment(?) struct_or_union identifier(?) '{' struct_
$return = "the $item{struct_or_union} $item{identifier}"; $return = "the $item{struct_or_union} $item{identifier}";
} }
struct_declaration_list : struct_declaration(s) struct_declaration_list:
struct_declaration(s)
{ {
my $finaldec; my $finaldec;
my @declarations = @{$item{'struct_declaration(s)'}}; my @declarations = @{$item{'struct_declaration(s)'}};
@ -1141,22 +1185,32 @@ struct_declaration_list : struct_declaration(s)
} }
} }
struct_declaration : comment(?) specifier_qualifier_list struct_declarator_list ';' struct_declaration:
comment(?) specifier_qualifier_list struct_declarator_list ';'
{ $return = join('', @{$item{'comment(?)'}}) . $item{specifier_qualifier_list} . ' ' . $item{struct_declarator_list}; } { $return = join('', @{$item{'comment(?)'}}) . $item{specifier_qualifier_list} . ' ' . $item{struct_declarator_list}; }
type_name : specifier_qualifier_list abstract_declarator(?) type_name:
specifier_qualifier_list abstract_declarator(?)
{ $return = $item{specifier_qualifier_list} . join('',@{$item{'abstract_declarator(?)'}}); } { $return = $item{specifier_qualifier_list} . join('',@{$item{'abstract_declarator(?)'}}); }
specifier_qualifier_list : type_specifier specifier_qualifier_list(?) specifier_qualifier_list:
type_specifier specifier_qualifier_list(?)
{ $return = $item{type_specifier} . join('', @{$item{'specifier_qualifier_list(?)'}}); } { $return = $item{type_specifier} . join('', @{$item{'specifier_qualifier_list(?)'}}); }
struct_declarator_list : struct_declarator | struct_declarator ',' struct_declarator_list struct_declarator_list:
struct_declarator
| struct_declarator ',' struct_declarator_list
{ $return = $item{struct_declarator} . join('',@{$item{struct_declarator_list}}); } { $return = $item{struct_declarator} . join('',@{$item{struct_declarator_list}}); }
struct_declarator : declarator | declarator(?) ':' constant_expression struct_declarator:
{ $return = join('',@{$item{'declarator(?)'}}) . " which is set off the bit field $item{constant_expression}"; } declarator
| declarator(?) ':' constant_expression
{ $return = join('',@{$item{'declarator(?)'}}) . " a bit field $item{constant_expression}"; }
struct_or_union : comment(?) ('struct' { $return = 'a structure'; } | 'an union') comment(?) struct_or_union:
comment(?) ('struct'
{ $return = 'a structure'; }
| 'an union') comment(?)
{ {
shift @item; shift @item;
foreach (@item) { foreach (@item) {
@ -1168,7 +1222,8 @@ struct_or_union : comment(?) ('struct' { $return = 'a structure'; } | 'an union'
} }
} }
enum_specifier : 'enum' identifier(?) '{' enumerator_list '}' enum_specifier:
'enum' identifier(?) '{' enumerator_list '}'
{ {
$return = 'enumeration ' ; $return = 'enumeration ' ;
@ -1180,7 +1235,8 @@ enum_specifier : 'enum' identifier(?) '{' enumerator_list '}'
} }
| 'enum' identifier | 'enum' identifier
enumerator_list : (enumerator ',')(s?) enumerator enumerator_list:
(enumerator ',')(s?) enumerator
{ {
my @enumerator_list = @{$item[1]}; my @enumerator_list = @{$item[1]};
@ -1193,7 +1249,8 @@ enumerator_list : (enumerator ',')(s?) enumerator
} }
} }
enumerator : identifier ( '=' constant_expression )(?) enumerator:
identifier ( '=' constant_expression )(?)
{ {
$return = $item[1]; $return = $item[1];
if (@{$item[-1]}) { if (@{$item[-1]}) {
@ -1201,31 +1258,73 @@ enumerator : identifier ( '=' constant_expression )(?)
} }
} }
comment : comment_c comment:
comment_c
{ $return = $item{comment_c}; } { $return = $item{comment_c}; }
| comment_cxx | comment_cxx
{ $return = $item{comment_cxx}; } { $return = $item{comment_cxx}; }
comment_c : m{/\*(.*?)\*/}s comment_c:
m{/\*(.*?)\*/}s
{ {
$return = $item[1]; $return = $item[1];
$return =~ s/^\/\*//; $return =~ s|^/\*+\s*||;
$return =~ s/\*\/$//; $return =~ s|\s*\*+/$||;
$return =~ s/"/\\"/g; $return =~ s/"/\\"/g;
$return = "\nThe author adds this comment here:\n\"" . $return . "\"\n"; $return = "\nA comment: \"$return\".\n";
} }
comment_cxx : m{\/\/(.*?)\n} comment_cxx:
m{//(.*?)\n}
{ {
$return = $item[1]; $return = $item[1];
$return =~ s/^\/\///; $return =~ s|^//\s*||;
$return = "\nThe author adds this quick comment here:\n" . $return . "\nNow back to the code.\n"; $return =~ s/\n*$//;
$return = "\nQuick comment: \"$return\".\n";
} }
identifier_word : /[a-z_\$][a-z0-9_]*/i constant:
/-?[0-9]*\.[0-9]+f?/
{
if ($item[1] =~ /\D/) {
$return = "the floating point number $item[1]";
} else {
$return = $item[1];
}
}
| /0x[0-9a-fA-F]+/ ('L')(?)
{
if ($item[-1]) {
$return = 'the long ' ."hexadecimal number $item[1]";
} else {
$return = 'the ' . "hexadecimal number $item[1]";
}
}
| /0\d+/
{ $return = "the octal number $item[1]"; }
|/-?[0-9]+[lu]?/i # integer constant
{
$return = $item[-1];
$return =~ s/[Uu]$/(unsigned)/;
$return =~ s/[Ll]$/(long)/;
}
| m{'.*?[^\']'} # character constant FIXME: doesn't handle escaped quotes
# | enumeration_constant
# needs more.
reserved : 'int' | 'double' | 'short' | 'volatile' | 'register' | 'float' | 'signed' | 'unsigned' | 'char' | integer_constant:
'for' | 'if' | 'switch' | 'while' | 'do' | 'case' | 'extern' | 'void' | 'exit' | 'return' | /[0-9]+/
'auto' | 'break' | 'const' | 'continue' | 'default' | 'else' | 'enum' | 'struct' | 'goto' | 'long' | 'register' |
'sizeof' | 'static' | 'typedef' | 'union' identifier_word:
/[a-z_\$][a-z0-9_]*/i
string:
/".*?[^\"]"/ # FIXME: doesn't handle escaped quotes
reserved:
'int' | 'double' | 'short' | 'volatile' | 'register' | 'float' | 'signed'
| 'unsigned' | 'char' | 'for' | 'if' | 'switch' | 'while' | 'do' | 'case'
| 'extern' | 'void' | 'exit' | 'return' | 'auto' | 'break' | 'const'
| 'continue' | 'default' | 'else' | 'enum' | 'struct' | 'goto' | 'long'
| 'register' | 'sizeof' | 'static' | 'typedef' | 'union'