URI:
       base-stemmer.js - sphere - GPU-based 3D discrete element method algorithm with optional fluid coupling
  HTML git clone git://src.adamsgaard.dk/sphere
   DIR Log
   DIR Files
   DIR Refs
   DIR LICENSE
       ---
       base-stemmer.js (12250B)
       ---
            1 // @ts-check
            2 
            3 /**@constructor*/
            4 BaseStemmer = function() {
            5     /** @protected */
            6     this.current = '';
            7     this.cursor = 0;
            8     this.limit = 0;
            9     this.limit_backward = 0;
           10     this.bra = 0;
           11     this.ket = 0;
           12 
           13     /**
           14      * @param {string} value
           15      */
           16     this.setCurrent = function(value) {
           17         this.current = value;
           18         this.cursor = 0;
           19         this.limit = this.current.length;
           20         this.limit_backward = 0;
           21         this.bra = this.cursor;
           22         this.ket = this.limit;
           23     };
           24 
           25     /**
           26      * @return {string}
           27      */
           28     this.getCurrent = function() {
           29         return this.current;
           30     };
           31 
           32     /**
           33      * @param {BaseStemmer} other
           34      */
           35     this.copy_from = function(other) {
           36         /** @protected */
           37         this.current          = other.current;
           38         this.cursor           = other.cursor;
           39         this.limit            = other.limit;
           40         this.limit_backward   = other.limit_backward;
           41         this.bra              = other.bra;
           42         this.ket              = other.ket;
           43     };
           44 
           45     /**
           46      * @param {number[]} s
           47      * @param {number} min
           48      * @param {number} max
           49      * @return {boolean}
           50      */
           51     this.in_grouping = function(s, min, max) {
           52         /** @protected */
           53         if (this.cursor >= this.limit) return false;
           54         var ch = this.current.charCodeAt(this.cursor);
           55         if (ch > max || ch < min) return false;
           56         ch -= min;
           57         if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return false;
           58         this.cursor++;
           59         return true;
           60     };
           61 
           62     /**
           63      * @param {number[]} s
           64      * @param {number} min
           65      * @param {number} max
           66      * @return {boolean}
           67      */
           68     this.go_in_grouping = function(s, min, max) {
           69         /** @protected */
           70         while (this.cursor < this.limit) {
           71             var ch = this.current.charCodeAt(this.cursor);
           72             if (ch > max || ch < min)
           73                 return true;
           74             ch -= min;
           75             if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0)
           76                 return true;
           77             this.cursor++;
           78         }
           79         return false;
           80     };
           81 
           82     /**
           83      * @param {number[]} s
           84      * @param {number} min
           85      * @param {number} max
           86      * @return {boolean}
           87      */
           88     this.in_grouping_b = function(s, min, max) {
           89         /** @protected */
           90         if (this.cursor <= this.limit_backward) return false;
           91         var ch = this.current.charCodeAt(this.cursor - 1);
           92         if (ch > max || ch < min) return false;
           93         ch -= min;
           94         if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return false;
           95         this.cursor--;
           96         return true;
           97     };
           98 
           99     /**
          100      * @param {number[]} s
          101      * @param {number} min
          102      * @param {number} max
          103      * @return {boolean}
          104      */
          105     this.go_in_grouping_b = function(s, min, max) {
          106         /** @protected */
          107         while (this.cursor > this.limit_backward) {
          108             var ch = this.current.charCodeAt(this.cursor - 1);
          109             if (ch > max || ch < min) return true;
          110             ch -= min;
          111             if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return true;
          112             this.cursor--;
          113         }
          114         return false;
          115     };
          116 
          117     /**
          118      * @param {number[]} s
          119      * @param {number} min
          120      * @param {number} max
          121      * @return {boolean}
          122      */
          123     this.out_grouping = function(s, min, max) {
          124         /** @protected */
          125         if (this.cursor >= this.limit) return false;
          126         var ch = this.current.charCodeAt(this.cursor);
          127         if (ch > max || ch < min) {
          128             this.cursor++;
          129             return true;
          130         }
          131         ch -= min;
          132         if ((s[ch >>> 3] & (0X1 << (ch & 0x7))) == 0) {
          133             this.cursor++;
          134             return true;
          135         }
          136         return false;
          137     };
          138 
          139     /**
          140      * @param {number[]} s
          141      * @param {number} min
          142      * @param {number} max
          143      * @return {boolean}
          144      */
          145     this.go_out_grouping = function(s, min, max) {
          146         /** @protected */
          147         while (this.cursor < this.limit) {
          148             var ch = this.current.charCodeAt(this.cursor);
          149             if (ch <= max && ch >= min) {
          150                 ch -= min;
          151                 if ((s[ch >>> 3] & (0X1 << (ch & 0x7))) != 0) {
          152                     return true;
          153                 }
          154             }
          155             this.cursor++;
          156         }
          157         return false;
          158     };
          159 
          160     /**
          161      * @param {number[]} s
          162      * @param {number} min
          163      * @param {number} max
          164      * @return {boolean}
          165      */
          166     this.out_grouping_b = function(s, min, max) {
          167         /** @protected */
          168         if (this.cursor <= this.limit_backward) return false;
          169         var ch = this.current.charCodeAt(this.cursor - 1);
          170         if (ch > max || ch < min) {
          171             this.cursor--;
          172             return true;
          173         }
          174         ch -= min;
          175         if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) {
          176             this.cursor--;
          177             return true;
          178         }
          179         return false;
          180     };
          181 
          182     /**
          183      * @param {number[]} s
          184      * @param {number} min
          185      * @param {number} max
          186      * @return {boolean}
          187      */
          188     this.go_out_grouping_b = function(s, min, max) {
          189         /** @protected */
          190         while (this.cursor > this.limit_backward) {
          191             var ch = this.current.charCodeAt(this.cursor - 1);
          192             if (ch <= max && ch >= min) {
          193                 ch -= min;
          194                 if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) != 0) {
          195                     return true;
          196                 }
          197             }
          198             this.cursor--;
          199         }
          200         return false;
          201     };
          202 
          203     /**
          204      * @param {string} s
          205      * @return {boolean}
          206      */
          207     this.eq_s = function(s)
          208     {
          209         /** @protected */
          210         if (this.limit - this.cursor < s.length) return false;
          211         if (this.current.slice(this.cursor, this.cursor + s.length) != s)
          212         {
          213             return false;
          214         }
          215         this.cursor += s.length;
          216         return true;
          217     };
          218 
          219     /**
          220      * @param {string} s
          221      * @return {boolean}
          222      */
          223     this.eq_s_b = function(s)
          224     {
          225         /** @protected */
          226         if (this.cursor - this.limit_backward < s.length) return false;
          227         if (this.current.slice(this.cursor - s.length, this.cursor) != s)
          228         {
          229             return false;
          230         }
          231         this.cursor -= s.length;
          232         return true;
          233     };
          234 
          235     /**
          236      * @param {Among[]} v
          237      * @return {number}
          238      */
          239     this.find_among = function(v)
          240     {
          241         /** @protected */
          242         var i = 0;
          243         var j = v.length;
          244 
          245         var c = this.cursor;
          246         var l = this.limit;
          247 
          248         var common_i = 0;
          249         var common_j = 0;
          250 
          251         var first_key_inspected = false;
          252 
          253         while (true)
          254         {
          255             var k = i + ((j - i) >>> 1);
          256             var diff = 0;
          257             var common = common_i < common_j ? common_i : common_j; // smaller
          258             // w[0]: string, w[1]: substring_i, w[2]: result, w[3]: function (optional)
          259             var w = v[k];
          260             var i2;
          261             for (i2 = common; i2 < w[0].length; i2++)
          262             {
          263                 if (c + common == l)
          264                 {
          265                     diff = -1;
          266                     break;
          267                 }
          268                 diff = this.current.charCodeAt(c + common) - w[0].charCodeAt(i2);
          269                 if (diff != 0) break;
          270                 common++;
          271             }
          272             if (diff < 0)
          273             {
          274                 j = k;
          275                 common_j = common;
          276             }
          277             else
          278             {
          279                 i = k;
          280                 common_i = common;
          281             }
          282             if (j - i <= 1)
          283             {
          284                 if (i > 0) break; // v->s has been inspected
          285                 if (j == i) break; // only one item in v
          286 
          287                 // - but now we need to go round once more to get
          288                 // v->s inspected. This looks messy, but is actually
          289                 // the optimal approach.
          290 
          291                 if (first_key_inspected) break;
          292                 first_key_inspected = true;
          293             }
          294         }
          295         do {
          296             var w = v[i];
          297             if (common_i >= w[0].length)
          298             {
          299                 this.cursor = c + w[0].length;
          300                 if (w.length < 4) return w[2];
          301                 var res = w[3](this);
          302                 this.cursor = c + w[0].length;
          303                 if (res) return w[2];
          304             }
          305             i = w[1];
          306         } while (i >= 0);
          307         return 0;
          308     };
          309 
          310     // find_among_b is for backwards processing. Same comments apply
          311     /**
          312      * @param {Among[]} v
          313      * @return {number}
          314      */
          315     this.find_among_b = function(v)
          316     {
          317         /** @protected */
          318         var i = 0;
          319         var j = v.length
          320 
          321         var c = this.cursor;
          322         var lb = this.limit_backward;
          323 
          324         var common_i = 0;
          325         var common_j = 0;
          326 
          327         var first_key_inspected = false;
          328 
          329         while (true)
          330         {
          331             var k = i + ((j - i) >> 1);
          332             var diff = 0;
          333             var common = common_i < common_j ? common_i : common_j;
          334             var w = v[k];
          335             var i2;
          336             for (i2 = w[0].length - 1 - common; i2 >= 0; i2--)
          337             {
          338                 if (c - common == lb)
          339                 {
          340                     diff = -1;
          341                     break;
          342                 }
          343                 diff = this.current.charCodeAt(c - 1 - common) - w[0].charCodeAt(i2);
          344                 if (diff != 0) break;
          345                 common++;
          346             }
          347             if (diff < 0)
          348             {
          349                 j = k;
          350                 common_j = common;
          351             }
          352             else
          353             {
          354                 i = k;
          355                 common_i = common;
          356             }
          357             if (j - i <= 1)
          358             {
          359                 if (i > 0) break;
          360                 if (j == i) break;
          361                 if (first_key_inspected) break;
          362                 first_key_inspected = true;
          363             }
          364         }
          365         do {
          366             var w = v[i];
          367             if (common_i >= w[0].length)
          368             {
          369                 this.cursor = c - w[0].length;
          370                 if (w.length < 4) return w[2];
          371                 var res = w[3](this);
          372                 this.cursor = c - w[0].length;
          373                 if (res) return w[2];
          374             }
          375             i = w[1];
          376         } while (i >= 0);
          377         return 0;
          378     };
          379 
          380     /* to replace chars between c_bra and c_ket in this.current by the
          381      * chars in s.
          382      */
          383     /**
          384      * @param {number} c_bra
          385      * @param {number} c_ket
          386      * @param {string} s
          387      * @return {number}
          388      */
          389     this.replace_s = function(c_bra, c_ket, s)
          390     {
          391         /** @protected */
          392         var adjustment = s.length - (c_ket - c_bra);
          393         this.current = this.current.slice(0, c_bra) + s + this.current.slice(c_ket);
          394         this.limit += adjustment;
          395         if (this.cursor >= c_ket) this.cursor += adjustment;
          396         else if (this.cursor > c_bra) this.cursor = c_bra;
          397         return adjustment;
          398     };
          399 
          400     /**
          401      * @return {boolean}
          402      */
          403     this.slice_check = function()
          404     {
          405         /** @protected */
          406         if (this.bra < 0 ||
          407             this.bra > this.ket ||
          408             this.ket > this.limit ||
          409             this.limit > this.current.length)
          410         {
          411             return false;
          412         }
          413         return true;
          414     };
          415 
          416     /**
          417      * @param {number} c_bra
          418      * @return {boolean}
          419      */
          420     this.slice_from = function(s)
          421     {
          422         /** @protected */
          423         var result = false;
          424         if (this.slice_check())
          425         {
          426             this.replace_s(this.bra, this.ket, s);
          427             result = true;
          428         }
          429         return result;
          430     };
          431 
          432     /**
          433      * @return {boolean}
          434      */
          435     this.slice_del = function()
          436     {
          437         /** @protected */
          438         return this.slice_from("");
          439     };
          440 
          441     /**
          442      * @param {number} c_bra
          443      * @param {number} c_ket
          444      * @param {string} s
          445      */
          446     this.insert = function(c_bra, c_ket, s)
          447     {
          448         /** @protected */
          449         var adjustment = this.replace_s(c_bra, c_ket, s);
          450         if (c_bra <= this.bra) this.bra += adjustment;
          451         if (c_bra <= this.ket) this.ket += adjustment;
          452     };
          453 
          454     /**
          455      * @return {string}
          456      */
          457     this.slice_to = function()
          458     {
          459         /** @protected */
          460         var result = '';
          461         if (this.slice_check())
          462         {
          463             result = this.current.slice(this.bra, this.ket);
          464         }
          465         return result;
          466     };
          467 
          468     /**
          469      * @return {string}
          470      */
          471     this.assign_to = function()
          472     {
          473         /** @protected */
          474         return this.current.slice(0, this.limit);
          475     };
          476 };