asearch@1.0.2
変更点
ESModuleにした
global に出せる関数を外に出した
関数を呼び出すたびに毎回生成するのは無駄
testをDenoで書いた
2021-06-19
16:16:49 worker用codeを作った
code:script.js
const INITPAT = 0x80000000; // 0100,0000,0000,0000,0000,0000,0000,0000
const MAXCHAR = 0x10000;
const isupper = c => (c >= 0x41) && (c <= 0x5a);
const islower = c => (c >= 0x61) && (c <= 0x7a);
const tolower = c => isupper(c) ? (c + 0x20) : c;
const toupper = c => islower(c) ? (c - 0x20) : c;
const unpack = str => str.split('').map(c => c.charCodeAt(0));
export function Asearch(source) {
let epsilon = 0;
// 受理状態を作る
let mask = INITPAT;
for (let i of unpack(source)) {
if (i === 0x20) {
epsilon |= mask;
} else {
mask >>>= 1;
}
}
const acceptpat = mask; // 受理状態 左から数えてunpack(source)の長さと等しい場所にフラグが立っている
function getState (state=INITSTATE, str = '') {
for (let c of unpack(str)) {
i3 = (i3 & epsilon) | ((i3 & mask) >>> 1) | (i2 >>> 1) | i2;
i2 = (i2 & epsilon) | ((i2 & mask) >>> 1) | (i1 >>> 1) | i1;
i1 = (i1 & epsilon) | ((i1 & mask) >>> 1) | (i0 >>> 1) | i0;
i0 = (i0 & epsilon) | ((i0 & mask) >>> 1);
i1 |= (i0 >>> 1);
i2 |= (i1 >>> 1);
i3 |= (i2 >>> 1);
}
}
function match (str, ambig = 0) {
const state = getState(INITSTATE, str);
if (ambig >= INITSTATE.length) {
ambig = INITSTATE.length-1;
}
return (stateambig & acceptpat) !== 0; }
match.source = source;
return match;
}
code:script.d.ts
export function Asearch(source: string): ((str: string, ambig: number) => boolean) & {source: string};
test code
code:sh
code:test.ts
import {Asearch} from './script.js';
Deno.test('pattern "abcde"', () => {
const match = Asearch('abcde');
assertEquals(match.source, 'abcde');
assert(match('abcde'));
assert(match('aBCDe'));
assert(match('abXcde',1));
assert(match('ab?de',1));
assert(match('abde',1));
assert(match('abXXde',2));
assert(!match('abXcde'));
assert(!match('ab?de'));
assert(!match('abde'));
assert(!match('abXXde',1));
});
Deno.test('pattern "ab de"', () => {
const match = Asearch('ab de');
assert(match('abcde'));
assert(match('abccde'));
assert(match('abXXXXXXXde'));
assert(match('abcccccxe',1));
assert(!match('abcccccxe'));
});
Deno.test('pattern "abcde"', () => {
const match = Asearch('abcde');
assert(match('abcde'));
assert(match('abcde',1));
assert(!match('abcd'));
assert(match('abcd',1));
});
Deno.test('pattern "漢字文字列"', () => {
const match = Asearch('漢字文字列');
assert(match('漢字文字列'));
assert(!match('漢字の文字列'));
assert(match('漢字の文字列', 1));
assert(!match('漢字文字'));
assert(match('漢字文字', 1));
assert(!match("漢字文字烈"));
assert(match("漢字文字烈", 1));
assert(!match("漢和辞典", 2));
});
worker用code
code:worker.js
const Asearch = (source) => {
const INITPAT = 0x80000000; // 0100,0000,0000,0000,0000,0000,0000,0000
const MAXCHAR = 0x10000;
const isupper = c => (c >= 0x41) && (c <= 0x5a);
const islower = c => (c >= 0x61) && (c <= 0x7a);
const tolower = c => isupper(c) ? (c + 0x20) : c;
const toupper = c => islower(c) ? (c - 0x20) : c;
const unpack = str => str.split('').map(c => c.charCodeAt(0));
let epsilon = 0;
// 受理状態を作る
let mask = INITPAT;
for (let i of unpack(source)) {
if (i === 0x20) {
epsilon |= mask;
} else {
mask >>>= 1;
}
}
const acceptpat = mask; // 受理状態 左から数えてunpack(source)の長さと等しい場所にフラグが立っている
function getState (state=INITSTATE, str = '') {
for (let c of unpack(str)) {
i3 = (i3 & epsilon) | ((i3 & mask) >>> 1) | (i2 >>> 1) | i2;
i2 = (i2 & epsilon) | ((i2 & mask) >>> 1) | (i1 >>> 1) | i1;
i1 = (i1 & epsilon) | ((i1 & mask) >>> 1) | (i0 >>> 1) | i0;
i0 = (i0 & epsilon) | ((i0 & mask) >>> 1);
i1 |= (i0 >>> 1);
i2 |= (i1 >>> 1);
i3 |= (i2 >>> 1);
}
}
function match (str, ambig = 0) {
const state = getState(INITSTATE, str);
if (ambig >= INITSTATE.length) {
ambig = INITSTATE.length-1;
}
return (stateambig & acceptpat) !== 0; }
match.source = source;
return match;
}