Skip to content

Instantly share code, notes, and snippets.

@monzou
Created June 12, 2011 13:36
Show Gist options
  • Save monzou/1021557 to your computer and use it in GitHub Desktop.
Save monzou/1021557 to your computer and use it in GitHub Desktop.
parser
class Parser
def initialize(text)
@tokens = text.scan(/\(|\)|[\w\.\*]+/)
end
def next_token
@tokens.shift
end
def expression
token = next_token
if token == nil
return nil
elsif token == '('
result = expression
raise "Expected )" unless next_token == ')'
return result
elsif token == 'all'
return All.new
elsif token == 'writable'
return Writable.new
elsif token == 'bigger'
return Bigger.new(next_token.to_i)
elsif token == 'filename'
return FileName.new(next_token)
elsif token == 'not'
return Not.new(expression)
elsif token == 'and'
return And.new(expression, expression)
elsif token == 'or'
return Or.new(expression, expression)
else
raise "Unexpected token: #{token}"
end
end
end
require 'find'
class Expression
end
class All < Expression
def evaluate(dir)
results = []
Find.find(dir) do |p|
next unless File.file?(p)
results << p
end
results
end
end
class FileName < Expression
def initialize(pattern)
@pattern = pattern
end
def evaluate(dir)
results = []
Find.find(dir) do |p|
next unless File.file?(p)
name = File.basename(p)
results << p if File.fnmatch(@pattern, name)
end
results
end
end
class Bigger < Expression
def initialize(size)
@size = size
end
def evaluate(dir)
results = []
Find.find(dir) do |p|
next unless File.file?(p)
results << p if (File.size(p) > @size)
end
results
end
end
class Writable < Expression
def evaluate(dir)
results = []
Find.find(dir) do |p|
next unless File.file?(p)
results << p if (File.writable?(p))
end
results
end
end
class Not < Expression
def initialize(expression)
@expression = expression
end
def evaluate(dir)
All.new.evaluate(dir) - @expression.evaluate(dir)
end
end
class Or < Expression
def initialize(expression1, expression2)
@expression1 = expression1
@expression2 = expression2
end
def evaluate(dir)
result1 = @expression1.evaluate(dir)
result2 = @expression2.evaluate(dir)
(result1 + result2).sort_uniq
end
end
class And < Expression
def initialize(expression1, expression2)
@expression1 = expression1
@expression2 = expression2
end
def evaluate(dir)
result1 = @expression1.evaluate(dir)
result2 = @expression2.evaluate(dir)
(result1 & result2)
end
end
expr = FileName.new("*.rb")
expr.evaluate(".").map { |f| puts f }
parser = Parser.new "and(and(bigger 512)(filename *.rb)) writable"
ast = parser.expression
ast.evaluate(".").map { |f| puts f }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment