Skip to content

Instantly share code, notes, and snippets.

@avescodes
Created October 1, 2008 21:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save avescodes/14199 to your computer and use it in GitHub Desktop.
Save avescodes/14199 to your computer and use it in GitHub Desktop.
Simple logic parser I did for an assignment
#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