forked from GitHub/gf-core
now fully functional Java API for custom literals
This commit is contained in:
@@ -75,6 +75,14 @@ throw_string_exception(JNIEnv *env, const char* class_name, const char* msg)
|
||||
throw_jstring_exception(env, class_name, jmsg);
|
||||
}
|
||||
|
||||
static JavaVM* cachedJVM;
|
||||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved)
|
||||
{
|
||||
cachedJVM = jvm;
|
||||
return JNI_VERSION_1_1;
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_org_grammaticalframework_pgf_PGF_readPGF__Ljava_lang_String_2(JNIEnv *env, jclass cls, jstring s)
|
||||
{
|
||||
@@ -645,15 +653,135 @@ JNIEXPORT jboolean JNICALL
|
||||
Java_org_grammaticalframework_pgf_Concr_hasLinearization(JNIEnv* env, jobject self, jstring jid)
|
||||
{
|
||||
PgfConcr* concr = get_ref(env, self);
|
||||
GuPool* tmp_pool = gu_new_pool();
|
||||
GuPool* tmp_pool = gu_local_pool();
|
||||
PgfCId id = j2gu_string(env, jid, tmp_pool);
|
||||
bool res = pgf_has_linearization(concr, id);
|
||||
gu_pool_free(tmp_pool);
|
||||
return res;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
PgfLiteralCallback callback;
|
||||
jobject jcallback;
|
||||
jmethodID match_methodId;
|
||||
GuFinalizer fin;
|
||||
} JPgfLiteralCallback;
|
||||
|
||||
static PgfExprProb*
|
||||
jpgf_literal_callback_fn(PgfLiteralCallback* self,
|
||||
size_t lin_idx,
|
||||
GuString sentence, size_t* poffset,
|
||||
GuPool *out_pool)
|
||||
{
|
||||
JPgfLiteralCallback* callback = gu_container(self, JPgfLiteralCallback, callback);
|
||||
|
||||
JNIEnv *env;
|
||||
(*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL);
|
||||
|
||||
jstring jsentence = gu2j_string(env, sentence);
|
||||
jobject result = (*env)->CallObjectMethod(env, callback->jcallback, callback->match_methodId, lin_idx, jsentence, *poffset);
|
||||
|
||||
jclass result_class = (*env)->GetObjectClass(env, result);
|
||||
|
||||
jfieldID epId = (*env)->GetFieldID(env, result_class, "ep", "Lorg/grammaticalframework/pgf/ExprProb;");
|
||||
jobject jep = (*env)->GetObjectField(env, result, epId);
|
||||
jclass ep_class = (*env)->GetObjectClass(env, jep);
|
||||
jfieldID exprId = (*env)->GetFieldID(env, ep_class, "expr", "Lorg/grammaticalframework/pgf/Expr;");
|
||||
jobject jexpr = (*env)->GetObjectField(env, jep, exprId);
|
||||
jfieldID probId = (*env)->GetFieldID(env, ep_class, "prob", "D");
|
||||
double prob = (*env)->GetDoubleField(env, jep, probId);
|
||||
|
||||
jfieldID offsetId = (*env)->GetFieldID(env, result_class, "offset", "I");
|
||||
*poffset = (*env)->GetIntField(env, result, offsetId);
|
||||
|
||||
PgfExprProb* ep = gu_new(PgfExprProb, out_pool);
|
||||
ep->expr = gu_variant_from_ptr(get_ref(env, jexpr));
|
||||
ep->prob = prob;
|
||||
|
||||
|
||||
{
|
||||
// This is an uggly hack. We first show the expression ep->expr
|
||||
// and then we read it back but in out_pool. The whole purpose
|
||||
// of this is to copy the expression from the temporary pool
|
||||
// that was created in the Java binding to the parser pool.
|
||||
// There should be a real copying function or even better
|
||||
// there must be a way to avoid copying at all.
|
||||
|
||||
GuPool* tmp_pool = gu_local_pool();
|
||||
|
||||
GuExn* err = gu_new_exn(NULL, gu_kind(type), tmp_pool);
|
||||
GuStringBuf* sbuf = gu_string_buf(tmp_pool);
|
||||
GuOut* out = gu_string_buf_out(sbuf);
|
||||
|
||||
pgf_print_expr(ep->expr, NULL, 0, out, err);
|
||||
|
||||
GuString str = gu_string_buf_freeze(sbuf, tmp_pool);
|
||||
GuIn* in = gu_data_in((uint8_t*) str, strlen(str), tmp_pool);
|
||||
|
||||
ep->expr = pgf_read_expr(in, out_pool, err);
|
||||
if (!gu_ok(err) || gu_variant_is_null(ep->expr)) {
|
||||
throw_string_exception(env, "org/grammaticalframework/pgf/PGFError", "The expression cannot be parsed");
|
||||
gu_pool_free(tmp_pool);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gu_pool_free(tmp_pool);
|
||||
}
|
||||
|
||||
return ep;
|
||||
}
|
||||
|
||||
static void
|
||||
jpgf_literal_callback_fin(GuFinalizer* self)
|
||||
{
|
||||
JPgfLiteralCallback* callback = gu_container(self, JPgfLiteralCallback, fin);
|
||||
|
||||
JNIEnv *env;
|
||||
(*cachedJVM)->AttachCurrentThread(cachedJVM, (void **)&env, NULL);
|
||||
|
||||
(*env)->DeleteGlobalRef(env, callback->jcallback);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_grammaticalframework_pgf_Pool_free(JNIEnv* env, jobject self, jlong ref)
|
||||
Java_org_grammaticalframework_pgf_Concr_addLiteral(JNIEnv* env, jobject self, jstring jcat, jobject jcallback)
|
||||
{
|
||||
PgfConcr* concr = get_ref(env, self);
|
||||
GuPool* pool = pgf_concr_get_pool(concr);
|
||||
|
||||
JPgfLiteralCallback* callback = gu_new(JPgfLiteralCallback, pool);
|
||||
callback->callback.match = jpgf_literal_callback_fn;
|
||||
callback->jcallback = (*env)->NewGlobalRef(env, jcallback);
|
||||
callback->fin.fn = jpgf_literal_callback_fin;
|
||||
|
||||
jclass callback_class = (*env)->GetObjectClass(env, jcallback);
|
||||
callback->match_methodId = (*env)->GetMethodID(env, callback_class, "match", "(ILjava/lang/String;I)Lorg/grammaticalframework/pgf/LiteralCallback$CallbackResult;");
|
||||
|
||||
gu_pool_finally(pool, &callback->fin);
|
||||
|
||||
GuPool* tmp_pool = gu_local_pool();
|
||||
GuExn* err = gu_new_exn(NULL, gu_kind(type), tmp_pool);
|
||||
pgf_concr_add_literal(concr, j2gu_string(env, jcat, tmp_pool), &callback->callback, err);
|
||||
|
||||
if (!gu_ok(err)) {
|
||||
if (gu_exn_caught(err) == gu_type(PgfExn)) {
|
||||
GuString msg = (GuString) gu_exn_caught_data(err);
|
||||
throw_string_exception(env, "org/grammaticalframework/pgf/PGFError", msg);
|
||||
} else {
|
||||
throw_string_exception(env, "org/grammaticalframework/pgf/PGFError", "The literal cannot be added");
|
||||
}
|
||||
}
|
||||
|
||||
gu_pool_free(tmp_pool);
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_org_grammaticalframework_pgf_Pool_alloc(JNIEnv* env, jclass clazz)
|
||||
{
|
||||
return p2l(gu_new_pool());
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_grammaticalframework_pgf_Pool_free(JNIEnv* env, jclass clazz, jlong ref)
|
||||
{
|
||||
gu_pool_free((GuPool*) l2p(ref));
|
||||
}
|
||||
@@ -700,10 +828,64 @@ Java_org_grammaticalframework_pgf_Expr_readExpr(JNIEnv* env, jclass clazz, jstri
|
||||
jmethodID pool_constrId = (*env)->GetMethodID(env, pool_class, "<init>", "(J)V");
|
||||
jobject jpool = (*env)->NewObject(env, pool_class, pool_constrId, p2l(pool));
|
||||
|
||||
jmethodID constrId = (*env)->GetMethodID(env, clazz, "<init>", "(Lorg/grammaticalframework/pgf/Pool;Lorg/grammaticalframework/pgf/PGF;J)V");
|
||||
jmethodID constrId = (*env)->GetMethodID(env, clazz, "<init>", "(Lorg/grammaticalframework/pgf/Pool;Ljava/lang/Object;J)V");
|
||||
return (*env)->NewObject(env, clazz, constrId, jpool, NULL, p2l(gu_variant_to_ptr(e)));
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_org_grammaticalframework_pgf_Expr_initStringLit(JNIEnv* env, jclass clazz, jstring jstr, jlong jpool)
|
||||
{
|
||||
GuPool* pool = l2p(jpool);
|
||||
PgfExpr expr;
|
||||
|
||||
PgfExprLit* e =
|
||||
gu_new_variant(PGF_EXPR_LIT,
|
||||
PgfExprLit,
|
||||
&expr, pool);
|
||||
|
||||
GuString str = (*env)->GetStringUTFChars(env, jstr, 0);
|
||||
PgfLiteralStr* slit =
|
||||
gu_new_flex_variant(PGF_LITERAL_STR,
|
||||
PgfLiteralStr,
|
||||
val, strlen(str)+1,
|
||||
&e->lit, pool);
|
||||
strcpy(slit->val, str);
|
||||
(*env)->ReleaseStringUTFChars(env, jstr, str);
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_org_grammaticalframework_pgf_Expr_initApp(JNIEnv* env, jclass clazz, jstring jfun, jobjectArray args, jlong jpool)
|
||||
{
|
||||
GuPool* pool = l2p(jpool);
|
||||
PgfExpr expr;
|
||||
|
||||
GuString fun = (*env)->GetStringUTFChars(env, jfun, 0);
|
||||
PgfExprFun* e =
|
||||
gu_new_flex_variant(PGF_EXPR_FUN,
|
||||
PgfExprFun,
|
||||
fun, strlen(fun)+1,
|
||||
&expr, pool);
|
||||
strcpy(e->fun, fun);
|
||||
(*env)->ReleaseStringUTFChars(env, jfun, fun);
|
||||
|
||||
size_t n_args = (*env)->GetArrayLength(env, args);
|
||||
for (size_t i = 0; i < n_args; i++) {
|
||||
PgfExpr fun = expr;
|
||||
PgfExpr arg = gu_variant_from_ptr(get_ref(env, (*env)->GetObjectArrayElement(env, args, i)));
|
||||
|
||||
PgfExprApp* e =
|
||||
gu_new_variant(PGF_EXPR_APP,
|
||||
PgfExprApp,
|
||||
&expr, pool);
|
||||
e->fun = fun;
|
||||
e->arg = arg;
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_org_grammaticalframework_pgf_Type_getCategory(JNIEnv* env, jobject self)
|
||||
{
|
||||
|
||||
@@ -4,18 +4,31 @@ import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Expr implements Serializable {
|
||||
private static final long serialVersionUID = 1148602474802492674L;
|
||||
|
||||
private Pool pool;
|
||||
private PGF gr;
|
||||
private Object master;
|
||||
private long ref;
|
||||
|
||||
Expr(Pool pool, PGF gr, long ref) {
|
||||
this.pool = pool;
|
||||
this.gr = gr;
|
||||
this.ref = ref;
|
||||
Expr(Pool pool, Object master, long ref) {
|
||||
this.pool = pool;
|
||||
this.master = master;
|
||||
this.ref = ref;
|
||||
}
|
||||
|
||||
public Expr(String s) {
|
||||
this.pool = new Pool();
|
||||
this.master = null;
|
||||
this.ref = initStringLit(s, pool.ref);
|
||||
}
|
||||
|
||||
public Expr(String fun, Expr... args) {
|
||||
this.pool = new Pool();
|
||||
this.master = Arrays.copyOf(args, args.length);
|
||||
this.ref = initApp(fun, args, pool.ref);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@@ -25,15 +38,18 @@ public class Expr implements Serializable {
|
||||
public static native Expr readExpr(String s) throws PGFError;
|
||||
|
||||
private static native String showExpr(long ref);
|
||||
|
||||
|
||||
private static native long initStringLit(String s, long pool);
|
||||
private static native long initApp(String fun, Expr[] args, long pool);
|
||||
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
out.writeObject(showExpr(ref));
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
Expr e = readExpr((String) in.readObject());
|
||||
pool = e.pool;
|
||||
gr = e.gr;
|
||||
ref = e.ref;
|
||||
pool = e.pool;
|
||||
master = e.master;
|
||||
ref = e.ref;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package org.grammaticalframework.pgf;
|
||||
|
||||
public class ExprBuilder {
|
||||
public ExprBuilder() {
|
||||
|
||||
}
|
||||
|
||||
ExprBuilder(long poolRef) {
|
||||
}
|
||||
|
||||
public native Expr mkApp(String fun, Expr... args);
|
||||
|
||||
public native Expr mkLiteral(String s);
|
||||
public native Expr mkLiteral(int n);
|
||||
public native Expr mkLiteral(double d);
|
||||
}
|
||||
@@ -1,5 +1,23 @@
|
||||
package org.grammaticalframework.pgf;
|
||||
|
||||
public interface LiteralCallback {
|
||||
public int match(Concr concr, int lin_idx, ExprBuilder builder, String sentence, int start_offset);
|
||||
public CallbackResult match(int lin_idx, String sentence, int start_offset);
|
||||
|
||||
public static class CallbackResult {
|
||||
private ExprProb ep;
|
||||
private int offset;
|
||||
|
||||
public CallbackResult(ExprProb ep, int offset) {
|
||||
this.ep = ep;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public ExprProb getExprProb() {
|
||||
return ep;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,36 @@
|
||||
package org.grammaticalframework.pgf;
|
||||
|
||||
public class NercLiteralCallback implements LiteralCallback {
|
||||
public int match(Concr concr, int lin_idx, ExprBuilder builder, String sentence, int start_offset) {
|
||||
return start_offset;
|
||||
public CallbackResult match(int lin_idx, String sentence, int offset) {
|
||||
StringBuilder sbuilder = new StringBuilder();
|
||||
|
||||
int i = 0;
|
||||
int end_offset = offset;
|
||||
while (offset < sentence.length() &&
|
||||
Character.isUpperCase(sentence.charAt(offset))) {
|
||||
if (i > 0)
|
||||
sbuilder.append(' ');
|
||||
i++;
|
||||
|
||||
while (offset < sentence.length() &&
|
||||
!Character.isWhitespace(sentence.charAt(offset))) {
|
||||
sbuilder.append(sentence.charAt(offset));
|
||||
offset++;
|
||||
}
|
||||
|
||||
end_offset = offset;
|
||||
while (offset < sentence.length() &&
|
||||
Character.isWhitespace(sentence.charAt(offset))) {
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
Expr expr = new Expr(sbuilder.toString());
|
||||
expr = new Expr("MkSymb", expr);
|
||||
return new CallbackResult(new ExprProb(expr, 0), end_offset);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
package org.grammaticalframework.pgf;
|
||||
|
||||
class Pool {
|
||||
private long ref;
|
||||
|
||||
public class Pool {
|
||||
final long ref;
|
||||
|
||||
public Pool(long ref) {
|
||||
this.ref = ref;
|
||||
}
|
||||
|
||||
|
||||
public Pool() {
|
||||
this.ref = alloc();
|
||||
}
|
||||
|
||||
public void finalize() {
|
||||
free(ref);
|
||||
}
|
||||
|
||||
private native void free(long ref);
|
||||
|
||||
public static native long alloc();
|
||||
public static native void free(long ref);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user