1 module libmecab.common; 2 3 import bindbc.mecab; 4 5 shared static this() 6 { 7 const support = loadMeCab(); 8 assert(support == MeCabSupport.mecab); 9 } 10 11 shared static ~this() 12 { 13 unloadMeCab(); 14 } 15 16 struct MeCabModel 17 { 18 private mecab_model_t* handle; 19 20 @disable this(); 21 @disable this(this); 22 23 package this(mecab_model_t* handle) 24 { 25 this.handle = handle; 26 } 27 28 ~this() 29 { 30 mecab_model_destroy(this.handle); 31 } 32 33 MeCabTagger createTagger() 34 { 35 return MeCabTagger(mecab_model_new_tagger(handle)); 36 } 37 38 MeCabLattice createLattice() 39 { 40 return MeCabLattice(mecab_model_new_lattice(handle)); 41 } 42 43 static MeCabModel create() 44 { 45 auto model = mecab_model_new(0, null); 46 return MeCabModel(model); 47 } 48 49 static MeCabModel create(string arg) 50 { 51 auto buf = new char[arg.length + 1]; 52 buf[0 .. $ - 1] = arg[]; 53 buf[$ - 1] = 0; 54 auto model = mecab_model_new2(buf.ptr); 55 return MeCabModel(model); 56 } 57 } 58 59 struct MeCabTagger 60 { 61 private mecab_t* handle; 62 63 @disable this(); 64 @disable this(this); 65 66 package this(mecab_t* handle) 67 { 68 this.handle = handle; 69 } 70 71 ~this() 72 { 73 mecab_destroy(handle); 74 } 75 76 MeCabNodeRange parseToNodes(scope ref MeCabLattice lattice) 77 { 78 mecab_parse_lattice(handle, lattice.handle); 79 return MeCabNodeRange(lattice.bosNode()); 80 } 81 82 MeCabNodeRange parseToNodes(string text) 83 { 84 auto lattice = MeCabLattice.create(); 85 lattice.sentence = text; 86 return parseToNodes(lattice); 87 } 88 89 static MeCabTagger create() 90 { 91 auto handle = mecab_new(0, null); 92 return MeCabTagger(handle); 93 } 94 } 95 96 struct MeCabLattice 97 { 98 private mecab_lattice_t* handle; 99 100 @disable this(); 101 @disable this(this); 102 103 package this(mecab_lattice_t* handle) 104 { 105 this.handle = handle; 106 } 107 108 void sentence(const(char)[] text) 109 { 110 mecab_lattice_set_sentence2(handle, text.ptr, text.length); 111 } 112 113 package mecab_node_t* bosNode() 114 { 115 return mecab_lattice_get_bos_node(handle); 116 } 117 118 static MeCabLattice create() 119 { 120 return MeCabLattice(mecab_lattice_new()); 121 } 122 } 123 124 struct MeCabNode 125 { 126 string surface; 127 string feature; 128 uint id; 129 ushort rcAttr; 130 ushort lcAttr; 131 ushort posId; 132 ubyte charType; 133 ubyte stat; 134 ubyte isBest; 135 float alpha; 136 float beta; 137 float prob; 138 long cost; 139 short wcost; 140 } 141 142 struct MeCabNodeRange 143 { 144 private mecab_node_t* node; 145 146 @disable this(); 147 148 this(mecab_node_t* node) 149 { 150 this.node = node; 151 } 152 153 bool empty() const pure nothrow @safe @nogc 154 { 155 return node is null; 156 } 157 158 auto front() const pure nothrow 159 in(!empty) 160 { 161 import std.conv : to; 162 163 return MeCabNode( 164 node.surface[0 .. node.length].to!string(), 165 node.feature.to!string(), 166 node.id, 167 node.rcAttr, 168 node.lcAttr, 169 node.posid, 170 node.char_type, 171 node.stat, 172 node.isbest, 173 node.alpha, 174 node.beta, 175 node.prob, 176 node.cost, 177 node.wcost 178 ); 179 } 180 181 void popFront() nothrow @safe @nogc 182 in(!empty) 183 { 184 this.node = this.node.next; 185 } 186 }