#!/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}; }
    <matchrule: $rule_name>(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: $rule_name>
      )[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: $rule_name>)[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 = <STDIN>;
}

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.'
<commit>
    (
     'We' 'return' 'the' 'following' "value: \""
     expression "\"."
     {
	 $return = $item[-2]; 
     }
     )(?)
{
    $return = 'return ' . join('',@{$item[-1]}) . ";\n"; 
}
|
    'Pray' 'for' 'forgiveness' 'from' 'the' 'Demiurge.' <commit>
    '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 : 
    <leftop:
    assignment_expression[context => $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 = <STDIN>; 
} 

    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 : 
    <leftop:  
    rel_add_mul_shift_expression[context => $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 : 
  <leftop:
    cast_expression[context => $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 : 
    <leftop: expression ',' expression >
{
    $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 (<CFILE>) {
    $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";






