特許庁が作成したmultimulticheckerに機能を追加した

# 1 始めに
　特許庁のmultimulticheckerは、ブラウザ上で動作し、請求の範囲に、マルチマルチクレームが記載されていることを警告するものです。JavaScript で記載されています。

https://www.jpo.go.jp/system/patent/shinsa/letter/multimultichecker.html

　そして、筆者による修正を施したmultimulticheckerを以下URLにデプロイしました。幾つかの機能が追加してありますので。よろしければお試しください。

https://jpoapi.azurewebsites.net/multimultichecker_ver_1_1_modified/multimultichecker_ver_1_1_modified.html

　筆者による修正版のmultimulticheckerでは、以下のようなマルチマルチクレームも検出可能です。
（１）　特開2008-84045の請求項４，８、９のように「請求項１から、請求項２・・・」のような、接続詞の前後に句点を含む記載。
（２）　再表2017/057087の請求項６のように「請求の範囲第１項から第６項・・・」のような記載（最近は、このような記載は認められないようですが）。
（３）　特開平9-1611の請求項4,6,8,9,10,11,13,14,15のように「特許請求の範囲第一項～第三項のいずれかに記載の・・」のような、請求項番号が漢数字の記載。
（４）　特開2020-190903　の請求項6の「請求項第１項乃至第５項」のような記載。
　
　そして、請求項が複数の請求項を択一的に引用していないとき、例えば「請求項１から３に記載の装置」のような場合には、その旨をエラー表示する機能を有しています。

　なお、同一の機能を有するWordアドインをリリースし、そのアドインに関する記事も投稿しています。

https://osdn.net/projects/multimultiwarning/

https://qiita.com/kenichiro_ayaki/items/e740c425fef981c2a75e

# 2 マルチマルチクレームとは

　マルチクレームとは、他の二以上の請求項の記載を択一的に引用する請求項のことをいいます。

　マルチマルチクレームとは、他の二以上の請求項の記載を択一的に引用して請求項を記載するときに、その引用する請求項が、他の二以上の請求項の記載を択一的に引用するもののことをいいます。つまり、マルチクレームを含む複数の請求項の記載を択一的に引用するもののことです。

　国際調和並びに審査処理負担及び第三者の監視負担の軽減の観点から、令和４年４月１日からマルチマルチクレームを記載してはならない旨の規定が施行されました。

>特許法施行規則第２４条の３第５項［新設］
>　他の二以上の請求項の記載を択一的に引用して請求項を記載するときは、引用する請求項は、他の二以上の請求項の記載を択一的に引用してはならない。

>実用新案法施行規則第２４条の３第５項［新設］
>　他の二以上の請求項の記載を択一的に引用して請求項を記載するときは、引用する請求項は、他の二以上の請求項の記載を択一的に引用してはならない。

　それと共に特許庁からマルチマルチクレームであるか否かを機械的にチェックするツールが配布されました。

　マルチマルチクレームの事例を以下に示します。

### 類型１：請求項４がマルチマルチクレーム
```
【書類名】特許請求の範囲
【請求項１】特定構造のボールベアリング。
【請求項２】内輪がステンレス鋼である請求項１記載のボールベアリング。
【請求項３】外輪がステンレス鋼である請求項１又は２記載のボールベアリング。
【請求項４】外輪の外側に環状緩衝体を設けた請求項１から請求項３のいずれか1項に記載のボールベアリング。
【請求項５】前記環状緩衝体はゴムである請求項４記載のボールベアリング。
```

### 類型２：カテゴリが異なる引用・・・請求項４がマルチマルチクレーム
```
【書類名】特許請求の範囲
【請求項１】特定構造のボールベアリング。
【請求項２】内輪がステンレス鋼である請求項１記載のボールベアリング。
【請求項３】外輪がステンレス鋼である請求項１又は２記載のボールベアリング。
【請求項４】 請求項１～３のいずれか１項に記載のボールベアリングを製造する方法。
```

### 類型３：複数個所の引用部を有する・・・請求項７がマルチマルチクレーム
```
【書類名】特許請求の範囲
【請求項１】特定構造のネジ山を有するボルト。
【請求項２】アルミニウム合金からなる請求項１記載のボルト。
【請求項３】さらにフランジ部を有する請求項１又は２記載のボルト。
【請求項４】特定構造のネジ溝を有するナット。
【請求項５】アルミニウム合金からなる請求項４記載のナット。
【請求項６】さらにフランジ部を有する請求項４又は５記載のナット。
【請求項７】 請求項１から請求項３のいずれか１項に記載のボルト、及び、請求項４から請求項６のいずれか１項に記載のナットからなる締結装置。
```

# 3 マルチマルチクレームチェッカー ver.1.1（特許庁作成）のコード解析結果

　以下の解析結果は、筆者が独自に解析を行ったものです。解析結果に関する問い合わせは当該記事のコメント等でお願いいたします。

## 3.1 fa関数：実行ボタンのクリック時の動作

```js:fa関数
function fa() {
	var a = document.getElementById('ic');
	var b = document.getElementById('or');
	b.innerHTML = '';
	var c;
	try {
		c = fb(a.value);
	} catch (err) {
		alert(err);
		b.value = err;
		return -1;
	}
	var r = fd(c);
	b.innerHTML = r.html;
}
```

　fa関数では、最初にブラウザ画面の「請求項入力」と「結果」のテキストボックスを取得します。
　ブラウザ画面の「請求項入力」のIDが 'ic' です。入力された請求項のテキストは a.value に格納されています。「結果」のIDが 'or' です。ここに結果が表示されます。

　ここでは、請求項テキストを、関数fbに入力して 変数cを得て、変数c を関数fdに入力して変数r を得ます。そして変数r をブラウザ画面の「結果」に表示します。
　なお、エラーが投げられた場合には、警告ダイアログを表示します。

## 3.2 fb関数：マルチマルチクレーム判定動作

```javascript:fb関数の前半
function fb(s) {
	var d = s.replace(/(【請求項[^\】]+】)/g, '【】$1').split('【】');
	s = fc(s);
	var c = {};
	var a = s.split(/【請求項\s*?([0-9]+)\s*?】/g);
	if (a.length === 1) throw new Error('請求項がありません。');
	for (var i = 1, p = -1, di = 1, len = a.length; i < len; i += 2, di++) {
		var k = parseInt(a[i], 10);
		p = (p === -1) ? k - 1 : p;
		if (c[k]) throw new Error('請求項が重複しています。（請求項' + k + ')');
		if (k < p) throw new Error('請求項が昇順に連続していません。（請求項' + k + ')');
		p = k;
		c[k] = {
			'idx': k,
			'org': d[di],
			't': a[i + 1]
		}
	}
```

　fb関数の前半は、請求項テキストをコード化するfc関数を呼び出し、請求項ごとに文章を区切って配列変数cに格納する機能が記載されています。

　c[k]['idx'] には、請求項の項番号が格納されます。
　c[k]['org'] には、請求項のオリジナルテキストが格納されます。例えば"【請求項４】外輪の外側に環状緩衝体を設けた請求項１から請求項３のいずれか1項に記載のボールベアリング。\n"です。
　c[k]['t'] には、請求項のコード化されたテキストが格納されます。例えば"外輪の外側に環状緩衝体を設けた請求項1,2,3の_1項に記載のボールベアリング。"です。

```javascript:fb関数の後半
	for (var k in c) {
		var t = c[k]['t'];
		var mt = t;
		var r = [];
		var m = false;
		var rm = false;
		var mm = false;
		var rmm = false;
		while (ma = mt.match(/(請求項[0-9][,\/&0-9]*)(.*)/)) {
			mt = ma[2];
			var re = new RegExp('(.*)' + ma[0].replace(/[\\^$.*+?()[\]{}|]/g, '\\$&'));
			r.push({
				'fr': t.replace(re, '$1'),
				'rs': ma[1],
				'ref': ma[1].replace('請求項', '').replace(/[,\/&]/g, '\t').replace(/\t+/g,
					'\t').split('\t'),
				'bk': ma[2],
				'nb': {},
				'or': false,
				'and': false,
				'ei': false,
				'm': false,
				'rm': false,
				'mm': false,
				'rmm': false,
			});
			var cr = r.length - 1;
			if (r[cr].fr.length <= 2) {
				r[cr].nb.fr2 = r[cr].fr;
			} else {
				r[cr].nb.fr2 = r[cr].fr.match(/(.[,\/&]*.[,\/&]*)?$/)[1];
			}
			r[cr].nb.bk2 = r[cr].bk.replace(/(.[,\/&]*.[,\/&]*)?(.*)/, '$1');
			r[cr].nb.fr20 = r[cr].fr.substring(r[cr].fr.length - 20);
			r[cr].nb.bk20 = r[cr].bk.substring(0, 20);
			if (r[cr].ref.length > 1) {
				r[cr].m = true;
			} else if (r[cr].nb.fr2.indexOf('/') != -1) {
				r[cr].m = true;
				r[cr].or = true;
				if (cr > 0) r[cr - 1].m = true;
			} else if (r[cr].nb.fr2.indexOf('&') != -1) {
				r[cr].and = true;
				if (r[cr].nb.bk20.indexOf('_') != -1) {
					r[cr].m = true;
					r[cr].ei = true;
					if (cr > 0) r[cr - 1].m = true;
				}
			}
			for (var j = 0, j_len = r[cr].ref.length; j < j_len; j++) {
				var n = parseInt(r[cr].ref[j], 10);
				if (isNaN(n)) continue;
				if (k <= n) {
					throw new Error('先に記載された請求項を引用していません。（請求項' + k + 'から請求項' + n + 'を引用)');
				}
				if (!c[n]) {
					throw new Error('存在しない請求項を引用しています。（請求項' + k + 'から請求項' + n + 'を引用)');
				}
				if (c[n].m || c[n].rm) {
					r[cr].rm = true;
				}
				if (c[n].mm || c[n].rmm) {
					r[cr].rmm = true;
				}
				if (r[cr].rm && r[cr].rmm) break;
			}
			m = (m || r[cr].m);
			rm = (rm || r[cr].rm);
			rmm = (rmm || r[cr].rmm);
			r[cr].mm = (r[cr].m && r[cr].rm);
			mm = (mm || r[cr].mm);
			if (mm && rmm) break;
		}
		c[k]['ref'] = r;
		c[k]['m'] = m;
		c[k]['rm'] = rm;
		c[k]['mm'] = mm;
		c[k]['rmm'] = rmm;
	}
	return c;
}
```
　fb関数の後半は、マルチマルチクレームの判定を行う部分です。
　変数rは、他の請求項を引用している部分の属性を示しています。同一の請求項内に２つの引用部分がある場合に、変数rは２個の要素を持つ配列となります。

　例えば類型３の請求項７の「 請求項１から請求項３のいずれか１項に記載のボルト、及び、請求項４から請求項６のいずれか１項に記載のナットからなる締結装置。」を例に説明すると、
　「請求項１から請求項３」が第１の引用部分、「請求項４から請求項６」が第２の引用部分です。

　r[cr].fr は、他の請求項を引用している部分よりも前の文字列を示します。
　r[cr].rs は、他の請求項を引用している部分本体の文字列です。
　r[cr].refは、他の請求項を引用している項番号の配列です。
　r[cr].bk は、他の請求項を引用している部分よりも後の文字列を示します。
　r[cr].or は、他の請求項を引用している部分よりも前の文字列に、「又は」などが記載されていることを示します。この変数は、他で参照されていません。
　r[cr].andは、他の請求項を引用している部分よりも前の文字列に、「及び」などが記載されていることを示します。この変数は、他で参照されていません。
　r[cr].eiは、他の請求項を引用している部分よりも後の２０文字目までの文字列　に「何れか」などの複数要素から択一的に引用する記載があることを示します。この変数は、他で参照されていません。
　r[cr].m は、この引用部分が複数請求項の択一的引用（マルチクレーム）であることを示します。r[cr].ref に複数の要素（引用している請求項が複数）が有る時に、この変数がtrueとなります。
　r[cr].rmは、この引用部分がマルチクレームの引用（参照）であることを示します。引用している請求項がマルチクレームのとき、この変数がtrueとなります。
　r[cr].mmは、この引用部分がマルチマルチクレームであることを示します。
　r[cr].rmmは、この引用部分がマルチマルチクレームの引用（参照）であることを示します。

　変数cは、請求項に係る配列です。

　c[k]['m'] は、この請求項が複数請求項の択一的引用（マルチクレーム）であることを示します。この請求項に記載されたすべての引用部分のr[cr].m の論理和です。
　c[k]['rm']は、この請求項がマルチクレームの引用（参照）であることを示します。この請求項に記載されたすべての引用部分の参照 r[cr].rm の論理和です。
　c[k]['mm']は、この請求項がマルチマルチクレームであることを示します。この請求項に記載されたすべての引用部分の参照 r[cr].mm の論理和です。
　c[k]['rmm']は、この請求項がマルチマルチクレームの引用（参照）であることを示します。この請求項に記載されたすべての引用部分の参照 r[cr].rmm の論理和です。


## 3.3 fc関数：請求項の引用部分のコード化

```javascript:fc関数
function fc(s) {
	s = s.replace(/[Ａ-Ｚａ-ｚ０-９]/g, function(m) {
		return String.fromCharCode(m.charCodeAt(0) - 0xFEE0);
	});
	s = s.replace(/\s/g, '');
	s = s.replace(
		/[\u30FC\uFF70\uFF0D\u002D\u2212\u301C\uFF5E\u007E\u02DC\u2053]/g, '-');
	s = s.replace(/請求([0-9]+)/g, '請求項$1');
	s = s.replace(/ないし|乃至|ー|～|－|から|~|より/g, '-');
	s = s.replace(
		/いずれか|いづれか|いずれ|いづれ|何れか|何か|何れ|どれか|どちらか|孰れか|孰か|孰れ|少なくとも|少くとも|すくなくとも|少なくても|少くても|すくなくても|少なくも|少くも|尠なくとも|尠くとも|尠なくても|尠くても|尠なくも|尠くも|すくなくも/g,
		'_');
	s = s.replace(/叉は|又は|または|叉|又|また|や|か|もしくは|若しくは|あるいは|或いは|或は|或|それとも|亦は|亦/g, '/');
	s = s.replace(/、|，|／|・|；|：|？/g, ',');
	s = s.replace(/及び|および|及|と|ならびに|並びに|並び|並に|並|かつ|且つ|且/g, '&');
	s = s.replace(/請求項([0-9]+)-請求項([0-9]+)/g, '請求項$1-$2');
	s = s.replace(/請求項([0-9]+)\/請求項([0-9]+)/g, '請求項$1/$2');
	s = s.replace(/請求項([0-9]+),請求項([0-9]+)/g, '請求項$1,$2');
	s = s.replace(/請求項([0-9]+)&請求項([0-9]+)/g, '請求項$1&$2');
	s = s.replace(/-+/g, '-').replace(/\/+/g, '/').replace(/,+/g, ',').replace(
		/&+/g, '&');
	s = s.replace(/請求項([\-,0-9]+)/g, function(m, g) {
		var o = [];
		var og = g.replace(/^,+/g, '').replace(/,+$/g, '').split(',');
		for (var i = 0; i < og.length; i++) {
			var ag = og[i].replace(/^\-+/g, '').replace(/\-+$/g, '').split('-');
			if (ag.length == 1) {
				o.push(parseInt(ag[0], 10));
			} else {
				var st = parseInt(ag[0], 10);
				var ed = parseInt(ag[ag.length - 1], 10);
				for (var jj = st; jj <= ed; jj++) {
					o.push(jj);
				}
			}
		}
		return '請求項' + o.join(',');
	});
	return s;
}
```

　fc関数は、引用部分をコード化する関数です。コード化において、請求項番号は半角に変換され、請求項の接続詞は、,&/-に変換されます。例えば以下です。

「請求項１に記載の…」⇒　「請求項1に記載の…」
「請求項１，２に記載の…」⇒　「請求項1,2に記載の…」
「請求項１または２に記載の…」⇒　「請求項1/2に記載の…」
「請求項１から３の何れかに記載の…」⇒　「請求項1-3の_に記載の…」
「請求項１および２の何れかに記載の…」⇒　「請求項1&2の_に記載の…」

そして、s.replace から呼び出される replacefunction により、値の範囲を示す '-' と、その両端の請求項番号は、以下のように数字とカンマに羅列に変換されます。
「請求項1-3の_に記載の…」⇒　「請求項1,2,3の_に記載の…」

## 3.4 fd関数：結果の生成

```javascript:fd関数
function fd(c) {
	var r = {
		str: '',
		html: '',
		del: [],
		mm: [],
		rmm: [],
	};
	var max = -1;
	for (var i in c) {
		i = parseInt(i, 10);
		if (max < i) max = i;
	}
	for (var i = 1; i <= max; i++) {
		if (!c[i]) {
			r.del.push(i);
			continue;
		}
		if (c[i].mm) {
			r.mm.push(i);
			r.html += '<span style="background-color:yellow;">';
		} else if (!c[i].mm && c[i].rmm) {
			r.rmm.push(i);
			r.html += '<span style="background-color:aqua;">';
		} else {
			r.html += '<span>'
		}
		r.html += c[i].org.replace(/\r\n/g, '\n').replace(/\n/g, '<br>') + '</span>';
	}
	if (r.del.length > 0) {
		r.str += '存在しない請求項：請求項' + r.del.join(',') + '\n';
	}
	if (r.mm.length > 0 && r.rmm.length > 0) {
		r.str += 'マルチマルチクレームとして検出された請求項：請求項' + r.mm.join(',') + '\n' +
			'上記の請求項以外でマルチマルチクレームを引用する請求項：請求項' + r.rmm.join(',') + '\n';
	} else if (r.mm.length > 0) {
		r.str += 'マルチマルチクレームとして検出された請求項：請求項' + r.mm.join(',') + '\n';
	} else {
		r.str += 'マルチマルチクレームは検出されませんでした。' + '\n';
	}
	r.html = '<span>' + r.str.replace('\n', '<br>') + '</span>' + '<br><br>' +
		'＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝' + '<br><br>' + r.html;
	return r;
}
```

　結果として、警告メッセージが変数rに設定されます。
　請求項の配列 c[k] に基づき、結果の構造体に３つの配列を設定しています。

　r.del は、存在しない請求項の番号の配列です。
　r.mm は、マルチマルチクレームとして検出された請求項の番号の配列です。
　r.rmm は、マルチマルチクレームの参照として検出された請求項の番号の配列です。
　r.str は、エラーメッセージです。
　r.html は、「結果」に表示されるhtml です。

## 3.5 fe関数：結果のクリア

```javascript:fe関数
function fe() {
	if (confirm('入力した請求項および結果をクリアしてよろしいですか？')) {
		document.getElementById('ic').value = '';
		document.getElementById('or').innerHTML = '';
	}
}
```
 fe関数は、クリアボタンが呼び出されたときの関数です。'入力した請求項および結果をクリアしてよろしいですか？'のメッセージボックスを表示したのち、請求項入力と結果をクリアします。

# 4 マルチマルチクレームチェッカー ver.1.1 の修正版のコード説明

　以下は、マルチマルチクレームチェッカー ver.1.1 に対して筆者が独自に修正したのです。修正に関する問い合わせは当該記事のコメント等でお願いいたします。
　fa関数、fd関数、fe関数は変更しておらず、fb関数とfc関数のみ修正しています。


## 4.1 fb関数：マルチマルチクレーム判定動作

```javascript:fb関数
function fb(s) {
	var d = s.replace(/(【請求項[^\】]+】)/g, '【】$1').split('【】');
	s = fc(s);
	var c = {};
	var a = s.split(/【請求項\s*?([0-9]+)\s*?】/g);
	if (a.length === 1) throw new Error('請求項がありません。');
	for (var i = 1, p = -1, di = 1, len = a.length; i < len; i += 2, di++) {
		var k = parseInt(a[i], 10);
		p = (p === -1) ? k - 1 : p;
		if (c[k]) throw new Error('請求項が重複しています。（請求項' + k + ')');
		if (k < p) throw new Error('請求項が昇順に連続していません。（請求項' + k + ')');
		p = k;
		c[k] = {
			'idx': k,
			'org': d[di],
			't': a[i + 1]
		}
	}
	for (var k in c) {
		var t = c[k]['t'];
		var mt = t;
		var r = [];
		var m = false;
		var rm = false;
		var mm = false;
		var rmm = false;
		var mc = '';
		while (ma = mt.match(/(請求項[0-9][,\/&0-9]*)(.*)/)) {
			mt = ma[2];
			r.push({
				'fr': mc,
				'rs': ma[1],
				'ref': ma[1].replace('請求項', '').replace(/[,\/&]/g, '\t').replace(/\t+/g,
					'\t').split('\t'),
				'bk': ma[2],
				'nb': {},
				'or': false,
				'and': false,
				'ei': false,
				'm': false,
				'rm': false,
				'mm': false,
				'rmm': false,
			});
			var cr = r.length - 1;
			if (cr == 0)
			{
				r[cr].nb.fr2 = '';
			}
			else if (r[cr].fr.length <= 2) {
				r[cr].nb.fr2 = r[cr].fr;
			} else {
				r[cr].nb.fr2 = r[cr].fr.match(/([,\/&]*)?$/)[1];
			}
			if (r[cr].bk.indexOf('請求項') != -1) {
				r[cr].bk = r[cr].bk.substring(0,r[cr].bk.indexOf('請求項'));
			}
			mc = r[cr].bk;
			r[cr].nb.bk20 = r[cr].bk.substring(0,20);
			if (r[cr].ref.length > 1) {
				r[cr].m = true;
			} else if (r[cr].nb.fr2.indexOf('/') != -1) {
				r[cr].m = true;
				r[cr].or = true;
				if (cr > 0) r[cr - 1].m = true;
			} else if (r[cr].nb.fr2.indexOf('&') != -1) {
				r[cr].and = true;
				if (r[cr].nb.bk20.indexOf('_') != -1) {
					r[cr].m = true;
					r[cr].ei = true;
					if (cr > 0) r[cr - 1].m = true;
				} else {
					throw new Error('請求項が択一的に引用されていません。（請求項' + k + ')');
				}
			}
			if (r[cr].rs.indexOf('&') != -1) {
				r[cr].and = true;
				if (r[cr].nb.bk20.indexOf('_') != -1) {
					r[cr].ei = true;
				} else {
					throw new Error('請求項が択一的に引用されていません。（請求項' + k + ')');
				}
			}
			for (var j = 0, j_len = r[cr].ref.length; j < j_len; j++) {
				var n = parseInt(r[cr].ref[j], 10);
				if (isNaN(n)) continue;
				if (k <= n) {
					throw new Error('先に記載された請求項を引用していません。（請求項' + k + 'から請求項' + n + 'を引用)');
				}
				if (!c[n]) {
					throw new Error('存在しない請求項を引用しています。（請求項' + k + 'から請求項' + n + 'を引用)');
				}
				if (c[n].m || c[n].rm) {
					r[cr].rm = true;
				}
				if (c[n].mm || c[n].rmm) {
					r[cr].rmm = true;
				}
			}
			m = (m || r[cr].m);
			rm = (rm || r[cr].rm);
			rmm = (rmm || r[cr].rmm);
			r[cr].mm = (r[cr].m && r[cr].rm);
			mm = (mm || r[cr].mm);
		}
		c[k]['ref'] = r;
		c[k]['m'] = m;
		c[k]['rm'] = rm;
		c[k]['mm'] = mm;
		c[k]['rmm'] = rmm;
	}
	return c;
}
```
 変数rは、他の請求項を引用している部分を示しています。同一の請求項内に２つの引用部分がある場合に、変数rは２個の要素を持つ配列となります。

　r[cr].fr は、他の請求項を引用している部分よりも前で、かつそれ以前の引用部分よりも後です。
　r[cr].rs は、他の請求項を引用している部分本体です。
　r[cr].refは、他の請求項を引用している項番号の配列です。
　r[cr].bk は、他の請求項を引用している部分よりも後で、かつ次の引用部分よりも前を示します。
　r[cr].or は、この引用部分にて他の請求項を「又は」で引用していることを示します。この変数は後で参照されていないので、削除しました。
　r[cr].andは、この引用部分にて他の請求項を「及び」で引用していることを示します。この変数は後で参照されておらず、請求項の状態を示すデバッグ用変数ではないかとおもいます。
　r[cr].eiは、この引用部分より後に、「何れか」などの複数要素から択一的に引用する記載があることを示します。この変数は後で参照されておらず、請求項の状態を示すデバッグ用変数ではないかとおもいます。

　なお「及び」などの接続詞で請求項番号を接続していながら、その後に「何れか」などの択一的に引用する記載がなければエラーを投げて終了します。

　r[cr].m は、この引用部分が複数請求項の択一的引用（マルチクレーム）であることを示します。
　r[cr].rmは、この引用部分がマルチクレームの引用（参照）であることを示します。
　r[cr].mmは、この引用部分がマルチマルチクレームであることを示します。
　r[cr].rmmは、この引用部分がマルチマルチクレームの引用（参照）であることを示します。

　c[k]['m'] は、この請求項が複数請求項の択一的引用（マルチクレーム）であることを示します。
　c[k]['rm']は、この請求項がマルチクレームの引用（参照）であることを示します。
　c[k]['mm']は、この請求項がマルチマルチクレームであることを示します。
　c[k]['rmm']は、この請求項がマルチマルチクレームの引用（参照）であることを示します。

## 4.2 fc関数：請求項の引用部分のコード化

```javascript:fc関数
function fc(s) {
	s = s.replace(/[Ａ-Ｚａ-ｚ０-９]/g, function(m) {
		return String.fromCharCode(m.charCodeAt(0) - 0xFEE0);
	});
	s = s.replace(/[〇一二三四五六七八九十百千万億兆]+/g, function(m) {
		const kansuji = "〇一二三四五六七八九";

		var val0 = 0;
		var val1 = 0;
		var val2 = 0;
		for(let i=0; i<m.length; i++) {
			if(kansuji.indexOf(m[i]) != -1) {
				val0 = kansuji.indexOf(m[i]) + val0*10;
			} else if(m[i] == "十") {
				if (val0 == 0) {
					val1 += 10;
				} else {
					val1 += val0*10;
					val0 = 0;
				}
			} else if(m[i] == "百") {
				if (val0 == 0) {
					val1 += 100;
				} else {
					val1 += val0*100;
					val0 = 0;
				}
			} else if(m[i] == "千") {
				if (val0 == 0) {
					val1 += 1000;
				} else {
					val1 += val0*1000;
					val0 = 0;
				}
			} else if(m[i] == "万") {
				if ((val0 + val1) == 0) {
					val2 += 10000;
				} else {
					val2 += (val1 + val0)*10000;
				}
				val1 = 0;
				val0 = 0;
			} else if(m[i] == "億") {
				if ((val0 + val1) == 0) {
					val2 += 10000*10000;
				} else {
					val2 += (val1 + val0)*10000*10000;
				}
				val1 = 0;
				val0 = 0;
			} else if(m[i] == "兆") {
				if ((val0 + val1) == 0) {
					val2 += 10000*10000*10000;
				} else {
					val2 += (val1 + val0)*10000*10000*10000;
				}
				val1 = 0;
				val0 = 0;
			}
		}
		val2 += (val1 + val0);
		return String(val2);
	});
	s = s.replace(/\s/g, '');
	s = s.replace(
		/[\u30FC\uFF70\uFF0D\u002D\u2212\u301C\uFF5E\u007E\u02DC\u2053]/g, '-');
	s = s.replace(/請求([0-9]+)/g, '請求項$1');
	s = s.replace(/ないし|乃至|ー|～|－|から|~|より/g, '-');
	s = s.replace(
		/の?(いずれか?|いづれか?|何れか?|何か|どれか|どちらか|孰れ?か|孰れ|少な?くとも|すくなくとも|少な?くても|すくなくても|少な?くも|尠な?くとも|尠な?くても|尠な?くも|すくなくも)/g,
		'_');
	s = s.replace(/叉は?|又は?|または?|や|か|もしくは|若しくは|あるいは|或い?は|或は?|それとも|亦は?/g, '/');
	s = s.replace(/、|，|／|・|；|：|？/g, ',');
	s = s.replace(/及び?|および|と|ならびに|並びに?|並び?|並に?|かつ|且つ?/g, '&');
	s = s.replace(/,+/g, ',');
	s = s.replace(/,&+,|,&+|&+,|&+/g, '&');
	s = s.replace(/,\/+,|,\/+|\/+,|\/+/g, '/');
	s = s.replace(/,-+,|,-+|-+,|-+/g, '-');
	s = s.replace(/請求項第?([0-9]+)項?/g, '請求項$1');
	s = s.replace(/請求の範囲第?([0-9]+)項?/g, '請求項$1');
	s = s.replace(/([,\/&\-])第?([0-9]+)項?/g, '$1$2');
	s = s.replace(/1項|一項|ひとつ|一つ|1つ/g, '_');
	do {
		var s1 = s;
		s = s.replace(/請求項([0-9]+)([-\/,&]+)請求項([0-9]+)/g, '請求項$1$2$3');
	} while(s1 != s);
	
	s = s.replace(/請求項([\-,0-9]+)/g, function(m, g) {
		var o = [];
		var og = g.replace(/^,+/g, '').replace(/,+$/g, '').split(',');
		for (var i = 0; i < og.length; i++) {
			var ag = og[i].replace(/^\-+/g, '').replace(/\-+$/g, '').split('-');
			if (ag.length == 1) {
				o.push(parseInt(ag[0], 10));
			} else {
				var st = parseInt(ag[0], 10);
				var ed = parseInt(ag[ag.length - 1], 10);
				for (var jj = st; jj <= ed; jj++) {
					o.push(jj);
				}
			}
		}
		return '請求項' + o.join('&');
	});
	return s;
}

```

　請求項の引用部分の接続詞の前後に句点を含む場合を考慮しました。これにより以下類型に対応可能です。

### 類型１の「から」の後に句点を入れた：請求項４がマルチマルチクレーム
```
【書類名】特許請求の範囲
【請求項１】特定構造のボールベアリング。
【請求項２】内輪がステンレス鋼である請求項１記載のボールベアリング。
【請求項３】外輪がステンレス鋼である請求項１又は２記載のボールベアリング。
【請求項４】外輪の外側に環状緩衝体を設けた請求項１から、請求項３のいずれか1項に記載のボールベアリング。
【請求項５】前記環状緩衝体はゴムである請求項４記載のボールベアリング。
```
　漢数字を半角数字に変換しました。これにより、請求項番号が漢数字で記載されている場合でもマルチマルチクレームを検出可能です。なお、漢数字は、従前の「三百」のような記載と、アラビア数字のように大数を桁で表す「三〇〇」のような記載の両方に対応しています。

### 類型１の漢数字による変形：請求項４がマルチマルチクレーム
```
【書類名】特許請求の範囲
【請求項１】特定構造のボールベアリング。
【請求項２】内輪がステンレス鋼である請求項一記載のボールベアリング。
【請求項３】外輪がステンレス鋼である請求項一又は二記載のボールベアリング。
【請求項４】外輪の外側に環状緩衝体を設けた請求項一から請求項三のいずれか一項に記載のボールベアリング。
【請求項５】前記環状緩衝体はゴムである請求項四記載のボールベアリング。
```
　そして、「請求の範囲第１項に記載の…」のような形式の記載があれば、「請求項１に記載の」に書き換えるようにしました。
　更に、「請求項第１項に記載の…」のような形式の記載があれば、「請求項１に記載の」に書き換えるようにしました。

　「請求項１から請求項３・・・」などの範囲を示す記載の場合、
　「請求項1&2&3・・・」のようにコード化しました。範囲を示す接続詞は、「及び」のような接続詞に準ずるためです。

# 5 謝辞
　このような大変に興味深いツールをご提供いただいた特許庁および、そののご担当者さまに、ここに感謝の意を表します。