Skip to content

Commit df473b6

Browse files
(?:(*MAX[A]{3})a|(*MAX[B]{5})b)*(*CMP{A,<,B})
1 parent 91f35b4 commit df473b6

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed

MEMO_onig/callout/015.txt

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
======================================================
2+
callout.c の結果と考察 no.015 2022/06/11
3+
======================================================
4+
5+
## line: 254
6+
test(enc, mp, "(?:(*MAX[A]{3})a|(*MAX[B]{5})b)*(*CMP{A,<,B})", "abababc");
7+
8+
9+
この1行による出力が以下のもの
10+
11+
--------------------------
12+
match at 1
13+
0: (1-6)
14+
--------------------------
15+
16+
17+
1. この正規表現の縮図
18+
19+
"abababc" =~ /(?:a|b)*/
20+
21+
22+
23+
2. [A] と [B]
24+
25+
(*MAX[A]{3}) => (*MAX{3}) に "A" という識別用の名前を付けたもの。
26+
27+
(*MAX[B]{5}) => (*MAX{5}) に "B" という識別用の名前を付けたもの。
28+
29+
この名前のことを "tag" と呼ぶ。
30+
31+
32+
33+
3. (*CMP{A,<,B})
34+
35+
これは以下の条件を満たした場合のみ (*CMP{A,<,B}) 自身のマッチに成功する。
36+
37+
-------------------------------------------------------------------------
38+
(*MAX[A]{3}) のマッチ回数 < (*MAX[B]{5}) のマッチ回数
39+
-------------------------------------------------------------------------
40+
41+
この "マッチ回数" とは (*CMP{A,<,B}) が試された時点での [A] と [B] のマッチ回数を指す。
42+
この条件を満たさない場合は (*FAIL) と同じ動作になり、バックトラックを発生させる。
43+
44+
この条件より、 "b" にマッチした回数が "a" にマッチした回数より多い場合でないと (*CMP{A,<,B}) のマッチは成功しない。
45+
46+
CALLOUTS.BUILTIN.ja : (*CMP ) の説明
47+
https://github.com/kkos/oniguruma/blob/316ee632e26cd71acfa65e2cdb93a603a147d05a/doc/CALLOUTS.BUILTIN.ja#L79
48+
49+
50+
51+
4. 0: (1-6)
52+
53+
対象テキストは "ababab" という順で始まっており、先頭の位置からの検索では "a" が先にマッチするため、
54+
"a" が "b" よりもマッチ回数が少なくなることは無い。
55+
そのため先頭の位置からの検索では (*CMP{A,<,B}) のマッチは成功しない。
56+
57+
検索開始位置が1つ進み、1 の位置から検索が始まると今度は "b" が先にマッチするので {A,<,B} の条件を満たす場面がある。
58+
繰り返しにより 6 の位置まで到達した時点ではマッチ回数が A=2, B=3 になっているので (*CMP{A,<,B}) は条件を満たし、
59+
全体マッチに成功する。 このため結果は (1-6) になる。
60+
61+
62+
63+
5. (*MAX )
64+
65+
今回のテストコードでは (*MAX ) がマッチ回数の上限に到達して (*FAIL) の動作になる場面は [A] , [B] ともにない。
66+
このマッチ回数の上限がいらない場合にはこれの代わりに (*COUNT ) を使うことが出来る。
67+
68+
CALLOUTS.BUILTIN.ja : (*COUNT ) の説明
69+
https://github.com/kkos/oniguruma/blob/316ee632e26cd71acfa65e2cdb93a603a147d05a/doc/CALLOUTS.BUILTIN.ja#L43
70+
71+
72+
## line: 254 のテストコードの (*MAX ) を (*COUNT ) で代用したコード
73+
------------------------------------
74+
test(enc, mp, "(?:(*COUNT[A]{X})a|(*COUNT[B]{X})b)*(*CMP{A,<,B})", "abababc");
75+
------------------------------------
76+
77+
この1行による出力が以下のもの
78+
79+
--------------------------
80+
match at 1
81+
0: (1-6)
82+
--------------------------
83+
84+
結果が line: 254 のテストコードと同じになっている。 => (*COUNT ) での代用成功
85+
86+
87+
(*COUNT ) の { } の中身が "X" になっている点に注意。 (*COUNT ) の { } の中ではカウント方法を指定をするが、
88+
(*COUNT ) のカウント方法がデフォルトでは ">" なのに対し、 (*MAX ) のカウント方法はデフォルトでは "X" なので
89+
(*MAX ) の代用として (*COUNT ) を使いたい場合には (*MAX ) と同じカウント方法を指定しなければならない。
90+
91+
(*MAX ) のデフォルトのカウント方法: "X"
92+
(*COUNT ) のデフォルトのカウント方法: ">"
93+
(*TOTAL_COUNT ) のデフォルトのカウント方法: ">"
94+
95+
96+
97+
98+
おわり
99+
100+
101+

0 commit comments

Comments
 (0)