149 lines
3.2 KiB
C
149 lines
3.2 KiB
C
#include "dat.h"
|
|
#include "fn.h"
|
|
|
|
static struct {
|
|
Rune base;
|
|
Rune tone[5]; /* s f r x j */
|
|
} vitone[] = {
|
|
{L'a', {L'á', L'à', L'ả', L'ã', L'ạ'}},
|
|
{L'â', {L'ấ', L'ầ', L'ẩ', L'ẫ', L'ậ'}},
|
|
{L'ă', {L'ắ', L'ằ', L'ẳ', L'ẵ', L'ặ'}},
|
|
{L'e', {L'é', L'è', L'ẻ', L'ẽ', L'ẹ'}},
|
|
{L'ê', {L'ế', L'ề', L'ể', L'ễ', L'ệ'}},
|
|
{L'i', {L'í', L'ì', L'ỉ', L'ĩ', L'ị'}},
|
|
{L'o', {L'ó', L'ò', L'ỏ', L'õ', L'ọ'}},
|
|
{L'ô', {L'ố', L'ồ', L'ổ', L'ỗ', L'ộ'}},
|
|
{L'ơ', {L'ớ', L'ờ', L'ở', L'ỡ', L'ợ'}},
|
|
{L'u', {L'ú', L'ù', L'ủ', L'ũ', L'ụ'}},
|
|
{L'ư', {L'ứ', L'ừ', L'ử', L'ữ', L'ự'}},
|
|
{L'y', {L'ý', L'ỳ', L'ỷ', L'ỹ', L'ỵ'}},
|
|
{L'A', {L'Á', L'À', L'Ả', L'Ã', L'Ạ'}},
|
|
{L'Â', {L'Ấ', L'Ầ', L'Ẩ', L'Ẫ', L'Ậ'}},
|
|
{L'Ă', {L'Ắ', L'Ằ', L'Ẳ', L'Ẵ', L'Ặ'}},
|
|
{L'E', {L'É', L'È', L'Ẻ', L'Ẽ', L'Ẹ'}},
|
|
{L'Ê', {L'Ế', L'Ề', L'Ể', L'Ễ', L'Ệ'}},
|
|
{L'I', {L'Í', L'Ì', L'Ỉ', L'Ĩ', L'Ị'}},
|
|
{L'O', {L'Ó', L'Ò', L'Ỏ', L'Õ', L'Ọ'}},
|
|
{L'Ô', {L'Ố', L'Ồ', L'Ổ', L'Ỗ', L'Ộ'}},
|
|
{L'Ơ', {L'Ớ', L'Ờ', L'Ở', L'Ỡ', L'Ợ'}},
|
|
{L'U', {L'Ú', L'Ù', L'Ủ', L'Ũ', L'Ụ'}},
|
|
{L'Ư', {L'Ứ', L'Ừ', L'Ử', L'Ữ', L'Ự'}},
|
|
{L'Y', {L'Ý', L'Ỳ', L'Ỷ', L'Ỹ', L'Ỵ'}},
|
|
};
|
|
|
|
static int tonetab[128] = {
|
|
['s'] = 1, ['f'] = 2, ['r'] = 3, ['x'] = 4, ['j'] = 5,
|
|
};
|
|
|
|
#define Istone(c) ((c) < 128 && tonetab[(c)] > 0)
|
|
#define Toneidx(c) (tonetab[(c)] - 1)
|
|
|
|
static int
|
|
isvowel(Rune c)
|
|
{
|
|
int i;
|
|
|
|
for(i = 0; i < nelem(vitone); i++)
|
|
if(vitone[i].base == c)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
static Rune
|
|
removetone(Rune c)
|
|
{
|
|
int i, j;
|
|
|
|
for(i = 0; i < nelem(vitone); i++){
|
|
if(vitone[i].base == c)
|
|
return c;
|
|
for(j = 0; j < 5; j++)
|
|
if(vitone[i].tone[j] == c)
|
|
return vitone[i].base;
|
|
}
|
|
return c;
|
|
}
|
|
|
|
static Rune
|
|
applytone(Rune c, int tidx)
|
|
{
|
|
int i;
|
|
Rune base;
|
|
|
|
base = removetone(c);
|
|
for(i = 0; i < nelem(vitone); i++)
|
|
if(vitone[i].base == base)
|
|
return vitone[i].tone[tidx];
|
|
return c;
|
|
}
|
|
|
|
Emit
|
|
transvi(Im *im, Rune c)
|
|
{
|
|
Emit e;
|
|
Str mapped, pre;
|
|
int i, tidx, vi, last, penult;
|
|
Rune v, b1, b2;
|
|
|
|
if(!Istone(c) && c != 'z')
|
|
return transmap(im, c);
|
|
|
|
memset(&e, 0, sizeof e);
|
|
if(im->pre.n == 0){
|
|
sputr(&e.s, c);
|
|
return e;
|
|
}
|
|
if(im->pre.r[im->pre.n - 1] == '\\'){
|
|
pre = im->pre;
|
|
pre.n--;
|
|
if(!mapget(im->l->map, &pre, &mapped))
|
|
mapped = pre;
|
|
sputr(&mapped, c);
|
|
e.eat = 1;
|
|
e.s = mapped;
|
|
return e;
|
|
}
|
|
if(!mapget(im->l->map, &im->pre, &mapped))
|
|
mapped = im->pre;
|
|
last = -1;
|
|
penult = -1;
|
|
for(i = 0; i < mapped.n; i++){
|
|
v = removetone(mapped.r[i]);
|
|
if(isvowel(v)){
|
|
penult = last;
|
|
last = i;
|
|
}
|
|
}
|
|
vi = -1;
|
|
if(last >= 0){
|
|
if(last < mapped.n - 1 || penult < 0)
|
|
vi = last;
|
|
else{
|
|
b1 = removetone(mapped.r[penult]);
|
|
b2 = removetone(mapped.r[last]);
|
|
if((b1 == 'o' || b1 == 'O') && (b2 == 'a' || b2 == 'A' || b2 == 'e' || b2 == 'E'))
|
|
vi = last;
|
|
else if((b1 == 'u' || b1 == 'U') && (b2 == 'y' || b2 == 'Y'))
|
|
vi = last;
|
|
else
|
|
vi = penult;
|
|
}
|
|
}
|
|
if(vi < 0){
|
|
e.eat = 1;
|
|
e.s = mapped;
|
|
sputr(&e.s, c);
|
|
return e;
|
|
}
|
|
|
|
if(c == 'z')
|
|
mapped.r[vi] = removetone(mapped.r[vi]);
|
|
else{
|
|
tidx = Toneidx(c);
|
|
mapped.r[vi] = applytone(mapped.r[vi], tidx);
|
|
}
|
|
e.eat = 1;
|
|
e.next = mapped;
|
|
return e;
|
|
}
|