LoginSignup
0
2

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-04-03

1 始めに

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

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

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

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

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

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

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

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

特許法施行規則第24条の3第5項[新設]
 他の二以上の請求項の記載を択一的に引用して請求項を記載するときは、引用する請求項は、他の二以上の請求項の記載を択一的に引用してはならない。

実用新案法施行規則第24条の3第5項[新設]
 他の二以上の請求項の記載を択一的に引用して請求項を記載するときは、引用する請求項は、他の二以上の請求項の記載を択一的に引用してはならない。

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

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

類型1:請求項4がマルチマルチクレーム

【書類名】特許請求の範囲
【請求項1】特定構造のボールベアリング。
【請求項2】内輪がステンレス鋼である請求項1記載のボールベアリング。
【請求項3】外輪がステンレス鋼である請求項1又は2記載のボールベアリング。
【請求項4】外輪の外側に環状緩衝体を設けた請求項1から請求項3のいずれか1項に記載のボールベアリング。
【請求項5】前記環状緩衝体はゴムである請求項4記載のボールベアリング。

類型2:カテゴリが異なる引用・・・請求項4がマルチマルチクレーム

【書類名】特許請求の範囲
【請求項1】特定構造のボールベアリング。
【請求項2】内輪がステンレス鋼である請求項1記載のボールベアリング。
【請求項3】外輪がステンレス鋼である請求項1又は2記載のボールベアリング。
【請求項4】 請求項1~3のいずれか1項に記載のボールベアリングを製造する方法。

類型3:複数個所の引用部を有する・・・請求項7がマルチマルチクレーム

【書類名】特許請求の範囲
【請求項1】特定構造のネジ山を有するボルト。
【請求項2】アルミニウム合金からなる請求項1記載のボルト。
【請求項3】さらにフランジ部を有する請求項1又は2記載のボルト。
【請求項4】特定構造のネジ溝を有するナット。
【請求項5】アルミニウム合金からなる請求項4記載のナット。
【請求項6】さらにフランジ部を有する請求項4又は5記載のナット。
【請求項7】 請求項1から請求項3のいずれか1項に記載のボルト、及び、請求項4から請求項6のいずれか1項に記載のナットからなる締結装置。

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

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

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

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関数:マルチマルチクレーム判定動作

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

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は、他の請求項を引用している部分の属性を示しています。同一の請求項内に2つの引用部分がある場合に、変数rは2個の要素を持つ配列となります。

 例えば類型3の請求項7の「 請求項1から請求項3のいずれか1項に記載のボルト、及び、請求項4から請求項6のいずれか1項に記載のナットからなる締結装置。」を例に説明すると、
 「請求項1から請求項3」が第1の引用部分、「請求項4から請求項6」が第2の引用部分です。

 r[cr].fr は、他の請求項を引用している部分よりも前の文字列を示します。
 r[cr].rs は、他の請求項を引用している部分本体の文字列です。
 r[cr].refは、他の請求項を引用している項番号の配列です。
 r[cr].bk は、他の請求項を引用している部分よりも後の文字列を示します。
 r[cr].or は、他の請求項を引用している部分よりも前の文字列に、「又は」などが記載されていることを示します。この変数は、他で参照されていません。
 r[cr].andは、他の請求項を引用している部分よりも前の文字列に、「及び」などが記載されていることを示します。この変数は、他で参照されていません。
 r[cr].eiは、他の請求項を引用している部分よりも後の20文字目までの文字列 に「何れか」などの複数要素から択一的に引用する記載があることを示します。この変数は、他で参照されていません。
 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関数:請求項の引用部分のコード化

fc関数
function fc(s) {
	s = s.replace(/[A-Za-z0-9]/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に記載の…」
「請求項1,2に記載の…」⇒ 「請求項1,2に記載の…」
「請求項1または2に記載の…」⇒ 「請求項1/2に記載の…」
「請求項1から3の何れかに記載の…」⇒ 「請求項1-3の_に記載の…」
「請求項1および2の何れかに記載の…」⇒ 「請求項1&2の_に記載の…」

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

3.4 fd関数:結果の生成

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] に基づき、結果の構造体に3つの配列を設定しています。

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

3.5 fe関数:結果のクリア

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関数:マルチマルチクレーム判定動作

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は、他の請求項を引用している部分を示しています。同一の請求項内に2つの引用部分がある場合に、変数rは2個の要素を持つ配列となります。

 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関数:請求項の引用部分のコード化

fc関数
function fc(s) {
	s = s.replace(/[A-Za-z0-9]/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の「から」の後に句点を入れた:請求項4がマルチマルチクレーム

【書類名】特許請求の範囲
【請求項1】特定構造のボールベアリング。
【請求項2】内輪がステンレス鋼である請求項1記載のボールベアリング。
【請求項3】外輪がステンレス鋼である請求項1又は2記載のボールベアリング。
【請求項4】外輪の外側に環状緩衝体を設けた請求項1から、請求項3のいずれか1項に記載のボールベアリング。
【請求項5】前記環状緩衝体はゴムである請求項4記載のボールベアリング。

 漢数字を半角数字に変換しました。これにより、請求項番号が漢数字で記載されている場合でもマルチマルチクレームを検出可能です。なお、漢数字は、従前の「三百」のような記載と、アラビア数字のように大数を桁で表す「三〇〇」のような記載の両方に対応しています。

類型1の漢数字による変形:請求項4がマルチマルチクレーム

【書類名】特許請求の範囲
【請求項1】特定構造のボールベアリング。
【請求項2】内輪がステンレス鋼である請求項一記載のボールベアリング。
【請求項3】外輪がステンレス鋼である請求項一又は二記載のボールベアリング。
【請求項4】外輪の外側に環状緩衝体を設けた請求項一から請求項三のいずれか一項に記載のボールベアリング。
【請求項5】前記環状緩衝体はゴムである請求項四記載のボールベアリング。

 そして、「請求の範囲第1項に記載の…」のような形式の記載があれば、「請求項1に記載の」に書き換えるようにしました。
 更に、「請求項第1項に記載の…」のような形式の記載があれば、「請求項1に記載の」に書き換えるようにしました。

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

5 謝辞

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

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2