左再帰
A : A B0
| A B1
...
| A Bn
| C0
| C1
...
| Cn
※1 B0 ... Bn はε(空)ではない
※2 C0 ... Cn は A を先頭に持たない
左再帰を消す
A : C0 A_tail?
| C1 A_tail?
...
| Cn A_tail?
A_tail : B0 A_tail?
| B1 A_tail?
...
| Bn A_tail?
いろいろやってみよう
左再帰
A : A B0
| A B1
...
| A Bn
| C0
| C1
...
| Cn
左再帰を消す
A : C0 A_tail?
| C1 A_tail?
...
| Cn A_tail?
A_tail : B0 A_tail?
| B1 A_tail?
...
| Bn A_tail?
厳密には正しくないけど今はまぁこれで十分な感じの正規表現
valid_chars = '[0-9A-Za-z_!#\$%&*+\-\/=\?^_{|}\~\.]+'
valid_pattern = Regexp.new("^(#{valid_chars})@(#{valid_chars})$", nil, 'n')