3
0
mirror of https://github.com/pragma-/pbot.git synced 2024-10-03 01:48:38 +02:00

CGrammar: Several fixes and improvements

This commit is contained in:
Pragmatic Software 2014-06-23 08:29:08 +00:00
parent c1de5f6c97
commit 76faa3f2ca
3 changed files with 174 additions and 115 deletions

View File

@ -13,8 +13,8 @@ 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 => 669, BUILD_REVISION => 670,
BUILD_DATE => "2014-06-21", BUILD_DATE => "2014-06-23",
}; };
1; 1;

View File

@ -406,7 +406,8 @@ if(not $output) {
# beautification # beautification
$output =~ s/the value the expression/the value of the expression/g; $output =~ s/the value the expression/the value of the expression/g;
$output =~ s/the value the address/the address/g; $output =~ s/the value the/the/g;
$output =~ s/(is true is)+/is/g;
print "$output\n"; print "$output\n";

View File

@ -144,7 +144,7 @@ external_declaration:
declaration declaration
function_definition: function_definition:
declaration_specifiers(?) declarator[context => 'function definition'] compound_statement[context => 'function definition'](?) declaration_specifiers[context => 'function definition'](?) declarator[context => 'function definition'] compound_statement[context => 'function definition'](?)
{ {
my $declaration_specifiers = join('', @{$item{'declaration_specifiers(?)'}}); my $declaration_specifiers = join('', @{$item{'declaration_specifiers(?)'}});
my $name = $item{declarator}->[0]; my $name = $item{declarator}->[0];
@ -157,6 +157,11 @@ function_definition:
$return_type = $declaration_specifiers; $return_type = $declaration_specifiers;
} }
if($return_type =~ s/( with.*)$//) {
my $storage_class_specifier = $1;
$parameter_list =~ s/function/function$storage_class_specifier/;
}
$return = "\nLet $name be a "; $return = "\nLet $name be a ";
$return .= $parameter_list; $return .= $parameter_list;
$return .= " $return_type.\nTo perform the function, ^L"; $return .= " $return_type.\nTo perform the function, ^L";
@ -164,7 +169,7 @@ function_definition:
} }
compound_statement: compound_statement:
'{' declaration_list(?) statement_list(?) '}' '{' declaration_list[context => 'compound statement'](?) statement_list[context => 'compound statement'](?) '}'
{ {
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(?)'}});
@ -227,7 +232,8 @@ iteration_statement:
} }
if ($item_expression) { if ($item_expression) {
$return .= "For as long as $item_expression, ^L"; my $istrue = $item{expression} =~ /(greater|less|equal|false$)/ ? '' : ' is true';
$return .= "For as long as ^L$item_expression$istrue, ^L";
} else { } else {
$return .= "Repeatedly ^L"; $return .= "Repeatedly ^L";
} }
@ -239,7 +245,7 @@ iteration_statement:
$return .= "After each iteration, ^L$increment.\n"; $return .= "After each iteration, ^L$increment.\n";
} }
} }
| 'while' '(' <commit> expression ')' statement[context => 'while loop'] | 'while' '(' <commit> expression[context => 'while conditional'] ')' statement[context => 'while loop']
{ {
if($item{expression} =~ /(^\d+$)/) { if($item{expression} =~ /(^\d+$)/) {
if($1 == 0) { if($1 == 0) {
@ -248,7 +254,8 @@ iteration_statement:
$return = "Repeatedly ^L"; $return = "Repeatedly ^L";
} }
} else { } else {
$return = "While $item{expression}, ^L"; my $istrue = $item{expression} =~ /(greater|less|equal|false$)/ ? '' : ' is true';
$return = "While ^L$item{expression}$istrue, ^L";
} }
if($item{statement}) { if($item{statement}) {
@ -257,36 +264,54 @@ iteration_statement:
$return .= "do nothing.\n"; $return .= "do nothing.\n";
} }
} }
| 'do' statement[context => 'do loop'] 'while' '(' expression ')' ';' | 'do' statement[context => 'do loop'] 'while' '(' expression[context => 'do while conditional'] ')' ';'
{ $return = "Do the following:^L $item{statement}Do this as long as $item{expression}.\n"; } {
$item{statement} =~ s/^do nothing/nothing/i;
$return = "Do the following:^L $item{statement}";
if($item{expression} =~ /(^\d+$)/) {
if($1 == 0) {
$return .= "Do this once.\n";
} else {
$return .= "Do this repeatedly.\n";
}
} else {
my $istrue = $item{expression} =~ /(greater|less|equal|false$)/ ? '' : ' is true';
$return .= "Do this as long as ^L$item{expression}$istrue.\n";
}
}
for_initialization: for_initialization:
expression[context => 'for loop'] expression[context => 'for loop']
for_expression: for_expression:
expression[context => 'for_expression'] expression[context => 'for conditional']
for_increment: for_increment:
expression[context => 'statement'] expression[context => 'statement']
selection_statement: selection_statement:
'if' <commit> '(' expression[context => 'if block'] ')' statement[context => 'if block'] 'if' <commit> '(' expression[context => 'if conditional'] ')' statement[context => 'if statement']
{ {
if($item{expression} =~ /^(\d+)$/) { if($item{expression} =~ /^(\d+)$/) {
if($1 == 0) { if($1 == 0) {
$item{expression} = "never"; $return = "Never ";
} else { } else {
$item{expression} = "always"; $return = "Always ";
} }
} else {
my $istrue = $item{expression} =~ /(greater|less|equal|false$)/ ? '' : ' is true';
$return = "If ^L$item{expression}$istrue then ";
} }
$return = "If $item{expression} then ^L$item{statement}"; $return .= "^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[context => 'switch conditional'] ')' statement[context => 'switch']
{ $return = "Given the expression \'$item{expression}\',\n^L$item{statement}"; } {
$return = "Given the expression \'^L$item{expression}\',\n^L$item{statement}";
}
jump_statement: jump_statement:
'break' ';' 'break' ';'
@ -301,7 +326,7 @@ jump_statement:
} }
| 'continue' ';' | 'continue' ';'
{ $return = "Return to the top of the current loop.\n"; } { $return = "Return to the top of the current loop.\n"; }
| 'return' <commit> expression[context => 'return'](?) ';' | 'return' <commit> expression[context => 'statement'](?) ';'
{ {
my $item_expression = join('', @{$item{'expression(?)'}}); my $item_expression = join('', @{$item{'expression(?)'}});
@ -347,9 +372,9 @@ expression:
} }
assignment_expression: assignment_expression:
unary_expression[context => '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']
{ {
my $assignment_expression = $item{assignment_expression}; my $assignment_expression = $item{assignment_expression};
my $assignment_operator = $item{assignment_operator}; my $assignment_operator = $item{assignment_operator};
@ -386,111 +411,111 @@ assignment_operator:
'=' '='
{ {
if ($arg{context} eq 'statement') { if ($arg{context} eq 'statement') {
$return = ['Assign to', 'the value' ]; $return = ['Assign to^L', 'the value^L' ];
} elsif ($arg{context} eq 'for loop') { } elsif ($arg{context} eq 'for loop') {
$return = ['assigning to', 'the value' ]; $return = ['assigning to^L', 'the value^L' ];
} else { } else {
$return = 'which is assigned to be'; $return = 'which is assigned to be^L';
} }
} }
| '+=' | '+='
{ {
if ($arg{context} eq 'statement') { if ($arg{context} eq 'statement') {
$return = ['Increment','by']; $return = ['Increment^L','by^L'];
} elsif ($arg{context} eq 'for loop') { } elsif ($arg{context} eq 'for loop') {
$return = ['incrementing','by']; $return = ['incrementing^L','by^L'];
} else { } else {
$return = 'which is incremented by'; $return = 'which is incremented by^L';
} }
} }
| '-=' | '-='
{ {
if ($arg{context} eq 'statement') { if ($arg{context} eq 'statement') {
$return = ['Decrement' , 'by']; $return = ['Decrement^L', 'by^L'];
} elsif ($arg{context} eq 'for loop') { } elsif ($arg{context} eq 'for loop') {
$return = ['decrementing' , 'by']; $return = ['decrementing^L' , 'by^L'];
} else { } else {
$return = 'which is decremented by'; $return = 'which is decremented by^L';
} }
} }
| '*=' | '*='
{ {
if ($arg{context} eq 'statement') { if ($arg{context} eq 'statement') {
$return = ['Multiply' , 'by']; $return = ['Multiply^L' , 'by^L'];
} elsif ($arg{context} eq 'for loop') { } elsif ($arg{context} eq 'for loop') {
$return = ['multiplying' , 'by']; $return = ['multiplying^L' , 'by^L'];
} else { } else {
$return = 'which is multiplied by'; $return = 'which is multiplied by^L';
} }
} }
| '/=' | '/='
{ {
if ($arg{context} eq 'statement') { if ($arg{context} eq 'statement') {
$return = ['Divide' , 'by' ]; $return = ['Divide^L' , 'by^L' ];
} elsif ($arg{context} eq 'for loop') { } elsif ($arg{context} eq 'for loop') {
$return = ['dividing' , 'by' ]; $return = ['dividing^L' , 'by^L' ];
} else { } else {
$return = 'which is divided by'; $return = 'which is divided by^L';
} }
} }
| '%=' | '%='
{ {
if ($arg{context} eq 'statement') { if ($arg{context} eq 'statement') {
$return = ['Reduce', 'to modulo '] ; $return = ['Reduce^L', 'to modulo ^L'] ;
} elsif ($arg{context} eq 'for loop') { } elsif ($arg{context} eq 'for loop') {
$return = ['reducing', 'to modulo '] ; $return = ['reducing^L', 'to modulo ^L'] ;
} else { } else {
$return = 'which is reduced to modulo'; $return = 'which is reduced to modulo^L';
} }
} }
| '<<=' | '<<='
{ {
if ($arg{context} eq 'statement') { if ($arg{context} eq 'statement') {
$return = ['Bit-shift', 'left by']; $return = ['Bit-shift^L', 'left by^L'];
} elsif ($arg{context} eq 'for loop') { } elsif ($arg{context} eq 'for loop') {
$return = ['bit-shifting', 'left by']; $return = ['bit-shifting^L', 'left by^L'];
} else { } else {
$return = 'which is bit-shifted left by'; $return = 'which is bit-shifted left by^L';
} }
} }
| '>>=' | '>>='
{ {
if ($arg{context} eq 'statement') { if ($arg{context} eq 'statement') {
$return = ['Bit-shift', 'right by']; $return = ['Bit-shift^L', 'right by^L'];
} elsif ($arg{context} eq 'for loop') { } elsif ($arg{context} eq 'for loop') {
$return = ['bit-shifting', 'right by']; $return = ['bit-shifting^L', 'right by^L'];
} else { } else {
$return = 'which is bit-shifted right by'; $return = 'which is bit-shifted right by^L';
} }
} }
| '&=' | '&='
{ {
if ($arg{context} eq 'statement') { if ($arg{context} eq 'statement') {
$return = ['Bit-wise ANDed', 'by' ]; $return = ['Bit-wise ANDed^L', 'by^L' ];
} elsif ($arg{context} eq 'for loop') { } elsif ($arg{context} eq 'for loop') {
$return = ['bit-wise ANDing', 'by' ]; $return = ['bit-wise ANDing^L', 'by^L' ];
} else { } else {
$return = 'which is bit-wise ANDed by'; $return = 'which is bit-wise ANDed by^L';
} }
} }
| '^=' | '^='
{ {
if ($arg{context} eq 'statement') { if ($arg{context} eq 'statement') {
$return = ['Exclusive-OR','by']; $return = ['Exclusive-OR^L','by^L'];
} elsif ($arg{context} eq 'for loop') { } elsif ($arg{context} eq 'for loop') {
$return = ['exclusive-ORing','by']; $return = ['exclusive-ORing^L','by^L'];
} else { } else {
$return = 'which is exclusive-ORed by'; $return = 'which is exclusive-ORed by^L';
} }
} }
| '|=' | '|='
{ {
if ($arg{context} eq 'statement') { if ($arg{context} eq 'statement') {
$return = ['Bit-wise ORed', 'by']; $return = ['Bit-wise ORed^L', 'by^L'];
} elsif ($arg{context} eq 'for loop') { } elsif ($arg{context} eq 'for loop') {
$return = ['bit-wise ORing', 'by']; $return = ['bit-wise ORing^L', 'by^L'];
} else { } else {
$return = 'which is bit-wise ORed by'; $return = 'which is bit-wise ORed by^L';
} }
} }
@ -503,54 +528,54 @@ logical_OR_AND_expression:
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']>
{ {
if (defined $arg{context} and $arg{context} eq 'for_expression') { print STDERR "hmm2\n"; } if (defined $arg{context} and $arg{context} eq 'for conditional') { print STDERR "hmm2\n"; }
my @ands = @{$item[1]}; $return = join ('' , @{$item[1]});
$return = join ('' , @ands);
} }
log_OR_AND_bit_or_and_eq: log_OR_AND_bit_or_and_eq:
'||' { $return = ' or '; } '||' { $return = ' or ^L'; }
| '&&' { $return = ' and '; } | '&&' { $return = ' and ^L'; }
| '|' { $return = ' bitwise-ORed by '; } | '|' { $return = ' bitwise-ORed by ^L'; }
| '&' { $return = ' bitwise-ANDed by '; } | '&' { $return = ' bitwise-ANDed by ^L'; }
| '^' { $return = ' bitwise-XORed by ';} | '^' { $return = ' bitwise-XORed by ^L';}
| '==' { $return = ' is equal to ' ; } | '==' { $return = ' is equal to ^L'; }
| '!=' { $return = ' is not equal to ' ; } | '!=' { $return = ' is not equal to ^L'; }
rel_mul_add_ex_op: rel_mul_add_ex_op:
'+' { $return = ' plus '; } '+' { $return = ' plus ^L'; }
| '-' { $return = ' minus '; } | '-' { $return = ' minus ^L'; }
| '*' { $return = ' times '; } | '*' { $return = ' times ^L'; }
| '/' { $return = ' divided by '; } | '/' { $return = ' divided by ^L'; }
| '%' { $return = ' modulo '; } | '%' { $return = ' modulo ^L'; }
| '<<' { $return = ' shifted left by '; } | '<<' { $return = ' shifted left by ^L'; }
| '>>' { $return = ' shifted right by '; } | '>>' { $return = ' shifted right by ^L'; }
| '>=' { $return = ' is greater than or equal to '; } | '>=' { $return = ' is greater than or equal to ^L'; }
| "<=" { $return = ' is less than or equal to '; } | "<=" { $return = ' is less than or equal to ^L'; }
| '>' { $return = ' is greater than '; } | '>' { $return = ' is greater than ^L'; }
| '<' { $return = ' is less than '; } | '<' { $return = ' is less than ^L'; }
unary_operator: unary_operator:
'&' { $return = 'the address of '; } '&' { $return = 'the address of '; }
| '*' { $return = 'the contents of '; } | '*' { $return = 'the dereference of '; }
| '+' { $return = ''; } | '+' { $return = ''; }
| '-' ...constant { $return = 'negative '; } | '-' ...identifier { $return = 'negative '; }
| '-' { $return = 'minus '; } | '-' { $return = 'minus '; }
| '~' { $return = "the one's complement of "; } | '~' { $return = "the one's complement of "; }
| '!' { $return = 'the logical negation of '; } | '!' '!' { $return = 'the normalized boolean value of '; }
| '!'
{
if($arg{context} =~ /conditional/) {
$return = ['', ' is false'];
} else {
$return = 'the logical negation of ';
}
}
rel_add_mul_shift_expression: rel_add_mul_shift_expression:
cast_expression[context => $arg{context}] ...';' cast_expression ...';'
{ $return = $item{cast_expression}; } { $return = $item{cast_expression}; }
| <leftop: | <leftop: cast_expression rel_mul_add_ex_op cast_expression>
cast_expression[context => $arg{context}] { $return = join ('' , @{$item[1]}); }
rel_mul_add_ex_op
cast_expression[context => 'add_mul_shift_expression'] >
{
my @ands = @{$item[1]};
$return = join ('' , @ands);
}
closure: closure:
',' | ';' | ')' ',' | ';' | ')'
@ -803,7 +828,7 @@ unary_expression:
if ($arg{context} eq 'statement' ) { if ($arg{context} eq 'statement' ) {
$return = "pre-increment $item{unary_expression}"; $return = "pre-increment $item{unary_expression}";
} else { } else {
$return = "the pre-incremented $item{unary_expression}"; $return = "pre-incremented $item{unary_expression}";
} }
} }
| '--' unary_expression | '--' unary_expression
@ -811,15 +836,23 @@ unary_expression:
if ($arg{context} eq 'statement' ) { if ($arg{context} eq 'statement' ) {
$return = "Pre-decrement $item{unary_expression}"; $return = "Pre-decrement $item{unary_expression}";
} else { } else {
$return = "the pre-decremented $item{unary_expression}"; $return = "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}; } {
|'sizeof' unary_expression if(ref $item{unary_operator} eq 'ARRAY') {
{ $return = "the size of $item{unary_expression}"; } $return = $item{unary_operator}->[0] . $item{cast_expression} . $item{unary_operator}->[1];
|'sizeof' '(' type_name ')' } else {
$return = $item{unary_operator} . $item{cast_expression};
}
}
| 'sizeof' '(' type_name[context => 'sizeof'] ')'
{ $return = "the size of the type $item{type_name}"; } { $return = "the size of the type $item{type_name}"; }
| 'sizeof' '(' assignment_expression[context => 'sizeof'] ')'
{ $return = "the size of the type of the expression ($item{assignment_expression})"; }
| 'sizeof' unary_expression[context => 'sizeof']
{ $return = "the size of $item{unary_expression}"; }
postfix_productions: postfix_productions:
'(' argument_expression_list(?) ')' postfix_productions[context => 'function call'](?) '(' argument_expression_list(?) ')' postfix_productions[context => 'function call'](?)
@ -928,11 +961,9 @@ postfix_productions:
{ {
my $increment = join('',@{$item[-1]}); my $increment = join('',@{$item[-1]});
if ($increment) { if ($increment) {
if ($arg{context} eq 'statement') { if($arg{context} eq 'struct access') {
$return = "increment $arg{primary_expression} by one";
} elsif($arg{context} eq 'struct access') {
$return = ['increment', 'by one']; $return = ['increment', 'by one'];
} else { } else {
$return = "post-incremented $arg{primary_expression}"; $return = "post-incremented $arg{primary_expression}";
} }
} }
@ -941,13 +972,11 @@ postfix_productions:
{ {
my $increment = join('',@{$item[-1]}); my $increment = join('',@{$item[-1]});
if ($increment) { if ($increment) {
if ($arg{context} eq 'statement') { if($arg{context} eq 'struct access') {
$return = "decrement $arg{primary_expression} by one";
} elsif($arg{context} eq 'struct access') {
$return = ['decrement', 'by one']; $return = ['decrement', 'by one'];
} else { } else {
$return = "post-decremented $arg{primary_expression}"; $return = "post-decremented $arg{primary_expression}";
} }
} }
} }
# having done the simplest cases, we go to the catch all for left recursions. # having done the simplest cases, we go to the catch all for left recursions.
@ -1008,13 +1037,17 @@ primary_expression:
my $expression = $item{expression} ; my $expression = $item{expression} ;
my $repeats = 1; my $repeats = 1;
if ($expression =~ /^the expression (\(+)/) { if ($expression =~ /^The expression (\(+)/) {
$repeats = (length $1) + 1; $repeats = (length $1) + 1;
$expression =~ s/^the expression \(+//; $expression =~ s/^The expression \(+//;
} }
$expression .= ')'; $expression .= ')';
$return = "the expression "; if($arg{context} eq 'statement') {
$return = "Evaluate the expression ";
} else {
$return = "The expression ";
}
$return .= '(' x $repeats; $return .= '(' x $repeats;
$return .= $expression; $return .= $expression;
} }
@ -1176,6 +1209,7 @@ direct_abstract_declarator:
| DAD '[' ']' | DAD '[' ']'
| DAD '[' constant_expression ']' | DAD '[' constant_expression ']'
| '(' ')' | '(' ')'
{ $return = 'function taking unspecified parameters and returning'; }
| '(' parameter_type_list ')' | '(' parameter_type_list ')'
{ $return = "function taking $item{parameter_type_list} and returning"; } { $return = "function taking $item{parameter_type_list} and returning"; }
| DAD '(' ')' | DAD '(' ')'
@ -1199,7 +1233,8 @@ pointer:
} }
| '*' pointer(?) | '*' pointer(?)
{ {
$return = join('', @{$item{'pointer(?)'}}); my $pointers = join('', @{$item{'pointer(?)'}});
$return .= "$pointers " if $pointers;
$return .= 'pointer to'; $return .= 'pointer to';
} }
@ -1214,8 +1249,15 @@ declaration_specifiers:
| comment(?) storage_class_specifier declaration_specifiers(?) | comment(?) storage_class_specifier declaration_specifiers(?)
{ {
my $decl_spec = join(' ', @{$item{'declaration_specifiers(?)'}}); my $decl_spec = join(' ', @{$item{'declaration_specifiers(?)'}});
$return = join('',@{$item{'comment(?)'}}) . $item{storage_class_specifier} ; $return = join('',@{$item{'comment(?)'}});
if ($decl_spec) { $return .= ' ' . $decl_spec; }
if($item{storage_class_specifier} =~ m/^with/) {
if ($decl_spec) { $return .= "$decl_spec "; }
$return .= $item{storage_class_specifier};
} else {
$return .= $item{storage_class_specifier};
if ($decl_spec) { $return .= " $decl_spec"; }
}
} }
| comment(?) type_specifier declaration_specifiers(?) | comment(?) type_specifier declaration_specifiers(?)
{ {
@ -1233,13 +1275,25 @@ declaration_specifiers:
storage_class_specifier: storage_class_specifier:
'auto' 'auto'
{ $return = "(auto)"; } { $return = "with automatic storage-duration"; }
| 'extern' | 'extern'
{ $return = "(declared elsewhere)"; } {
if($arg{context} eq 'function definition') {
$return = "with external linkage";
} else {
$return = "with external linkage, possibly defined elsewhere";
}
}
| 'static' | 'static'
{ $return = "(this declaration is not to be shared)"; } {
if($arg{context} eq 'function definition') {
$return = "with internal linkage";
} else {
$return = "with internal linkage and life-time duration";
}
}
| 'register' | 'register'
{ $return = "(suggestion to be as fast as possible)"; } { $return = "with a suggestion to be as fast as possible"; }
| 'typedef' | 'typedef'
{ $return = 'type definition of'; } { $return = 'type definition of'; }
@ -1311,8 +1365,12 @@ struct_declaration:
{ $return = join('', @{$item[1]}) . $item{declaration} . join('', @{$item[-1]}); } { $return = join('', @{$item[1]}) . $item{declaration} . join('', @{$item[-1]}); }
type_name: type_name:
specifier_qualifier_list abstract_declarator(?) specifier_qualifier_list abstract_declarator(?)
{ $return = $item{specifier_qualifier_list}. join('',@{$item{'abstract_declarator(?)'}}); } {
my $abstract_declarator = join('',@{$item{'abstract_declarator(?)'}});
$return = "$abstract_declarator " if $abstract_declarator;
$return .= $item{specifier_qualifier_list};
}
specifier_qualifier_list: specifier_qualifier_list:
type_specifier specifier_qualifier_list(?) type_specifier specifier_qualifier_list(?)
@ -1369,7 +1427,7 @@ enumerator:
{ {
$return = $item[1]; $return = $item[1];
if (@{$item[-1]}) { if (@{$item[-1]}) {
$return .= 'marking ' . join('', @{$item[-1]}); $return .= ' marking ' . join('', @{$item[-1]});
} }
} }