Created
October 1, 2008 21:37
-
-
Save avescodes/14199 to your computer and use it in GitHub Desktop.
Simple logic parser I did for an assignment
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Here I add a two helper methods to the Fixnum class to aid in creating cases | |
class Fixnum | |
#returns T/F (actually F/T) if number is zero. | |
def bool | |
self.zero? | |
end | |
#Create a number of cases based on the calling number | |
#i.e. 2 returns [ [T,T], [T,F], [F,T], [F,F]] | |
def create_cases | |
#This block of code uses the binary of 2^num to generate each case, and | |
# append it to "big_array", the return array. | |
big_array = [] | |
(0...(2**self)).each do |num| | |
array = [] | |
(0...self).each do |i| | |
array << num[i].bool | |
end | |
big_array << array | |
end | |
big_array | |
end | |
end | |
class String | |
#A "ruby-ism" to create a symbol from a string | |
def to_sym | |
eval(":#{self}") | |
end | |
#The beef of the code lies here, I'll in detail explain each bit. | |
def logical_parse | |
#Create empty symbols set -- this will hold symbols like p, q, r | |
symbols = {} | |
#Process the string a little by making symbols uppercase | |
str = self.upcase | |
#raise an exception if we encounter non handled chars | |
str.scan(/[^A-Z^v\)\(~\s+]/) { |m| raise "Invalid character exists in string:"+m } | |
#then translate math logic to programming logic | |
str = str.gsub('~','!').gsub('V', "or").gsub("^","and").gsub("+","^") | |
#For every symbol in the string create a symbol in our table | |
str.scan(/[A-Z]/) do |match| | |
symbols[match.to_sym] = false | |
end | |
#Fill our cases array with a 2d representation of all possible T/F | |
# combos for 'x' symbols | |
cases = symbols.count.create_cases | |
#Print out top row | |
print "|" | |
symbols.each_key { |k| print "#{k.to_s.center(7)}|"} | |
print " #{str.center(str.length + 2)}|\n" | |
#Run over all the cases | |
cases.each do |c| | |
#Map each symbol to its "truthiness" form the case | |
encountered = [] | |
str.scan(/[A-Z]/) do |match| | |
if encountered.index(match) == nil | |
symbols[match.to_sym] = c.pop | |
encountered << match | |
end | |
end | |
print "|" | |
#Print out the table of truthiness for the case | |
symbols.each_value { |v| print "#{v.to_s.center(7)}|"} | |
#Create the string of truths to be evaluated | |
result_str = str.gsub(/([A-Z])/) { |m| "#{symbols[$1.to_sym]} "} | |
#A test printout for checking validity | |
# print " #{result_str }" | |
#evaluate the whole string and format it | |
print "#{eval(result_str).to_s.center(str.length + 2)} |" | |
print "\n" | |
end | |
end | |
end | |
"~((P ^ Q) ^ (~P v R)) ^ ~(~(~(~S v P) ^ Q) v S) ".logical_parse | |
######################## Output ############################## | |
# | P | Q | R | S | !((P and Q) and (!P or R)) and !(!(!(!S or P) and Q) or S) | | |
# | true | true | true | true | false | | |
# | true | true | true | false | false | | |
# | true | true | false | true | false | | |
# | true | true | false | false | false | | |
# | true | false | true | true | false | | |
# | true | false | true | false | false | | |
# | true | false | false | true | false | | |
# | true | false | false | false | false | | |
# | false | true | true | true | false | | |
# | false | true | true | false | false | | |
# | false | true | false | true | false | | |
# | false | true | false | false | false | | |
# | false | false | true | true | false | | |
# | false | false | true | false | false | | |
# | false | false | false | true | false | | |
# | false | false | false | false | false | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment