#!/usr/athena/bin/perl #!/afs/athena.mit.edu/contrib/perl5/bin/perl5.6.0 # #-w RD_TRACE # #/usr/athena/bin/perl # #-I /afs/athena.mit.edu/user/o/c/ocschwar/perllib #push @INC, "/afs/athena.mit.edu/user/o/c/ocschwar/perllib"; use Parse::RecDescent; $::RD_HINT = 1; $Parse::RecDescent::skip = '\s*'; use Getopt::Std; getopts('Tth'); if ($opt_h) { undef $::RD_HINT; } if ($opt_T ) { $::RD_TRACE = 1; } else { undef $::RD_TRACE ; } # # ReCSS : Restore C from .eng Statements and Subroutines # # Project commences : September 2000. # # status: this script is written around a moving target. # Thus it is not at all complete. # my $Grammar = q[ { my ($foo,$function_name,$rule_name); my @defined_types = ('FILE') ; } startrule0 : preamble startrule1 startrule1: startrule { print $item{startrule}; } startrule1(?) startrule: preproc[matchrule => 'startrule'] #{print $item{preproc}; $return = $item[1]; } | comment #{print $item{comment};$return = $item[1]; } | global_var_declaration #{print $item{global_var_declaration};$return = $item[1]; } | function_definition #{print $item{function_definition};$return = $item[1]; } | function_prototype #{print $item{function_prototype};$return = $item[1]; } preamble : 'This' 'file' 'was' 'generated' 'by' 'DECSS:' 'Descriptive' 'English' 'for' 'C' 'Statements' 'and' 'Subroutines.' 'The' 'C' 'source' 'file' 'for' 'it' 'was' 'called' "'" filename "'" '.' # # note: # *_slug_* stands for our English insertions. # A 'slug' should never be anything buy a quote or regexp # # preproc : 'Note:' ( definition | undefinition | inclusion | line | error | pragma | preproc_conditional[matchrule => $arg{matchrule}] )[matchrule => $arg{matchrule}] definition : 'we' 'define' 'the' 'macro' plain_identifier 'with' 'the' 'symbol' symbol_set 'to' 'use' 'the' 'token' 'sequence' '"' token_sequence '"' '.' { $return = "\n#define $item{plain_identifier}$item{symbol_set}". " $item{token_sequence}\n"; } | 'we' 'define' plain_identifier 'to' 'mean' '"' token_sequence '"' '.' { $return = "\n#define $item{plain_identifier} ". "$item{token_sequence}\n"; } symbol_set : sym_identifier { $return = "($item[1])"; } | 's' sym_identifier ( ( ',' sym_identifier )(s) ',' { $return = join(',',@{$item[-2]}); } )(?) 'and' sym_identifier { $return = '(' . $item[2] . ',' . join(',',@{$item[-3]}) . ','.$item[-1]. ')' ; } line : 'for' 'debugging' 'this' 'is' 'line' 'number' constant ('and' 'filename' filename)(?) '.' { $return = "\n#line ". $item{constant} . join('',@{$item[-2]}) ."\n"; } pragma : 'a' 'compiler-dependent' 'pragma' token_sequence(?) 'is' 'added' 'here.' { $return = "\n#pragma ". join('',@{$item{token_sequence}}) ."\n"; } undefinition : 'here' 'we' 'annul' 'the' 'definition' 'of' '"' plain_identifier '"' '.' { $return = "\nundef $item{plain_identifier}\n"; } inclusion : 'This' 'program' 'makes' 'use' 'of' 'the' 'system' 'file' "'" filename "'" '.' { $return = "\n#include <$item{filename}>\n"; } | 'This' 'program' 'makes' 'use' 'of' 'the' 'user' 'file' "'" filename "'" '.' { $return = "\n#include \"$item{filename}\"\n"; } # defined filenames are an issue here. filename : /[_\\.\\-\\w\\/]+/ preproc_conditional : 'The' 'current' 'context' 'is' 'interrupted' '.' 'The' 'next' 'section' 'is' 'used' 'only' 'if' if_line[matchrule => $arg{matchrule}] { $rule_name = $arg{matchrule}; } (s?) { $return = $item{if_line} . join('',@{$item[-1]}); } # prog_text matchrule! (elif_parts[matchrule => $rule_name])(s?) (else_parts[matchrule => $rule_name])(?) 'Note:' 'This' 'ends' 'a' 'conditional' 'inclusion' 'section.' { $return .= "\n#endif\n"; } if_line : 'we' 'meet' 'this' 'macro' 'condition:' '"' constant_expression '"' '.'# { print STDERR "#if!$arg{matchrule}!\n"; } { $return = "\n#if $item{constant_expression}\n"; } | 'if' plain_identifier 'is' 'defined' '.' { $return= "\n#ifdef $item{plain_identifier}\n"; } | 'if' plain_identifier 'is' 'NOT' 'defined' '.' { $return= "\n#ifndef $item{plain_identifier}\n"; } elif_parts : 'Note:' 'we' 'interrupt' 'the' 'current' 'context' 'again.' 'Instead' 'of' 'the' 'previous' 'precondition,' 'we' 'include' 'the' 'following' 'text' 'based' 'on' 'this' 'condition:' '"' constant_expression '".' ( )[matchrule => $arg{matchrule}](s?) { $return .= join('',@{$item[-1]}); } # matchrule needed else_parts : 'Note:' 'we' 'interrupt' 'the' 'current' 'context' 'once' 'more.' 'The' 'following' 'section' 'gets' 'included' 'if' 'the' 'previous' 'precondition' 'fails.' ()[matchrule => $arg{matchrule}](s?) # matchrule needed token_sequence : token(s) { $return = join(' ',@{$item[1]}); } token : /\\\\\\n/ |#/\\S+/ /(\\\\"|[^ \\t\\n"])+/ { $return = $item[-1]; $return =~ s/\\\"/\"/g; } global_var_declaration : declaration function_definition : 'This' 'is' 'the' 'definition' 'of' 'the' 'function' sym_identifier '.' ( 'It' 'returns' 'a' 'value' 'of' 'the' 'type' return_value '.' {$return = $item{return_value};} )(?) { $function_name = $item{sym_identifier}; $return = join('',@{$item[-1]}); if (!$return) { $return = 'void '; } $return .=' ' . $item{sym_identifier}; } ( 'The' 'function' "'$function_name'" # 'has' 'the' 'following' 'parameters:' #{ print STDERR "parameter_declaration_list\n"; } parameter_declaration_list '.' { $return = $item{parameter_declaration_list}; } )(?) { $return .= '(' . join('',@{$item[-1]}) . ")\n{\n"; # print STDERR "function definition3 $return\n"; } ( 'The' 'local' 'variables' 'for' 'the' 'function' "'$function_name'" 'begin here:' declaration_list { $return = $item{declaration_list}; } )(?) { $return .= join('',@{$item[-1]}) ; # print STDERR "function definition4 $return\n"; } ( 'And' 'now' 'comes' 'the' 'instruction' 'set' 'for' 'the' 'function' "'$function_name'" '.' # todo: statement list fails to evaluate. Investigate tomorrow. statement_list { $return = $item{statement_list}; } )(?) { $return .= join('',@{$item[-1]}) ; print STDERR "function definition5 $return\n"; } 'And' 'here' 'ends' 'the' 'definition' 'of' 'the' 'function' "'$function_name'" '.' { # reassemble the return value! $return .= "\n}\n"; } # flip the pointer decl and type decl for C purposes.. return_value : ( pointer 'to' 'a' { $return = $item{pointer}; } )(?) declaration_specifiers { $return = $item{declaration_specifiers} . join('',@{$item[1]}); } function_prototype : 'Here' 'is' 'a' 'prototype' 'definition' 'for' 'a' 'function' 'named' sym_identifier '.' 'It' 'has' 'the' 'return' 'value' return_value '.' parameter_list(?) { $return = "$item{return_value} $item{sym_identifier}(" . join(@{$item{parameter_list}}) . ");\n" ; } parameter_declaration_list : parameter_list ( ',' 'and' 'possibly' 'other' 'arguments' { $return = ', ...'; } )(?) { $return = $item{parameter_list} . join('',@{$item[-1]}); } parameter_list : parameter_declaration ( parameter_secondary_list { $return = ','.$item{parameter_secondary_list}; } )(?) { $return = $item{parameter_declaration} . join('',@{$item[-1]}); # print STDERR "parameter_list1 $return.\n"; } parameter_secondary_list : (',')(?) 'and' parameter_declaration | ',' parameter_declaration parameter_secondary_list { $return = $item{parameter_declaration} . ','. $item{parameter_secondary_list}; } parameter_declaration : declaration_specifiers #{ print STDERR "parameter_declaration test0 $item[-1]\n"; } declarator { $return = $item{declaration_specifiers} . ' ' . $item{declarator}; # print STDERR "parameter_declaration $return.\n"; } | declaration_specifiers abstract_declarator(?) { $return = $item{declaration_specifiers} . join('',@{$item{abstract_declarator}}); } compound_statement : 'A' 'compound' 'statement' 'begins' 'here.' { $return = "{\n"; } ( 'Some' 'variables' 'are' 'declared.' declaration_list)(?) { $return .= join('',@{$item[-1]}); } ( 'And' 'now' 'some' 'statements.' statement_list )(?) { $return .= join('',@{$item[-1]}); } 'A' 'compound' 'block' 'of' 'instructions' ( 'for' 'a' loop_type )(?) 'ends' 'here.' { $return .= "\n}\n"; } loop_type : 'for' 'loop' | 'while' 'loop' | 'do' 'loop' | 'n' 'else' 'block' | 'switch' | 'n' 'if' 'block' declaration_list: declaration(s) { $return = join('',@{$item[-1]}); } declaration : 'Specifying' 'the' 'type' declaration_specifiers ',' 'allocate' 'the' ('variables' |'variable') init_declarator_list '.' { $return = "$item[4] $item{init_declarator_list} ;\n"; } | 'Note' 'a' declaration_specifiers ',' 'and' 'call' 'it' init_declarator_list '.' { $return = "$item{declaration_specifiers} $item{init_declarator_list} ;\n"; push @defined_types, split(',',$item{init_declarator_list}) ; foreach (@defined_types) { s/\\s//;} # print STDERR "defineds\n" .join("\n",@defined_types) . "\nends\n"; } # ....... # the string "the variable" in declarations is causing a breakage here. init_declarator_list : init_declarator #{print STDERR "init declarator test\n"; } { $return = $item{init_declarator}; } (( ( ',' init_declarator )(s) { $return = ', '.join(', ',@{$item[-1]}) ; } ',' )(?) 'and' init_declarator { $return .= join('',@{$item[-3]}) . ', ' . $item{init_declarator}; } )(?) { $return .= join('',@{$item[-1]}) ; } init_declarator : declarator { $return = $item{declarator}; } ( '(' 'initialized' 'to' initializer ')' { $return = "= $item{initializer}"; } | 'and' 'initialized' 'to' initializer { $return = "= $item{initializer}"; } )(?) { $return .= join('',@{$item[-1]}); } initializer : assignment_expression | 'the' 'set' initializer_list { $return = '{' . $item{initializer_list} . '}' } initializer_list : initializer { $return = $item{initializer}; } ( ( ( ',' initializer )(s) { $return = join(', ',@{$item[-1]}) ; } ',')(?) 'and' initializer { $return .= join(', ',@{$item[-3]}) . ', ' . $item{initializer}; } )(?) { if (@{$item[-1]}) { $return .= ', ' . join('',@{$item[-1]}) ; } } declarator : pointer(?) direct_declarator { $return = join('',@{$item{pointer}}) . $item{direct_declarator}; } direct_declarator : "'" plain_identifier "'" { $return = $item[-2]; } #plain_identifier # ..... todo!! ( ',' 'defined' 'to' 'be' 'an' 'array' 'with' 'the' 'size' array_size )(?) { $return .= join('',@{$item[-1]}); } array_size : arr_exp ('by' array_size)(?) { $return = '[' . $item[1] . ']' . join('',@{$item[-1]}); } arr_exp : 'nil' { $return = ''; } | constant_expression constant_expression : conditional_expression pointer : ( /\\d+\\w{2}/ '-level' { $return = int $item[1]; } )(?) 'pointer' { my $level = 1; $return = '*'; if (@{item[1]}) { $level = join('',@{$item[1]}); if ($level >1) { $return x= $level; } } # print STDERR "\n\npointer level: $level\n\n"; # $level = ; } declaration_specifiers : storage_class_specifier declaration_specifiers(?) { $return = $item{storage_class_specifier} . ' ' . join('',@{$item{declaration_specifiers}}); } | type_specifier declaration_specifiers(?) { $return = $item{type_specifier} . ' ' . join('',@{$item{declaration_specifiers}}); } | type_qualifier declaration_specifiers(?) { $return = $item{type_qualifier} . ' ' . join('',@{$item{declaration_specifiers}}); } #| # plain_identifier # this breaks declarations of just two parameters # when they are not pointers. # there needs to be an action to restrict this to # defined types. storage_class_specifier : '(' 'declared' 'elsewhere' ')' { $return = 'extern'; } | '(' 'this' 'declaration' 'is' 'not' 'to' 'be' 'shared' ')' { $return = 'static'; } # more stuff..... | register | 'type' 'definition' 'of' { $return = 'typedef'; } type_specifier : 'double' 'precision' 'floating' 'point' 'number' { $return = 'double'; } | 'character' { $return = 'char'; } | 'integer' { $return = 'int'; } | 'floating' 'point' 'number' { $return = 'float'; } | 'signed' | 'unsigned' | struct_or_union_specifier | enum_specifier | 'void' | # defined types are tested for here. plain_identifier { my $answer = 0; foreach (@defined_types) { if ($item{plain_identifier} eq $_) { $answer = 1; $return = $item{plain_identifier}; # print STDERR "typedef name $return\n"; } } if (!$answer) { undef $answer; } $answer; } # the forward script is sufficiently pedantic that we # need not worry here. # much todo. struct_or_union_specifier : struct_or_union ( 'which' 'is' 'called' identifier )(?) 'which' 'contains' 'the' 'following:' struct_declaration_list { $return = $item{struct_or_union} . join('',@{$item[2]}) . "\n{\n" . $item{struct_declaration_list} . "\n}\n"; } | 'the' struct_or_union plain_identifier { $return = $item{struct_or_union} .' '. $item{plain_identifier}; } struct_declaration_list : struct_declaration ( ( ',' struct_declaration )(s?) (',')(?) 'and' struct_declaration { $return = join('',@{$item[1]}) . $item[-1]; } )(?) { $return = $item[1] . join('',@{$item[-1]}); } struct_declaration : specifier_qualifier_list struct_declarator_list { $return = $item{specifier_qualifier_list} . $item{struct_declarator_list} . ';' ; } type_name : specifier_qualifier_list abstract_declarator(?) { $return = $item{specifier_qualifier_list} . join('',@{$item{abstract_declarator}}); } specifier_qualifier_list : type_specifier specifier_qualifier_list(?) { $return = $item{type_specifier} . join('', @{$item{specifier_qualifier_list}} ); } struct_declarator_list : struct_declarator | struct_declarator ',' struct_declarator_list { $return = $item{struct_declarator} . join('',@{$item{struct_declarator_list}}); } #todo: this is WRONG. struct_declarator : declarator | declarator(?) 'which' 'is' 'set' 'off' 'the' 'bit' 'field' constant_expression { $return = join('',@{$item{declarator}}) . ':' . $item{constant_expression}; } struct_or_union : 'structure' { $return = 'struct'; } | 'union' type_qualifier : 'constant' { $return = 'const' ; } | 'volatile' statement_list : comment(?) preproc[matchrule => 'statement'](?) statement statement_list(?) # { $return = join('',@{$item{comment}}) . join('',@{$item{preproc}}) . $item{statement} . join('',@{$item{statement_list}}) ; } statement : # jump_statement 'Here' 'we' 'break' 'from' 'the' 'current' 'loop.' { $return = "break;\n"; } | 'Here' 'we' 'return' 'to' 'the' 'top' 'of' 'the' 'current' 'loop' 'and' 'continue' 'it.' { $return = "continue;\n"; } | 'Here' 'we' 'end' 'the' 'current' 'subroutine.' ( 'We' 'return' 'the' 'following' "value: \"" expression "\"." { $return = $item[-2]; } )(?) { $return = 'return ' . join('',@{$item[-1]}) . ";\n"; } | 'Pray' 'for' 'forgiveness' 'from' 'the' 'Demiurge.' 'Then,' 'go' 'to' 'the' 'section' 'marked' identifier '.' { $return = "goto $item{identifier};\n"; } | compound_statement[context => $arg{context} , name => $arg{context} ] # | iteration_statement # | selection_statement # | #labeled_statement # #labeled_statement : 'The' 'following' 'statement' 'is' 'preceded' 'by' 'the' 'label' identifier '.' statement { $return = "$item{identifier} : $item{statement}"; } | # case statement 'In' 'the' 'case' 'it' 'has' 'the' 'value' constant_expression ',' 'do' 'this:' statement { $return = "case $item{constant_expression} : $item{statement}"; } | # default case statement 'In' 'the' 'default' 'case,' 'do' 'this:' statement { $return = "default: $item{statement}"; } | # expression_statement # This sucker is the hard one. It has the assignments and function calls. # expression_statement : 'There' 'is' 'a' 'no-op' 'here.' { $return = ';'; } | expression '.' { $return = $item{expression} . ";\n"; } expression : $arg{context}] exp_sep assignment_expression[context => $arg{context}] > { $return = join('',@{$item[-1]}); } exp_sep : '.' "We're" 'not' 'done' 'yet.' {$return = ',';} #todo: # handling of comma separated expressions needed. assignment_expression : # note the order! assignment_operator_prefix unary_expression #note the quote marks! assignment_operator_suffix '"' assignment_expression '"' { if ($item{assignment_operator_prefix} =~ /\w/) { $return = "$item{unary_expression} $item{assignment_operator_suffix} $item{assignment_expression}"; } else { $return = "$item{unary_expression} $item{assignment_operator_prefix} $item{assignment_expression}"; } } | unary_expression assignment_operator assignment_expression { $return = join('',@item); } | conditional_expression[context => $arg{context}] { $return = $item[-1]; # if ($arg{context} eq 'statement') { print STDERR "cond_stat $return"}; } assignment_operator_prefix : 'Assign to' { $return = "="; } | 'Increase' { $return = "+="; } | 'Decrease' { $return = "-="; } | 'Multiply' { $return = "*="; } | 'Divide' { $return = "/="; } | 'Pare' 'down' { $return = "%="; } | 'Bit' 'shift' { $return = "<<>>trip"; } | 'Bit' 'mask' { $return = "&|^trip"; } assignment_operator_suffix : 'the' 'value' | 'to' 'modulo' | 'left' 'by' { $return = "<<="; } | 'right' 'by' { $return = ">>="; } | 'in' 'an' 'exclusive-or' 'operation' 'by' { $return = "^="; } | 'down' 'by' { $return = "&="; } | 'up' 'by' { $return = "|="; } | 'by' assignment_operator : ',' 'which' 'is' 'assigned' 'to' 'be' { $return = "="; } | 'which' 'is' 'increased' 'by' { $return = "+="; } | 'which' 'is' 'decreased' 'by' { $return = "-="; } | 'which' 'is' 'multiplied' 'by ' { $return = "*="; } | 'which' 'is' 'divided' 'by' { $return = "/="; } | 'which' 'is' 'reduced' 'to' 'modulo' { $return = "%="; } | 'which' 'is' 'bitshifted' 'left' 'by ' { $return = "<<="; } | 'which' 'is' 'bitshifted' 'right' 'by' { $return = ">>="; } | 'which' 'is' 'bitmasked' 'down' 'by' { $return = "&="; } | 'which' 'is' 'xorred' 'by' { $return = "^="; } | 'which' 'is' 'bitmasked' 'up' 'by' { $return = "|="; } selection_statement : # if statement 'Execute' 'the' 'following' 'part' 'if' 'the' 'expression' '"' { print STDERR "if bloack $item{expression} \n"; print STDERR substr($text,0,100)."\n"; # $foo = ; } expression '"' 'evaluates' 'as' 'positive:' statement { $return = "if($item{expression}) \n$item{statement}"; } ( 'If' 'the' 'expression' 'evaluated' 'as' 'negative,' 'execute' 'this' 'section:' statement { $return = "else\n$item{statement}"; } )(?) { $return .= join('',@{$item[-1]}); } #switch statemnt | 'This' 'section' 'is' 'controlled' 'by' 'a' 'switch' 'based' 'on' 'the' 'expression' "'" expression "':" statement { $return = "switch ($item{expression}) \n$item{statement}"; } iteration_statement : # for loop 'Here' 'we' 'set' 'up' 'for' 'an' 'iteration' 'loop.' ( 'We' 'initialize' 'by' 'performing' 'this' 'instruction:' # for_initialization expression[context => 'statement'] '.' { # print STDERR "\n oy! for initialization!\n"; $return = $item[-2]; } )(?) ( 'We' 'continue' 'the' 'loop' 'as' 'long' 'as' 'the' 'following' 'expression' 'comes' 'out' 'positive:' '"' # for_expression expression[context => 'for_expression'] '"' '.' { $return = $item{expression}; } )(?) ( 'At' 'the' 'end' 'of' 'each' 'repetition' 'we' 'perform' 'this' 'to' 'increment' 'things:' expression[context => 'statement'] { print STDERR "Oy! for inc1!\n"; print STDERR substr($text,0,100). "\n"; }# for_increment '.' { print STDERR "Oy! for increment!\n"; print STDERR substr($text,0,100). "\n"; $return = $item{expression}; } )(?) 'This' 'is' 'the' 'loop:' statement { # watch the indices! my $trio = join('',@{$item[-8]}) . ';'. join('',@{$item[-7]}) . ';'. join('',@{$item[-6]}) ; $return = "for ($trio)" ."\n$item{statement}"; } # while loop | 'Here' 'we' 'go' 'into' 'a' 'repetition' 'loop' 'which' 'we' 'stay' 'in' 'as' 'long' { print STDERR "\nwhile --- --- \n"; } 'as' 'the' 'following' 'expression' { print STDERR "\nwhile --- --- ---\n"; } 'evaluates' 'as' 'positive:' "'" { print STDERR "\nwhile --- --- --- ---\n"; } expression "'" statement 'Now' 'ends' 'the' 'repetition' 'loop.' { $return = "while ($item{expression}) $item{statement}"; } #do loop | 'Do' 'the' 'following:' statement 'Do' 'this' 'as' 'long' 'as' "'" expression "'" 'evaluates' 'to' 'a' 'positive' 'number.' { $return = "do $item{statement}\nwhile($item{expression});\n"; } conditional_expression : 'the' 'choice' 'dependent' 'on' 'the' 'value' 'of' logical_OR_AND_expression 'comprising' 'of' expression 'or' conditional_expression { $return = $item{logical_or_AND_expression} . ' ?' . $item{expression} . ':'. $item{conditional_expression}; } | {print STDERR ',';} logical_OR_AND_expression[context => $arg{context}] logical_OR_AND_expression : $arg{context}] log_OR_AND_bit_or_and_eq rel_add_mul_shift_expression > { $return = join ('' ,@{$item[1]}); } log_OR_AND_bit_or_and_eq : 'logically' 'orred' 'by' { $return = '||'; } | 'logically' 'anded' 'by' { $return = '&&'; } | 'bitwise' 'orred' 'by' { $return = '|'; } | 'bitwise' 'xorred' 'by' { $return = '^'; } | 'bitwise' 'anded' 'by' { $return = '&'; } | 'checked' 'for' 'equality' 'against' { $return = '=='; } | 'checked' 'for' 'inequality' 'against' { $return = '!='; } rel_mul_add_ex_op : 'plus' { $return = '+'; } | 'minus' { $return = '-'; } | 'times' { $return = '*'; } | 'divided' 'by' { $return = '/'; } | 'modulo' { $return = '%'; } | 'shifted' 'left' 'by' { $return = '<<'; } | 'shifted' 'right' 'by' { $return = '>>'; } | 'checked' 'to' 'be' 'greater' 'than' 'or' 'equal' 'to' { $return = '>='; } | 'checked' 'to' 'be' 'less' 'than' 'or' 'equal' 'to' { $return = '<='; } | 'checked' 'to' 'be' 'greater' 'than' { $return = '>'; } | 'checked' 'to' 'be' 'less' 'than' { $return = '<'; } rel_add_mul_shift_expression : $arg{context}] rel_mul_add_ex_op cast_expression[context => 'add_mul_shift_expression'] > { $return = join ('' , @{$item[1]}); # print STDERR "rel_add_mul_shift_expression $return\n"; } cast_expression : 'a' 'casting' 'into' 'the' 'type' "'" type_name "'" 'of' cast_expression { $return= "($item{type_name})$item{cast_expression}"; } | unary_expression { $return = $item[-1]; } unary_expression : postfix_expression { $return = $item[1]; } | ( 'Uptick' | 'the' 'now' 'upticked' ) unary_expression { $return = "++$item{unary_expression}"; } | ( 'Downtick' | 'the' 'now' 'downticked' ) unary_expression { $return = "--$item{unary_expression}"; } | unary_operator cast_expression { $return = "$item{unary_operator} $item{cast_expression}"; } | 'the memory size of the datatype' type_name { $return = "sizeof($item{type_name})"; } unary_operator : 'the' 'memory' 'location' 'of' { $return = '&'; } | 'the' 'memory' 'contents' 'of' { $return = '*'; } | 'the' 'value' 'of' { $return = '+'; } | 'negative' { $return = '-'; } | 'minus' { $return = '-'; } | 'the' "one\'s" 'complement' 'of' { $return = '~'; } | 'the' 'logical' 'negation' 'of' { $return = '!'; } # note: here is where the quoting policy must be set. identifier_1 : identifier sym_identifier : "'" plain_identifier "'" { $return = $item{plain_identifier}; } identifier : "`" plain_identifier "'" { $return = $item{plain_identifier}; } plain_identifier : / [a-z_] # LEADING ALPHA OR UNDERSCORE [a-z0-9_]* # THEN DIGITS ALSO ALLOWED /ix # CASE/SPACE/COMMENT INSENSITIVE # ponder this closely... argument_expression_list : 's' "'" assignment_expression "'" { $return = $item{assignment_expression}; } ( ( ',' "'" assignment_expression "'" { $return = $item{assignment_expression}; } )(s) { $return = join(',',@{$item[-1]}); } ',' )(?) { if (@{$item[-1]}){ $return .= ',' . join(',',@{$item[-1]}); } } 'and' "'" assignment_expression "'" { $return .= ','. $item[-2]; } | "'" assignment_expression "'" { $return = $item{assignment_expression}; } #todo: this will be a hard one. postfix_expression : ('Perform' )(?) 'the' 'function' ( identifier | 'pointed' 'by' primary_expression ) ( 'as' 'applied' 'to' 'the' 'argument' argument_expression_list { $return = '('. $item{argument_expression_list}. ')'; } | 'without' 'any' 'arguments' { $return = '()' ; } ) { $return = $item[-2] . $item[-1]; # if (@{$item[1]}) { # $text =~ /^\\s*\\.//; # } } | 'the' 'macro' identifier 'as' 'applied' 'to' 'the' 'argument' argument_expression_list { $return = $item{identifier} . '('. $item{argument_expression_list} . ')'; } | 'array' plain_identifier "'s" 'element' 'at' 'address' '(' array_address ')' { $return = $item{plain_identifier} . $item{array_address}; } | /[Ss]tructure/ identifier "'s" 'member' identifier_1 { $return = $item{identifier} . '.' . $item{identifier_1} ; } | /the/i 'member' plain_identifier 'of' 'the' 'structure' 'pointed' 'by' primary_expression { $return = $item{primary_expression} . '->' . $item{plain_identifier} ; } # todo: more situations. | primary_expression ( '(' 'which' 'is' 'incremented' 'down' 'by' 'one' ')' {$return = '--';} | '(' 'which' 'is' 'incremented' 'up' 'by' 'one' ')' {$return = '++';} )(?) { $return = $item{primary_expression} . join('',@{$item[-1]}); } | 'Increment' primary_expression ( 'down' 'by' 'one' {$return = '--';} | 'up' 'by' 'one' {$return = '++';} ) { $return = $item{primary_expression} . $item[-1]; } comment : 'The' 'author' 'adds' 'this' (comment_cxx | comment_c ) 'Now' 'back' 'to' 'the' 'code.' { $return = $item[5]; } # check regex for newlines.... comment_c : 'comment' 'here:' /\"(.*?)[^\\\\]\"/sm { $return = "/*". $1. "*/\n"; } comment_cxx : 'quick' 'comment' 'here:' /\".*?\"/ { $return = $item[-1]; $return =~ s/Now back to the code$//; $return = '//' . $return . "\n"; } array_address : { $return = '[' . join('][',@{$item[-1]}) .']' ; } short : 'two' 'byte' 'integer' { $return = 'short'; } long : 'eight' 'byte' 'integer' { $return = 'long'; } auto : '(' 'high' 'priority' 'variable' ')' { $return = 'auto' ; } register : '(' 'should' 'remain' 'in' 'the' 'register' ')' { $return = 'register'; } constant : 'the' 'floating' 'point' 'number' /-?[0-9]*\\.[0-9]+f?/ { $return = $item[-1]; } | 'the' 'hexadecimal' 'number' /0x[0-9a-fA-F]+/ { $return = $item[-1]; } | 'the' 'octal' 'number' /0\\d+/ { $return = $item[-1]; } # integer_constant | /-?[0-9]+(\\(unsigned\\)|\\(long\\))?/i | m{'.*?[^\']'} | enumeration_constant # needs more. # todo: the now dropped at the end... primary_expression : identifier | 'the' ( /\\d+\\-layered/ )(?) 'parenthetical' 'expression' { my $addon; my $level = join('',@{$item[-3]}); $level =~ s/\-layered$//; if ($level >1) { $level --; $addon = ' the parenthetical expression ' x $level; $text = $addon . $text; } } expression ( 'now' | '(' 'now' 'drop' /\\d+/ 'layers' 'of' 'context' ')' { my $level = $item[4] ; $level --; my $addon2 = ' now '; $addon2 x= $level; $text = $addon2 . $text; $return = $level; } | ...m{\"\\s*\\.} | ...m{\'\\s*\\,} | ...m{\'\\s*and} ) { $return = "($item{expression})"; print STDERR "\nparen $return\n". substr($text,0,50) ; } | constant | string string : m{\".*?\"} ]; print STDERR "Examining the grammar.\n"; $parser = new Parse::RecDescent ($Grammar) or die "Bad grammar!\n"; print STDERR "Opening file. $ARGV[0]\n"; open(CFILE,"$ARGV[0]") or die "Could not open $ARGV[0].\n"; while () { $text .= $_; } close(CFILE); print STDERR "parsing...\n"; # for debugging... if ($opt_t) { $::RD_TRACE = 1; } else { undef $::RD_TRACE ; } defined $parser->startrule0(\$text) or die "Bad text!\n$text\n"; print STDERR "\ndone.\n" . substr($text,0,200). "\n";