public static string DiacritizeWord(WordInfo Word) { StringBuilder sb = new StringBuilder(); if (Word.Prefix.WordClass.StartsWith("N2")) { if (Tashkeel.SilentLam(Word.Word[0])) { //لام شمسية Word.Prefix.Tashkeel = Word.Prefix.Tashkeel.Substring(0, Word.Prefix.Tashkeel.Length - 1) + '9'; Word.Diacritics = (char)(Word.Diacritics[0] + 3) + Word.Diacritics.Substring(1); } } sb.Append(Word.Prefix.Tashkeel); if (Word.Suffix.ConnectedLetter != "") { if (Word.Diacritics.EndsWith("#")) { Word.Diacritics = Word.Diacritics.Replace('#', (char)(Word.Suffix.ConnectedLetter[0] + 3)); } else { Word.Diacritics = Word.Diacritics.Replace('!', Word.Suffix.ConnectedLetter[0]); } } sb.Append(Word.Diacritics); sb.Append(Word.Suffix.Tashkeel); return(sb.ToString()); }
public static string AnalyzeText(string TextToParse, ref BackgroundWorker BackGroundProcess) { Corrections = 0; NotRecognized = 0; ArabicWords = ExtractArabicWords(TextToParse); //للاحتفاظ باحتمالات النطق المختلفة لكل كلمة لأغراض التعديل AllWordsInfo = new List <List <WordInfo> >(); StringBuilder OutPutText = new StringBuilder(); conn.Open(); con.Open(); LoadInterpreterData(); for (int i = 0; i < ArabicWords.Count; i++) //التحليل الصرفي { // ///http://ar.wikipedia.org/wiki/%D8%B2%D8%A7%D8%A6%D8%AF%D8%A9_(%D9%84%D8%BA%D8%A9) List <WordInfo> NewWordInfo = ProcessWord(ArabicWords[i]); //ابدأ معالجة الكلمة الجديدة AllWordsInfo.Add(NewWordInfo); //أضف ناتج المعالجة لمعلومات الكلمات if (NewWordInfo.Count == 0) //إذا لم يجد تفسير للكلمة { //فشل تفسير الكلمة والتشكيل بناء على تتابع الحروف -غالبا للكلمات الأعجمية //هذه الخوارزمية تحتاج تحسين //للتعامل مع الكلمات الأعجمية المضاف لها ألف ولام أو ياء نسب WordInfo NewWord = new WordInfo(); NewWord.Word = ArabicWords[i].word; NewWord.Diacritics = Tashkeel.Guess(ArabicWords[i].word); NewWordInfo.Add(NewWord); NotRecognized += 1; } BackGroundProcess.ReportProgress((i + 1) * 100 / ArabicWords.Count);//تحديث شريط التقدم } int LastAdded = -1; WordInfo WordToAdd; GrammarRelation GR; for (int i = 0; i < ArabicWords.Count; i++) { GR = new GrammarRelation(); i += Interpreter.StartInterpreting(ref GR, i, "", 1, false); } for (int i = 0; i < ArabicWords.Count; i++) { WordToAdd = AllWordsInfo[i][0]; OutPutText.Append(TextToParse.Substring(LastAdded + 1, ArabicWords[i].Start - (LastAdded + 1))); OutPutText.Append(WordToAdd.ToString()); LastAdded = ArabicWords[i].End; //آخر حرف أضيف هو آخر حروف الكلمة //إضافة الحروف غير العربية التالية إلى المخرجات كما هي if (i + 1 == ArabicWords.Count && LastAdded + 1 < TextToParse.Length) { OutPutText.Append(TextToParse.Substring(LastAdded + 1)); } } conn.Close(); con.Close(); return(OutPutText.ToString()); }
/// <summary> /// البحث عن الوزن في جدول WordTemplates وإرجاعه لبدء عمليات التحليل الصرفي /// </summary> /// <param name="word"></param> /// <param name="mask"></param> /// <param name="Meanings"></param> /// <param name="Results"></param> /// <returns></returns> public static List <string[]> CheckWordMask(string word, string mask, List <string> Meanings, List <string[]> Results) { SqlCommand com = new SqlCommand("select * from WordTemplates where Mask='" + mask + "'", Analyzer.conn); SqlDataReader dread = com.ExecuteReader(); string[] fields; while (dread.Read()) { //اختبار توافق تشكيل الوزن مع حروف الكلمة if (dread["Class"].ToString().StartsWith("V2"))//إذا كان وزن فعل مضارع { if (!Tashkeel.CheckTashkeel(word, dread[1].ToString().Substring(1))) { continue; //استثناء حرف المضارعة } } else if (!Tashkeel.CheckTashkeel(word, dread[1].ToString())) { continue; } //اختبار توافق نوع الوزن مع النوع المتوقع foreach (string M in Meanings) { string MergedMeaning; if (Interpreter.CompareMeanings(dread["Class"].ToString(), M, out MergedMeaning)) { fields = new string[8]; for (int f = 0; f < fields.Length; f++) { if (f == 3) { fields[f] = MergedMeaning; continue; } fields[f] = dread[f].ToString(); } Results.Add(fields); } } } dread.Close(); return(Results); }
public override string ToString() { return(Tashkeel.SetTashkeel(Prefix.Text + Word + Suffix.Text, CompleteDiacritics)); }
/// <summary> /// الإجراء الرئيسي في التحليل الصرفي؛ يقوم بتحليل الكلمة وإنتاج قائمة باحتمالات التحليل الصرفي. /// </summary> /// <param name="WordToProcess"></param> /// <returns></returns> private static List <WordInfo> ProcessWord(ArabicWord WordToProcess) { List <WordInfo> CurrentWordInfo = new List <WordInfo>(); WordInfo NewInfo; Morphology.CheckForSpecialWord(WordToProcess, ref CurrentWordInfo); if (CurrentWordInfo.Count > 0) { goto AddWord; } Morphology.CheckForPronoun(WordToProcess, ref CurrentWordInfo); List <WordPrefix> ValidPrefixes = WordPrefix.CheckPrefix(WordToProcess.word); List <WordSuffix> ValidSuffixes = WordSuffix.CheckSuffixes(WordToProcess.word); //المعاني الافتراضية عند عدم وجود إضافات ValidPrefixes.Add(new WordPrefix() { WordClass = "N1" }); //الأسماء نكرة ValidPrefixes.Add(new WordPrefix() { WordClass = "V1" }); //فعل ماض ValidPrefixes.Add(new WordPrefix() { WordClass = "V3" }); //فعل أمر ValidSuffixes.Add(new WordSuffix() { WordClass = "N001" }); //اسم مذكر ValidSuffixes.Add(new WordSuffix() { WordClass = "V10311" }); //فعل ماض غائب مفرد مذكر ValidSuffixes.Add(new WordSuffix() { WordClass = "V20211" }); //فعل مضارع مخاطب مفرد مذكر ValidSuffixes.Add(new WordSuffix() { WordClass = "V201" }); //فعل مضارع متكلم ValidSuffixes.Add(new WordSuffix() { WordClass = "V2031" }); //فعل مضارع غائب مفرد ValidSuffixes.Add(new WordSuffix() { WordClass = "V30011" }); //فعل أمر مفرد مذكر List <string[]> Result = new List <string[]>(); string Stem; for (int i = 0; i < ValidPrefixes.Count; i++) { for (int j = 0; j < ValidSuffixes.Count; j++) { Result = new List <string[]>(); if (WordToProcess.word.Length <= (ValidSuffixes[j].Text.Length + ValidPrefixes[i].Text.Length)) { //طول الإضافات يغطي طول الكلمة بأكملها continue; } List <string> CompatibleAdditions = Morphology.CheckAdditionsCompatibility(ValidPrefixes[i].WordClass, ValidSuffixes[j].WordClass); if (CompatibleAdditions.Count == 0) { //إضافات غير متوافقة continue; } Stem = WordToProcess.word.Substring(ValidPrefixes[i].Text.Length, WordToProcess.word.Length - (ValidPrefixes[i].Text.Length + ValidSuffixes[j].Text.Length)); //ابحث عن الأوزان المتوافقة مع الإضافات المحددة Result = Morphology.LookForTemplate(Stem, CompatibleAdditions, Result); if (Result.Count == 0) { continue; } /* اختبار وجود جذر للكلمة متوافق مع الوزن المحدد * واختبار توافق الجذر الموجود مع هذا الوزن * يمكن الاستغناء عن بعض هذه الخطوات عند إكمال قاعدة البيانات * */ #region اختبار توافق الوزن والجذر string[] CurrentResult; string CurrentRoot = ""; List <ArabicRoot> CheckRootResults = new List <ArabicRoot>(); for (int R = 0; R < Result.Count; R++) { CurrentResult = Result[R]; Morphology.RootCompatibility RootResult = Morphology.CheckRoot(Stem, CurrentResult[2], CurrentResult[4], CurrentResult[5], CurrentResult[6], CurrentResult[7], ref CurrentRoot); switch (RootResult) //اختبار وجود الجذر حسب الوزن { case Morphology.RootCompatibility.InvalidRoot: Result.RemoveAt(R); R--; break; case Morphology.RootCompatibility.CompatibleRoot: for (int prev = 0; prev < R; prev++) { //عثر على جذر متوافق احذف كل الأوزان السابقة التي ليس لها جذور متوافقة //if (CurrentResult[2] == Result[prev][2]) //نفس نمط الوزن { if (CheckRootResults[prev].RootCompatibility == Morphology.RootCompatibility.IncompatibleValidRoot) { Result.RemoveAt(prev); CheckRootResults.RemoveAt(prev); R--; prev--; } } } CheckRootResults.Add(new ArabicRoot() { Root = CurrentRoot, RootCompatibility = RootResult }); break; case Morphology.RootCompatibility.IncompatibleValidRoot: bool AddThisOne = true; for (int prev = 0; prev < R; prev++) { if (CurrentResult[2] == Result[prev][2]) //نفس نمط الوزن { if (CheckRootResults[prev].RootCompatibility == Morphology.RootCompatibility.CompatibleRoot) { AddThisOne = false; //عثر من قبل على جذور متوافقة لها أولوية Result.RemoveAt(R--); break; } } //مفاضلة الأوزان من نفس قاعدة الاشتقاق byte CompareResult = Morphology.CompareRules(CurrentResult[7], Result[prev][7]); if (CompareResult == 1) { CheckRootResults.RemoveAt(prev); Result.RemoveAt(prev--); R--; } else if (CompareResult == 2) //الوزن المضاف مسبقا أولى { AddThisOne = false; Result.RemoveAt(R--); break; } } if (AddThisOne) { CheckRootResults.Add(new ArabicRoot() { Root = CurrentRoot, RootCompatibility = RootResult, DerivationRules = CurrentResult[7] }); } break; } } #endregion for (int R = 0; R < Result.Count; R++) { NewInfo = new WordInfo(); NewInfo.Word = Stem; NewInfo.Diacritics = Result[R][1]; NewInfo.Template = Result[R][0]; NewInfo.Meaning = Result[R][3]; NewInfo.Root = CheckRootResults[R]; NewInfo.Prefix = ValidPrefixes[i]; NewInfo.Suffix = ValidSuffixes[j]; Tashkeel.DiacritizeWord(NewInfo); CurrentWordInfo.Add(NewInfo); } } } AddWord: for (int W = 0; W < CurrentWordInfo.Count; W++) { if (CurrentWordInfo[W].Root.RootCompatibility == Morphology.RootCompatibility.CompatibleRoot) { WordInfo Temp; for (int prev = W; prev > 0; prev--) { Temp = CurrentWordInfo[prev]; CurrentWordInfo[prev] = CurrentWordInfo[prev - 1]; CurrentWordInfo[prev - 1] = Temp; } } } return(CurrentWordInfo); }