package slangc.parser; import slang.data.List; import slangc.streams.LogWriter; public class CleopatraModeLanguage extends Language { private Option[] options = new Option[0]; private final boolean enableFallbacks; public CleopatraModeLanguage(boolean enableFallbacks) { this.enableFallbacks = enableFallbacks; } public static class Option { public final String language; public final Key key; public final String value; public Option(String language, Key key, String value) { this.language = language; this.key = key; this.value = value; } } public void addOption(Option o) { Option[] newarr = new Option[options.length + 1]; for (int i = 0; i < newarr.length; i++) { newarr[i] = (i < options.length ? options[i] : o); } options = newarr; } public void addOption(String language, Key key, String value) { addOption(new Option(language, key, value)); } public void addOption(Medu medu, Key key, String value) { addOption(""+medu /*.name()*/, key, value); } String[] cachedKeywords = null; @Override public String[] getKeywords() { if (cachedKeywords == null) { cachedKeywords = recalculateKeywords(); } return cachedKeywords; } public String[] recalculateKeywords() { String[] initial; if (enableFallbacks) { initial = super.getKeywords(); } else { initial = new String[0]; } String[] result = new String[initial.length + options.length]; for (int i = 0; i < result.length; i++) { result[i] = (i < initial.length ? initial[i] : options[i - initial.length].value); } return result; } @Override public boolean matches(Key key, String str) { for (int i = 0; i < options.length; i++) { if (options[i].key == key && options[i].value.equals(str)) { return true; } } if (enableFallbacks) { return super.matches(key, str); } else { return false; } } public enum Medu { USERDEFINED, NETER, NUBIAN, COPTIC, GREEK } public void addMedu(Medu m) { switch (m) { case Medu.NUBIAN: addNubian(); break; case Medu.COPTIC: addCoptic(); break; default: throw new Error("TODO: This medu mode " + m + " is not implemented yet"); } } public void printTable(LogWriter out) { /* List columns = new List(); for (int i = 0; i < options.length; i++) { if (!columns.contains(options[i].language)) { columns.add(options[i].language); } } out.print("[%header,cols=\"1,"); for (int i = 0; i < columns.size(); i++) { if (i != 0) { out.print(","); } out.print(2); } out.println("\"]"); out.println("|==="); out.print("|Keyword Id "); for (int i = 0; i < columns.size(); i++) { //if (i != 0) { // out.print(","); //} out.print("|" + columns.get(i) + " "); } out.println(); out.println(); for (int i = 0; i < Key.values().length; i++) { printTableRow(out, columns, Key.values()[i]); out.println(); } out.println("|==="); */ throw new Error("TODO: Printing language tables"); } public void printTableRow(LogWriter out, List columns, Key key) { out.print("|" + key + " "); for (int i = 0; i < columns.count(); i++) { out.print("| "); boolean addedOne = false; for (int j = 0; j < options.length; j++) { Option o = options[j]; if (o.key == key && o.language.equals(columns.get(i))) { if (addedOne) { out.print(", "); } else { addedOne = true; } out.print("`" + o.value + "`"); } } if (addedOne) { out.print(" "); } } out.println(); } public void addNubian() { addOption(Medu.NUBIAN, Key.CLASS, "ⲕⲗⲁⲥⲥ"); addOption(Medu.NUBIAN, Key.PUBLIC, "ⲡⲩⲃⲗⲓⲕ"); // From "An English-Nubian Comparative Dictionary", 1923 // NOTE: There is a small but strong Nubian community on Twitter that can provide more links. addOption(Medu.NUBIAN, Key.THIS, "ⲉⲓⲛ"); // p.xxxv, p.73 (note: "that" would be ⲙⲁⲛ) addOption(Medu.NUBIAN, Key.BREAK, "ⲡⲁⲗ"); // p.49 addOption(Medu.NUBIAN, Key.TRUE, "ⲉⲩⲟ"); // ⲡ.48 ("yes", speculative spelling, only phonetics provided) addOption(Medu.NUBIAN, Key.VOID, "ⲡⲁⲣⲕ"); //ⲡ.50 (a valley or place water goes without releasing) addOption(Medu.NUBIAN, Key.IF, "ⲡⲉϣϣ"); //ⲡ.51 ("judge") addOption(Medu.NUBIAN, Key.IF, "ⲟⲛ"); // p.188 (and/if) addOption(Medu.NUBIAN, Key.STATIC, "ⲡⲓ"); //ⲡ.52 (i.e. to stay, as in the sentence "I'm staying at home") addOption(Medu.NUBIAN, Key.RETURN, "ⳟⲓⲡⲓⲣⲧ"); //p.60 (repeat or return, NOTE: need to check first character) addOption(Medu.NUBIAN, Key.THROW, "ⳝⲟⳝ"); //ⲡ.62 (kill/fight/sacrifice) addOption(Medu.NUBIAN, Key.THROW, "ⲙⲟⲩⲣⲧ"); //ⲡ.125 (warn) addOption(Medu.NUBIAN, Key.FOR, "ⲕⲉⲗ"); // p.95 (limit or boundary, related to the word used for WHILE) addOption(Medu.NUBIAN, Key.WHILE, "ⲕⲉⲗⲗ"); //p.95 ("as much as", "sometimes", related to the word used for FOR) addOption(Medu.NUBIAN, Key.DUCK, "ⲕⲉⲗⲁⲓ"); // p.95 (wild duck, speculative spelling, only phonetics provided) addOption(Medu.NUBIAN, Key.NULL, "ⲕⲓⳡ"); // p.99 (empty or exhausted, NOTE: need to check last character) addOption(Medu.NUBIAN, Key.FINAL, "ⲕⲓⲣⲓⳟ"); // p.100 (finished or complete, NOTE: need to check last character) addOption(Medu.NUBIAN, Key.ABSTRACT, "ⲙⲓⲛⲇⲓ"); // ⲡ.122 (partial, incomplete, NOTE: this seems to be a rarely-used word) addOption(Medu.NUBIAN, Key.NEW, "ⳟⲁⲓⲉⲣ"); // ⲡ.134 ("bring to life") addOption(Medu.NUBIAN, Key.INT, "ⲥⲁⲗ"); // p.144 ("word", which fits with an old way of basically saying int - "machine word") addOption(Medu.NUBIAN, Key.EXTENDS, "ⲥⲉⲩ"); // p.147 ("inherit") addOption(Medu.NUBIAN, Key.MODULE, "ϣⲟⲗ"); // p.157 (a book or charm) addOption(Medu.NUBIAN, Key.PRIVATE, "ⲧⲟⲩ"); // p.169 (internals, belly/guts) addOption(Medu.NUBIAN, Key.THIS, "ⲟⲩⲣ"); // p. 178 ("self") // p.161 for class/etc.? // ⲉⲧⲉⲣ for "do"? p.48 } public void addCoptic() { // From "Aegyptisches Glossar", 1904 // NOTE: This source was chosen as the primary one because it focuses on words // present in both Medu Neter and Coptic (also with many connections to Greek, Hebrew, // Arabic and so on). addOption(Medu.COPTIC, Key.WHILE, "ⲟⲩⲱϩⲙ"); // p.32, "repeat"/"to repeat" addOption(Medu.COPTIC, Key.FOR, "ⲟⲩⲱϣ"); // p.32, "search" // NOTE: See also p.56 for iteration-releated words addOption(Medu.COPTIC, Key.RETURN, "ⲟⲩⲱϣⲃ"); // p.34, "answer" addOption(Medu.COPTIC, Key.TRY, "ⲟⲩⲇⲁⲓ"); // p.35, "be safe" // NOTE: See also p.56 for "witness", p.65 for "harness" addOption(Medu.COPTIC, Key.THROW, "ⲕⲱ"); // p.90, literally "throw" or "leave" addOption(Medu.COPTIC, Key.DO, "ⲃⲁⲕ"); // p.39, "work" addOption(Medu.COPTIC, Key.CATCH, "ⲡⲏⲓ"); // p.41, "escaped" (fits with "catch" because that's why you need to catch it!) addOption(Medu.COPTIC, Key.FINALLY, "ⲁϩⲟⲩ"); // p.43, "the end"/"the rear" (as in "reaching the end"? literally "ahoy"? The Euros seem to think not) addOption(Medu.COPTIC, Key.FINALLY, "ⲡⲁϩⲟⲩ"); // Alternative spelling // See also p.124 for a word for "tail" addOption(Medu.COPTIC, Key.FINAL, "ⲙⲟⲩⲛⲕ"); // p.51, "complete" (literally "monk") addOption(Medu.COPTIC, Key.FINAL, "ⲧⲱⲱⲃⲉ"); // p. 155, "seal" addOption(Medu.COPTIC, Key.SUPER, "ⲡⲧⲁϩ"); // p.45 (Ptah = Phthah, we still use the same word "father" in English) addOption(Medu.COPTIC, Key.SUPER, "ⲙⲁⲁⲩ"); // p.49, (Maa', from which mother is derived) addOption(Medu.COPTIC, Key.ELSE, "ⲙ"); // p.46, "Negation of the Imperative" lmao perfect (ⲙ︦? needs line above?) addOption(Medu.COPTIC, Key.TRUE, "ⲙⲉ"); // p.47, "true" addOption(Medu.COPTIC, Key.TRUE, "ⲙⲏⲓ"); // Alternative spelling? (or I've interpreted this entry incorrectly...) addOption(Medu.COPTIC, Key.STATIC, "ⲙⲟⲩⲛ"); // p.50, "stay" addOption(Medu.COPTIC, Key.NEW, "ⲙⲓⲥⲉ"); // p.55, "give birth", "generate", "form" addOption(Medu.COPTIC, Key.VOID, "ⲛⲟⲩϥⲉⲛ"); // p.62, spelling assumed based on nearby term. Intended meaning is "never", related to "nether". addOption(Medu.COPTIC, Key.NULL, "ϣⲱⲩⲉⲓⲧ"); // p.127, "be empty of something" addOption(Medu.COPTIC, Key.DUCK, "ⲣⲟ"); // p.70, slight pun (a goose is basically a duck right?) addOption(Medu.COPTIC, Key.BREAK, "ⲗⲟ"); // p.71, "stop" or "flee" addOption(Medu.COPTIC, Key.PRIVATE, "ϩⲱⲃⲥ"); // p.82, "conceal" or "dress" addOption(Medu.COPTIC, Key.SWITCH, "ⲥⲱⲧⲡ"); // p.122, "choose" addOption(Medu.COPTIC, Key.CASE, "ⲥⲟⲡ"); // p.103, "type of" or "case of" (note, type seems to be "Art" in German?) addOption(Medu.COPTIC, Key.SHORT, "ϣⲓⲣⲉ"); // p.130, "be small" addOption(Medu.COPTIC, Key.BYTE, "ϣⲏⲣⲉ"); // p.130, "smaller" (literally same as ϣⲓⲣⲉ except shorter "i" vowel) addOption(Medu.COPTIC, Key.CLASS, "ⲕⲟⲧ"); // p.135, "circle", "shape", "kind", "essence" // p.140 for "equip" as extends/implements? 151 for similar // p.153 for "enter" as main? // p.33 for "say" as logLine? // p.45 for "run" ? // p.58 for "depth" as length? } public boolean applySetting(String key, String value, boolean reset, boolean append) { if (reset && key == "*") { options = new Option[0]; return true; } else if (append && value != null && !reset) { Key k; try { k = (Key) Key.lookup(Key.class, key); } catch (Error e) { return false; } addOption(Medu.USERDEFINED, k, value); return true; } else { return super.applySetting(key, value, reset, append); } } }