Skip to content

Instantly share code, notes, and snippets.

@pstuifzand
Last active December 11, 2015 10:28
Show Gist options
  • Save pstuifzand/4587128 to your computer and use it in GitHub Desktop.
Save pstuifzand/4587128 to your computer and use it in GitHub Desktop.
package Logic;
use strict;
use Marpa::R2 2.041_000;
sub new {
my ($class) = @_;
my $self = bless {}, $class;
$self->{grammar} = Marpa::R2::Scanless::G->new(
{
action_object => 'Logic::Actions',
source => \(<<'END_OF_SOURCE'),
:start ::= Sentence
Sentence ::= Literal action => do_literal
| '(' Sentence ')' action => do_paren
| '[' Sentence ']' action => do_paren
| Sentence Op Sentence action => do_op
| UnaryOp Sentence action => do_not
Literal ~ [a-zA-Z]+
Op ~ '⇒' | '⇔' | '∧' | '∨' | '=>' | '<=>' | '^' | 'v'
UnaryOp ~ '~' | '¬'
:discard ~ whitespace
whitespace ~ [\s]+
END_OF_SOURCE
}
);
return $self;
}
sub parse {
my ($string) = @_;
my $self = Logic->new();
my $re = Marpa::R2::Scanless::R->new( { grammar => $self->{grammar} } );
$re->read(\$string);
my $value_ref = $re->value();
return ${$value_ref};
}
sub visit_tree {
my ($tree, $helper) = @_;
if (ref($tree) eq 'ARRAY') {
my ($op, $l, $r) = @$tree;
if ($op eq 'not') {
$helper->('op', $op);
visit_tree($l, $helper);
}
else {
print '(';
visit_tree($l, $helper);
$helper->('op', $op);
visit_tree($r, $helper);
print ')';
}
}
else {
$helper->('literal', $tree);
}
}
my %ascii_op = (
'and' => '^',
'or' => 'v',
'xor' => '<=>',
'impl' => '=>',
'not' => '~',
);
my %utf8_op = (
'and' => '∧',
'or' => '∨',
'xor' => '⇔',
'impl' => '⇒',
'not' => '¬',
);
sub convert_to_unicode {
my ($tree) = @_;
visit_tree($tree, sub {
my ($type, $val) = @_;
if ($type eq 'op') {
print ' ' . $utf8_op{$val} . ' ' if $val ne 'not';
print $utf8_op{$val} if $val eq 'not';
}
elsif ($type eq 'literal') {
print $val;
}
});
print "\n";
}
sub convert_to_ascii {
my ($tree) = @_;
visit_tree($tree, sub {
my ($type, $val) = @_;
if ($type eq 'op') {
print ' ' . $ascii_op{$val} . ' ' if $val ne 'not';
print $ascii_op{$val} if $val eq 'not';
}
elsif ($type eq 'literal') {
print $val;
}
});
print "\n";
}
package Logic::Actions;
use strict;
sub new {
my ($class) = @_;
return bless {}, $class;
}
sub do_paren {
shift;
return $_[1];
}
my %ops = (
'⇔' => 'xor',
'<=>' => 'xor',
'∨' => 'or',
'v' => 'or',
'∧' => 'and',
'^' => 'and',
'¬' => 'not',
'~' => 'not',
'⇒' => 'impl',
'=>' => 'impl',
);
sub deop {
my $op = shift;
return $ops{$op} || $op;
}
sub do_op {
shift;
my ($l, $op, $r) = @_;
return [ deop($op), $l, $r ];
}
sub do_not {
shift;
my ($op, $r) = @_;
return [ deop($op), $r ];
}
sub do_literal {
shift;
return $_[0];
}
1;
use Logic;
my $data = Logic::parse(q{A});
$data = Logic::parse(q{A ∨ B});
Logic::convert_to_ascii($data);
Logic::convert_to_unicode($data);
print "--------------------\n";
$data = Logic::parse(q{A ∧ B});
Logic::convert_to_ascii($data);
Logic::convert_to_unicode($data);
print "--------------------\n";
$data = Logic::parse(q{A ∧ (B ∧ C)});
Logic::convert_to_ascii($data);
Logic::convert_to_unicode($data);
print "--------------------\n";
$data = Logic::parse(q{A ∧ (B ∨ C)});
Logic::convert_to_ascii($data);
Logic::convert_to_unicode($data);
print "--------------------\n";
$data = Logic::parse(q{A ⇒ B});
Logic::convert_to_ascii($data);
Logic::convert_to_unicode($data);
print "--------------------\n";
$data = Logic::parse(q{A => B});
Logic::convert_to_ascii($data);
Logic::convert_to_unicode($data);
print "--------------------\n";
$data = Logic::parse(q{~A => B});
Logic::convert_to_ascii($data);
Logic::convert_to_unicode($data);
print "--------------------\n";
$data = Logic::parse(q{~(A => B)});
Logic::convert_to_ascii($data);
Logic::convert_to_unicode($data);
print "--------------------\n";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment