
=head1 NAME
X<NAME>

Math::Notation::PostfixInfix - Math Notation for Postfix and Infix Expressions

=head1 SYNOPSIS
X<SYNOPSIS>

 use Math::Notation::PostfixInfix;

 Infix_to_Postfix
    I<@array_of_rule = Infix_to_Postfix ( I<"infix string"> );

 Postfix_to_Infix
    I<$infix_notation> = Postfix_to_Infix ( I<@array_of_rule> );

 Postfix_Test
    I<$bolean> = Postfix_Test ( I<arrayref_of_rule>,
                             [ I<\&external_subrot>, [ I<\@subrot_options> ]]
                           );

=head1 DESCRIPTION
X<DESCRIPTION>

This module was created for: 

=over

 (a) Convert INFIX expressions to POSTFIX; 
 (b) Convert POSTFIX expressions to INFIX and; 
 (c) Perform POSTFIX context validations.

=back

Context validation can be implemented in item selection routines or data context validation, 
when it is possible to identify data to be selected or ignored in some data analysis process.

=head1 EXAMPLES
X<EXAMPLES>

The examples below were created in the hope that it will be useful.

=head2 Infix_to_Postfix
X<Infix_to_Postfix>

This example demonstrates how to convert an INFIX notaton to POSTFIX.

=over

code:

  use Math::Notation::PostfixInfix;

  my @array = Math::Notation::PostfixInfix->Infix_to_Postfix ( "a && b || c && d" );

results:

  @array = [ "a", "b", "&", "c", "d", "&", "|" ];

=back

=head2 Postfix_to_Infix
X<Postfix_to_Infix>

This example demonstrates how to convert an POSTFIX notaton to INFIX.

=over

code:

  use Math::Notation::PostfixInfix;

  my $string = Math::Notation::PostfixInfix->Postfix_to_Infix
                     ( [ "a","b","&","c","d","&","|" ] );
  or
  my $string = Math::Notation::PostfixInfix->Infix_to_Postfix
                     ( \@array );

results:

  $string = "a and b or c and d";

=back

=head2 Postfix_Test Bolean_Value
X<Postfix_Test Bolean_Value>

The script below is a simple example of logical comparation using constant data.

=over

code:

  ## file: /tmp/t1

  use Math::Notation::PostfixInfix;

  my $mymod = new Math::Notation::PostfixInfix;

  my %hash = ( A=>1, B=>0, C=>1, D=>0 );

  my @array =
  (
     [ $mymod->Infix_to_Postfix("A && B && C && D") ],
     [ $mymod->Infix_to_Postfix("A && B || C && D") ],
     [ $mymod->Infix_to_Postfix("A && B || C && D") ],
     [ $mymod->Infix_to_Postfix("A || B && C || D") ],
     [ $mymod->Infix_to_Postfix("A || B || C || D") ],
  );

  print "\n"; 
  print "test1 = ".$mymod->Postfix_Test($array[0],\&subrot)."\n";
  print "test2 = ".$mymod->Postfix_Test($array[1],\&subrot)."\n";
  print "test3 = ".$mymod->Postfix_Test($array[2],\&subrot)."\n";
  print "test4 = ".$mymod->Postfix_Test($array[3],\&subrot)."\n";
  print "test5 = ".$mymod->Postfix_Test($array[4],\&subrot)."\n";
  exit;

  # rule = field information
  # oper = operator (lt,le,eq,gt,ge,*) ('*' is no operator found)
  # val1 = left part of field information (for 'oper' not '*')
  # val2 = right part of field information (for 'oper' not '*')
  # opts = subroutine options passed on Postfix_Test (3rd args)

  sub subrot
  {
     my $rule = shift;	# full field information
     my $oper = shift;	# may be: lt, le, eq, gt, ge, '*'
     my $val1 = shift;	# value is '0' if oper = '*'
     my $val2 = shift;	# value is '0' if oper = '*'
     my $opts = shift;	# subroution options
     return $hash{$rule};
  }

results:

  # perl /tmp/t1

  test1 = 0
  test2 = 0
  test3 = 0
  test4 = 1
  test5 = 1

=back

=head2 Postfix_Test Hash_Table
X<Postfix_Test Hash_Table>

The script below was create to establish the concepts of context selection and exclusion rules based on data in HASH tables.

=over

code:

  ## file: /tmp/t2

  use Math::Notation::PostfixInfix;

  ## testing arguments
  #
  die "$0 argv1 is missing" if (!@ARGV);

  ## convertin args as string e get the postfix rule
  #
  my $mymod = new Math::Notation::PostfixInfix;

  my @rule = $mymod->Infix_to_Postfix(join(" ",@ARGV));

  print "\nrule: [ ",join(", ",@rule)," ]\n\n";

  ## test and select the data base the rule
  #
  while (my $buf = <DATA>)
  {
     $buf =~ s/[\n\r]//g;

     ## matching formated data
     #
     if ($buf =~ /^(.*),(.*),(.*)$/i)
     {
        ## initialize the fields to test
        #
        my %test = (country=>$1, name=>$2, genre=>$3);

        ## apply the rules on the fields
        #
        ($mymod->Postfix_Test(\@rule,\&subrot,\%test)) ?
            print "[match]" :
            print "[unmatch]";
     }

     ## unmatching dat record
     #
     else {print "[regexp-error]";}

     ## append the data record on the status
     #
     print " ",$buf,"\n";
  }
  exit;

  ## my context test
  #
  sub subrot
  {
      ## get the envs
      #
      my $rule = shift;
      my $oper = shift;
      my $val1 = shift;
      my $val2 = shift;
      my $test = shift;

      ## return as match if equal/match and data match
      #
      return 1 if ($oper eq "eq" && $test->{$val1} eq $val2);

      ## return as match if notequal/operator and data mismatch
      #
      return 1 if ($oper eq "ne" && $test->{$val1} ne $val2);

      ## otherwise return as umatch
      #
      return 0;
  }

  __DATA__
  usa,peter,male
  brazil,mary,female
  france,jean,male
  france,maria,female

results:

   # perl /tmp/t2 country eq france

   rule: [ country eq france ]

   [unmatch] usa,peter,male
   [unmatch] brazil,mary,female
   [match] france,jean,male
   [match] france,maria,female

   # perl /tmp/t2 country eq france and name ne jean

   rule: [ country eq france, name ne jean, & ]

   [unmatch] usa,peter,male
   [unmatch] brazil,mary,female
   [unmatch] france,jean,male
   [match] france,maria,female

=back

=head1 DEPENDENCIES
X<DEPENDENCIES>

no dependencies

=head1 AUTHOR
X<AUTHOR>

Carlos Celso, E<lt>ccelso@cpan.orgE<gt>

=head1 COPYRIGHT
X<COPYRIGHT>

Copyright (C) 2022-2023 Carlos Celso

=head1 LICENSE
X<LICENSE>

This package is free software; can, at your discretion, also be used,
modified and redistributed under the terms of the "GPLv3 - GNU Library
General Public License".

=cut
