From 9de4812482807e3123d66ceaf65f7dce0419e3e3 Mon Sep 17 00:00:00 2001 From: "kr.angelov" Date: Wed, 27 Nov 2013 22:16:05 +0000 Subject: [PATCH] better dictionary visualization in the Android App --- lib/src/bulgarian/ParseBul.gf | 10 + lib/src/english/ParseEng.gf | 4 + lib/src/english/ParseEngAbs.gf | 5 + lib/src/swedish/ParseSwe.gf | 10 +- src/runtime/java/jpgf.c | 26 + .../org/grammaticalframework/pgf/Hypo.java | 7 + .../org/grammaticalframework/pgf/Type.java | 14 + src/ui/android/res/xml/inflection_bg.xml | 1245 +++++++++-------- src/ui/android/res/xml/inflection_cmn.xml | 161 ++- src/ui/android/res/xml/inflection_en.xml | 193 +-- src/ui/android/res/xml/inflection_sv.xml | 457 +++--- .../ui/android/LexicalEntryActivity.java | 92 +- .../ui/android/Translator.java | 191 ++- 13 files changed, 1337 insertions(+), 1078 deletions(-) create mode 100644 src/runtime/java/org/grammaticalframework/pgf/Hypo.java diff --git a/lib/src/bulgarian/ParseBul.gf b/lib/src/bulgarian/ParseBul.gf index 812f752fb..951f8b44e 100644 --- a/lib/src/bulgarian/ParseBul.gf +++ b/lib/src/bulgarian/ParseBul.gf @@ -154,4 +154,14 @@ lin UttAdV adv = adv; +lincat + Feat = Str; +lin FeatN2, FeatN = \n -> + case n.g of { + AMasc Human => "(м.р.л.)" ; + AMasc NonHuman => "(м.р.)" ; + AFem => "(ж.р.)" ; + ANeut => "(ср.р.)" + } ; + } diff --git a/lib/src/english/ParseEng.gf b/lib/src/english/ParseEng.gf index 28f05b37f..57126161c 100644 --- a/lib/src/english/ParseEng.gf +++ b/lib/src/english/ParseEng.gf @@ -149,5 +149,9 @@ lin PPos = {s = [] ; p = CPos} ; PNeg = {s = [] ; p = CNeg True} ; -- contracted: don't UncNeg = {s = [] ; p = CNeg False} ; + +lincat + Feat = Str; +lin FeatN, FeatN2 = \_ -> ""; } diff --git a/lib/src/english/ParseEngAbs.gf b/lib/src/english/ParseEngAbs.gf index 06de9560b..6a5320fcf 100644 --- a/lib/src/english/ParseEngAbs.gf +++ b/lib/src/english/ParseEngAbs.gf @@ -72,4 +72,9 @@ fun CompoundCN : Num -> N -> CN -> CN ; AdAdV : AdA -> AdV -> AdV ; UttAdV : AdV -> Utt; + +cat Feat; +fun FeatN : N -> Feat; + FeatN2 : N2 -> Feat; + } diff --git a/lib/src/swedish/ParseSwe.gf b/lib/src/swedish/ParseSwe.gf index 2b05dd83e..a5c5e849b 100644 --- a/lib/src/swedish/ParseSwe.gf +++ b/lib/src/swedish/ParseSwe.gf @@ -123,5 +123,13 @@ lin lin UncNeg = {s = [] ; p = Neg} ; - + +lincat + Feat = Str; +lin FeatN2, FeatN = \n -> + case n.g of { + Utr => "(utr)" ; + Neutr => "(neutr)" + } ; + } diff --git a/src/runtime/java/jpgf.c b/src/runtime/java/jpgf.c index 8cfe2c705..50574cf6e 100644 --- a/src/runtime/java/jpgf.c +++ b/src/runtime/java/jpgf.c @@ -212,6 +212,25 @@ Java_org_grammaticalframework_pgf_PGF_getStartCat(JNIEnv* env, jobject self) return gu2j_string(env, pgf_start_cat(get_ref(env, self))); } +JNIEXPORT jobject JNICALL +Java_org_grammaticalframework_pgf_PGF_getFunctionType(JNIEnv* env, jobject self, jstring jid) +{ + PgfPGF* pgf = get_ref(env, self); + GuPool* tmp_pool = gu_new_pool(); + PgfCId id = j2gu_string(env, jid, tmp_pool); + PgfType* tp = pgf_function_type(pgf, id); + gu_pool_free(tmp_pool); + + if (tp == NULL) + return NULL; + + jclass type_class = (*env)->FindClass(env, "org/grammaticalframework/pgf/Type"); + jmethodID constrId = (*env)->GetMethodID(env, type_class, "", "(Lorg/grammaticalframework/pgf/PGF;J)V"); + jobject jtype = (*env)->NewObject(env, type_class, constrId, self, p2l(tp)); + + return jtype; +} + typedef struct { GuMapItor fn; JNIEnv *env; @@ -535,6 +554,13 @@ Java_org_grammaticalframework_pgf_Expr_readExpr(JNIEnv* env, jclass clazz, jstri return (*env)->NewObject(env, clazz, constrId, jpool, NULL, p2l(gu_variant_to_ptr(e))); } +JNIEXPORT jstring JNICALL +Java_org_grammaticalframework_pgf_Type_getCategory(JNIEnv* env, jobject self) +{ + PgfType* tp = get_ref(env, self); + return gu2j_string(env, tp->cid); +} + JNIEXPORT jobject JNICALL Java_org_grammaticalframework_pgf_Generator_generateAll(JNIEnv* env, jclass clazz, jobject jpgf, jstring jstartCat) { diff --git a/src/runtime/java/org/grammaticalframework/pgf/Hypo.java b/src/runtime/java/org/grammaticalframework/pgf/Hypo.java new file mode 100644 index 000000000..a0aced647 --- /dev/null +++ b/src/runtime/java/org/grammaticalframework/pgf/Hypo.java @@ -0,0 +1,7 @@ +package org.grammaticalframework.pgf; + +public class Hypo { + public native boolean getBindType(); + public native String getVariable(); + public native Type getType(); +} diff --git a/src/runtime/java/org/grammaticalframework/pgf/Type.java b/src/runtime/java/org/grammaticalframework/pgf/Type.java index 061771b71..db7a9888f 100644 --- a/src/runtime/java/org/grammaticalframework/pgf/Type.java +++ b/src/runtime/java/org/grammaticalframework/pgf/Type.java @@ -1,4 +1,18 @@ package org.grammaticalframework.pgf; public class Type { + public native String getCategory(); + public native Expr[] getExprs(); + public native Hypo[] getHypos(); + + ////////////////////////////////////////////////////////////////// + // private stuff + + private PGF gr; + private long ref; + + private Type(PGF gr, long ref) { + this.gr = gr; + this.ref = ref; + } } diff --git a/src/ui/android/res/xml/inflection_bg.xml b/src/ui/android/res/xml/inflection_bg.xml index 6d666fddf..4b3d599cb 100644 --- a/src/ui/android/res/xml/inflection_bg.xml +++ b/src/ui/android/res/xml/inflection_bg.xml @@ -1,615 +1,642 @@ - - -

Съществително

+ + + N + N2 + същ + + + + A + A2 + пр + + + + Adv + нар + + + + Prep + пр + + + + V + V2 + V3 + V2V + VV + VS + гл + + + diff --git a/src/ui/android/res/xml/inflection_cmn.xml b/src/ui/android/res/xml/inflection_cmn.xml index fa3fa7c8b..58cb7607c 100644 --- a/src/ui/android/res/xml/inflection_cmn.xml +++ b/src/ui/android/res/xml/inflection_cmn.xml @@ -1,67 +1,94 @@ - - -

Noun

- - - - - - - - - - -
s
s
c
c
-
- -

Adjective

- - - - - - -
s
s
-
- -

Adverb

-

s

-
- -

Preposition

-

prepPre
-
prepPost

-
- -

Verb

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
s
s
dp
dp
ds
ds
ep
ep
neg
neg
pp
pp
sn
sn
-
-
+ + + N + N2 + n + + + + A + A2 + a + + + + Adv + adv + + + + Prep + prep + + + + V + V2 + V3 + V2V + VV + VS + v + + + diff --git a/src/ui/android/res/xml/inflection_en.xml b/src/ui/android/res/xml/inflection_en.xml index 83ea1259c..47ec449a5 100644 --- a/src/ui/android/res/xml/inflection_en.xml +++ b/src/ui/android/res/xml/inflection_en.xml @@ -1,84 +1,111 @@ - - -

Noun

+ + + N + N2 + n + + + + A + A2 + a + + + + Adv + adv + + + + Prep + prep + + + + V + V2 + V3 + V2V + VV + VS + v + + + diff --git a/src/ui/android/res/xml/inflection_sv.xml b/src/ui/android/res/xml/inflection_sv.xml index 578cc8ee7..229762cae 100644 --- a/src/ui/android/res/xml/inflection_sv.xml +++ b/src/ui/android/res/xml/inflection_sv.xml @@ -1,215 +1,242 @@ - - -

Substantiv

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
obestbest
nomsg
s Sg Indef Nom
s Sg Def Nom
pl
s Pl Indef Nom
s Pl Def Nom
gensg
s Sg Indef Gen
s Sg Def Gen
pl
s Pl Indef Gen
s Pl Def Gen
-
- -

Adjektiv

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
nominativ
positkomparsuperl
obestutr
s (AF (APosit (Strong (GSg Utr))) Nom)
s (AF ACompar Nom)
s (AF (ASuperl SupStrong) Nom)
neut
s (AF (APosit (Strong (GSg Neutr))) Nom)
pl
s (AF (APosit (Strong GPl)) Nom)
bestsg
s (AF (APosit (Weak Sg)) Nom)
s (AF (ASuperl SupWeak) Nom)
pl
s (AF (APosit (Weak Pl)) Nom)
genitiv
obestutr
s (AF (APosit (Strong (GSg Utr))) Gen)
s (AF ACompar Gen)
s (AF (ASuperl SupStrong) Gen)
neut
s (AF (APosit (Strong (GSg Neutr))) Gen)
pl
s (AF (APosit (Strong GPl)) Gen)
bestsg
s (AF (APosit (Weak Sg)) Gen)
s (AF (ASuperl SupWeak) Gen)
pl
s (AF (APosit (Weak Pl)) Gen)
-
- -

Adverb

-

s

-
- -

Preposition

-

s

-
- -

Verb

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
activepassive
infitiv
s (VI (VInfin Act))
s (VI (VInfin Pass))
presens
s (VF (VPres Act))
s (VF (VPres Pass))
preteritum
s (VF (VPret Act))
s (VF (VPret Pass))
supinum
s (VI (VSupin Act))
s (VI (VSupin Pass))
imperativ
s (VF (VImper Act))
s (VF (VImper Pass))
- -

Particip Presens

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
obestbest
nomsg
s (VI (VPtPres Sg Indef Nom))
s (VI (VPtPres Sg Def Nom))
pl
s (VI (VPtPres Pl Indef Nom))
s (VI (VPtPres Pl Def Nom))
gensg
s (VI (VPtPres Sg Indef Gen))
s (VI (VPtPres Sg Def Gen))
pl
s (VI (VPtPres Pl Indef Gen))
s (VI (VPtPres Pl Def Gen))
- -

Particip Perfekt

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
nominativgenitiv
obestutr
s (VI (VPtPret (Strong (GSg Utr)) Nom))
s (VI (VPtPret (Strong (GSg Utr)) Gen))
neut
s (VI (VPtPret (Strong (GSg Neutr)) Nom))
s (VI (VPtPret (Strong (GSg Neutr)) Gen))
pl
s (VI (VPtPret (Strong GPl) Nom))
s (VI (VPtPret (Strong GPl) Gen))
bestsg
s (VI (VPtPret (Weak Sg) Nom))
s (VI (VPtPret (Weak Sg) Gen))
pl
s (VI (VPtPret (Weak Pl) Nom))
s (VI (VPtPret (Weak Pl) Gen))
-
-
+ + + N + N2 + s + + + + A + A2 + a + + + + Adv + adv + + + + Prep + prep + + + + V + V2 + V3 + V2V + VV + VS + v + + + diff --git a/src/ui/android/src/org/grammaticalframework/ui/android/LexicalEntryActivity.java b/src/ui/android/src/org/grammaticalframework/ui/android/LexicalEntryActivity.java index 72ce457ed..60c6b45b2 100644 --- a/src/ui/android/src/org/grammaticalframework/ui/android/LexicalEntryActivity.java +++ b/src/ui/android/src/org/grammaticalframework/ui/android/LexicalEntryActivity.java @@ -1,14 +1,11 @@ package org.grammaticalframework.ui.android; -import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.Map; import android.app.Activity; import android.app.ListActivity; import android.content.Context; -import android.content.res.XmlResourceParser; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -23,7 +20,6 @@ import android.widget.TextView; import org.grammaticalframework.pgf.*; import org.grammaticalframework.ui.android.LanguageSelector.OnLanguageSelectedListener; -import org.xmlpull.v1.XmlPullParserException; public class LexicalEntryActivity extends ListActivity { @@ -93,27 +89,6 @@ public class LexicalEntryActivity extends ListActivity { } private void expand(View view, String lemma) { - String tag = null; - if (lemma.endsWith("_N") || lemma.endsWith("_N2")) - tag = "noun"; - else if (lemma.endsWith("_V") || lemma.endsWith("_V2") || - lemma.endsWith("_V3") || lemma.endsWith("_V2V") || - lemma.endsWith("_VV") || lemma.endsWith("_VS")) - tag = "verb"; - else if (lemma.endsWith("_A") || lemma.endsWith("_A2")) - tag = "adjective"; - else if (lemma.endsWith("_Prep")) - tag = "prep"; - else if (lemma.endsWith("_Adv")) - tag = "adverb"; - - if (tag == null) - return; - - int res = mTranslator.getTargetLanguage().getInflectionResource(); - if (res == 0) - return; - ImageView arrow = (ImageView) view.findViewById(R.id.arrow); arrow.setImageResource(R.drawable.close_arrow); @@ -127,69 +102,8 @@ public class LexicalEntryActivity extends ListActivity { ((RelativeLayout) view).addView(inflectionView, params); } - Expr expr = Expr.readExpr(lemma); - Map lins = mTranslator.tabularLinearize(expr); - XmlResourceParser parser = getResources().getXml(res); - StringBuilder builder = new StringBuilder(); - builder.append(""); - - try { - boolean emit = false; - boolean form = false; - int event = parser.next(); - while (event != XmlResourceParser.END_DOCUMENT) { - switch (event) { - case XmlResourceParser.START_TAG: - if (tag.equals(parser.getName())) { - emit = true; - } if ("form".equals(parser.getName())) { - form = true; - } else if (emit) { - builder.append("<"+parser.getName()); - int n_attrs = parser.getAttributeCount(); - for (int i = 0; i < n_attrs; i++) { - builder.append(' '); - builder.append(parser.getAttributeName(i)); - builder.append("=\""); - builder.append(parser.getAttributeValue(i)); - builder.append("\""); - } - builder.append(">"); - } - break; - case XmlResourceParser.END_TAG: - if (tag.equals(parser.getName())) { - emit = false; - } else if ("form".equals(parser.getName())) { - form = false; - } else if (emit) { - builder.append(""); - } - break; - case XmlResourceParser.TEXT: - if (emit) { - if (form) { - String s = lins.get(parser.getText()); - if (s != null) - builder.append(s); - } else { - builder.append(parser.getText()); - } - } - break; - } - event = parser.next(); - } - } catch (IOException e) { - e.printStackTrace(); - } catch (XmlPullParserException e) { - e.printStackTrace(); - } finally { - parser.close(); - } - - builder.append(""); - inflectionView.loadData(builder.toString(), "text/html; charset=UTF-8", null); + String html = mTranslator.getInflectionTable(lemma); + inflectionView.loadData(html, "text/html; charset=UTF-8", null); expandedView = view; } @@ -211,7 +125,7 @@ public class LexicalEntryActivity extends ListActivity { TextView descView = (TextView) convertView.findViewById(R.id.lexical_desc); - String phrase = mTranslator.generateTranslationEntry(lemma); + String phrase = mTranslator.generateLexiconEntry(lemma); descView.setText(phrase); convertView.setOnClickListener(new OnClickListener() { diff --git a/src/ui/android/src/org/grammaticalframework/ui/android/Translator.java b/src/ui/android/src/org/grammaticalframework/ui/android/Translator.java index f25e07e2f..d4709ed7d 100644 --- a/src/ui/android/src/org/grammaticalframework/ui/android/Translator.java +++ b/src/ui/android/src/org/grammaticalframework/ui/android/Translator.java @@ -2,6 +2,7 @@ package org.grammaticalframework.ui.android; import android.content.Context; import android.content.SharedPreferences; +import android.content.res.XmlResourceParser; import android.util.Log; import org.grammaticalframework.pgf.Concr; @@ -9,6 +10,7 @@ import org.grammaticalframework.pgf.Expr; import org.grammaticalframework.pgf.MorphoAnalysis; import org.grammaticalframework.pgf.PGF; import org.grammaticalframework.pgf.ParseError; +import org.xmlpull.v1.XmlPullParserException; import java.io.FileNotFoundException; import java.io.IOException; @@ -38,6 +40,8 @@ public class Translator { new Language("sv-SE", "Swedish", "ParseSwe", R.xml.inflection_sv, R.xml.qwerty), }; + private Context mContext; + private Language mSourceLanguage; private Language mTargetLanguage; @@ -69,9 +73,11 @@ public class Translator { } public Translator(Context context) { - mGrammarLoader = new GrammarLoader(context); + mContext = context; + + mGrammarLoader = new GrammarLoader(); mGrammarLoader.start(); - + mSharedPref = context.getSharedPreferences( context.getString(R.string.global_preferences_key), Context.MODE_PRIVATE); @@ -131,20 +137,183 @@ public class Translator { } } - public String generateTranslationEntry(String lemma) { + private String getLemmaTag(String lemma) { + String cat = getGrammar().getFunctionType(lemma).getCategory(); + + int res = getTargetLanguage().getInflectionResource(); + if (res == 0) + return ""; + + XmlResourceParser parser = mContext.getResources().getXml(res); + + try { + int state = 0; + int event = parser.next(); + String tag = null; + boolean found = false; + while (event != XmlResourceParser.END_DOCUMENT) { + switch (event) { + case XmlResourceParser.START_TAG: + if (state == 0 && "inflection".equals(parser.getName())) { + state = 1; + tag = null; + found = false; + } else if (state == 1 && "cat".equals(parser.getName())) { + state = 2; + } else if (state == 1 && "tag".equals(parser.getName())) { + state = 3; + } else if (state == 1 && "template".equals(parser.getName())) { + state = 4; + } + break; + case XmlResourceParser.END_TAG: + if (state == 1 && "inflection".equals(parser.getName())) { + state = 0; + if (found) + return tag+"."; + } else if (state == 2 && "cat".equals(parser.getName())) { + state = 1; + } else if (state == 3 && "tag".equals(parser.getName())) { + state = 1; + } else if (state == 4 && "template".equals(parser.getName())) { + state = 1; + } + break; + case XmlResourceParser.TEXT: + if (state == 2) { + if (cat.equals(parser.getText())) { + found = true; + } + } else if (state == 3) { + tag = parser.getText(); + } + break; + } + event = parser.next(); + } + } catch (IOException e) { + Log.e(TAG, "getLemmaTag", e); + } catch (XmlPullParserException e) { + Log.e(TAG, "getLemmaTag", e); + } finally { + parser.close(); + } + + return ""; + } + + public String generateLexiconEntry(String lemma) { Expr e = Expr.readExpr(lemma); Concr sourceLang = getConcr(getSourceLanguage().getConcrete()); Concr targetLang = getConcr(getTargetLanguage().getConcrete()); if (targetLang.hasLinearization(lemma)) - return sourceLang.linearize(e) + " - " + targetLang.linearize(e); + return sourceLang.linearize(e) + " - " + getLemmaTag(lemma) + " " + targetLang.linearize(e); else - return sourceLang.linearize(e); + return sourceLang.linearize(e) + " " + getLemmaTag(lemma); } - public Map tabularLinearize(Expr e) { + public String getInflectionTable(String lemma) { + String cat = getGrammar().getFunctionType(lemma).getCategory(); + + int res = getTargetLanguage().getInflectionResource(); + if (res == 0) + return ""; + + Expr expr = Expr.readExpr(lemma); Concr targetLang = getConcr(getTargetLanguage().getConcrete()); - return targetLang.tabularLinearize(e); - } + Map lins = targetLang.tabularLinearize(expr); + XmlResourceParser parser = mContext.getResources().getXml(res); + StringBuilder builder = new StringBuilder(); + builder.append(""); + + try { + int state = 0; + int event = parser.next(); + boolean emit = false; + boolean form = false; + boolean lin = false; + StringBuilder abstrBuilder = null; + while (event != XmlResourceParser.END_DOCUMENT) { + switch (event) { + case XmlResourceParser.START_TAG: + if (state == 0 && "inflection".equals(parser.getName())) { + state = 1; + } else if (state == 1 && "cat".equals(parser.getName())) { + state = 2; + } else if (state == 1 && "template".equals(parser.getName())) { + state = 4; + } else if (state == 4 && "form".equals(parser.getName())) { + form = true; + } else if (state == 4 && emit && "lin".equals(parser.getName())) { + lin = true; + emit = false; + abstrBuilder = new StringBuilder(); + } else if (state == 4 && lin && "cat".equals(parser.getName())) { + abstrBuilder.append(cat); + } else if (state == 4 && lin && "lemma".equals(parser.getName())) { + abstrBuilder.append(lemma); + } else if (state == 4 && emit) { + builder.append("<"+parser.getName()); + int n_attrs = parser.getAttributeCount(); + for (int i = 0; i < n_attrs; i++) { + builder.append(' '); + builder.append(parser.getAttributeName(i)); + builder.append("=\""); + builder.append(parser.getAttributeValue(i)); + builder.append("\""); + } + builder.append(">"); + } + break; + case XmlResourceParser.END_TAG: + if (state == 1 && "inflection".equals(parser.getName())) { + state = 0; + } else if (state == 2 && "cat".equals(parser.getName())) { + state = 1; + } else if (state == 4 && "template".equals(parser.getName())) { + state = 1; + emit = false; + } else if (state == 4 && "form".equals(parser.getName())) { + form = false; + } else if (state == 4 && lin && "lin".equals(parser.getName())) { + Expr expr2 = Expr.readExpr(abstrBuilder.toString()); + builder.append(targetLang.linearize(expr2)); + emit = true; + } else if (state == 4 && emit) { + builder.append(""); + } + break; + case XmlResourceParser.TEXT: + if (state == 2) { + if (cat.equals(parser.getText())) + emit = true; + } else if (state == 4 && emit) { + if (form) { + String s = lins.get(parser.getText()); + if (s != null) + builder.append(s); + } else { + builder.append(parser.getText()); + } + } else if (state == 4 && lin) { + abstrBuilder.append(parser.getText()); + } + break; + } + event = parser.next(); + } + } catch (IOException e) { + e.printStackTrace(); + } catch (XmlPullParserException e) { + e.printStackTrace(); + } finally { + parser.close(); + } + + builder.append(""); + + return builder.toString(); + } public List lookupMorpho(String sentence) { return getConcr(getSourceLanguage().getConcrete()).lookupMorpho(sentence); @@ -164,12 +333,6 @@ public class Translator { } private class GrammarLoader extends Thread { - private final Context mContext; - - public GrammarLoader(Context context) { - mContext = context; - } - public void run() { InputStream in = null;