Skip to content

Instantly share code, notes, and snippets.

@znz
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save znz/9835956 to your computer and use it in GitHub Desktop.
Save znz/9835956 to your computer and use it in GitHub Desktop.
Ruby/Rails勉強会@関西 60th #rubykansai のプレゼン用に作成した正規表現(ごく一部)の動作をステップ表示するアプリ
source "https://rubygems.org"
ruby "2.1.1"
gem "sinatra"
GEM
remote: https://rubygems.org/
specs:
rack (1.5.2)
rack-protection (1.5.2)
rack
sinatra (1.4.4)
rack (~> 1.4)
rack-protection (~> 1.4)
tilt (~> 1.3, >= 1.3.4)
tilt (1.4.1)
PLATFORMS
ruby
DEPENDENCIES
sinatra
web: bundle exec ruby regexp-201403.rb -p $PORT
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
require 'sinatra'
def make_link(re, str)
require 'erb'
%Q[<li><a href="/#{URI.encode_www_form_component(re)}/#{URI.encode_www_form_component(str)}/0">/#{ERB::Util.h(re)}/ =~ "#{ERB::Util.h(str)}"</a></li>]
end
example = [
make_link("abc", "abracadabra"),
make_link("ada", "abracadabra"),
make_link("a(?=br)a", "abracadabra"),
make_link("a(?=.r)b.a", "abracadabra"),
make_link("foo(?=bar)", "foobar"),
make_link("(?=foo)bar", "foobar"),
]
get '/' do
example.join('')
end
def step(state)
STDERR.puts state.inspect
return state if state[:step] <= 0
reg_range = state[:reg_range]
str_range = state[:str_range]
if state[:reg][reg_range.end, 3] == '(?='
state[:outer_range] = {
reg_range: reg_range,
str_range: str_range,
}
state[:reg_range] = reg_range.end+3...reg_range.end+3
state[:str_range] = str_range.end...str_range.end
elsif state[:reg][reg_range.end] == ')' && state[:outer_range]
state[:reg_range] = reg_range.end+1...reg_range.end+1
state[:str_range] = state[:outer_range][:str_range].end...state[:outer_range][:str_range].end
elsif state[:reg][reg_range.end] == '.'
state[:reg_range] = reg_range.begin...reg_range.end+1
state[:str_range] = str_range.begin...str_range.end+1
elsif state[:reg][reg_range.end] == state[:str][str_range.end]
state[:reg_range] = reg_range.begin...reg_range.end+1
state[:str_range] = str_range.begin...str_range.end+1
elsif state[:finished]
state[:reg_range] = 0...0
state[:str_range] = str_range.begin+1...str_range.begin+1
state[:finished] = false
else
if state[:reg].length == reg_range.end
state[:finished] = :matched
else
state[:finished] = :failed
end
end
state[:step] -= 1
step(state)
end
get '/:reg/:str/:step' do
reg = params[:reg]
str = params[:str]
n = params[:step].to_i
result = step(reg: reg, str: str, step: n, reg_range: 0...0, str_range: 0...0, finished: false)
reg_range = result[:reg_range]
str_range = result[:str_range]
finished = result[:finished]
case finished
when :failed
reg[reg_range.end, 1] &&= '<span class="failed">' + reg[reg_range.end, 1] + '</span>'
str[str_range.end, 1] &&= '<span class="failed">' + str[str_range.end, 1] + '</span>'
end
reg[reg_range] &&= '<span class="reg-step">' + reg[reg_range] + '</span>'
if str[str_range]
str[str_range] &&= '<span class="str-step">' + str[str_range] + '</span>'
else
match_failed = true
end
[
%Q[<style type="text/css">.failed{border:5px solid red} .reg-step{border:5px solid green} .str-step{border:5px solid blue}</style>],
%Q[<p style="font-size:128px">/#{reg}/ =~ "#{str}"</p>],
finished == :matched ? %Q[<p>matched</p>] : "",
match_failed ? %Q[<p>failed</p>] : "",
%Q[<p><a href="#{n-1}">prev</a> <a href="#{n+1}">next</a></p>],
*example,
].join("")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment