MorPHP는 Morphology + PHP로 PHP로 형태소 처리를 위해서 만들어졌습니다. 직접적인 동기는 살아있는 라틴어 사전에서 제공하던 어형 변화표 기능이 여러모로 확장성도 부족하고, 코드도 스파게티화되어가고 있어서, 아예 굴절 규칙을 별도의 서술 언어로 빼버리고, 해석기를 통해서 굴절 변화표를 생성하는 방식이 기존 방식보다 좋겠다는 생각이 들어서였죠.
MorPHP를 통한 형태소 처리 프로그램은 다음과 같은 순서로 개발됩니다.
2012년인가 13년도에 Derivae라고해서 범용 언어 규칙 서술 언어를 개발하던게 있었는데, 모든 언어 규칙을 망라할 수 있어야한다는 생각에 막강한 규칙을 지원하려다보니, 해석기가 너무 복잡해지고 오히려 언어 규칙 서술마저 지저분해져서 목표한 바를 이루지 못하고 휴지통에 버려야만 했던 프로젝트였죠. 이번 MorPHP는 그 Derivae의 축소판 PHP버전인셈입니다. 최대한 단순하게 제한된 규칙만을 제공하면서 되도록이면 많은 언어들의 형태론을 묘사하는게 목표입니다. 최근 주로하는 작업이 라틴어와 헬라어 사전이다보니 MorPHP로 서술 가능한 언어가 인구어족 계통의 굴절어로 한정되어버린 경향이 없잖아 있긴합니다. (하지만 해보니 한국어 동사변화도 서술가능하고, 스와힐리어 등 포합어에 대해서도 실험중에 있습니다. 최종 보스는 어근 사이사이에 각종 모음들이 막 끼어들어가는 아랍어나 히브리어가 될듯합니다.)
계획을 세운것은 꽤 오래되었는데, 실제로 코딩작업을 한 것은 저번 휴가즈음부터였습니다. 백엔드로 Javascript와 PHP를 지원하는데, PHP 문법이 영 뒤죽박죽이라서 백엔드를 작성하는데 상당히 오래걸렸습니다. 그래도 오늘 드디어 PHP 백엔드를 완성하고 테스트를 끝냈습니다! 짝짝짝~!
서론이 길었는데, 실제로 MorPHP가 어떤 녀석인지 만나보시죠. MorPHP로 라틴어 명사 곡용 규칙을 서술한 예제입니다.
/* 라틴어 명사 곡용 규칙 */
// 언어 자질 정의
[Gender] := [mas, fem, neu]
[Number] := [sng, plr]
[Case] := [nom, gen, dat, acc, abl, voc]
[NClass] := [n1, n2, n3, n3i, n4, n5, ng1, ng2, ng4, ng5]
[Clitic] := [noclitic, and, or, rog]
// 명사 규칙 정의
<<Noun>> := <*NStem> <Ending> <Clitics>;
// 어근 형태소 패턴 정의
<*NStem> := {
morph nominative '' [sng, nom|voc, mas|fem] [sng, nom|voc|acc, neu],
morph genitive '' [sng, gen|dat|acc|abl, mas|fem] [sng, gen|dat|abl, neu] [plr]
}
// 어미 형태소 패턴 정의
<Ending> := {
morph 'a' [n1, sng, nom|voc],
morph 'ae' [n1, sng, gen|dat] [n1, plr, nom|voc],
morph 'am' [n1, sng, acc],
morph 'a:' [n1, sng, abl],
morph 'a:rum' [n1, plr, gen],
morph 'i:s' [n1|n2, plr, dat|abl],
morph 'a:s' [n1, plr, acc],
morph 'us' [n2|n4, sng, nom, mas|fem] [n4, sng, voc],
morph 'i:' [n2, sng, gen] [n2, plr, nom|voc, mas|fem],
morph 'o:' [n2, sng, dat|abl],
morph 'um' [n2|n4, sng, acc, mas|fem] [n2, sng, nom|voc|acc, neu],
morph 'e' [n2, sng, voc, mas|fem],
morph 'o:rum' [n2, plr, gen],
morph 'o:s' [n2, plr, acc, mas|fem],
morph 'a' [n2|n3, plr, nom|voc|acc, neu],
morph '' [n3|n3i, sng, nom|voc, mas|fem] [n3|n3i, sng, nom|voc|acc, neu],
morph 'is' [n3|n3i, sng, gen],
morph 'i:' [n3|n3i, sng, dat],
morph 'em' [n3|n3i, sng, acc],
morph 'e' [n3|n3i, sng, abl],
morph 'e:s' [n3|n3i, plr, nom|voc|acc],
morph 'um' [n3, plr, gen],
morph 'ium' [n3i, plr, gen],
morph 'ia' [n3i, plr, nom|voc|acc, neu],
morph 'ibus' [n3|n3i|n4, plr, dat|abl],
morph 'u:s' [n4, sng, gen] [n4, plr, nom|voc|acc, mas|fem],
morph 'ui:' [n4, sng, dat],
morph 'u:' [n4, sng, abl, mas|fem] [n4, sng, neu],
morph 'uum' [n4, plr, gen],
morph 'ua' [n4, plr, nom|voc|acc, neu],
morph 'e:s' [n5, sng, nom|voc] [n5, plr, nom|voc|acc],
morph 'ei:' [n5, sng, gen|dat],
morph 'em' [n5, sng, acc],
morph 'e:' [n5, sng, abl],
morph 'e:rum' [n5, plr, gen],
morph 'e:bus' [n5, plr, dat|abl]
}
// 접어 형태소 패턴 정의
<Clitics> := {
empty [],
morph 'que' [and],
morph 've' [or],
morph 'ne' [rog]
}
이 소스코드를 MorPHP 해석기에 넣으면 해석기가 규칙을 번역하여 PHP 또는 JS로 실행가능한 소스코드를 만들어줍니다. 이 프로그램을 이용하여 프로그래밍 단에서는 별도의 형태소 규칙 프로그래밍 없이 형태소 처리를 간편하게 하고, 언어 규칙 단에서는 별도의 프로그래밍 없이 규칙만 서술하는 것이죠. 이렇게되면 언어 규칙과 프로그래밍 부분이 분할되면서 유지보수가 용이해지고, 분업이 간편해집니다. 또한 하나의 언어 규칙을 다양한 백엔드 언어(현재는 PHP, JS뿐이지만, 앞으로 C++, JAVA도 지원하는게 목표입니다.)에 활용할 수 있고, 한 규칙으로 형태소 합성과 형태소 분석을 동시에 할 수 있어서 매우 편리합니다.
위 형태 규칙을 MorPHP 해석기를 통해 PHP, JS로 번역하면 다음과 같은 결과가 나오는데, 가독성 좋은 코드와는 거리가 머므로 숨겨두었습니다. 궁금하신 분만 살펴보세요.
Javascript 코드
var Latina = {};(function(){
function form(id,cond) {this.id=id;this.cond=cond;}form.prototype={mutate:function(pre,post,env,preM,postM,envM){for(var x in this.opt){if(this.cond[x](pre,post,env,preM,postM,envM)) {return cF(this.opt[x],pre,post,env,preM,postM,envM);}}
return cF(this.def,pre,post,env,preM,postM,envM);}};function dR(ms,fs) {this.ms=ms;this.fs=fs;}function decom(f,morphs,morphs2,b,m) {this.f=f;this.morphs=morphs;this.morphs2=morphs2;this.b=b;this.m=m;}function morph(id,form,bit,mask,nid,empty) {this.id=id;this.form=form;this.bit=bit;this.mask=mask;this.nid=nid;this.empty=empty;}morph.prototype={test:function(f,fs){for(var i in this.bit){if((f&this.mask[i])==this.bit[i] && (fs&this.mask[i])==this.mask[i]) {return i;}}
return -1;},get:function(n,mc){return new morphet(this.id,this.form,this.bit[n],this.mask[n],mc);}};function morphet(id,form,bit,mask,mclass) {this.id=id;this.form=form;this.bit=bit;this.mask=mask;this.mclass=mclass;}function err0(id,f,fm){return new Error('Morphset '+id+' doesnt have element matching with ['+FTS(f,fm)+']');}
function err1(id,s,f,fm){return new Error('Morphset '+id+' doesnt have element matching with '+s+' ['+FTS(f,fm)+']');}
function cF(ar, pre, post, env, preM, postM, envM) {
var m = '';
for(var y in ar) {
if(ar[y] instanceof form) m += ar[y].mutate(pre, post, env, preM, postM, envM);
else m += ar[y];
}
return m;
}
function cC(ar,p){
var s=p.join('\x01');
for(var i in ar) {
s=s.replace(ar[i][0],ar[i][1]);
}
return s.split('\x01');
}
function cJ(ar) {
return ar.join('');
}
if (!String.prototype.endsWith) {
String.prototype.endsWith = function(searchString, position) {
var subjectString = this.toString();
if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
position = subjectString.length;
}
position -= searchString.length;
var lastIndex = subjectString.indexOf(searchString, position);
return lastIndex !== -1 && lastIndex === position;
};
}
if (!String.prototype.startsWith) {
String.prototype.startsWith = function(searchString, position) {
position = position || 0;
return this.indexOf(searchString, position) === position;
};
}Latina.F_mas=0;Latina.F_fem=1;Latina.F_neu=2;Latina.F_sng=0;Latina.F_plr=4;Latina.F_nom=0;Latina.F_gen=8;Latina.F_dat=16;Latina.F_acc=24;Latina.F_abl=32;Latina.F_voc=40;Latina.F_ind=0;Latina.F_sbj=64;Latina.F_imp=128;Latina.F_inf=192;Latina.F_ptp=256;Latina.F_prs=0;Latina.F_pst=512;Latina.F_ftr=1024;Latina.F_impf=0;Latina.F_perf=2048;Latina.F_act=0;Latina.F_psv=4096;Latina.F_p1=0;Latina.F_p2=8192;Latina.F_p3=16384;Latina.F_g1=0;Latina.F_g2=32768;Latina.F_g3=65536;Latina.F_g4=98304;Latina.F_g3io=131072;Latina.F_n1=0;Latina.F_n2=262144;Latina.F_n3=524288;Latina.F_n3i=786432;Latina.F_n4=1048576;Latina.F_n5=1310720;Latina.F_ng1=1572864;Latina.F_ng2=1835008;Latina.F_ng4=2097152;Latina.F_ng5=2359296;Latina.F_noclitic=0;Latina.F_and=4194304;Latina.F_or=8388608;Latina.F_rog=12582912;Latina.FS_Gender=3;Latina.FS_Number=4;Latina.FS_Case=56;Latina.FS_Mood=448;Latina.FS_Tense=1536;Latina.FS_Aspect=2048;Latina.FS_Voice=4096;Latina.FS_Person=24576;Latina.FS_VClass=229376;Latina.FS_NClass=3932160;Latina.FS_Clitic=12582912;function FTS(f,fm){r=[];if((fm&3)==3) {r.push((['mas','fem','neu'])[(f&3)/1]);}if((fm&4)==4) {r.push((['sng','plr'])[(f&4)/4]);}if((fm&56)==56) {r.push((['nom','gen','dat','acc','abl','voc'])[(f&56)/8]);}if((fm&448)==448) {r.push((['ind','sbj','imp','inf','ptp'])[(f&448)/64]);}if((fm&1536)==1536) {r.push((['prs','pst','ftr'])[(f&1536)/512]);}if((fm&2048)==2048) {r.push((['impf','perf'])[(f&2048)/2048]);}if((fm&4096)==4096) {r.push((['act','psv'])[(f&4096)/4096]);}if((fm&24576)==24576) {r.push((['p1','p2','p3'])[(f&24576)/8192]);}if((fm&229376)==229376) {r.push((['g1','g2','g3','g4','g3io'])[(f&229376)/32768]);}if((fm&3932160)==3932160) {r.push((['n1','n2','n3','n3i','n4','n5','ng1','ng2','ng4','ng5'])[(f&3932160)/262144]);}if((fm&12582912)==12582912) {r.push((['noclitic','and','or','rog'])[(f&12582912)/4194304]);}return r;};var FTVE2;var Fweak_a;var Fweak_i;var Fm_i;var Fstrong_i;var Fweak_o;var Fve_short;var Fve_long;var Fom;var Fpsv_inf;var Fsbj_perf;var Fve_ind;var Fve_sbj;var Fve_inf;var Fve_imp;var Fve_ptp;var MSStem;var OStem;var MSPE;var MST;var MSVE;var MSNE;var MSNStem;var ONStem;var MSNE2;var MSClitics;var C0;var C1;var FAS_Gender;var FAS_Number;var FAS_Case;var FAS_Mood;var FAS_Tense;var FAS_Aspect;var FAS_Voice;var FAS_Person;var FAS_VClass;var FAS_NClass;var FAS_Clitic;var WORD;FTVE2=new form('TVE2',[function(a,b,c,d,e,f){return (((c)&26116)==1024&&((f)&26116)==26116);}]);Fweak_a=new form('weak_a',[function(a,b,c,d,e,f){return ((((b)&24580)==0&&((e)&24580)==24580)&&(((c)&1984)==0&&((f)&1984)==1984));}]);Fweak_i=new form('weak_i',[function(a,b,c,d,e,f){return (((b)&24580)==0&&((e)&24580)==24580);},function(a,b,c,d,e,f){return ((((b)&24580)==16388&&((e)&24580)==24580)&&(((c)&2048)==0&&((f)&2048)==2048));},function(a,b,c,d,e,f){return (((b)&1536)==512&&((e)&1536)==1536);},function(a,b,c,d,e,f){return (((b)&28676)==12288&&((e)&28676)==28676&&((b)&448)!=128&&((e)&448)==448);},function(a,b,c,d,e,f){return ((((b)&1536)==1024&&((e)&1536)==1536&&((b)&448)!=128&&((e)&448)==448)&&((((c)&0x38800)==65536&&((f)&0x38800)==0x38800)||(((c)&0x38800)==98304&&((f)&0x38800)==0x38800)||(((c)&0x38800)==0x20000&&((f)&0x38800)==0x38800)));}]);Fm_i=new form('m_i',[function(a,b,c,d,e,f){return (((b)&24580)==16388&&((e)&24580)==24580);},function(a,b,c,d,e,f){return (((b)&1536)==512&&((e)&1536)==1536);}]);Fstrong_i=new form('strong_i',[function(a,b,c,d,e,f){return (((b)&24580)==16388&&((e)&24580)==24580);},function(a,b,c,d,e,f){return (((b)&1536)==512&&((e)&1536)==1536);}]);Fweak_o=new form('weak_o',[function(a,b,c,d,e,f){return ((((a)&3584)==512&&((d)&3584)==3584)||(((a)&448)==64&&((d)&448)==448));},function(a,b,c,d,e,f){return ((((a)&1536)==1024&&((d)&1536)==1536)&&((((c)&0x38000)==65536&&((f)&0x38000)==0x38000)||(((c)&0x38000)==98304&&((f)&0x38000)==0x38000)||(((c)&0x38000)==0x20000&&((f)&0x38000)==0x38000)));}]);Fve_short=new form('ve_short',[]);Fve_long=new form('ve_long',[]);Fom=new form('om',[function(a,b,c,d,e,f){return ((((c)&1984)==0&&((f)&1984)==1984)||(((c)&0x387c0)==1024&&((f)&0x387c0)==0x387c0)||(((c)&0x387c0)==33792&&((f)&0x387c0)==0x387c0)||(((c)&3584)==3072&&((f)&3584)==3584));}]);Fpsv_inf=new form('psv_inf',[function(a,b,c,d,e,f){return ((((c)&0x38000)==65536&&((f)&0x38000)==0x38000)||(((c)&0x38000)==0x20000&&((f)&0x38000)==0x38000));}]);Fsbj_perf=new form('sbj_perf',[function(a,b,c,d,e,f){return (((c)&1536)==512&&((f)&1536)==1536);}]);Fve_ind=new form('ve_ind',[function(a,b,c,d,e,f){return (((c)&0x38000)==0&&((f)&0x38000)==0x38000);},function(a,b,c,d,e,f){return (((c)&0x38000)==32768&&((f)&0x38000)==0x38000);},function(a,b,c,d,e,f){return (((c)&0x38000)==65536&&((f)&0x38000)==0x38000);},function(a,b,c,d,e,f){return (((c)&0x38000)==98304&&((f)&0x38000)==0x38000);},function(a,b,c,d,e,f){return (((c)&0x38000)==0x20000&&((f)&0x38000)==0x38000);}]);Fve_sbj=new form('ve_sbj',[function(a,b,c,d,e,f){return (((c)&0x38000)==0&&((f)&0x38000)==0x38000);},function(a,b,c,d,e,f){return (((c)&0x38000)==32768&&((f)&0x38000)==0x38000);},function(a,b,c,d,e,f){return (((c)&0x38000)==65536&&((f)&0x38000)==0x38000);},function(a,b,c,d,e,f){return (((c)&0x38000)==98304&&((f)&0x38000)==0x38000);},function(a,b,c,d,e,f){return (((c)&0x38000)==0x20000&&((f)&0x38000)==0x38000);}]);Fve_inf=new form('ve_inf',[function(a,b,c,d,e,f){return (((c)&0x38000)==0&&((f)&0x38000)==0x38000);},function(a,b,c,d,e,f){return (((c)&0x38000)==32768&&((f)&0x38000)==0x38000);},function(a,b,c,d,e,f){return ((((b)&448)==192&&((e)&448)==448)&&((((c)&0x39000)==69632&&((f)&0x39000)==0x39000)||(((c)&0x39000)==0x21000&&((f)&0x39000)==0x39000)));},function(a,b,c,d,e,f){return ((((c)&0x38000)==65536&&((f)&0x38000)==0x38000)||(((c)&0x38000)==0x20000&&((f)&0x38000)==0x38000));},function(a,b,c,d,e,f){return (((c)&0x38000)==98304&&((f)&0x38000)==0x38000);}]);Fve_imp=new form('ve_imp',[function(a,b,c,d,e,f){return (((c)&0x38000)==0&&((f)&0x38000)==0x38000);},function(a,b,c,d,e,f){return (((c)&0x38000)==32768&&((f)&0x38000)==0x38000);},function(a,b,c,d,e,f){return ((((b)&4)==0&&((e)&4)==4)&&((((c)&0x38000)==65536&&((f)&0x38000)==0x38000)||(((c)&0x38000)==0x20000&&((f)&0x38000)==0x38000)));},function(a,b,c,d,e,f){return ((((b)&4)==4&&((e)&4)==4)&&((((c)&0x38000)==65536&&((f)&0x38000)==0x38000)||(((c)&0x38000)==0x20000&&((f)&0x38000)==0x38000)));},function(a,b,c,d,e,f){return (((c)&0x38000)==98304&&((f)&0x38000)==0x38000);}]);Fve_ptp=new form('ve_ptp',[function(a,b,c,d,e,f){return (((c)&0x38000)==0&&((f)&0x38000)==0x38000);},function(a,b,c,d,e,f){return (((c)&0x38000)==32768&&((f)&0x38000)==0x38000);},function(a,b,c,d,e,f){return (((c)&0x38000)==65536&&((f)&0x38000)==0x38000);},function(a,b,c,d,e,f){return ((((c)&0x38000)==98304&&((f)&0x38000)==0x38000)||(((c)&0x38000)==0x20000&&((f)&0x38000)==0x38000));}]);MSStem=[new morph('imperfect',[''],[0,64,128,192,256,5376],[2496,2496,2496,2496,6080,6080],0,false),new morph('perfect',[''],[2048],[2048],1,false),new morph('supine',[''],[4864,1280],[6080,6080],2,false)];OStem=['imperfect','perfect','supine'];MSPE=[new morph('',[],[256],[448],0,true),new morph('',['re'],[192],[6592],1,false),new morph('',[Fom],[0,64,2112,2560,3072],[31172,31172,31172,32260,32260],2,false),new morph('',[Fve_long,'s'],[8192,8256,10304,10752,11264],[31172,31172,31172,32260,32260],3,false),new morph('',['t'],[16384,16448,18496,18944,19456],[31172,31172,31172,32260,32260],4,false),new morph('',[Fve_long,'mus'],[4,68,2116,2564,3076],[31172,31172,31172,32260,32260],5,false),new morph('',[Fve_long,'tis'],[8196,8260,10308,10756,11268],[31172,31172,31172,32260,32260],6,false),new morph('',['nt'],[16388,16452,18500,18948,19460],[31172,31172,31172,32260,32260],7,false),new morph('',[Fpsv_inf],[4288],[6592],8,false),new morph('',[Fweak_o,'r'],[4096,4160],[31172,31172],9,false),new morph('',[Fve_long,'ris'],[12288,12352],[31172,31172],10,false),new morph('',[Fve_long,'re'],[12288,12352],[31172,31172],11,false),new morph('',[Fve_long,'tur'],[20480,20544],[31172,31172],12,false),new morph('',[Fve_long,'mur'],[4100,4164],[31172,31172],13,false),new morph('',[Fve_long,'mini:'],[12292,12356],[31172,31172],14,false),new morph('',['ntur'],[20484,20548],[31172,31172],15,false),new morph('',['isse'],[2240],[6592],16,false),new morph('',['i:'],[2048],[32708],17,false),new morph('',['isti:'],[10240],[32708],18,false),new morph('',['it'],[18432],[32708],19,false),new morph('',['imus'],[2052],[32708],20,false),new morph('',['istis'],[10244],[32708],21,false),new morph('',['e:runt'],[18436],[32708],22,false),new morph('',['e:re'],[18436],[32708],23,false),new morph('',[''],[8320],[32708],24,false),new morph('',['te'],[8324],[32708],25,false),new morph('',['re'],[12416],[32708],26,false),new morph('',['mini:'],[12420],[32708],27,false),new morph('',[Fve_long,'to:'],[9344,17536],[32708,32708],28,false),new morph('',[Fve_long,'to:te'],[9348],[32708],29,false),new morph('',['nto'],[17540],[32708],30,false),new morph('',[Fve_long,'tor'],[13440,21632],[32708,32708],31,false),new morph('',['ntor'],[21636],[32708],32,false)];MST=[new morph('',[],[0,1152],[1536,1984],0,true),new morph('',[FTVE2],[66560,99328,0x20400],[0x38fc0,0x38fc0,0x38fc0],1,false),new morph('',[Fve_long,'b',Fweak_i],[1024,33792],[0x38fc0,0x38fc0],2,false),new morph('',[Fve_long,'b',Fweak_a],[512],[4032],3,false),new morph('',['re'],[576],[4032],4,false),new morph('',['er',Fweak_i],[3072],[4032],5,false),new morph('',['er',Fweak_a],[2560],[4032],6,false),new morph('',['isse'],[2624],[4032],7,false),new morph('',[Fve_long,'nt'],[256],[6080],8,false),new morph('',[''],[4864],[6080],9,false),new morph('',['u:r'],[1280],[6080],10,false),new morph('',['nd'],[5376],[6080],11,false)];MSVE=[new morph('indicative',[Fve_ind],[0],[2496],0,false),new morph('subjunctive',[Fve_sbj],[64],[4032],1,false),new morph('subjunctive',[Fve_inf],[576],[4032],2,false),new morph('infinitive',[Fve_inf],[192],[2496],3,false),new morph('indicative',[''],[2048],[2496],4,false),new morph('subjunctive',[Fsbj_perf],[2112],[2496],5,false),new morph('infinitive',[''],[2240],[2496],6,false),new morph('imperative',[Fve_imp],[128],[1984],7,false),new morph('imperative',[Fve_ind],[1152],[1984],8,false),new morph('participle',[Fve_ptp],[256,5376],[6080,6080],9,false),new morph('',[],[4864,1280],[6080,6080],10,true)];MSNE=[new morph('',[],[0,64,128,192],[448,448,448,448],0,true)];MSNStem=[new morph('nominative',[''],[0,40,1,41,2,42,26],[63,63,63,63,63,63,63],0,false),new morph('genitive',[''],[8,16,24,32,9,17,25,33,10,18,34,4],[63,63,63,63,63,63,63,63,63,63,63,4],1,false)];ONStem=['nominative','genitive'];MSNE2=[new morph('',['a'],[0,40],[0x3c003c,0x3c003c],0,false),new morph('',['ae'],[8,16,4,44],[0x3c003c,0x3c003c,0x3c003c,0x3c003c],1,false),new morph('',['am'],[24],[0x3c003c],2,false),new morph('',['a:'],[32],[0x3c003c],3,false),new morph('',['a:rum'],[12],[0x3c003c],4,false),new morph('',['i:s'],[20,0x40014,36,0x40024],[0x3c003c,0x3c003c,0x3c003c,0x3c003c],5,false),new morph('',['a:s'],[28],[0x3c003c],6,false),new morph('',['us'],[0x40000,0x100000,0x40001,0x100001,0x100028],[0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003c],7,false),new morph('',['i:'],[0x40008,0x40004,0x4002c,0x40005,0x4002d],[0x3c003c,0x3c003f,0x3c003f,0x3c003f,0x3c003f],8,false),new morph('',['o:'],[0x40010,0x40020],[0x3c003c,0x3c003c],9,false),new morph('',['um'],[0x40018,0x100018,0x40019,0x100019,0x40002,0x4002a,0x4001a],[0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f],10,false),new morph('',['e'],[0x40028,0x40029],[0x3c003f,0x3c003f],11,false),new morph('',['o:rum'],[0x4000c],[0x3c003c],12,false),new morph('',['o:s'],[0x4001c,0x4001d],[0x3c003f,0x3c003f],13,false),new morph('',['a'],[0x40006,0x80006,0x4002e,0x8002e,0x4001e,0x8001e],[0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f],14,false),new morph('',[''],[0x80000,0xc0000,0x80028,0xc0028,0x80001,0xc0001,0x80029,0xc0029,0x80002,0xc0002,0x8002a,0xc002a,0x8001a,0xc001a],[0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f],15,false),new morph('',['is'],[0x80008,0xc0008],[0x3c003c,0x3c003c],16,false),new morph('',['i:'],[0x80010,0xc0010],[0x3c003c,0x3c003c],17,false),new morph('',['em'],[0x80018,0xc0018],[0x3c003c,0x3c003c],18,false),new morph('',['e'],[0x80020,0xc0020],[0x3c003c,0x3c003c],19,false),new morph('',['e:s'],[0x80004,0xc0004,0x8002c,0xc002c,0x8001c,0xc001c],[0x3c003c,0x3c003c,0x3c003c,0x3c003c,0x3c003c,0x3c003c],20,false),new morph('',['um'],[0x8000c],[0x3c003c],21,false),new morph('',['ium'],[0xc000c],[0x3c003c],22,false),new morph('',['ia'],[0xc0006,0xc002e,0xc001e],[0x3c003f,0x3c003f,0x3c003f],23,false),new morph('',['ibus'],[0x80014,0xc0014,0x100014,0x80024,0xc0024,0x100024],[0x3c003c,0x3c003c,0x3c003c,0x3c003c,0x3c003c,0x3c003c],24,false),new morph('',['u:s'],[0x100008,0x100004,0x10002c,0x10001c,0x100005,0x10002d,0x10001d],[0x3c003c,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f],25,false),new morph('',['ui:'],[0x100010],[0x3c003c],26,false),new morph('',['u:'],[0x100020,0x100021,0x100002],[0x3c003f,0x3c003f,0x3c0007],27,false),new morph('',['uum'],[0x10000c],[0x3c003c],28,false),new morph('',['ua'],[0x100006,0x10002e,0x10001e],[0x3c003f,0x3c003f,0x3c003f],29,false),new morph('',['e:s'],[0x140000,0x140028,0x140004,0x14002c,0x14001c],[0x3c003c,0x3c003c,0x3c003c,0x3c003c,0x3c003c],30,false),new morph('',['ei:'],[0x140008,0x140010],[0x3c003c,0x3c003c],31,false),new morph('',['em'],[0x140018],[0x3c003c],32,false),new morph('',['e:'],[0x140020],[0x3c003c],33,false),new morph('',['e:rum'],[0x14000c],[0x3c003c],34,false),new morph('',['e:bus'],[0x140014,0x140024],[0x3c003c,0x3c003c],35,false)];MSClitics=[new morph('',[],[0],[0],0,true),new morph('',['que'],[0x400000],[0xc00000],1,false),new morph('',['ve'],[0x800000],[0xc00000],2,false),new morph('',['ne'],[0xc00000],[0xc00000],3,false)];C0=[[/;\x01:/,"\x01"]];C1=[[/a\x01:/,"ā\x01"],[/e\x01:/,"ē\x01"],[/i\x01:/,"ī\x01"],[/o\x01:/,"ō\x01"],[/u\x01:/,"ū\x01"],[/;\x01()/,"\x01"]];FTVE2.opt=[['a']];FTVE2.def=['e'];Fweak_a.opt=[['']];Fweak_a.def=['a'];Fweak_i.opt=[[''],['u'],['e'],['e',Fve_short],['']];Fweak_i.def=['i',Fve_short];Fm_i.opt=[['iu'],['ie']];Fm_i.def=['i',Fve_short];Fstrong_i.opt=[['iu'],['ie']];Fstrong_i.def=['i'];Fweak_o.opt=[[''],['']];Fweak_o.def=['o'];Fve_short.opt=[];Fve_short.def=[';'];Fve_long.opt=[];Fve_long.def=[':'];Fom.opt=[['o',Fve_long]];Fom.def=['m'];Fpsv_inf.opt=[['i:']];Fpsv_inf.def=['ri:'];Fsbj_perf.opt=[['']];Fsbj_perf.def=['eri'];Fve_ind.opt=[[Fweak_a],['e'],[Fweak_i],[Fstrong_i],[Fm_i]];Fve_ind.def=['ERR'];Fve_sbj.opt=[['e'],['ea'],['a'],['ia'],['ia']];Fve_sbj.def=['ERR'];Fve_inf.opt=[['a:'],['e:'],[''],['e'],['i:']];Fve_inf.def=['ERR'];Fve_imp.opt=[['a:'],['e:'],['e'],['i'],['i:']];Fve_imp.def=['ERR'];Fve_ptp.opt=[['a'],['e'],['e'],['ie']];Fve_ptp.def=['ERR'];FAS_Gender={mas:0,fem:1,neu:2};FAS_Number={sng:0,plr:4};FAS_Case={nom:0,gen:8,dat:16,acc:24,abl:32,voc:40};FAS_Mood={ind:0,sbj:64,imp:128,inf:192,ptp:256};FAS_Tense={prs:0,pst:512,ftr:1024};FAS_Aspect={impf:0,perf:2048};FAS_Voice={act:0,psv:4096};FAS_Person={p1:0,p2:8192,p3:16384};FAS_VClass={g1:0,g2:32768,g3:65536,g4:98304,g3io:131072};FAS_NClass={n1:0,n2:262144,n3:524288,n3i:786432,n4:1048576,n5:1310720,ng1:1572864,ng2:1835008,ng4:2097152,ng5:2359296};FAS_Clitic={noclitic:0,and:4194304,or:8388608,rog:12582912};WORD={Verb:'Stem',Noun:'NStem'};function SMStem(f,fs){var r=[];
for(var i in MSStem){if((t=MSStem[i].test(f,fs))>=0) {r.push([i,t]);}}
return r;};Latina.getOpenStem=function(){return OStem;};function SMPE(f,fs){var r=[];
for(var i in MSPE){if((t=MSPE[i].test(f,fs))>=0) {r.push([i,t]);}}
return r;};function SMT(f,fs){var r=[];
for(var i in MST){if((t=MST[i].test(f,fs))>=0) {r.push([i,t]);}}
return r;};function SMVE(f,fs){var r=[];
for(var i in MSVE){if((t=MSVE[i].test(f,fs))>=0) {r.push([i,t]);}}
return r;};function SMNE(f,fs){var r=[];
for(var i in MSNE){if((t=MSNE[i].test(f,fs))>=0) {r.push([i,t]);}}
return r;};function SMNStem(f,fs){var r=[];
for(var i in MSNStem){if((t=MSNStem[i].test(f,fs))>=0) {r.push([i,t]);}}
return r;};Latina.getOpenNStem=function(){return ONStem;};function SMNE2(f,fs){var r=[];
for(var i in MSNE2){if((t=MSNE2[i].test(f,fs))>=0) {r.push([i,t]);}}
return r;};function SMClitics(f,fs){var r=[];
for(var i in MSClitics){if((t=MSClitics[i].test(f,fs))>=0) {r.push([i,t]);}}
return r;};Latina.getFeatGender=function(){return FAS_Gender;};Latina.getFeatNumber=function(){return FAS_Number;};Latina.getFeatCase=function(){return FAS_Case;};Latina.getFeatMood=function(){return FAS_Mood;};Latina.getFeatTense=function(){return FAS_Tense;};Latina.getFeatAspect=function(){return FAS_Aspect;};Latina.getFeatVoice=function(){return FAS_Voice;};Latina.getFeatPerson=function(){return FAS_Person;};Latina.getFeatVClass=function(){return FAS_VClass;};Latina.getFeatNClass=function(){return FAS_NClass;};Latina.getFeatClitic=function(){return FAS_Clitic;};
function apC(a,b,m){if(b=='PE')m=cC(C0,m);m=cC(C1,m);return m;};Latina.composeVerb=function(s,f,fm){var i;var t;var m=[];
var r;var rr;var a;a=SMStem(f,fm);if(a.length==0) {throw err0('Stem',f,fm);}var om=MSStem[a[0][0]].get(a[0][1],'Stem');
if(!s[om.id]) {return false;}om.form=[s[om.id]];m.push([om]);a=SMVE(f,fm);if(a.length==0) {throw err0('VE',f,fm);}t=[];for(var i in a){if(!MSVE[a[i][0]].empty) {t.push(MSVE[a[i][0]].get(a[i][1],'VE'));}}
if(t.length) {m.push(t);}a=SMT(f,fm);if(a.length==0) {throw err0('T',f,fm);}t=[];for(var i in a){if(!MST[a[i][0]].empty) {t.push(MST[a[i][0]].get(a[i][1],'T'));}}
if(t.length) {m.push(t);}a=SMPE(f,fm);if(a.length==0) {throw err0('PE',f,fm);}t=[];for(var i in a){if(!MSPE[a[i][0]].empty) {t.push(MSPE[a[i][0]].get(a[i][1],'PE'));}}
if(t.length) {m.push(t);}a=SMNE(f,fm);if(a.length==0) {throw err0('NE',f,fm);}t=[];for(var i in a){if(!MSNE[a[i][0]].empty) {t.push(MSNE[a[i][0]].get(a[i][1],'NE'));}}
if(t.length) {m.push(t);}a=SMClitics(f,fm);if(a.length==0) {throw err0('Clitics',f,fm);}t=[];for(var i in a){if(!MSClitics[a[i][0]].empty) {t.push(MSClitics[a[i][0]].get(a[i][1],'Clitics'));}}
if(t.length) {m.push(t);}var j;var rs=[];
var rrs=[];
var cs=[];
t=1;for(var i in m){t*=m[i].length;cs.push(m[i].length);}
for(j=0;j<t;j++){r=[];var jt=j;
var ik=[];
for(var i in m){ik.push(jt%cs[i]);jt=(jt/cs[i])|0;}
for(var i in m){var c;var d;var n;var o;if(i>0) {c=m[i-1][ik[i-1]].bit;n=m[i-1][ik[i-1]].mask;}if(i<m.length-1) {d=m[(i|0)+1][ik[(i|0)+1]].bit;o=m[(i|0)+1][ik[(i|0)+1]].mask;}r.push(cF(m[i][ik[i]].form,c,d,f,n,o,fm));if(i==0) {rr=[r[0]];}else {var rt=[rr[i-1],r[i]];
rt=apC(m[i-1][ik[i-1]].mclass,m[i][ik[i]].mclass,rt);rr[i-1]=rt[0];rr[i]=rt[1];}}
rs.push(r);rrs.push(rr);}return {f:rrs.map(cJ),fs:rs};};Latina.decomposeVerb=function(s,f,fm) {if(typeof fm=='undefined')fm=0xFFFFFFFF;var r;var t;var nt;r=EMClitics(s,0,f,0,fm);
if(r.length==0)throw err1('Clitics',s,f,fm);t=[];
for(var i in r)t.push(new decom(s.substr(0,s.length-r[i].form.length),[],[r[i]],r[i].bit,r[i].mask));nt=[];for(var i in t){
var tm2=t[i].morphs2;r=EMNE(t[i].f,tm2[tm2.length-1].bit,t[i].b,tm2[tm2.length-1].mask,t[i].m);
if(r.length==0)continue;for(var j in r)nt.push(new decom(t[i].f.substr(0,t[i].f.length-r[j].form.length),t[i].morphs,r[j].id?tm2:tm2.concat(r[j]),t[i].b|r[j].bit,t[i].m|r[j].mask));}
t=nt;
if(t.length==0)throw err1('NE',s,f,fm);nt=[];for(var i in t){
var tm2=t[i].morphs2;r=EMPE(t[i].f,tm2[tm2.length-1].bit,t[i].b,tm2[tm2.length-1].mask,t[i].m);
if(r.length==0)continue;for(var j in r)nt.push(new decom(t[i].f.substr(0,t[i].f.length-r[j].form.length),t[i].morphs,r[j].id?tm2:tm2.concat(r[j]),t[i].b|r[j].bit,t[i].m|r[j].mask));}
t=nt;
if(t.length==0)throw err1('PE',s,f,fm);nt=[];for(var i in t){
var tm2=t[i].morphs2;r=EMT(t[i].f,tm2[tm2.length-1].bit,t[i].b,tm2[tm2.length-1].mask,t[i].m);
if(r.length==0)continue;for(var j in r)nt.push(new decom(t[i].f.substr(0,t[i].f.length-r[j].form.length),t[i].morphs,r[j].id?tm2:tm2.concat(r[j]),t[i].b|r[j].bit,t[i].m|r[j].mask));}
t=nt;
if(t.length==0)throw err1('T',s,f,fm);nt=[];for(var i in t){
var tm2=t[i].morphs2;r=EMVE(t[i].f,tm2[tm2.length-1].bit,t[i].b,tm2[tm2.length-1].mask,t[i].m);
if(r.length==0)continue;for(var j in r)nt.push(new decom(t[i].f.substr(0,t[i].f.length-r[j].form.length),t[i].morphs,r[j].id?tm2:tm2.concat(r[j]),t[i].b|r[j].bit,t[i].m|r[j].mask));}
t=nt;
if(t.length==0)throw err1('VE',s,f,fm);r=[];for(var i in t) {
var ms={};
for(var j in t[i].morphs) {
var a=t[i].morphs[j];
ms[a.mclass]=a.form;
}
ms.Stem=t[i].f;
for(var j=t[i].morphs2.length-1;j>=0;j--) {
var a=t[i].morphs2[j];
ms[a.mclass]=a.form;
}
r.push(new dR(ms, FTS(t[i].b,t[i].m)));
}return r;};
Latina.composeNoun=function(s,f,fm){var i;var t;var m=[];
var r;var rr;var a;a=SMNStem(f,fm);if(a.length==0) {throw err0('NStem',f,fm);}var om=MSNStem[a[0][0]].get(a[0][1],'NStem');
if(!s[om.id]) {return false;}om.form=[s[om.id]];m.push([om]);a=SMNE2(f,fm);if(a.length==0) {throw err0('NE2',f,fm);}t=[];for(var i in a){if(!MSNE2[a[i][0]].empty) {t.push(MSNE2[a[i][0]].get(a[i][1],'NE2'));}}
if(t.length) {m.push(t);}a=SMClitics(f,fm);if(a.length==0) {throw err0('Clitics',f,fm);}t=[];for(var i in a){if(!MSClitics[a[i][0]].empty) {t.push(MSClitics[a[i][0]].get(a[i][1],'Clitics'));}}
if(t.length) {m.push(t);}var j;var rs=[];
var rrs=[];
var cs=[];
t=1;for(var i in m){t*=m[i].length;cs.push(m[i].length);}
for(j=0;j<t;j++){r=[];var jt=j;
var ik=[];
for(var i in m){ik.push(jt%cs[i]);jt=(jt/cs[i])|0;}
for(var i in m){var c;var d;var n;var o;if(i>0) {c=m[i-1][ik[i-1]].bit;n=m[i-1][ik[i-1]].mask;}if(i<m.length-1) {d=m[(i|0)+1][ik[(i|0)+1]].bit;o=m[(i|0)+1][ik[(i|0)+1]].mask;}r.push(cF(m[i][ik[i]].form,c,d,f,n,o,fm));if(i==0) {rr=[r[0]];}else {var rt=[rr[i-1],r[i]];
rt=apC(m[i-1][ik[i-1]].mclass,m[i][ik[i]].mclass,rt);rr[i-1]=rt[0];rr[i]=rt[1];}}
rs.push(r);rrs.push(rr);}return {f:rrs.map(cJ),fs:rs};};Latina.decomposeNoun=function(s,f,fm) {if(typeof fm=='undefined')fm=0xFFFFFFFF;var r;var t;var nt;r=EMClitics(s,0,f,0,fm);
if(r.length==0)throw err1('Clitics',s,f,fm);t=[];
for(var i in r)t.push(new decom(s.substr(0,s.length-r[i].form.length),[],[r[i]],r[i].bit,r[i].mask));nt=[];for(var i in t){
var tm2=t[i].morphs2;r=EMNE2(t[i].f,tm2[tm2.length-1].bit,t[i].b,tm2[tm2.length-1].mask,t[i].m);
if(r.length==0)continue;for(var j in r)nt.push(new decom(t[i].f.substr(0,t[i].f.length-r[j].form.length),t[i].morphs,r[j].id?tm2:tm2.concat(r[j]),t[i].b|r[j].bit,t[i].m|r[j].mask));}
t=nt;
if(t.length==0)throw err1('NE2',s,f,fm);r=[];for(var i in t) {
var ms={};
for(var j in t[i].morphs) {
var a=t[i].morphs[j];
ms[a.mclass]=a.form;
}
ms.NStem=t[i].f;
for(var j=t[i].morphs2.length-1;j>=0;j--) {
var a=t[i].morphs2[j];
ms[a.mclass]=a.form;
}
r.push(new dR(ms, FTS(t[i].b,t[i].m)));
}return r;};
Latina.getWord=function(){return WORD;};}());
PHP 코드
<?php namespace Latina;
class form{function __construct($id,$cond){$this->id=$id;$this->cond=$cond;}function mutate($pre,$post,$env,$preM,$postM,$envM){foreach($this->opt as $x=>$xb){if($this->cond[$x]($pre,$post,$env,$preM,$postM,$envM)) {return Latina::cF($this->opt[$x],$pre,$post,$env,$preM,$postM,$envM);}}return Latina::cF($this->def,$pre,$post,$env,$preM,$postM,$envM);}};class dR{function __construct($ms,$fs){$this->ms=$ms;$this->fs=$fs;}};class decom{function __construct($f,$morphs,$morphs2,$b,$m){$this->f=$f;$this->morphs=$morphs;$this->morphs2=$morphs2;$this->b=$b;$this->m=$m;}};class morph{function __construct($id,$form,$bit,$mask,$nid,$empty){$this->id=$id;$this->form=$form;$this->bit=$bit;$this->mask=$mask;$this->nid=$nid;$this->empty=$empty;}function test($f,$fs){foreach($this->bit as $i=>$ib){if(($f&$this->mask[$i])==$this->bit[$i] && ($fs&$this->mask[$i])==$this->mask[$i]) {return $i;}}return -1;}function get($n,$mc){return new morphet($this->id,$this->form,$this->bit[$n],$this->mask[$n],$mc);}};class morphet{function __construct($id,$form,$bit,$mask,$mclass){$this->id=$id;$this->form=$form;$this->bit=$bit;$this->mask=$mask;$this->mclass=$mclass;}};class Latina{static function err0($id,$f,$fm){return new \Exception("Morphset ".$id." doesnt have element matching with [".implode(",",self::FTS($f, $fm))."]");}
static function err1($id,$s,$f,$fm){return new \Exception("Morphset ".$id." doesnt have element matching with ".$s."[".implode(",",self::FTS($f, $fm))."]");}
static function cF($ar,$pre,$post,$env,$preM,$postM,$envM) {
$m = "";
foreach($ar as $y) {
if(is_object($y)) $m.=$y->mutate($pre,$post,$env,$preM,$postM,$envM);
else $m.=$y;
}
return $m;
}
static function cC($ar,$p){
$s=implode("\x01",$p);
foreach($ar as $i) {
$s=preg_replace($i[0],$i[1],$s);
}
return explode("\x01",$s);
}
static $cJ;
static function startsWith($haystack, $needle)
{
$length = strlen($needle);
return (substr($haystack, 0, $length) === $needle);
}
static function id($x) {return $x;}
static function endsWith($haystack, $needle)
{
$length = strlen($needle);
if ($length == 0) {
return true;
}
return (substr($haystack, -$length) === $needle);
}const F_mas=0;const F_fem=1;const F_neu=2;const F_sng=0;const F_plr=4;const F_nom=0;const F_gen=8;const F_dat=16;const F_acc=24;const F_abl=32;const F_voc=40;const F_ind=0;const F_sbj=64;const F_imp=128;const F_inf=192;const F_ptp=256;const F_prs=0;const F_pst=512;const F_ftr=1024;const F_impf=0;const F_perf=2048;const F_act=0;const F_psv=4096;const F_p1=0;const F_p2=8192;const F_p3=16384;const F_g1=0;const F_g2=32768;const F_g3=65536;const F_g4=98304;const F_g3io=131072;const F_n1=0;const F_n2=262144;const F_n3=524288;const F_n3i=786432;const F_n4=1048576;const F_n5=1310720;const F_ng1=1572864;const F_ng2=1835008;const F_ng4=2097152;const F_ng5=2359296;const F_noclitic=0;const F_and=4194304;const F_or=8388608;const F_rog=12582912;const FS_Gender=3;const FS_Number=4;const FS_Case=56;const FS_Mood=448;const FS_Tense=1536;const FS_Aspect=2048;const FS_Voice=4096;const FS_Person=24576;const FS_VClass=229376;const FS_NClass=3932160;const FS_Clitic=12582912;static function FTS($f,$fm){$r=array();if(($fm&3)==3) {$r[]=self::id(array('mas','fem','neu'))[($f&3)/1];}if(($fm&4)==4) {$r[]=self::id(array('sng','plr'))[($f&4)/4];}if(($fm&56)==56) {$r[]=self::id(array('nom','gen','dat','acc','abl','voc'))[($f&56)/8];}if(($fm&448)==448) {$r[]=self::id(array('ind','sbj','imp','inf','ptp'))[($f&448)/64];}if(($fm&1536)==1536) {$r[]=self::id(array('prs','pst','ftr'))[($f&1536)/512];}if(($fm&2048)==2048) {$r[]=self::id(array('impf','perf'))[($f&2048)/2048];}if(($fm&4096)==4096) {$r[]=self::id(array('act','psv'))[($f&4096)/4096];}if(($fm&24576)==24576) {$r[]=self::id(array('p1','p2','p3'))[($f&24576)/8192];}if(($fm&229376)==229376) {$r[]=self::id(array('g1','g2','g3','g4','g3io'))[($f&229376)/32768];}if(($fm&3932160)==3932160) {$r[]=self::id(array('n1','n2','n3','n3i','n4','n5','ng1','ng2','ng4','ng5'))[($f&3932160)/262144];}if(($fm&12582912)==12582912) {$r[]=self::id(array('noclitic','and','or','rog'))[($f&12582912)/4194304];}return $r;}static $FTVE2;
static $Fweak_a;
static $Fweak_i;
static $Fm_i;
static $Fstrong_i;
static $Fweak_o;
static $Fve_short;
static $Fve_long;
static $Fom;
static $Fpsv_inf;
static $Fsbj_perf;
static $Fve_ind;
static $Fve_sbj;
static $Fve_inf;
static $Fve_imp;
static $Fve_ptp;
static $MSStem;
static $OStem;
static $MSPE;
static $MST;
static $MSVE;
static $MSNE;
static $MSNStem;
static $ONStem;
static $MSNE2;
static $MSClitics;
static $C0;
static $C1;
static $FAS_Gender;
static $FAS_Number;
static $FAS_Case;
static $FAS_Mood;
static $FAS_Tense;
static $FAS_Aspect;
static $FAS_Voice;
static $FAS_Person;
static $FAS_VClass;
static $FAS_NClass;
static $FAS_Clitic;
static $WORD;
static function init(){
self::$cJ = function($ar) {
return implode('', $ar);
};
self::$FTVE2=new form('TVE2',array(function($a,$b,$c,$d,$e,$f){return ((($c)&26116)==1024&&(($f)&26116)==26116);}));self::$Fweak_a=new form('weak_a',array(function($a,$b,$c,$d,$e,$f){return (((($b)&24580)==0&&(($e)&24580)==24580)&&((($c)&1984)==0&&(($f)&1984)==1984));}));self::$Fweak_i=new form('weak_i',array(function($a,$b,$c,$d,$e,$f){return ((($b)&24580)==0&&(($e)&24580)==24580);},function($a,$b,$c,$d,$e,$f){return (((($b)&24580)==16388&&(($e)&24580)==24580)&&((($c)&2048)==0&&(($f)&2048)==2048));},function($a,$b,$c,$d,$e,$f){return ((($b)&1536)==512&&(($e)&1536)==1536);},function($a,$b,$c,$d,$e,$f){return ((($b)&28676)==12288&&(($e)&28676)==28676&&(($b)&448)!=128&&(($e)&448)==448);},function($a,$b,$c,$d,$e,$f){return (((($b)&1536)==1024&&(($e)&1536)==1536&&(($b)&448)!=128&&(($e)&448)==448)&&(((($c)&0x38800)==65536&&(($f)&0x38800)==0x38800)||((($c)&0x38800)==98304&&(($f)&0x38800)==0x38800)||((($c)&0x38800)==0x20000&&(($f)&0x38800)==0x38800)));}));self::$Fm_i=new form('m_i',array(function($a,$b,$c,$d,$e,$f){return ((($b)&24580)==16388&&(($e)&24580)==24580);},function($a,$b,$c,$d,$e,$f){return ((($b)&1536)==512&&(($e)&1536)==1536);}));self::$Fstrong_i=new form('strong_i',array(function($a,$b,$c,$d,$e,$f){return ((($b)&24580)==16388&&(($e)&24580)==24580);},function($a,$b,$c,$d,$e,$f){return ((($b)&1536)==512&&(($e)&1536)==1536);}));self::$Fweak_o=new form('weak_o',array(function($a,$b,$c,$d,$e,$f){return (((($a)&3584)==512&&(($d)&3584)==3584)||((($a)&448)==64&&(($d)&448)==448));},function($a,$b,$c,$d,$e,$f){return (((($a)&1536)==1024&&(($d)&1536)==1536)&&(((($c)&0x38000)==65536&&(($f)&0x38000)==0x38000)||((($c)&0x38000)==98304&&(($f)&0x38000)==0x38000)||((($c)&0x38000)==0x20000&&(($f)&0x38000)==0x38000)));}));self::$Fve_short=new form('ve_short',array());self::$Fve_long=new form('ve_long',array());self::$Fom=new form('om',array(function($a,$b,$c,$d,$e,$f){return (((($c)&1984)==0&&(($f)&1984)==1984)||((($c)&0x387c0)==1024&&(($f)&0x387c0)==0x387c0)||((($c)&0x387c0)==33792&&(($f)&0x387c0)==0x387c0)||((($c)&3584)==3072&&(($f)&3584)==3584));}));self::$Fpsv_inf=new form('psv_inf',array(function($a,$b,$c,$d,$e,$f){return (((($c)&0x38000)==65536&&(($f)&0x38000)==0x38000)||((($c)&0x38000)==0x20000&&(($f)&0x38000)==0x38000));}));self::$Fsbj_perf=new form('sbj_perf',array(function($a,$b,$c,$d,$e,$f){return ((($c)&1536)==512&&(($f)&1536)==1536);}));self::$Fve_ind=new form('ve_ind',array(function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==0&&(($f)&0x38000)==0x38000);},function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==32768&&(($f)&0x38000)==0x38000);},function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==65536&&(($f)&0x38000)==0x38000);},function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==98304&&(($f)&0x38000)==0x38000);},function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==0x20000&&(($f)&0x38000)==0x38000);}));self::$Fve_sbj=new form('ve_sbj',array(function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==0&&(($f)&0x38000)==0x38000);},function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==32768&&(($f)&0x38000)==0x38000);},function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==65536&&(($f)&0x38000)==0x38000);},function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==98304&&(($f)&0x38000)==0x38000);},function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==0x20000&&(($f)&0x38000)==0x38000);}));self::$Fve_inf=new form('ve_inf',array(function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==0&&(($f)&0x38000)==0x38000);},function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==32768&&(($f)&0x38000)==0x38000);},function($a,$b,$c,$d,$e,$f){return (((($b)&448)==192&&(($e)&448)==448)&&(((($c)&0x39000)==69632&&(($f)&0x39000)==0x39000)||((($c)&0x39000)==0x21000&&(($f)&0x39000)==0x39000)));},function($a,$b,$c,$d,$e,$f){return (((($c)&0x38000)==65536&&(($f)&0x38000)==0x38000)||((($c)&0x38000)==0x20000&&(($f)&0x38000)==0x38000));},function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==98304&&(($f)&0x38000)==0x38000);}));self::$Fve_imp=new form('ve_imp',array(function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==0&&(($f)&0x38000)==0x38000);},function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==32768&&(($f)&0x38000)==0x38000);},function($a,$b,$c,$d,$e,$f){return (((($b)&4)==0&&(($e)&4)==4)&&(((($c)&0x38000)==65536&&(($f)&0x38000)==0x38000)||((($c)&0x38000)==0x20000&&(($f)&0x38000)==0x38000)));},function($a,$b,$c,$d,$e,$f){return (((($b)&4)==4&&(($e)&4)==4)&&(((($c)&0x38000)==65536&&(($f)&0x38000)==0x38000)||((($c)&0x38000)==0x20000&&(($f)&0x38000)==0x38000)));},function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==98304&&(($f)&0x38000)==0x38000);}));self::$Fve_ptp=new form('ve_ptp',array(function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==0&&(($f)&0x38000)==0x38000);},function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==32768&&(($f)&0x38000)==0x38000);},function($a,$b,$c,$d,$e,$f){return ((($c)&0x38000)==65536&&(($f)&0x38000)==0x38000);},function($a,$b,$c,$d,$e,$f){return (((($c)&0x38000)==98304&&(($f)&0x38000)==0x38000)||((($c)&0x38000)==0x20000&&(($f)&0x38000)==0x38000));}));self::$MSStem=array(new morph('imperfect',array(''),array(0,64,128,192,256,5376),array(2496,2496,2496,2496,6080,6080),0,false),new morph('perfect',array(''),array(2048),array(2048),1,false),new morph('supine',array(''),array(4864,1280),array(6080,6080),2,false));self::$OStem=array('imperfect','perfect','supine');self::$MSPE=array(new morph('',array(),array(256),array(448),0,true),new morph('',array('re'),array(192),array(6592),1,false),new morph('',array(self::$Fom),array(0,64,2112,2560,3072),array(31172,31172,31172,32260,32260),2,false),new morph('',array(self::$Fve_long,'s'),array(8192,8256,10304,10752,11264),array(31172,31172,31172,32260,32260),3,false),new morph('',array('t'),array(16384,16448,18496,18944,19456),array(31172,31172,31172,32260,32260),4,false),new morph('',array(self::$Fve_long,'mus'),array(4,68,2116,2564,3076),array(31172,31172,31172,32260,32260),5,false),new morph('',array(self::$Fve_long,'tis'),array(8196,8260,10308,10756,11268),array(31172,31172,31172,32260,32260),6,false),new morph('',array('nt'),array(16388,16452,18500,18948,19460),array(31172,31172,31172,32260,32260),7,false),new morph('',array(self::$Fpsv_inf),array(4288),array(6592),8,false),new morph('',array(self::$Fweak_o,'r'),array(4096,4160),array(31172,31172),9,false),new morph('',array(self::$Fve_long,'ris'),array(12288,12352),array(31172,31172),10,false),new morph('',array(self::$Fve_long,'re'),array(12288,12352),array(31172,31172),11,false),new morph('',array(self::$Fve_long,'tur'),array(20480,20544),array(31172,31172),12,false),new morph('',array(self::$Fve_long,'mur'),array(4100,4164),array(31172,31172),13,false),new morph('',array(self::$Fve_long,'mini:'),array(12292,12356),array(31172,31172),14,false),new morph('',array('ntur'),array(20484,20548),array(31172,31172),15,false),new morph('',array('isse'),array(2240),array(6592),16,false),new morph('',array('i:'),array(2048),array(32708),17,false),new morph('',array('isti:'),array(10240),array(32708),18,false),new morph('',array('it'),array(18432),array(32708),19,false),new morph('',array('imus'),array(2052),array(32708),20,false),new morph('',array('istis'),array(10244),array(32708),21,false),new morph('',array('e:runt'),array(18436),array(32708),22,false),new morph('',array('e:re'),array(18436),array(32708),23,false),new morph('',array(''),array(8320),array(32708),24,false),new morph('',array('te'),array(8324),array(32708),25,false),new morph('',array('re'),array(12416),array(32708),26,false),new morph('',array('mini:'),array(12420),array(32708),27,false),new morph('',array(self::$Fve_long,'to:'),array(9344,17536),array(32708,32708),28,false),new morph('',array(self::$Fve_long,'to:te'),array(9348),array(32708),29,false),new morph('',array('nto'),array(17540),array(32708),30,false),new morph('',array(self::$Fve_long,'tor'),array(13440,21632),array(32708,32708),31,false),new morph('',array('ntor'),array(21636),array(32708),32,false));self::$MST=array(new morph('',array(),array(0,1152),array(1536,1984),0,true),new morph('',array(self::$FTVE2),array(66560,99328,0x20400),array(0x38fc0,0x38fc0,0x38fc0),1,false),new morph('',array(self::$Fve_long,'b',self::$Fweak_i),array(1024,33792),array(0x38fc0,0x38fc0),2,false),new morph('',array(self::$Fve_long,'b',self::$Fweak_a),array(512),array(4032),3,false),new morph('',array('re'),array(576),array(4032),4,false),new morph('',array('er',self::$Fweak_i),array(3072),array(4032),5,false),new morph('',array('er',self::$Fweak_a),array(2560),array(4032),6,false),new morph('',array('isse'),array(2624),array(4032),7,false),new morph('',array(self::$Fve_long,'nt'),array(256),array(6080),8,false),new morph('',array(''),array(4864),array(6080),9,false),new morph('',array('u:r'),array(1280),array(6080),10,false),new morph('',array('nd'),array(5376),array(6080),11,false));self::$MSVE=array(new morph('indicative',array(self::$Fve_ind),array(0),array(2496),0,false),new morph('subjunctive',array(self::$Fve_sbj),array(64),array(4032),1,false),new morph('subjunctive',array(self::$Fve_inf),array(576),array(4032),2,false),new morph('infinitive',array(self::$Fve_inf),array(192),array(2496),3,false),new morph('indicative',array(''),array(2048),array(2496),4,false),new morph('subjunctive',array(self::$Fsbj_perf),array(2112),array(2496),5,false),new morph('infinitive',array(''),array(2240),array(2496),6,false),new morph('imperative',array(self::$Fve_imp),array(128),array(1984),7,false),new morph('imperative',array(self::$Fve_ind),array(1152),array(1984),8,false),new morph('participle',array(self::$Fve_ptp),array(256,5376),array(6080,6080),9,false),new morph('',array(),array(4864,1280),array(6080,6080),10,true));self::$MSNE=array(new morph('',array(),array(0,64,128,192),array(448,448,448,448),0,true));self::$MSNStem=array(new morph('nominative',array(''),array(0,40,1,41,2,42,26),array(63,63,63,63,63,63,63),0,false),new morph('genitive',array(''),array(8,16,24,32,9,17,25,33,10,18,34,4),array(63,63,63,63,63,63,63,63,63,63,63,4),1,false));self::$ONStem=array('nominative','genitive');self::$MSNE2=array(new morph('',array('a'),array(0,40),array(0x3c003c,0x3c003c),0,false),new morph('',array('ae'),array(8,16,4,44),array(0x3c003c,0x3c003c,0x3c003c,0x3c003c),1,false),new morph('',array('am'),array(24),array(0x3c003c),2,false),new morph('',array('a:'),array(32),array(0x3c003c),3,false),new morph('',array('a:rum'),array(12),array(0x3c003c),4,false),new morph('',array('i:s'),array(20,0x40014,36,0x40024),array(0x3c003c,0x3c003c,0x3c003c,0x3c003c),5,false),new morph('',array('a:s'),array(28),array(0x3c003c),6,false),new morph('',array('us'),array(0x40000,0x100000,0x40001,0x100001,0x100028),array(0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003c),7,false),new morph('',array('i:'),array(0x40008,0x40004,0x4002c,0x40005,0x4002d),array(0x3c003c,0x3c003f,0x3c003f,0x3c003f,0x3c003f),8,false),new morph('',array('o:'),array(0x40010,0x40020),array(0x3c003c,0x3c003c),9,false),new morph('',array('um'),array(0x40018,0x100018,0x40019,0x100019,0x40002,0x4002a,0x4001a),array(0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f),10,false),new morph('',array('e'),array(0x40028,0x40029),array(0x3c003f,0x3c003f),11,false),new morph('',array('o:rum'),array(0x4000c),array(0x3c003c),12,false),new morph('',array('o:s'),array(0x4001c,0x4001d),array(0x3c003f,0x3c003f),13,false),new morph('',array('a'),array(0x40006,0x80006,0x4002e,0x8002e,0x4001e,0x8001e),array(0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f),14,false),new morph('',array(''),array(0x80000,0xc0000,0x80028,0xc0028,0x80001,0xc0001,0x80029,0xc0029,0x80002,0xc0002,0x8002a,0xc002a,0x8001a,0xc001a),array(0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f),15,false),new morph('',array('is'),array(0x80008,0xc0008),array(0x3c003c,0x3c003c),16,false),new morph('',array('i:'),array(0x80010,0xc0010),array(0x3c003c,0x3c003c),17,false),new morph('',array('em'),array(0x80018,0xc0018),array(0x3c003c,0x3c003c),18,false),new morph('',array('e'),array(0x80020,0xc0020),array(0x3c003c,0x3c003c),19,false),new morph('',array('e:s'),array(0x80004,0xc0004,0x8002c,0xc002c,0x8001c,0xc001c),array(0x3c003c,0x3c003c,0x3c003c,0x3c003c,0x3c003c,0x3c003c),20,false),new morph('',array('um'),array(0x8000c),array(0x3c003c),21,false),new morph('',array('ium'),array(0xc000c),array(0x3c003c),22,false),new morph('',array('ia'),array(0xc0006,0xc002e,0xc001e),array(0x3c003f,0x3c003f,0x3c003f),23,false),new morph('',array('ibus'),array(0x80014,0xc0014,0x100014,0x80024,0xc0024,0x100024),array(0x3c003c,0x3c003c,0x3c003c,0x3c003c,0x3c003c,0x3c003c),24,false),new morph('',array('u:s'),array(0x100008,0x100004,0x10002c,0x10001c,0x100005,0x10002d,0x10001d),array(0x3c003c,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f,0x3c003f),25,false),new morph('',array('ui:'),array(0x100010),array(0x3c003c),26,false),new morph('',array('u:'),array(0x100020,0x100021,0x100002),array(0x3c003f,0x3c003f,0x3c0007),27,false),new morph('',array('uum'),array(0x10000c),array(0x3c003c),28,false),new morph('',array('ua'),array(0x100006,0x10002e,0x10001e),array(0x3c003f,0x3c003f,0x3c003f),29,false),new morph('',array('e:s'),array(0x140000,0x140028,0x140004,0x14002c,0x14001c),array(0x3c003c,0x3c003c,0x3c003c,0x3c003c,0x3c003c),30,false),new morph('',array('ei:'),array(0x140008,0x140010),array(0x3c003c,0x3c003c),31,false),new morph('',array('em'),array(0x140018),array(0x3c003c),32,false),new morph('',array('e:'),array(0x140020),array(0x3c003c),33,false),new morph('',array('e:rum'),array(0x14000c),array(0x3c003c),34,false),new morph('',array('e:bus'),array(0x140014,0x140024),array(0x3c003c,0x3c003c),35,false));self::$MSClitics=array(new morph('',array(),array(0),array(0),0,true),new morph('',array('que'),array(0x400000),array(0xc00000),1,false),new morph('',array('ve'),array(0x800000),array(0xc00000),2,false),new morph('',array('ne'),array(0xc00000),array(0xc00000),3,false));self::$C0=array(array("/;\x01:/","\x01"));self::$C1=array(array("/a\x01:/","ā\x01"),array("/e\x01:/","ē\x01"),array("/i\x01:/","ī\x01"),array("/o\x01:/","ō\x01"),array("/u\x01:/","ū\x01"),array("/;\x01()/","\x01"));self::$FTVE2->opt=array(array('a'));self::$FTVE2->def=array('e');self::$Fweak_a->opt=array(array(''));self::$Fweak_a->def=array('a');self::$Fweak_i->opt=array(array(''),array('u'),array('e'),array('e',self::$Fve_short),array(''));self::$Fweak_i->def=array('i',self::$Fve_short);self::$Fm_i->opt=array(array('iu'),array('ie'));self::$Fm_i->def=array('i',self::$Fve_short);self::$Fstrong_i->opt=array(array('iu'),array('ie'));self::$Fstrong_i->def=array('i');self::$Fweak_o->opt=array(array(''),array(''));self::$Fweak_o->def=array('o');self::$Fve_short->opt=array();self::$Fve_short->def=array(';');self::$Fve_long->opt=array();self::$Fve_long->def=array(':');self::$Fom->opt=array(array('o',self::$Fve_long));self::$Fom->def=array('m');self::$Fpsv_inf->opt=array(array('i:'));self::$Fpsv_inf->def=array('ri:');self::$Fsbj_perf->opt=array(array(''));self::$Fsbj_perf->def=array('eri');self::$Fve_ind->opt=array(array(self::$Fweak_a),array('e'),array(self::$Fweak_i),array(self::$Fstrong_i),array(self::$Fm_i));self::$Fve_ind->def=array('ERR');self::$Fve_sbj->opt=array(array('e'),array('ea'),array('a'),array('ia'),array('ia'));self::$Fve_sbj->def=array('ERR');self::$Fve_inf->opt=array(array('a:'),array('e:'),array(''),array('e'),array('i:'));self::$Fve_inf->def=array('ERR');self::$Fve_imp->opt=array(array('a:'),array('e:'),array('e'),array('i'),array('i:'));self::$Fve_imp->def=array('ERR');self::$Fve_ptp->opt=array(array('a'),array('e'),array('e'),array('ie'));self::$Fve_ptp->def=array('ERR');self::$FAS_Gender=array('mas'=>0,'fem'=>1,'neu'=>2);self::$FAS_Number=array('sng'=>0,'plr'=>4);self::$FAS_Case=array('nom'=>0,'gen'=>8,'dat'=>16,'acc'=>24,'abl'=>32,'voc'=>40);self::$FAS_Mood=array('ind'=>0,'sbj'=>64,'imp'=>128,'inf'=>192,'ptp'=>256);self::$FAS_Tense=array('prs'=>0,'pst'=>512,'ftr'=>1024);self::$FAS_Aspect=array('impf'=>0,'perf'=>2048);self::$FAS_Voice=array('act'=>0,'psv'=>4096);self::$FAS_Person=array('p1'=>0,'p2'=>8192,'p3'=>16384);self::$FAS_VClass=array('g1'=>0,'g2'=>32768,'g3'=>65536,'g4'=>98304,'g3io'=>131072);self::$FAS_NClass=array('n1'=>0,'n2'=>262144,'n3'=>524288,'n3i'=>786432,'n4'=>1048576,'n5'=>1310720,'ng1'=>1572864,'ng2'=>1835008,'ng4'=>2097152,'ng5'=>2359296);self::$FAS_Clitic=array('noclitic'=>0,'and'=>4194304,'or'=>8388608,'rog'=>12582912);self::$WORD=array('Verb'=>'Stem','Noun'=>'NStem');}static function SMStem($f,$fs){$r=array();
foreach(self::$MSStem as $i=>$ib){if(($t=self::$MSStem[$i]->test($f,$fs))>=0) {$r[]=array($i,$t);}}return $r;}static function SMPE($f,$fs){$r=array();
foreach(self::$MSPE as $i=>$ib){if(($t=self::$MSPE[$i]->test($f,$fs))>=0) {$r[]=array($i,$t);}}return $r;}static function SMT($f,$fs){$r=array();
foreach(self::$MST as $i=>$ib){if(($t=self::$MST[$i]->test($f,$fs))>=0) {$r[]=array($i,$t);}}return $r;}static function SMVE($f,$fs){$r=array();
foreach(self::$MSVE as $i=>$ib){if(($t=self::$MSVE[$i]->test($f,$fs))>=0) {$r[]=array($i,$t);}}return $r;}static function SMNE($f,$fs){$r=array();
foreach(self::$MSNE as $i=>$ib){if(($t=self::$MSNE[$i]->test($f,$fs))>=0) {$r[]=array($i,$t);}}return $r;}static function SMNStem($f,$fs){$r=array();
foreach(self::$MSNStem as $i=>$ib){if(($t=self::$MSNStem[$i]->test($f,$fs))>=0) {$r[]=array($i,$t);}}return $r;}static function SMNE2($f,$fs){$r=array();
foreach(self::$MSNE2 as $i=>$ib){if(($t=self::$MSNE2[$i]->test($f,$fs))>=0) {$r[]=array($i,$t);}}return $r;}static function SMClitics($f,$fs){$r=array();
foreach(self::$MSClitics as $i=>$ib){if(($t=self::$MSClitics[$i]->test($f,$fs))>=0) {$r[]=array($i,$t);}}return $r;}static function getFeatGender(){return self::$FAS_Gender;}static function getFeatNumber(){return self::$FAS_Number;}static function getFeatCase(){return self::$FAS_Case;}static function getFeatMood(){return self::$FAS_Mood;}static function getFeatTense(){return self::$FAS_Tense;}static function getFeatAspect(){return self::$FAS_Aspect;}static function getFeatVoice(){return self::$FAS_Voice;}static function getFeatPerson(){return self::$FAS_Person;}static function getFeatVClass(){return self::$FAS_VClass;}static function getFeatNClass(){return self::$FAS_NClass;}static function getFeatClitic(){return self::$FAS_Clitic;}static function apC($a,$b,$m){if($b=='PE')$m=self::cC(self::$C0,$m);$m=self::cC(self::$C1,$m);return $m;}static function composeVerb($s,$f,$fm){$m=array();
$a=self::SMStem($f,$fm);if(count($a)==0) {throw self::err0('Stem',$f,$fm);}$om=self::$MSStem[$a[0][0]]->get($a[0][1],'Stem');
if(!$s[$om->id]) {return false;}$om->form=array($s[$om->id]);$m[]=array($om);$a=self::SMVE($f,$fm);if(count($a)==0) {throw self::err0('VE',$f,$fm);}$t=array();foreach($a as $i=>$ib){if(!self::$MSVE[$a[$i][0]]->empty) {$t[]=self::$MSVE[$a[$i][0]]->get($a[$i][1],'VE');}}if(count($t)) {$m[]=$t;}$a=self::SMT($f,$fm);if(count($a)==0) {throw self::err0('T',$f,$fm);}$t=array();foreach($a as $i=>$ib){if(!self::$MST[$a[$i][0]]->empty) {$t[]=self::$MST[$a[$i][0]]->get($a[$i][1],'T');}}if(count($t)) {$m[]=$t;}$a=self::SMPE($f,$fm);if(count($a)==0) {throw self::err0('PE',$f,$fm);}$t=array();foreach($a as $i=>$ib){if(!self::$MSPE[$a[$i][0]]->empty) {$t[]=self::$MSPE[$a[$i][0]]->get($a[$i][1],'PE');}}if(count($t)) {$m[]=$t;}$a=self::SMNE($f,$fm);if(count($a)==0) {throw self::err0('NE',$f,$fm);}$t=array();foreach($a as $i=>$ib){if(!self::$MSNE[$a[$i][0]]->empty) {$t[]=self::$MSNE[$a[$i][0]]->get($a[$i][1],'NE');}}if(count($t)) {$m[]=$t;}$a=self::SMClitics($f,$fm);if(count($a)==0) {throw self::err0('Clitics',$f,$fm);}$t=array();foreach($a as $i=>$ib){if(!self::$MSClitics[$a[$i][0]]->empty) {$t[]=self::$MSClitics[$a[$i][0]]->get($a[$i][1],'Clitics');}}if(count($t)) {$m[]=$t;}$rs=array();
$rrs=array();
$cs=array();
$t=1;foreach($m as $i=>$ib){$t*=count($m[$i]);$cs[]=count($m[$i]);}for($j=0;$j<$t;$j++){$r=array();$jt=$j;
$ik=array();
foreach($m as $i=>$ib){$ik[]=$jt%$cs[$i];$jt=($jt/$cs[$i])|0;}foreach($m as $i=>$ib){if($i>0) {$c=$m[$i-1][$ik[$i-1]]->bit;$n=$m[$i-1][$ik[$i-1]]->mask;}if($i<count($m)-1) {$d=$m[($i|0)+1][$ik[($i|0)+1]]->bit;$o=$m[($i|0)+1][$ik[($i|0)+1]]->mask;}$r[]=self::cF($m[$i][$ik[$i]]->form,$c,$d,$f,$n,$o,$fm);if($i==0) {$rr=array($r[0]);}else {$rt=array($rr[$i-1],$r[$i]);
$rt=self::apC($m[$i-1][$ik[$i-1]]->mclass,$m[$i][$ik[$i]]->mclass,$rt);$rr[$i-1]=$rt[0];$rr[$i]=$rt[1];}}$rs[]=$r;$rrs[]=$rr;}return array('f'=>array_map(self::$cJ,$rrs),'fs'=>$rs);}static function composeNoun($s,$f,$fm){$m=array();
$a=self::SMNStem($f,$fm);if(count($a)==0) {throw self::err0('NStem',$f,$fm);}$om=self::$MSNStem[$a[0][0]]->get($a[0][1],'NStem');
if(!$s[$om->id]) {return false;}$om->form=array($s[$om->id]);$m[]=array($om);$a=self::SMNE2($f,$fm);if(count($a)==0) {throw self::err0('NE2',$f,$fm);}$t=array();foreach($a as $i=>$ib){if(!self::$MSNE2[$a[$i][0]]->empty) {$t[]=self::$MSNE2[$a[$i][0]]->get($a[$i][1],'NE2');}}if(count($t)) {$m[]=$t;}$a=self::SMClitics($f,$fm);if(count($a)==0) {throw self::err0('Clitics',$f,$fm);}$t=array();foreach($a as $i=>$ib){if(!self::$MSClitics[$a[$i][0]]->empty) {$t[]=self::$MSClitics[$a[$i][0]]->get($a[$i][1],'Clitics');}}if(count($t)) {$m[]=$t;}$rs=array();
$rrs=array();
$cs=array();
$t=1;foreach($m as $i=>$ib){$t*=count($m[$i]);$cs[]=count($m[$i]);}for($j=0;$j<$t;$j++){$r=array();$jt=$j;
$ik=array();
foreach($m as $i=>$ib){$ik[]=$jt%$cs[$i];$jt=($jt/$cs[$i])|0;}foreach($m as $i=>$ib){if($i>0) {$c=$m[$i-1][$ik[$i-1]]->bit;$n=$m[$i-1][$ik[$i-1]]->mask;}if($i<count($m)-1) {$d=$m[($i|0)+1][$ik[($i|0)+1]]->bit;$o=$m[($i|0)+1][$ik[($i|0)+1]]->mask;}$r[]=self::cF($m[$i][$ik[$i]]->form,$c,$d,$f,$n,$o,$fm);if($i==0) {$rr=array($r[0]);}else {$rt=array($rr[$i-1],$r[$i]);
$rt=self::apC($m[$i-1][$ik[$i-1]]->mclass,$m[$i][$ik[$i]]->mclass,$rt);$rr[$i-1]=$rt[0];$rr[$i]=$rt[1];}}$rs[]=$r;$rrs[]=$rr;}return array('f'=>array_map(self::$cJ,$rrs),'fs'=>$rs);}static function getWord(){return self::$WORD;}};Latina::init();?>
지금 남은 문제는 속도입니다. 이 녀석 해석기가 PHP를 기반으로 작성되어서 규칙 서술 언어를 파싱할때도, 그리고 추상트리에서 목적 언어를 생성해낼때도 상당히 느립니다. 이것은 번역결과를 캐싱하는 방식으로 일단 해결했는데, 그래도 느립니다. 아직은 제가 직접 손수 작성한 PHP 라틴어 단어 굴절 코드가 더 빠르다는게 함정이죠. (그래서 아직 살아있는 라틴어 사전에는 전격 도입하지 못하고 살아있는 헬라어 사전 명사 굴절에만 부분 도입해서 사용하고 있습니다.) 컴파일 타임 최적화를 통해 속도를 높일 수 있는 부분은 높이도록 좀더 공부를 해봐야할것 같습니다.
아직 전격적으로 공개하기에는 좀더 개선할부분이 있어서 코드 공개는 좀 미루고, 대신 웹에서 MorPHP의 동작원리를 살펴볼수있는 페이지를 만들었습니다. 관심있는 분들은 참고하시면될듯합니다.
MorPHP를 통한 한국어 동사 변화 규칙 서술 (0) | 2015.12.22 |
---|---|
XpressEngine, PHP5.5 + MySQL에서 PHP7.0 + MariaDB로 갈아탄 후기 (4) | 2015.12.21 |
MorPHP를 이용한 스와힐리어 문법 서술 (0) | 2015.12.15 |
[PHP, MySQL] 클러스터링을 이용한 동음이의어 분리 (0) | 2015.10.18 |
XE 페이지 주소 통일하기 (0) | 2015.09.19 |
자바스크립트로 수식 파싱하기 (0) | 2015.09.09 |
댓글 영역