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

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

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

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

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')