import files
This commit is contained in:
commit
6a6fdb12fb
165
LICENSE
Normal file
165
LICENSE
Normal file
|
@ -0,0 +1,165 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
57
Rakefile
Normal file
57
Rakefile
Normal file
|
@ -0,0 +1,57 @@
|
|||
require 'rubygems'
|
||||
require 'rake'
|
||||
|
||||
begin
|
||||
require 'jeweler'
|
||||
Jeweler::Tasks.new do |gem|
|
||||
gem.name = "RegExpr"
|
||||
gem.summary = %Q{Regular Expression Creator}
|
||||
gem.description = %Q{Write Regular Expressions in a Hash and generats an optimized Regex}
|
||||
gem.email = "Denis.Knauf@gmail.com"
|
||||
gem.homepage = "http://github.com/DenisKnauf/RegExpr"
|
||||
gem.authors = ["Denis Knauf"]
|
||||
gem.files = ["README.md", "VERSION", "lib/**/*.rb", "test/**/*.rb"]
|
||||
gem.require_paths = ["lib"]
|
||||
end
|
||||
Jeweler::GemcutterTasks.new
|
||||
rescue LoadError
|
||||
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
||||
end
|
||||
|
||||
require 'rake/testtask'
|
||||
Rake::TestTask.new(:test) do |test|
|
||||
test.libs << 'lib' << 'test' << 'ext'
|
||||
test.pattern = 'test/**/*_test.rb'
|
||||
test.verbose = true
|
||||
end
|
||||
|
||||
begin
|
||||
require 'rcov/rcovtask'
|
||||
Rcov::RcovTask.new do |test|
|
||||
test.libs << 'test'
|
||||
test.pattern = 'test/**/*_test.rb'
|
||||
test.verbose = true
|
||||
end
|
||||
rescue LoadError
|
||||
task :rcov do
|
||||
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
||||
end
|
||||
end
|
||||
|
||||
task :test => :check_dependencies
|
||||
|
||||
task :default => :test
|
||||
|
||||
require 'rake/rdoctask'
|
||||
Rake::RDocTask.new do |rdoc|
|
||||
if File.exist?('VERSION')
|
||||
version = File.read('VERSION')
|
||||
else
|
||||
version = ""
|
||||
end
|
||||
|
||||
rdoc.rdoc_dir = 'rdoc'
|
||||
rdoc.title = "sbdb #{version}"
|
||||
rdoc.rdoc_files.include('README*')
|
||||
rdoc.rdoc_files.include('lib/**/*.rb')
|
||||
end
|
39
RegExpr.gemspec
Normal file
39
RegExpr.gemspec
Normal file
|
@ -0,0 +1,39 @@
|
|||
# Generated by jeweler
|
||||
# DO NOT EDIT THIS FILE DIRECTLY
|
||||
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = %q{RegExpr}
|
||||
s.version = "0.0.1"
|
||||
|
||||
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||
s.authors = ["Denis Knauf"]
|
||||
s.date = %q{2010-03-18}
|
||||
s.description = %q{Write Regular Expressions in a Hash and generats an optimized Regex}
|
||||
s.email = %q{Denis.Knauf@gmail.com}
|
||||
s.extra_rdoc_files = [
|
||||
"LICENSE"
|
||||
]
|
||||
s.files = [
|
||||
"VERSION",
|
||||
"lib/regexpr-uri.rb",
|
||||
"lib/regexpr.rb"
|
||||
]
|
||||
s.homepage = %q{http://github.com/DenisKnauf/RegExpr}
|
||||
s.rdoc_options = ["--charset=UTF-8"]
|
||||
s.require_paths = ["lib"]
|
||||
s.rubygems_version = %q{1.3.6}
|
||||
s.summary = %q{Regular Expression Creator}
|
||||
|
||||
if s.respond_to? :specification_version then
|
||||
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
||||
s.specification_version = 3
|
||||
|
||||
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
||||
else
|
||||
end
|
||||
else
|
||||
end
|
||||
end
|
||||
|
62
lib/regexpr-uri.rb
Normal file
62
lib/regexpr-uri.rb
Normal file
|
@ -0,0 +1,62 @@
|
|||
require 'regexpr.rb'
|
||||
|
||||
class Uri
|
||||
class Flags< Array
|
||||
class <<self
|
||||
def new p
|
||||
self[ p. split( /[&;]/) ]
|
||||
end
|
||||
end
|
||||
|
||||
def to_s
|
||||
join '&'
|
||||
end
|
||||
end
|
||||
|
||||
class <<self
|
||||
def new uri
|
||||
uri. instance_of?( Uri) ? uri. dup : super( uri)
|
||||
end
|
||||
end
|
||||
|
||||
attr_accessor :scheme, :username, :password, :host, :port, :path, :file, :flags, :fragment
|
||||
def initialize( uri) self. uri= uri end
|
||||
def uri() self. pre+ self. uri+ (self. fragment ? '#'+ self. fragment : '') end
|
||||
alias to_s uri
|
||||
def pre() (self. scheme ? self. scheme+ '://' : '')+ self. serv end
|
||||
def serv() (self. host|| '')+ (self. port ? ':'+ self. port : '') end
|
||||
|
||||
def uri
|
||||
(self. path || '')+ (self. file || '')+ (self. flags ? '?'+ self. flags : '')
|
||||
end
|
||||
|
||||
RegExpr = ::RegExpr[
|
||||
:scheme => '( "http" | "ftp" ) "s" ? | "sftp" | "fish"',
|
||||
:username => '[^:@]*',
|
||||
:password => '[^@]*',
|
||||
:host => 'hostname | ipv4',
|
||||
:port => 'digit +',
|
||||
:path => '( "/" ? [^?#]* "/" ) ?',
|
||||
:file => '[^/?#] *',
|
||||
:flags => '[^#] *',
|
||||
:fragment => '. *',
|
||||
'ipv4digits' => '0..255',
|
||||
'ipv6digits' => '[0-9a-bA-B] {1,4}',
|
||||
'userinfo' => 'username ( ":" password ) ?',
|
||||
'domainlabel' => 'alphadigit ( ( alphadigit | "-" ) * alphadigit ) ?',
|
||||
'hostname' => 'domainlabel ( "." | domainlabel ) *',
|
||||
'ipv4' => 'ipv4digits ( "." ipv4digits ) {3}',
|
||||
'request_uri' => '( path ? file ) ? ( "?" flags ) ?',
|
||||
'serv' => 'host ( ":" port ? ) ?',
|
||||
'pre' => '( ( scheme "://" ) ( auth "@" ) ? serv ) ?',
|
||||
'uri' => 'pre request_uri ( "#" fragment ) ?',
|
||||
'main' => 'uri'
|
||||
]
|
||||
RegExpr. def self, :path, :uri, :pre, :serv, :request_uri
|
||||
end
|
||||
|
||||
def Uri( uri) Uri.new uri end
|
||||
|
||||
class String
|
||||
def to_uri() Uri. new self end
|
||||
end
|
458
lib/regexpr.rb
Normal file
458
lib/regexpr.rb
Normal file
|
@ -0,0 +1,458 @@
|
|||
|
||||
class RegExpr< Hash
|
||||
end
|
||||
|
||||
class RegExpr::Segment
|
||||
attr_accessor :value
|
||||
def initialize( val) self. value= val end
|
||||
def to_r() self. value. to_s end
|
||||
def empty?() self. value. nil? end
|
||||
def names() @value. names. flatten. compact end
|
||||
|
||||
def optimize
|
||||
self. value= self. class. optimize self. value
|
||||
self
|
||||
end
|
||||
|
||||
class <<self
|
||||
def optimize v
|
||||
v= v. optimize
|
||||
v= nil if v && v. empty?
|
||||
v= v. value[ 0] if v. instance_of?( RegExpr::Block) && v. hidden && v. size == 1
|
||||
v
|
||||
end
|
||||
|
||||
def deepest
|
||||
self. class_eval do
|
||||
def names() [] end
|
||||
end
|
||||
end
|
||||
|
||||
def novalue
|
||||
self. class_eval do
|
||||
def initialize() end
|
||||
def empty?() false end
|
||||
def to_r() '' end
|
||||
def optimize() self end
|
||||
end
|
||||
end
|
||||
|
||||
def nooptimize
|
||||
self. class_eval do
|
||||
def optimize() self end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class RegExpr::Block< RegExpr::Segment
|
||||
attr_accessor :name, :hidden
|
||||
def hidden?() @hidden end
|
||||
def optimize() self. dup. optimize! end
|
||||
def push( *v) @value. push *v end
|
||||
def pop() @value. pop end
|
||||
def empty?() @value. empty? end
|
||||
def size() @value. size end
|
||||
|
||||
def names
|
||||
names= @value. collect {|v| v. names }
|
||||
names. push( name) unless self. hidden?
|
||||
names. flatten. compact
|
||||
end
|
||||
|
||||
def initialize *val
|
||||
val= val[ 0] if val. size == 1 && val[ 0]. instance_of?( Array)
|
||||
super val
|
||||
@hidden= true
|
||||
end
|
||||
|
||||
def optimize!
|
||||
list, chars= [[]], RegExpr::Chars. new( '')
|
||||
|
||||
@value. each do |v|
|
||||
v= self. class. optimize v
|
||||
if v.instance_of? RegExpr::Or
|
||||
list. push []
|
||||
else list[ -1]. push v
|
||||
end
|
||||
end
|
||||
|
||||
list. delete_if do |v|
|
||||
if v. size == 1 && ( v[ 0]. instance_of?( RegExpr::Chars) || v[ 0]. instance_of?( RegExpr::Char) )
|
||||
chars+= v[ 0]
|
||||
else false
|
||||
end
|
||||
end
|
||||
chars= chars. optimize
|
||||
|
||||
values= []
|
||||
list. each do |v|
|
||||
values. push RegExpr::Or. new
|
||||
values+= if v. size == 1 &&
|
||||
v[ 0]. instance_of?( RegExpr::Block) &&
|
||||
v[ 0]. hidden
|
||||
v[ 0]. value
|
||||
else
|
||||
v. collect do |w|
|
||||
if w. instance_of?( RegExpr::Block) && w. hidden
|
||||
u= false
|
||||
w. value. each do |i|
|
||||
break unless u||= i. instance_of?( RegExpr::Or)
|
||||
end
|
||||
u ? w : w. value
|
||||
else w
|
||||
end
|
||||
end. flatten
|
||||
end
|
||||
end
|
||||
values.push RegExpr::Or. new, chars if chars. size > 0
|
||||
values. shift
|
||||
@value= values
|
||||
self
|
||||
end
|
||||
|
||||
def to_r()
|
||||
(@hidden ? '(?:%s)' : '(%s)')% @value. collect {|i| i.to_r }. join( '')
|
||||
end
|
||||
end
|
||||
|
||||
class RegExpr::Not< RegExpr::Segment
|
||||
deepest
|
||||
novalue
|
||||
def to_r
|
||||
if @value. instance_of? RegExpr::Chars
|
||||
@value. not!
|
||||
@value. to_s
|
||||
else '(?!%s)'% @value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class RegExpr::Range< RegExpr::Segment
|
||||
novalue
|
||||
attr_accessor :v1, :v2
|
||||
def names() [] end
|
||||
def optimize() self. value. optimize end
|
||||
def to_r() self. optimize. to_r end
|
||||
def initialize( v1, v2) @v1, @v2= v1, v2 end
|
||||
|
||||
# algo stolen from thomas leitner
|
||||
def value
|
||||
a, b= @v1< @v2 ? [ @v1, @v2] : [ @v2, @v1]
|
||||
arr= Array[ a]
|
||||
|
||||
af= a == 0 ? 1.0 : a. to_f
|
||||
bf= b == 0 ? 1.0 : b. to_f
|
||||
1. upto( b. to_s. length- 1) do |i|
|
||||
pot= 10** i
|
||||
num= (af/ pot). ceil* pot # next higher number with i zeros
|
||||
arr. insert i, num if num < @v2
|
||||
num= (bf/ pot). floor* pot # next lower number with i zeros
|
||||
arr. insert -i, num
|
||||
end
|
||||
arr. uniq!
|
||||
arr. push b+ 1 # +1 -> to handle it in the same way as the other elements
|
||||
|
||||
result= RegExpr::Block. new
|
||||
0. upto( arr. length- 2) do |i|
|
||||
first= arr[ i]. to_s
|
||||
second= (arr[ i+ 1]- 1).to_s
|
||||
result. push RegExpr::Or. new
|
||||
0. upto( first. length- 1) do |j|
|
||||
result. push( if first[ j] == second[ j]
|
||||
RegExpr::Char. new first[ j]. chr
|
||||
else
|
||||
RegExpr::Chars. new '%c-%c'% [ first[ j], second[ j] ]
|
||||
end)
|
||||
end
|
||||
end
|
||||
result. value. shift
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
class RegExpr::Chars< RegExpr::Segment
|
||||
deepest
|
||||
attr_reader :chars, :not
|
||||
def to_r() '[%s]'% self. value end
|
||||
def not?() @not end
|
||||
def empty?() @chars. empty? end
|
||||
def size() @chars. size end
|
||||
def value=( val) @chars= (@not= val[ 0] == ?^) ? val[ 1.. -1] : val end
|
||||
def value() (self. not? ? '^' : '')+ (@chars) end
|
||||
def not!() @not= !@not end
|
||||
alias -@ not!
|
||||
|
||||
def split
|
||||
chars= []
|
||||
@chars. gsub( /\\-/) do |r|
|
||||
chars. push ?-
|
||||
nil
|
||||
end. gsub( /.-./) do |r|
|
||||
chars+= ((r[ 0] .. r[ 2]). to_a)
|
||||
nil
|
||||
end. each_byte do |c|
|
||||
chars. push c
|
||||
end
|
||||
chars
|
||||
end
|
||||
|
||||
def optimize!
|
||||
b2chr= lambda do |b|
|
||||
"-[]".include?( b.chr) ? '\%c'% b : b. chr
|
||||
end
|
||||
chars= self. chars. bytes. sort. uniq
|
||||
$stderr.puts chars.inspect
|
||||
@chars= ''
|
||||
return self if chars. empty?
|
||||
b= chars. shift
|
||||
chars. each do |i|
|
||||
if b+1 == i
|
||||
unless @chars[ -1] == ?- && @chars[-2] != ?\\
|
||||
@chars+= b2chr. call( b)+ '-'
|
||||
end
|
||||
else @chars+= b2chr. call b
|
||||
end
|
||||
b= i
|
||||
end
|
||||
@chars+= b2chr. call b
|
||||
self
|
||||
end
|
||||
|
||||
def optimize
|
||||
n= self. dup. optimize!
|
||||
if (n. size == 1 || (n. size == 2 && n. value[ 0] == ?\\ )) && ! n. not?
|
||||
RegExpr::Char. new n. chars[ -1]. chr
|
||||
else n
|
||||
end
|
||||
end
|
||||
|
||||
def + b
|
||||
chars= self. not? ? '^' : ''
|
||||
chars+= if b. instance_of? RegExpr::Char
|
||||
self. split.push b. value[ 0]
|
||||
elsif self. not? == b. not?
|
||||
self. split+ b. split
|
||||
elsif self. not?
|
||||
(0.. 255). to_a- self. split+ b. split
|
||||
else
|
||||
(0.. 255). to_a- b. split+ self. split
|
||||
end. compact. uniq. collect {|i| i. chr }. join( '')
|
||||
self. class. new chars
|
||||
end
|
||||
end
|
||||
|
||||
class RegExpr::Repeat< RegExpr::Segment
|
||||
attr_reader :min, :max
|
||||
|
||||
def minandmax x
|
||||
case x
|
||||
when nil, '' then nil
|
||||
else x. to_i
|
||||
end
|
||||
end
|
||||
|
||||
def optimize
|
||||
super
|
||||
min == 1 && max == 1 ? @value : self
|
||||
end
|
||||
|
||||
def initialize value, min= 1, max= min
|
||||
super value
|
||||
@min, @max= self. minandmax( min), self. minandmax( max)
|
||||
end
|
||||
|
||||
def to_r
|
||||
t= '{%s,%s}'% [ @min||'', @max||'' ]
|
||||
t= Hash[ *%w<{,1} ? {0,1} ? {0,} * {,} * {1,} +>+ ['{1,1}', ''] ][ t]|| t
|
||||
@value. to_r+ t
|
||||
end
|
||||
end
|
||||
|
||||
class RegExpr::Char< RegExpr::Segment
|
||||
deepest
|
||||
nooptimize
|
||||
def to_r() ::Regexp. quote @value end
|
||||
def size() 1 end
|
||||
|
||||
def self. new x
|
||||
x= x. split( ''). collect {|i| super i }
|
||||
x. size == 1 ? x[ 0] : RegExpr::Block. new( x)
|
||||
end
|
||||
end
|
||||
|
||||
class RegExpr::Regexp< RegExpr::Segment
|
||||
deepest
|
||||
nooptimize
|
||||
def to_r() @value. to_s end
|
||||
end
|
||||
|
||||
class RegExpr::Or< RegExpr::Segment
|
||||
deepest
|
||||
novalue
|
||||
def to_r() '|' end
|
||||
def to_s() '|' end
|
||||
end
|
||||
|
||||
class RegExpr::End< RegExpr::Segment
|
||||
deepest
|
||||
novalue
|
||||
def to_r() '$' end
|
||||
def to_s() '$' end
|
||||
end
|
||||
|
||||
class RegExpr::Begin< RegExpr::Segment
|
||||
deepest
|
||||
novalue
|
||||
def to_r() '^' end
|
||||
def to_s() '^' end
|
||||
end
|
||||
|
||||
class RegExpr::WildCard< RegExpr::Segment
|
||||
deepest
|
||||
nooptimize
|
||||
def to_r() @value end
|
||||
def to_s() @value end
|
||||
end
|
||||
|
||||
class RegExpr
|
||||
class <<self
|
||||
STDEXP= Hash[
|
||||
'loalpha' => '[a-z]',
|
||||
'hialpha' => '[A-Z]',
|
||||
'alpha' => 'loalpha | hialpha',
|
||||
'digit' => '[0-9]',
|
||||
'alphadigit' => 'alpha | digit',
|
||||
'hexdigit' => 'digit | [a-fA-F]',
|
||||
'octdigit' => '[0-7]',
|
||||
'bindigit' => '[01]',
|
||||
'space' => '[ \t\n\r\v]'
|
||||
]
|
||||
|
||||
def [] *vals
|
||||
ret= super *vals
|
||||
STDEXP. each {|k, v| ret[ k]||= v }
|
||||
ret
|
||||
end
|
||||
|
||||
def new *vals
|
||||
ret= super *vals
|
||||
STDEXP. each {|k, v| ret[ k]||= v }
|
||||
ret
|
||||
end
|
||||
end
|
||||
|
||||
def to_r exp= :main
|
||||
r = self. to_re( exp). optimize
|
||||
h, r = r. hidden?, r. to_r
|
||||
r = r[ 1...-1] unless h
|
||||
::Regexp. new r
|
||||
end
|
||||
|
||||
def to_re exp= :main
|
||||
u= RegExpr::Block. new
|
||||
t, u. hidden= if exp. instance_of? Symbol
|
||||
u. name= exp. to_sym
|
||||
if self[ exp]
|
||||
[ self[ exp], false]
|
||||
else [ self[ exp. to_s], true]
|
||||
end
|
||||
else [ exp. to_s, true]
|
||||
end
|
||||
|
||||
until !t || t. empty?
|
||||
v, t= self. to_r_next t
|
||||
case v
|
||||
when ')' then return u, t
|
||||
when RegExpr::Repeat then v. value= u. pop
|
||||
end
|
||||
u. push v
|
||||
end
|
||||
u
|
||||
end
|
||||
|
||||
def to_r_next exp
|
||||
exp. strip!
|
||||
/^/. match exp[ 1.. -1]
|
||||
t= case exp[ 0]
|
||||
when ?^ then return RegExpr::Begin. new, exp[ 1.. -1]
|
||||
when ?$ then return RegExpr::End. new, exp[ 1.. -1]
|
||||
when ?\\
|
||||
h= case exp[ 1]
|
||||
when ?D, ?S, ?W, ?a, ?d.. ?f, ?n, ?r.. ?t, ?v, ?w
|
||||
return RegExpr::WildCard. new( '\%c'% exp[ 1]), exp[ 2.. -1]
|
||||
when ?x then 16
|
||||
when ?o then 8
|
||||
when ?b then 2
|
||||
when ?0.. ?9
|
||||
exp= 'XX'+ exp[ 1.. -1]
|
||||
10
|
||||
else Kernel. raise ArgumentError, 'Unknown form "%s"'% exp
|
||||
end
|
||||
i= exp[ 2.. -1]. to_i h
|
||||
return RegExpr::Char. new( i.chr), exp[ (i. to_s( h). size+ 2).. -1]
|
||||
|
||||
when ?. then return RegExpr::WildCard. new( '.'), exp[ 1.. -1]
|
||||
|
||||
when ?0
|
||||
case exp[ 1]
|
||||
when ?x then %r<^0x([0-9a-f]+)>i. match exp
|
||||
return '', $1. to_i( 16). to_s+ $'
|
||||
when ?o then %r<^0o([0-8]+)>. match exp
|
||||
return '', $1. to_i( 8). to_s+ $'
|
||||
when ?b then %r<^0b([01]+)>. match exp
|
||||
return '', $1. to_i( 2). to_s+ $'
|
||||
else
|
||||
case exp
|
||||
when %r<(\d+)..(\d+)> then RegExpr::Range. new $1. to_i, $2. to_i
|
||||
when %r<^(\d+,\d+|,\d+|\d+,?)> then RegExpr::Repeat. new '', *$1. split( ',')
|
||||
else Kernel. raise ArgumentError, 'Unknown form "%s"'% exp
|
||||
end
|
||||
end
|
||||
|
||||
when ?( then return self. to_re( exp[ 1.. -1])
|
||||
when ?) then ')'
|
||||
when ?| then RegExpr::Or. new
|
||||
|
||||
when ?+ then RegExpr::Repeat. new '', 1, nil
|
||||
when ?* then RegExpr::Repeat. new '', nil
|
||||
when ?? then RegExpr::Repeat. new '', 0, 1
|
||||
|
||||
when ?" then RegExpr::Char. new %r<^"((?:[^"]|\\")*)">. match( exp)[ 1]
|
||||
when ?[ then RegExpr::Chars. new %r<^\[((?:[^\]]|\\\])*[^\\]|)\]>. match( exp)[ 1]
|
||||
when ?/ then exp =~ %r<^/((?:[^/]|\\/)*)/(im?|mi)?>
|
||||
RegExpr::Regexp. new ::Regexp. new( $1,
|
||||
($2 =~ /i/ ? ::Regexp::IGNORECASE : 0)+
|
||||
($2 =~ /m/ ? ::Regexp::MULTILINE : 0))
|
||||
|
||||
else
|
||||
case exp
|
||||
when %r<^([a-z_][a-z_0-9]*\b)>i then self. to_re $1. to_sym
|
||||
when %r<(\d+)..(\d+)> then RegExpr::Range. new $1. to_i, $2. to_i
|
||||
when %r<^(\d+,\d+|,\d+|\d+,?)> then RegExpr::Repeat. new '', *$1. split( ',')
|
||||
else Kernel. raise ArgumentError, 'Unknown form "%s"'% exp
|
||||
end
|
||||
end
|
||||
[ t, $' ]
|
||||
end
|
||||
|
||||
def def cl= Class. new, *exp
|
||||
exp= [ :main ] if exp. empty?
|
||||
exp. each do |e|
|
||||
re= self. to_re e
|
||||
names= re. names. collect {|n| '@%s'% n }. join ', '
|
||||
re= ::Regexp. new '^%s$'% re. optimize. to_r
|
||||
ev= <<-EOF
|
||||
def #{e}= val
|
||||
m= #{re. inspect}. match val
|
||||
raise ArgumentError, 'Unallowed Chars! (%s =~ #{re. inspect})'% val. inspect unless m
|
||||
#{names}= *m[ 1.. -1]
|
||||
end
|
||||
EOF
|
||||
cl. class_eval ev
|
||||
end
|
||||
cl
|
||||
end
|
||||
|
||||
def match( m, exp= :main) self. to_r( exp). match m end
|
||||
end
|
Loading…
Reference in a new issue