deprecated/buildtools/buildsystemtools/lib/Parse/Yapp/Grammar.pm
author lorewang
Thu, 11 Nov 2010 11:26:32 +0800
changeset 677 44e49837144a
parent 655 3f65fd25dfd4
permissions -rw-r--r--
update release info
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
655
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     1
#
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     2
# Module Parse::Yapp::Grammar
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     3
#
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     4
# (c) Copyright 1998-2001 Francois Desarmenien, all rights reserved.
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     5
# (see the pod text in Parse::Yapp module for use and distribution rights)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     6
#
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     7
package Parse::Yapp::Grammar;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     8
@ISA=qw( Parse::Yapp::Options );
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     9
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    10
require 5.004;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    11
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    12
use Carp;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    13
use strict;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    14
use Parse::Yapp::Options;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    15
use Parse::Yapp::Parse;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    16
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    17
###############
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    18
# Constructor #
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    19
###############
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    20
sub new {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    21
    my($class)=shift;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    22
    my($values);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    23
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    24
    my($self)=$class->SUPER::new(@_);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    25
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    26
    my($parser)=new Parse::Yapp::Parse;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    27
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    28
        defined($self->Option('input'))
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    29
    or  croak "No input grammar";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    30
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    31
    $values = $parser->Parse($self->Option('input'));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    32
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    33
    undef($parser);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    34
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    35
    $$self{GRAMMAR}=_ReduceGrammar($values);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    36
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    37
        ref($class)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    38
    and $class=ref($class);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    39
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    40
    bless($self, $class);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    41
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    42
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    43
###########
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    44
# Methods #
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    45
###########
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    46
##########################
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    47
# Method To View Grammar #
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    48
##########################
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    49
sub ShowRules {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    50
    my($self)=shift;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    51
    my($rules)=$$self{GRAMMAR}{RULES};
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    52
    my($ruleno)=-1;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    53
    my($text);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    54
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    55
    for (@$rules) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    56
        my($lhs,$rhs)=@$_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    57
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    58
        $text.=++$ruleno.":\t".$lhs." -> ";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    59
        if(@$rhs) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    60
            $text.=join(' ',map { $_ eq chr(0) ? '$end' : $_ } @$rhs);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    61
        }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    62
        else {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    63
            $text.="/* empty */";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    64
        }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    65
        $text.="\n";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    66
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    67
    $text;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    68
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    69
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    70
###########################
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    71
# Method To View Warnings #
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    72
###########################
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    73
sub Warnings {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    74
    my($self)=shift;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    75
    my($text);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    76
    my($grammar)=$$self{GRAMMAR};
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    77
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    78
        exists($$grammar{UUTERM})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    79
    and    do {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    80
            $text="Unused terminals:\n\n";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    81
            for (@{$$grammar{UUTERM}}) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    82
                $text.="\t$$_[0], declared line $$_[1]\n";    
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    83
            }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    84
        $text.="\n";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    85
        };
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    86
        exists($$grammar{UUNTERM})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    87
    and    do {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    88
            $text.="Useless non-terminals:\n\n";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    89
            for (@{$$grammar{UUNTERM}}) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    90
                $text.="\t$$_[0], declared line $$_[1]\n";    
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    91
            }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    92
        $text.="\n";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    93
        };
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    94
        exists($$grammar{UURULES})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    95
    and    do {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    96
            $text.="Useless rules:\n\n";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    97
            for (@{$$grammar{UURULES}}) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    98
                $text.="\t$$_[0] -> ".join(' ',@{$$_[1]})."\n";    
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    99
            }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   100
        $text.="\n";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   101
        };
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   102
    $text;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   103
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   104
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   105
######################################
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   106
# Method to get summary about parser #
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   107
######################################
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   108
sub Summary {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   109
    my($self)=shift;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   110
    my($text);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   111
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   112
    $text ="Number of rules         : ".
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   113
            scalar(@{$$self{GRAMMAR}{RULES}})."\n";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   114
    $text.="Number of terminals     : ".
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   115
            scalar(keys(%{$$self{GRAMMAR}{TERM}}))."\n";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   116
    $text.="Number of non-terminals : ".
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   117
            scalar(keys(%{$$self{GRAMMAR}{NTERM}}))."\n";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   118
    $text;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   119
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   120
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   121
###############################
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   122
# Method to Ouput rules table #
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   123
###############################
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   124
sub RulesTable {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   125
    my($self)=shift;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   126
    my($inputfile)=$self->Option('inputfile');
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   127
    my($linenums)=$self->Option('linenumbers');
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   128
    my($rules)=$$self{GRAMMAR}{RULES};
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   129
    my($ruleno);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   130
    my($text);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   131
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   132
        defined($inputfile)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   133
    or  $inputfile = 'unkown';
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   134
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   135
    $text="[\n\t";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   136
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   137
    $text.=join(",\n\t",
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   138
                map {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   139
                    my($lhs,$rhs,$code)=@$_[0,1,3];
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   140
                    my($len)=scalar(@$rhs);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   141
                    my($text);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   142
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   143
                    $text.="[#Rule ".$ruleno++."\n\t\t '$lhs', $len,";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   144
                    if($code) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   145
                        $text.= "\nsub".
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   146
                                (  $linenums
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   147
                                 ? qq(\n#line $$code[1] "$inputfile"\n)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   148
                                 : " ").
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   149
                                "{$$code[0]}";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   150
                    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   151
                    else {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   152
                        $text.=' undef';
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   153
                    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   154
                    $text.="\n\t]";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   155
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   156
                    $text;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   157
                } @$rules);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   158
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   159
    $text.="\n]";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   160
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   161
    $text;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   162
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   163
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   164
################################
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   165
# Methods to get HEAD and TAIL #
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   166
################################
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   167
sub Head {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   168
    my($self)=shift;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   169
    my($inputfile)=$self->Option('inputfile');
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   170
    my($linenums)=$self->Option('linenumbers');
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   171
    my($text);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   172
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   173
        $$self{GRAMMAR}{HEAD}[0]
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   174
    or  return '';
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   175
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   176
        defined($inputfile)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   177
    or  $inputfile = 'unkown';
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   178
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   179
    for (@{$$self{GRAMMAR}{HEAD}}) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   180
            $linenums
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   181
        and $text.=qq(#line $$_[1] "$inputfile"\n);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   182
        $text.=$$_[0];
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   183
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   184
    $text
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   185
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   186
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   187
sub Tail {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   188
    my($self)=shift;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   189
    my($inputfile)=$self->Option('inputfile');
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   190
    my($linenums)=$self->Option('linenumbers');
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   191
    my($text);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   192
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   193
        $$self{GRAMMAR}{TAIL}[0]
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   194
    or  return '';
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   195
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   196
        defined($inputfile)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   197
    or  $inputfile = 'unkown';
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   198
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   199
        $linenums
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   200
    and $text=qq(#line $$self{GRAMMAR}{TAIL}[1] "$inputfile"\n);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   201
    $text.=$$self{GRAMMAR}{TAIL}[0];
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   202
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   203
    $text
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   204
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   205
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   206
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   207
#################
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   208
# Private Stuff #
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   209
#################
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   210
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   211
sub _UsefulRules {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   212
    my($rules,$nterm) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   213
    my($ufrules,$ufnterm);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   214
    my($done);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   215
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   216
    $ufrules=pack('b'.@$rules);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   217
    $ufnterm={};
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   218
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   219
    vec($ufrules,0,1)=1;    #start rules IS always useful
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   220
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   221
    RULE:
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   222
    for (1..$#$rules) { # Ignore start rule
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   223
        for my $sym (@{$$rules[$_][1]}) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   224
                exists($$nterm{$sym})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   225
            and next RULE;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   226
        }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   227
        vec($ufrules,$_,1)=1;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   228
        ++$$ufnterm{$$rules[$_][0]};
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   229
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   230
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   231
    do {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   232
        $done=1;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   233
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   234
        RULE:
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   235
        for (grep { vec($ufrules,$_,1) == 0 } 1..$#$rules) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   236
            for my $sym (@{$$rules[$_][1]}) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   237
                    exists($$nterm{$sym})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   238
                and not exists($$ufnterm{$sym})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   239
                and next RULE;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   240
            }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   241
            vec($ufrules,$_,1)=1;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   242
                exists($$ufnterm{$$rules[$_][0]})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   243
            or  do {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   244
                $done=0;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   245
                ++$$ufnterm{$$rules[$_][0]};
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   246
            };
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   247
        }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   248
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   249
    }until($done);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   250
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   251
    ($ufrules,$ufnterm)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   252
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   253
}#_UsefulRules
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   254
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   255
sub _Reachable {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   256
    my($rules,$nterm,$term,$ufrules,$ufnterm)=@_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   257
    my($reachable);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   258
    my(@fifo)=( 0 );
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   259
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   260
    $reachable={ '$start' => 1 }; #$start is always reachable
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   261
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   262
    while(@fifo) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   263
        my($ruleno)=shift(@fifo);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   264
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   265
        for my $sym (@{$$rules[$ruleno][1]}) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   266
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   267
                exists($$term{$sym})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   268
            and do {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   269
                ++$$reachable{$sym};
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   270
                next;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   271
            };
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   272
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   273
                (   not exists($$ufnterm{$sym})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   274
                 or exists($$reachable{$sym}) )
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   275
            and next;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   276
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   277
            ++$$reachable{$sym};
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   278
            push(@fifo, grep { vec($ufrules,$_,1) } @{$$nterm{$sym}});
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   279
        }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   280
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   281
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   282
    $reachable
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   283
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   284
}#_Reachable
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   285
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   286
sub _SetNullable {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   287
    my($rules,$term,$nullable) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   288
    my(@nrules);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   289
    my($done);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   290
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   291
    RULE:
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   292
    for (@$rules) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   293
        my($lhs,$rhs)=@$_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   294
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   295
            exists($$nullable{$lhs})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   296
        and next;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   297
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   298
        for (@$rhs) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   299
                exists($$term{$_})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   300
            and next RULE;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   301
        }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   302
        push(@nrules,[$lhs,$rhs]);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   303
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   304
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   305
    do {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   306
        $done=1;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   307
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   308
        RULE:
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   309
        for (@nrules) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   310
            my($lhs,$rhs)=@$_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   311
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   312
                    exists($$nullable{$lhs})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   313
                and next;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   314
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   315
                for (@$rhs) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   316
                        exists($$nullable{$_})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   317
                    or  next RULE;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   318
                }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   319
            $done=0;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   320
            ++$$nullable{$lhs};
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   321
        }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   322
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   323
    }until($done);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   324
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   325
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   326
sub _ReduceGrammar {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   327
    my($values)=@_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   328
    my($ufrules,$ufnterm,$reachable);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   329
    my($grammar)={ HEAD => $values->{HEAD},
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   330
                   TAIL => $values->{TAIL},
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   331
                   EXPECT => $values->{EXPECT} };
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   332
    my($rules,$nterm,$term) =  @$values {'RULES', 'NTERM', 'TERM'};
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   333
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   334
    ($ufrules,$ufnterm) = _UsefulRules($rules,$nterm);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   335
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   336
        exists($$ufnterm{$values->{START}})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   337
    or  die "*Fatal* Start symbol $values->{START} derives nothing, at eof\n";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   338
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   339
    $reachable = _Reachable($rules,$nterm,$term,$ufrules,$ufnterm);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   340
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   341
    $$grammar{TERM}{chr(0)}=undef;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   342
    for my $sym (keys %$term) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   343
            (   exists($$reachable{$sym})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   344
             or exists($values->{PREC}{$sym}) )
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   345
        and do {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   346
            $$grammar{TERM}{$sym}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   347
                = defined($$term{$sym}[0]) ? $$term{$sym} : undef;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   348
            next;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   349
        };
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   350
        push(@{$$grammar{UUTERM}},[ $sym, $values->{SYMS}{$sym} ]);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   351
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   352
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   353
    $$grammar{NTERM}{'$start'}=[];
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   354
    for my $sym (keys %$nterm) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   355
            exists($$reachable{$sym})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   356
        and do {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   357
                exists($values->{NULL}{$sym})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   358
            and ++$$grammar{NULLABLE}{$sym};
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   359
            $$grammar{NTERM}{$sym}=[];
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   360
            next;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   361
        };
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   362
        push(@{$$grammar{UUNTERM}},[ $sym, $values->{SYMS}{$sym} ]);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   363
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   364
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   365
    for my $ruleno (0..$#$rules) {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   366
            vec($ufrules,$ruleno,1)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   367
        and exists($$grammar{NTERM}{$$rules[$ruleno][0]})
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   368
        and do {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   369
            push(@{$$grammar{RULES}},$$rules[$ruleno]);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   370
            push(@{$$grammar{NTERM}{$$rules[$ruleno][0]}},$#{$$grammar{RULES}});
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   371
            next;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   372
        };
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   373
        push(@{$$grammar{UURULES}},[ @{$$rules[$ruleno]}[0,1] ]);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   374
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   375
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   376
    _SetNullable(@$grammar{'RULES', 'TERM', 'NULLABLE'});
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   377
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   378
    $grammar;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   379
}#_ReduceGrammar
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   380
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   381
1;