diff --git a/src/runtime/java/jni_utils.c b/src/runtime/java/jni_utils.c index f897b8372..13edd812d 100644 --- a/src/runtime/java/jni_utils.c +++ b/src/runtime/java/jni_utils.c @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include "jni_utils.h" #ifndef __MINGW32__ #include @@ -59,6 +61,35 @@ gu2j_string_buf(JNIEnv *env, GuStringBuf* sbuf) { return gu2j_string_len(env, gu_string_buf_data(sbuf), gu_string_buf_length(sbuf)); } +JPGF_INTERNAL jstring +gu2j_string_capit(JNIEnv *env, GuString s, PgfCapitState capit) { + const char* utf8 = s; + size_t len = strlen(s); + + jchar* utf16 = alloca(len*sizeof(jchar)); + jchar* dst = utf16; + while (s-utf8 < len) { + GuUCS ucs = gu_utf8_decode((const uint8_t**) &s); + + if (capit == PGF_CAPIT_FIRST) { + ucs = gu_ucs_to_upper(ucs); + capit == PGF_CAPIT_NONE; + } else if (capit == PGF_CAPIT_NEXT) { + ucs = gu_ucs_to_upper(ucs); + } + + if (ucs <= 0xFFFF) { + *dst++ = ucs; + } else { + ucs -= 0x10000; + *dst++ = 0xD800+((ucs >> 10) & 0x3FF); + *dst++ = 0xDC00+(ucs & 0x3FF); + } + } + + return (*env)->NewString(env, utf16, dst-utf16); +} + JPGF_INTERNAL GuString j2gu_string(JNIEnv *env, jstring s, GuPool* pool) { GuString str = (*env)->GetStringUTFChars(env, s, 0); diff --git a/src/runtime/java/jni_utils.h b/src/runtime/java/jni_utils.h index e45f5b7bd..b69372979 100644 --- a/src/runtime/java/jni_utils.h +++ b/src/runtime/java/jni_utils.h @@ -26,6 +26,9 @@ gu2j_string_len(JNIEnv *env, const char* s, size_t len); JPGF_INTERNAL_DECL jstring gu2j_string_buf(JNIEnv *env, GuStringBuf* sbuf); +JPGF_INTERNAL jstring +gu2j_string_capit(JNIEnv *env, GuString s, PgfCapitState capit); + JPGF_INTERNAL_DECL GuString j2gu_string(JNIEnv *env, jstring s, GuPool* pool); diff --git a/src/runtime/java/jpgf.c b/src/runtime/java/jpgf.c index fd7fe337d..181d7cd3d 100644 --- a/src/runtime/java/jpgf.c +++ b/src/runtime/java/jpgf.c @@ -930,6 +930,9 @@ typedef struct { GuPool* tmp_pool; GuBuf* stack; GuBuf* list; + bool bind; + PgfCapitState capit; + jobject bind_instance; jclass object_class; jclass bracket_class; jmethodID bracket_constrId; @@ -941,8 +944,23 @@ pgf_bracket_lzn_symbol_token(PgfLinFuncs** funcs, PgfToken tok) PgfBracketLznState* state = gu_container(funcs, PgfBracketLznState, funcs); JNIEnv* env = state->env; - jstring jname = gu2j_string(env, tok); - gu_buf_push(state->list, jobject, jname); + if (state->bind) { + jobject bind_instance = (*env)->NewLocalRef(env, state->bind_instance); + gu_buf_push(state->list, jobject, bind_instance); + state->bind = false; + } else { + if (state->capit == PGF_CAPIT_NEXT) + state->capit = PGF_CAPIT_NONE; + } + + if (state->capit == PGF_CAPIT_ALL) + state->capit = PGF_CAPIT_NEXT; + + jstring jtok = gu2j_string_capit(env, tok, state->capit); + gu_buf_push(state->list, jobject, jtok); + + if (state->capit == PGF_CAPIT_FIRST) + state->capit = PGF_CAPIT_NONE; } static void @@ -993,6 +1011,20 @@ pgf_bracket_lzn_end_phrase(PgfLinFuncs** funcs, PgfCId cat, int fid, size_t lind state->list = parent; } +static void +pgf_bracket_lzn_symbol_bind(PgfLinFuncs** funcs) +{ + PgfBracketLznState* state = gu_container(funcs, PgfBracketLznState, funcs); + state->bind = true; +} + +static void +pgf_bracket_lzn_symbol_capit(PgfLinFuncs** funcs, PgfCapitState capit) +{ + PgfBracketLznState* state = gu_container(funcs, PgfBracketLznState, funcs); + state->capit = capit; +} + static void pgf_bracket_lzn_symbol_meta(PgfLinFuncs** funcs, PgfMetaId id) { @@ -1004,8 +1036,8 @@ static PgfLinFuncs pgf_bracket_lin_funcs = { .begin_phrase = pgf_bracket_lzn_begin_phrase, .end_phrase = pgf_bracket_lzn_end_phrase, .symbol_ne = NULL, - .symbol_bind = NULL, - .symbol_capit = NULL, + .symbol_bind = pgf_bracket_lzn_symbol_bind, + .symbol_capit = pgf_bracket_lzn_symbol_capit, .symbol_meta = pgf_bracket_lzn_symbol_meta }; @@ -1022,6 +1054,16 @@ Java_org_grammaticalframework_pgf_Concr_bracketedLinearize(JNIEnv* env, jobject jmethodID bracket_constrId = (*env)->GetMethodID(env, bracket_class, "", "(Ljava/lang/String;Ljava/lang/String;II[Ljava/lang/Object;)V"); if (!bracket_constrId) return NULL; + + jclass bind_class = (*env)->FindClass(env, "org/grammaticalframework/pgf/BIND"); + if (!bind_class) + return NULL; + jfieldID bind_instance_id = (*env)->GetStaticFieldID(env, bind_class, "instance", "Lorg/grammaticalframework/pgf/BIND;"); + if (!bind_instance_id) + return NULL; + jobject bind_instance = (*env)->GetStaticObjectField(env, bind_class, bind_instance_id); + if (!bind_instance) + return NULL; GuPool* tmp_pool = gu_local_pool(); GuExn* err = gu_exn(tmp_pool); @@ -1056,6 +1098,9 @@ Java_org_grammaticalframework_pgf_Concr_bracketedLinearize(JNIEnv* env, jobject state.tmp_pool = tmp_pool; state.stack = gu_new_buf(GuBuf*, tmp_pool); state.list = gu_new_buf(jobject, tmp_pool); + state.bind = true; + state.capit = PGF_CAPIT_NONE; + state.bind_instance = bind_instance; state.object_class = object_class; state.bracket_class = bracket_class; state.bracket_constrId = bracket_constrId; diff --git a/src/runtime/java/org/grammaticalframework/pgf/BIND.java b/src/runtime/java/org/grammaticalframework/pgf/BIND.java new file mode 100644 index 000000000..5cbbe4ce5 --- /dev/null +++ b/src/runtime/java/org/grammaticalframework/pgf/BIND.java @@ -0,0 +1,8 @@ +package org.grammaticalframework.pgf; + +public class BIND { + private BIND() { + } + + public static final BIND instance = new BIND(); +}