|
| 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