Experimental change for kana2romaji.
[jmdict-cli.git] / kana2romaji.cpp
1 /*
2 jmdict, a frontend to the JMdict file. http://mandrill.fuxx0r.net/jmdict.php
3 Copyright (C) 2004 Florian Bluemel (florian.bluemel@uni-dortmund.de)
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 */
19 // encoding: utf-8
20 #include "kana2romaji.h"
21 #include <map>
22 #include <iostream>
23 #include <ostream>
24 #include <string>
25
26 using namespace std;
27
28 namespace  {
29 void utfchar(const string& from, string::size_type pos, string& to) {
30     string::value_type first = from[pos];
31     if ((first & 0x80) == 0)
32         to = from[pos];
33     else {
34         string::size_type len = 0;
35         while (first & 0x80) {
36             ++len;
37             first <<= 1;
38         }
39         to = from.substr(pos, len);
40     }
41 }
42 }
43
44 typedef map<string, string> romaji_map;
45 romaji_map romaji;
46
47 void initRomaji() {
48     // -- hiragana -----
49     romaji["あ"] = "a";
50     romaji["い"] = "i";
51     romaji["う"] = "u";
52     romaji["え"] = "e";
53     romaji["お"] = "o";    
54     romaji["か"] = "ka";
55     romaji["き"] = "ki";
56     romaji["く"] = "ku";
57     romaji["け"] = "ke";
58     romaji["こ"] = "ko";
59     romaji["さ"] = "sa";
60     romaji["し"] = "shi";
61     romaji["す"] = "su";
62     romaji["せ"] = "se";
63     romaji["そ"] = "so";
64     romaji["た"] = "ta";
65     romaji["ち"] = "chi";
66     romaji["つ"] = "tsu";
67     romaji["て"] = "te";
68     romaji["と"] = "to";
69     romaji["な"] = "na";
70     romaji["に"] = "ni";
71     romaji["ぬ"] = "nu";
72     romaji["ね"] = "ne";
73     romaji["の"] = "no";
74     romaji["は"] = "ha";
75     romaji["ひ"] = "hi";
76     romaji["ふ"] = "fu";
77     romaji["へ"] = "he";
78     romaji["ほ"] = "ho";
79     romaji["ま"] = "ma";
80     romaji["み"] = "mi";
81     romaji["む"] = "mu";
82     romaji["め"] = "me";
83     romaji["も"] = "mo";
84     romaji["や"] = "ya";
85     romaji["ゆ"] = "yu";
86     romaji["よ"] = "yo";
87     romaji["ら"] = "ra";
88     romaji["り"] = "ri";
89     romaji["る"] = "ru";
90     romaji["れ"] = "re";
91     romaji["ろ"] = "ro";
92     romaji["わ"] = "wa";
93     romaji["ゐ"] = "wi";
94     romaji["ゑ"] = "we";
95     romaji["を"] = "wo";
96     romaji["ん"] = "n";
97     
98     romaji["ぁ"] = "\1a";
99     romaji["ぃ"] = "\1i";
100     romaji["ぇ"] = "\1e";
101     romaji["ぉ"] = "\1o";
102     romaji["ゃ"] = "\1ya";
103     romaji["ゅ"] = "\1yu";
104     romaji["ょ"] = "\1yo";
105     romaji["っ"] = "\2";
106
107     romaji["ゔ"] = "vu";
108     romaji["が"] = "ga";
109     romaji["ぎ"] = "gi";
110     romaji["ぐ"] = "gu";
111     romaji["げ"] = "ge";
112     romaji["ご"] = "go";
113     romaji["ざ"] = "za";
114     romaji["じ"] = "ji";
115     romaji["ず"] = "zu";
116     romaji["ぜ"] = "ze";
117     romaji["ぞ"] = "zo";
118     romaji["だ"] = "da";
119     romaji["ぢ"] = "dzi";
120     romaji["づ"] = "dzu";
121     romaji["で"] = "de";
122     romaji["ど"] = "do";
123     romaji["ば"] = "ba";
124     romaji["び"] = "bi";
125     romaji["ぶ"] = "bu";
126     romaji["べ"] = "be";
127     romaji["ぼ"] = "bo";
128     romaji["ぱ"] = "pa";
129     romaji["ぴ"] = "pi";
130     romaji["ぷ"] = "pu";
131     romaji["ぺ"] = "pe";
132     romaji["ぽ"] = "po";
133
134     // -- katakana -----
135     romaji["ア"] = "a";
136     romaji["イ"] = "i";
137     romaji["ウ"] = "u";
138     romaji["エ"] = "e";
139     romaji["オ"] = "o";    
140     romaji["カ"] = "ka";
141     romaji["キ"] = "ki";
142     romaji["ク"] = "ku";
143     romaji["ケ"] = "ke";
144     romaji["コ"] = "ko";
145     romaji["サ"] = "sa";
146     romaji["シ"] = "shi";
147     romaji["ス"] = "su";
148     romaji["セ"] = "se";
149     romaji["ソ"] = "so";
150     romaji["タ"] = "ta";
151     romaji["チ"] = "chi";
152     romaji["ツ"] = "tsu";
153     romaji["テ"] = "te";
154     romaji["ト"] = "to";
155     romaji["ナ"] = "na";
156     romaji["ニ"] = "ni";
157     romaji["ヌ"] = "nu";
158     romaji["ネ"] = "ne";
159     romaji["ノ"] = "no";
160     romaji["ハ"] = "ha";
161     romaji["ヒ"] = "hi";
162     romaji["フ"] = "fu";
163     romaji["ヘ"] = "he";
164     romaji["ホ"] = "ho";
165     romaji["マ"] = "ma";
166     romaji["ミ"] = "mi";
167     romaji["ム"] = "mu";
168     romaji["メ"] = "me";
169     romaji["モ"] = "mo";
170     romaji["ヤ"] = "ya";
171     romaji["ユ"] = "yu";
172     romaji["ヨ"] = "yo";
173     romaji["ラ"] = "ra";
174     romaji["リ"] = "ri";
175     romaji["ル"] = "ru";
176     romaji["レ"] = "re";
177     romaji["ロ"] = "ro";
178     romaji["ワ"] = "wa";
179     romaji["ヰ"] = "wi";
180     romaji["ヱ"] = "we";
181     romaji["ヲ"] = "wo";
182     romaji["ン"] = "n";
183     
184     romaji["ァ"] = "\1a";
185     romaji["ィ"] = "\1i";
186     romaji["ゥ"] = "\1u";
187     romaji["ェ"] = "\1e";
188     romaji["ォ"] = "\1o";
189     romaji["ヮ"] = "\1wa";
190     romaji["ャ"] = "\1ya";
191     romaji["ュ"] = "\1yu";
192     romaji["ョ"] = "\1yo";
193     romaji["ッ"] = "\2";
194
195     romaji["ヴ"] = "vu";
196     romaji["ガ"] = "ga";
197     romaji["ギ"] = "gi";
198     romaji["グ"] = "gu";
199     romaji["ゲ"] = "ge";
200     romaji["ゴ"] = "go";
201     romaji["ザ"] = "za";
202     romaji["ジ"] = "ji";
203     romaji["ズ"] = "zu";
204     romaji["ゼ"] = "ze";
205     romaji["ゾ"] = "zo";
206     romaji["ダ"] = "da";
207     romaji["ヂ"] = "dzi";
208     romaji["ヅ"] = "dzu";
209     romaji["デ"] = "de";
210     romaji["ド"] = "do";
211     romaji["バ"] = "ba";
212     romaji["ビ"] = "bi";
213     romaji["ブ"] = "bu";
214     romaji["ベ"] = "be";
215     romaji["ボ"] = "bo";
216     romaji["パ"] = "pa";
217     romaji["ピ"] = "pi";
218     romaji["プ"] = "pu";
219     romaji["ペ"] = "pe";
220     romaji["ポ"] = "po";
221     romaji["ー"] = "";
222     
223     // -- double width letters ------
224     romaji["A"] = "A";
225     romaji["B"] = "B";
226     romaji["C"] = "C";
227     romaji["D"] = "D";
228     romaji["E"] = "E";
229     romaji["F"] = "F";
230     romaji["G"] = "G";
231     romaji["H"] = "H";
232     romaji["I"] = "I";
233     romaji["J"] = "J";
234     romaji["K"] = "K";
235     romaji["L"] = "L";
236     romaji["M"] = "M";
237     romaji["N"] = "N";
238     romaji["O"] = "O";
239     romaji["P"] = "P";
240     romaji["Q"] = "Q";
241     romaji["R"] = "R";
242     romaji["S"] = "S";
243     romaji["T"] = "T";
244     romaji["U"] = "U";
245     romaji["V"] = "V";
246     romaji["W"] = "W";
247     romaji["X"] = "X";
248     romaji["Y"] = "Y";
249     romaji["Z"] = "Z";
250
251     romaji["a"] = "a";
252     romaji["b"] = "b";
253     romaji["c"] = "c";
254     romaji["d"] = "d";
255     romaji["e"] = "e";
256     romaji["f"] = "f";
257     romaji["g"] = "g";
258     romaji["h"] = "h";
259     romaji["i"] = "i";
260     romaji["j"] = "j";
261     romaji["k"] = "k";
262     romaji["l"] = "l";
263     romaji["m"] = "m";
264     romaji["n"] = "n";
265     romaji["o"] = "o";
266     romaji["p"] = "p";
267     romaji["q"] = "q";
268     romaji["r"] = "r";
269     romaji["s"] = "s";
270     romaji["t"] = "t";
271     romaji["u"] = "u";
272     romaji["v"] = "v";
273     romaji["w"] = "w";
274     romaji["x"] = "x";
275     romaji["y"] = "y";
276     romaji["z"] = "z";
277
278     romaji["0"] = "0";
279     romaji["1"] = "1";
280     romaji["2"] = "2";
281     romaji["3"] = "3";
282     romaji["4"] = "4";
283     romaji["5"] = "5";
284     romaji["6"] = "6";
285     romaji["7"] = "7";
286     romaji["8"] = "8";
287     romaji["9"] = "9";
288    
289     romaji["!"] = "!";
290     romaji["""] = "\"";
291     romaji["#"] = "#";
292     romaji["$"] = "$";
293     romaji["%"] = "%";
294     romaji["&"] = "&";
295     romaji["'"] = "'"; // TODO:
296     romaji["("] = "(";
297     romaji[")"] = ")";
298     romaji["*"] = "*";
299     romaji["+"] = "+";
300     romaji[","] = ",";
301     romaji["-"] = "-";
302     romaji["."] = ".";
303     romaji["/"] = "/";
304
305     romaji[":"] = ":";
306     romaji[";"] = ";";
307     romaji["<"] = "<";
308     romaji["="] = "=";
309     romaji[">"] = ">";
310     romaji["?"] = "?";
311     romaji["@"] = "@";
312
313     romaji["["] = "[";
314     romaji["\"] = "\\";
315     romaji["]"] = "]";
316     romaji["^"] = "^";
317     romaji["_"] = "_";
318     romaji["`"] = "`";
319
320     romaji["{"] = "{";
321     romaji["|"] = "|";
322     romaji["}"] = "}";
323     romaji["~"] = "~";
324
325
326     // don't know where those belong to
327     romaji["〜"] = "~";
328     romaji["、"] = ","; // TODO:
329     romaji["−"] = "-";
330     
331     romaji[" "] = " ";
332     romaji["―"] = "-";
333     romaji["・"] = "-"; // FIXME
334 }
335
336 void kana2romaji(const string& kana, string& rom) {
337     rom.clear();
338     for (string::size_type pos = 0; pos < kana.size(); ) {
339         string ch;
340         utfchar(kana, pos, ch);
341         romaji_map::const_iterator trans = romaji.find(ch);
342         if (trans == romaji.end()) {
343             rom += ch;
344             if (ch.size() > 1)
345                 cout << "Don't know how to translate '" << ch << "' in '" << kana << "' to romaji." << endl;
346         }
347         else
348             rom += trans->second;
349         pos += ch.size();
350     }
351     for (string::size_type pos = 0; pos < rom.size(); ++pos)
352         if (rom[pos] == '\1') {
353             string::size_type count = 1;
354
355             if (pos > 2) {
356                string const pred = rom.substr(pos - 3, 3);
357                if(pred == "chi" ||
358                   pred == "shi" ||
359                   pred == "dzi"
360                ) {
361                  count = (pos + 1 < rom.size() && rom[pos + 1] == 'y') ? 3 : 2;
362                  rom.erase(pos - 1, count);
363                  continue;
364                }
365             }
366             if (pos > 1) {
367              
368                string const pred = rom.substr(pos - 2, 2);
369                if(pred == "ki" ||
370                   pred == "ni" ||
371                   pred == "mi" ||
372                   pred == "ri" ||
373                   pred == "gi" ||
374                   pred == "ji" ||
375                   pred == "bi" ||
376                   pred == "pi"
377                 )
378                {
379                   count = (pos + 1 < rom.size() && rom[pos + 1] == 'y') ? 3 : 2;
380                   rom.erase(pos - 1, count);
381                   continue;
382                }
383                 
384                 if(pred == "fu" ||
385                    pred == "de" ||
386                    pred == "te" ||
387                    pred == "vu")
388                 {
389                   count = (pos + 1 < rom.size() && rom[pos + 1] == 'y') ? 3 : 2;
390                   rom.erase(pos - 1, count);
391                   continue;
392                 }
393             }
394         }
395         else if (rom[pos] == '\2' && pos + 1 < rom.size())
396             rom[pos] = rom[pos + 1];
397 }