Schemeの数値リテラルにマッチする正規表現

3839bytes.もっと短くしたいなぁ.見辛いので適当に改行を挿入.

/(?:(?:(?:#b)(?:(?:#[ei])?)|(?:(?:#[ei])?)(?:#b))(?:(?:(?:(?:[+-])?)(?:(?:(?:[01
])+#*)|(?:(?:(?:[01])+#*)\/(?:(?:[01])+#*))|(?:(?!))))|(?:(?:(?:(?:[+-])?)(?:(?:
(?:[01])+#*)|(?:(?:(?:[01])+#*)\/(?:(?:[01])+#*))|(?:(?!))))@(?:(?:(?:[+-])?)(?:
(?:(?:[01])+#*)|(?:(?:(?:[01])+#*)\/(?:(?:[01])+#*))|(?:(?!)))))|(?:(?:(?:(?:[+-
])?)(?:(?:(?:[01])+#*)|(?:(?:(?:[01])+#*)\/(?:(?:[01])+#*))|(?:(?!))))[+\-](?:(?
:(?:[01])+#*)|(?:(?:(?:[01])+#*)\/(?:(?:[01])+#*))|(?:(?!)))?i)|(?:[+\-](?:(?:(?
:[01])+#*)|(?:(?:(?:[01])+#*)\/(?:(?:[01])+#*))|(?:(?!)))?i)))|(?:(?:(?:#o)(?:(?
:#[ei])?)|(?:(?:#[ei])?)(?:#o))(?:(?:(?:(?:[+-])?)(?:(?:(?:[0-7])+#*)|(?:(?:(?:[
0-7])+#*)\/(?:(?:[0-7])+#*))|(?:(?!))))|(?:(?:(?:(?:[+-])?)(?:(?:(?:[0-7])+#*)|(
?:(?:(?:[0-7])+#*)\/(?:(?:[0-7])+#*))|(?:(?!))))@(?:(?:(?:[+-])?)(?:(?:(?:[0-7])
+#*)|(?:(?:(?:[0-7])+#*)\/(?:(?:[0-7])+#*))|(?:(?!)))))|(?:(?:(?:(?:[+-])?)(?:(?
:(?:[0-7])+#*)|(?:(?:(?:[0-7])+#*)\/(?:(?:[0-7])+#*))|(?:(?!))))[+\-](?:(?:(?:[0
-7])+#*)|(?:(?:(?:[0-7])+#*)\/(?:(?:[0-7])+#*))|(?:(?!)))?i)|(?:[+\-](?:(?:(?:[0
-7])+#*)|(?:(?:(?:[0-7])+#*)\/(?:(?:[0-7])+#*))|(?:(?!)))?i)))|(?:(?:(?:(?:#d)?)
(?:(?:#[ei])?)|(?:(?:#[ei])?)(?:(?:#d)?))(?:(?:(?:(?:[+-])?)(?:(?:(?:[0-9])+#*)|
(?:(?:(?:[0-9])+#*)\/(?:(?:[0-9])+#*))|(?:(?:(?:(?:[0-9])+#*)(?:(?:(?:[esfdl])(?
:(?:[+-])?)(?:[0-9])+)?))|(?:\.(?:[0-9])+#*(?:(?:(?:[esfdl])(?:(?:[+-])?)(?:[0-9
])+)?))|(?:(?:[0-9])+\.(?:[0-9])*#*(?:(?:(?:[esfdl])(?:(?:[+-])?)(?:[0-9])+)?))|
(?:\.(?:[0-9])+#+\.#*(?:(?:(?:[esfdl])(?:(?:[+-])?)(?:[0-9])+)?)))))|(?:(?:(?:(?
:[+-])?)(?:(?:(?:[0-9])+#*)|(?:(?:(?:[0-9])+#*)\/(?:(?:[0-9])+#*))|(?:(?:(?:(?:[
0-9])+#*)(?:(?:(?:[esfdl])(?:(?:[+-])?)(?:[0-9])+)?))|(?:\.(?:[0-9])+#*(?:(?:(?:
[esfdl])(?:(?:[+-])?)(?:[0-9])+)?))|(?:(?:[0-9])+\.(?:[0-9])*#*(?:(?:(?:[esfdl])
(?:(?:[+-])?)(?:[0-9])+)?))|(?:\.(?:[0-9])+#+\.#*(?:(?:(?:[esfdl])(?:(?:[+-])?)(
?:[0-9])+)?)))))@(?:(?:(?:[+-])?)(?:(?:(?:[0-9])+#*)|(?:(?:(?:[0-9])+#*)\/(?:(?:
[0-9])+#*))|(?:(?:(?:(?:[0-9])+#*)(?:(?:(?:[esfdl])(?:(?:[+-])?)(?:[0-9])+)?))|(
?:\.(?:[0-9])+#*(?:(?:(?:[esfdl])(?:(?:[+-])?)(?:[0-9])+)?))|(?:(?:[0-9])+\.(?:[
0-9])*#*(?:(?:(?:[esfdl])(?:(?:[+-])?)(?:[0-9])+)?))|(?:\.(?:[0-9])+#+\.#*(?:(?:
(?:[esfdl])(?:(?:[+-])?)(?:[0-9])+)?))))))|(?:(?:(?:(?:[+-])?)(?:(?:(?:[0-9])+#*
)|(?:(?:(?:[0-9])+#*)\/(?:(?:[0-9])+#*))|(?:(?:(?:(?:[0-9])+#*)(?:(?:(?:[esfdl])
(?:(?:[+-])?)(?:[0-9])+)?))|(?:\.(?:[0-9])+#*(?:(?:(?:[esfdl])(?:(?:[+-])?)(?:[0
-9])+)?))|(?:(?:[0-9])+\.(?:[0-9])*#*(?:(?:(?:[esfdl])(?:(?:[+-])?)(?:[0-9])+)?)
)|(?:\.(?:[0-9])+#+\.#*(?:(?:(?:[esfdl])(?:(?:[+-])?)(?:[0-9])+)?)))))[+\-](?:(?
:(?:[0-9])+#*)|(?:(?:(?:[0-9])+#*)\/(?:(?:[0-9])+#*))|(?:(?:(?:(?:[0-9])+#*)(?:(
?:(?:[esfdl])(?:(?:[+-])?)(?:[0-9])+)?))|(?:\.(?:[0-9])+#*(?:(?:(?:[esfdl])(?:(?
:[+-])?)(?:[0-9])+)?))|(?:(?:[0-9])+\.(?:[0-9])*#*(?:(?:(?:[esfdl])(?:(?:[+-])?)
(?:[0-9])+)?))|(?:\.(?:[0-9])+#+\.#*(?:(?:(?:[esfdl])(?:(?:[+-])?)(?:[0-9])+)?))
))?i)|(?:[+\-](?:(?:(?:[0-9])+#*)|(?:(?:(?:[0-9])+#*)\/(?:(?:[0-9])+#*))|(?:(?:(
?:(?:[0-9])+#*)(?:(?:(?:[esfdl])(?:(?:[+-])?)(?:[0-9])+)?))|(?:\.(?:[0-9])+#*(?:
(?:(?:[esfdl])(?:(?:[+-])?)(?:[0-9])+)?))|(?:(?:[0-9])+\.(?:[0-9])*#*(?:(?:(?:[e
sfdl])(?:(?:[+-])?)(?:[0-9])+)?))|(?:\.(?:[0-9])+#+\.#*(?:(?:(?:[esfdl])(?:(?:[+
-])?)(?:[0-9])+)?))))?i)))|(?:(?:(?:#x)(?:(?:#[ei])?)|(?:(?:#[ei])?)(?:#x))(?:(?
:(?:(?:[+-])?)(?:(?:(?:[0-9a-f])+#*)|(?:(?:(?:[0-9a-f])+#*)\/(?:(?:[0-9a-f])+#*)
)|(?:(?!))))|(?:(?:(?:(?:[+-])?)(?:(?:(?:[0-9a-f])+#*)|(?:(?:(?:[0-9a-f])+#*)\/(
?:(?:[0-9a-f])+#*))|(?:(?!))))@(?:(?:(?:[+-])?)(?:(?:(?:[0-9a-f])+#*)|(?:(?:(?:[
0-9a-f])+#*)\/(?:(?:[0-9a-f])+#*))|(?:(?!)))))|(?:(?:(?:(?:[+-])?)(?:(?:(?:[0-9a
-f])+#*)|(?:(?:(?:[0-9a-f])+#*)\/(?:(?:[0-9a-f])+#*))|(?:(?!))))[+\-](?:(?:(?:[0
-9a-f])+#*)|(?:(?:(?:[0-9a-f])+#*)\/(?:(?:[0-9a-f])+#*))|(?:(?!)))?i)|(?:[+\-](?
:(?:(?:[0-9a-f])+#*)|(?:(?:(?:[0-9a-f])+#*)\/(?:(?:[0-9a-f])+#*))|(?:(?!)))?i)))
/i

テスト結果.

accept: 0
accept: 10
accept: 256
accept: +10
accept: -10
accept: 10.0
accept: .0
accept: 0.
accept: 10e3
accept: 10e+2
accept: 10e-2
accept: 10s+3
accept: 10f+3
accept: 10d+3
accept: 10l+3
accept: 13+3i
accept: +i
accept: -i
accept: 13.0+3.0i
accept: +.1i
accept: .1+i
accept: #d256
accept: #xff
accept: #b1010
accept: #o256
accept: #e256
accept: #i256
accept: #e#xff
accept: #x#eff
accept: 3/4
accept: #i3/4
accept: #e3/4
accept: #i.75
accept: #e.75
accept: 1@1
accept: 1.2@3.4
reject: #xff.ff
reject: 10e+i
reject: #b2
reject: #o9
reject: f
reject: +
reject: #f

多分いけてる.こんなに長い正規表現を書いたのは初めてだなぁ.手書きじゃないけど.強欲マッチにできるところは強欲マッチにしないと,遅いかもしれない.
上の正規表現を生成するコード.

exponent_marker = /[esfdl]/
sign = /(?:[+-])?/
exactness = /(?:#[ei])?/
radix_ary = /#b/, /#o/, /(?:#d)?/, /#x/
digit = /[0-9]/
digit_ary = /[01]/, /[0-7]/, digit, /[0-9a-f]/
suffix = /(?:#{exponent_marker}#{sign}#{digit}+)?/

ary = Array.new(4) {|i|
  r_prefix = /#{radix_ary[i]}#{exactness}|#{exactness}#{radix_ary[i]}/
  r_nosign_integer = /#{digit_ary[i]}+#*/
  r_float = if 2 == i
              Regexp.union(/#{r_nosign_integer}#{suffix}/,
                           /\.#{digit}+#*#{suffix}/,
                           /#{digit}+\.#{digit}*#*#{suffix}/,
                           /\.#{digit}+#+\.#*#{suffix}/)
            else
              /(?!)/
            end
  r_nosign_real = Regexp.union(r_nosign_integer,
                               /#{r_nosign_integer}\/#{r_nosign_integer}/,
                               r_float)
  r_real = /#{sign}#{r_nosign_real}/
  r_complex = Regexp.union(r_real,
                           /#{r_real}@#{r_real}/,
                           /#{r_real}[+\-]#{r_nosign_real}?i/,
                           /[+\-]#{r_nosign_real}?i/)
  r_number = /#{r_prefix}#{r_complex}/
}

re = Regexp.new(Regexp.union(ary).source.gsub(/-mix/, ""), Regexp::IGNORECASE)