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

Pattern Matching

Pattern Matching

MagRails 2011

Aaron Patterson

May 11, 2011
Tweet

More Decks by Aaron Patterson

Other Decks in Programming

Transcript

  1. omg

  2. 0. Excited to be in England 1. English country, I

    have accent. 2. Fear and guilt 3. Fear of plugs and outlets 4. Can't stop thinking of strange 5. Romance Ebi
  3. digraph nfa { rankdir=LR; world [shape = doublecircle]; hello [shape

    = circle]; hello -> world [label="greeting"]; } graph.dot
  4. digraph nfa { rankdir=LR; world [shape = doublecircle]; hello [shape

    = circle]; goodbye [shape = circle]; hello -> world [label="greeting"]; goodbye -> world } graph.dot
  5. References • Compilers: Principles, Techniques, & Tools (Aho, Lam, Sethi,

    Ullman) • Intro to Formal Languages and Automata (Linz)
  6. ◦ ◦ b ◦ b a * a b ()

    | Describe node types
  7. OR AST parser = Journey::Parser.new trees = [ '/articles(.:format)', '/articles/new(.:format)',

    ].map { |s| parser.parse s } ast = Journey::Nodes::Or.new trees puts ast.to_dot
  8. | ◦ ◦ ◦ () / articles ◦ . :format

    ◦ () ◦ new ◦ / / articles ◦ . :format
  9. 3 0 b 2 a b 1 a a b

    b a Double circle is acceptance state
  10. Storage class DFA attr_reader :table def initialize @table = Hash.new

    { |h, from| h[from] = {} } @table[0]['a'] = 1 @table[0]['b'] = 0 @table[1]['a'] = 1 @table[1]['b'] = 2 @table[2]['a'] = 1 @table[2]['b'] = 3 @table[3]['b'] = 0 @table[3]['a'] = 2 end end
  11. class Simulator def initialize(dfa) @dfa = dfa end def simulate(symbols)

    state = 0 until symbols.empty? state = @dfa.move(state, symbols.shift) end state end end
  12. 6 0 2 ε 4 ε 3 a 5 b

    ε ε nil-closure
  13. Storage class NFA def initialize @table = Hash.new { |h,

    from| h[from] = Hash.new { |i,sym| i[sym] = [] } } @table[0][nil] << 2 @table[0][nil] << 4 @table[2]['a'] << 3 @table[4]['b'] << 5 @table[3][nil] << 6 @table[5][nil] << 6 end def nil_closure(states) states.map { |s| @table[s][nil] }.flatten end end
  14. FSM Simulation class Simulator def initialize(nfa) @nfa = nfa end

    def simulate(symbols) states = @nfa.nil_closure([0]) until symbols.empty? next_s = @nfa.move(states, symbols.shift) states = @nfa.nil_closure(next_s) end states end end
  15. irb> sim = Simulator.new(NFA.new) => #<Simulator:0x007faa188a5f88 ...> irb> sim.simulate %w{

    a } => [6] irb> sim.simulate %w{ b } => [6] irb> sim.simulate %w{ b b } => [] irb> sim.simulate %w{ c } => []
  16. 6 0 1 / 2 articles ε 3 ε 4

    . 5 :format ε /articles(.:format)
  17. CODES! parser = Journey::Parser.new ast = parser.parse '/articles(.:format)' nfa =

    Journey::NFA::Builder.new ast tt = nfa.transition_table.generalized_table puts tt.to_dot
  18. SHORTER CODES! parser = Journey::Parser.new ast = parser.parse '/articles(.:format)' dfa

    = Journey::GTG::Builder.new ast tt = dfa.transition_table puts tt.to_dot
  19. 2 3 . 4 / 5 6 8 . 7

    9 / 10 . 11 12 14 . 13 15 0 1 / users (?-mix:[^./?]+) new (?-mix:[^./?]+) (?-mix:[^./?]+) edit (?-mix:[^./?]+) (?-mix:[^./?]+) resource :users
  20. Rails Console irb> File.open('out.html', 'wb') { |f| irb* f.write( irb*

    Wot::Application.routes.router.visualizer irb> )} => 69074
  21. Table => JSON parser = Journey::Parser.new ast = parser.parse '/articles(.:format)'

    dfa = Journey::GTG::Builder.new ast tt = dfa.transition_table puts tt.to_json
  22. Table => SVG parser = Journey::Parser.new ast = parser.parse '/articles(.:format)'

    dfa = Journey::GTG::Builder.new ast tt = dfa.transition_table puts tt.to_svg
  23. JS Tokenizer function tokenize(input, callback) { while(input.length > 0) {

    callback(input.match(/^[\/\.\?]|[^\/\.\?]+/)[0]); input = input.replace(/^[\/\.\?]|[^\/\.\?]+/, ''); } }
  24. JS Simulator tokenize(input, function(token) { var new_states = []; for(var

    key in states) { var state = states[key]; if(string_states[state] && string_states[state][token]) { var new_state = string_states[state][token]; highlight_edge(state, new_state); highlight_state(new_state); new_states.push(new_state); } } if(new_states.length == 0) { return; } states = new_states; });