Skip to content

Instantly share code, notes, and snippets.

@mmagm
Created August 27, 2013 13:19
Show Gist options
  • Save mmagm/6353411 to your computer and use it in GitHub Desktop.
Save mmagm/6353411 to your computer and use it in GitHub Desktop.
require 'find'
class Expression
def |(other)
Or.new(self,other)
end
def &(other)
And.new(self,other)
end
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
def all
All.new
end
def bigger(size)
Bigger.new(size)
end
def file_name(pattern)
FileName.new(pattern)
end
def except(expression)
Not.new(expression)
end
def writable
Writable.new
end
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 == ')'
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
expr_all = All.new
files = expr_all.evaluate('/home/mma/work/develop/ruby/')
expr_not_writable = Not.new(Writable.new)
readonly_files = expr_not_writable.evaluate('test_dir')
small_expr = Not.new(Bigger.new(1024))
small_files = small_expr.evaluate('test_dir')
not_mp3_expr = Not.new(FileName.new('*.mp3'))
not_mp3s = not_mp3_expr.evaluate('test_dir')
big_or_mp3_expr = Or.new(Bigger.new(1024), FileName.new('*.mp3'))
big_or_mp3s = big_or_mp3_expr.evaluate('test_dir')
complex_expression = And.new(
And.new(Bigger.new(1024),
FileName.new('*.mp3')),
Not.new(Writable.new))
complex_expression.evaluate('test_dir')
complex_expression.evaluate('/tmp')
parser = Parser.new "and (and(bigger 1024)(filename *.mp3)) writable"
ast = parser.expression
(bigger(2000) & except(writable) ) | file_name('*.mp3')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment