Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Паттерны проектирования 6.2

Паттерны проектирования 6.2

Паттерн Интерпретатор.

Avatar for Vitaly Shlyaga

Vitaly Shlyaga

December 14, 2012
Tweet

More Decks by Vitaly Shlyaga

Other Decks in Education

Transcript

  1. Интерпретатор 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
  2. Интерпретатор 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
  3. Интерпретатор 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
  4. Интерпретатор 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
  5. Интерпретатор class Not < Expression def initialize(expression) @expression = expression

    end def evaluate(dir) All.new.evaluate(dir) - @expression.evaluate(dir) end end 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')
  6. Интерпретатор 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 big_or_mp3_expr = Or.new( Bigger.new(1024), FileName.new('*.mp3') ) big_or_mp3s = big_or_mp3_expr.evaluate('test_dir')
  7. Интерпретатор 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
  8. # and (and(bigger 1024)(filename *.mp3)) writable 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
  9. Интерпретатор class Expression def |(other) Or.new(self, other) end def &(other)

    And.new(self, other) end end #Or.new( # And.new(Bigger.new(2000), Not.new(Writable.new)), # FileName.new('*.mp3')) (Bigger.new(2000) & Not.new(Writable.new)) | FileName.new("*.mp3")
  10. Интерпретатор def all All.new end def bigger(size) Bigger.new(size) end def

    name(pattern) FileName.new(pattern) end def except(expression) Not.new(expression) end def writable Writable.new end # (bigger(2000) & except(writable) ) | file_name('*.mp3')