/* Trida Parser. ============= Tato trida je soucasti projektu Derivovani. Trida Parser ma pouze jednu verejnou metodu nazvanou "stringNaVyraz". Tato metoda prevede matematicky vyraz v podobe znakoveho retezce na instance tridy Vyraz. Pokud dojde k nejake chybe, ulozi se jeji popis do promenne "chyba" a funkce stringNaVyraz vrati hodnotu null. */ package derivovani; import sugar.Sys; import derivovani.Vyraz; public class Parser { public static String chyba; // popis chyby (pokud k nejake dojde) // globalni promenne pro funkci zpracujVstup: private static String vstup; // vstupni retezec private static int iVstup; // poloha ve vstupnim retezci // funkce, ktera zjisti, zda je vstupni znak cislice, desetinna carka ci tecka private static boolean jeZnakCisla(char znak) { return ( ( (znak >= '0') && (znak <= '9')) || (znak == '.') || (znak == ',') ); } // funkce, ktera zjisti, zda je zadany znak znakem operatoru private static boolean jeOperator(char znak) { return ( (znak == '+') || (znak == '-') || (znak == '*') || (znak == '/') || (znak == '^') ); } // funkce, ktera ze vstupu nacte aktualni znak. // Pokud jiz na vstupu nic neni, funkce vraci hodnotu 0. private static char aktualniZnakNaVstupu() { if (iVstup < vstup.length()) return vstup.charAt(iVstup); else return 0; } // funkce, ktera ze vstupu nacte cislo (jako retezec znaku) private static String nactiZeVstupuCislo() { String cislo = ""; // retezec pro ulozeni nacitaneho cisla char znak = aktualniZnakNaVstupu(); while (jeZnakCisla(znak)) { cislo += znak; iVstup++; znak = aktualniZnakNaVstupu(); } return cislo; } // funkce, ktera ze vstupu nacte jeden vyraz (cislo, zavorku, x) // navratovou hodnotou je reference na tridu, kam se vyraz ulozil private static Vyraz nactiZeVstupuJedenVyraz() { // nacteni cisla String cislo = nactiZeVstupuCislo(); if (chyba != null) return null; // pokud doslo k chybe, koncim if (cislo != "") return new Vyraz(Sys.getDouble(cislo)); // pokud na vstupu nebylo cislo, nactu jeden znak char znak = aktualniZnakNaVstupu(); if (znak==0) { chyba = "Vyraz neni dokonceny! Ocekavam dalsi operand!"; return null; } iVstup++; // nacteni vyrazu (uzavreneho zavorkami) if (znak == '(') { Vyraz vyraz = nactiVstup(Vyraz.uSoucet); iVstup++; // preskocim pravou zavorku return vyraz; } // nacteni promenne "x" if (znak == 'x') return new Vyraz(Vyraz.tX, null, null); // znamenko "-" if (znak == '-') return new Vyraz(Vyraz.tRozdil, new Vyraz(0), nactiVstup(Vyraz.uSoucin)); // chyba chyba = "Neplatny znak na pozici [" + (iVstup-1) + "]! Ocekavam operand!"; return null; } // Funkce, ktera prevede vstupni retezec na instance tridy Vyraz. // S prevodem se konci, pokud narazim na operator s nizsi urovni nez "minimalniUroven". // Navratovou hodnotou je reference na objekt, kam se retezec prevedl. private static Vyraz nactiVstup(int minimalniUroven) { // nactu prvni (levy) operand ("x", cislo nebo vyraz v zavorkach) // a vytvorim vystupni vyraz Vyraz vystup = nactiZeVstupuJedenVyraz(); // vystupni promenna teto funkce if (chyba != null) return null; // pokud doslo k chybe, koncim while (true) { // nactu dalsi znak char znak = aktualniZnakNaVstupu(); // konec zavorky nebo retezce nebo nalezeni operatoru s nizsi urovni if ((znak == ')') || (znak == 0)) return vystup; int urovenZnaku = Vyraz.urovenOperatoru(znak); if (urovenZnaku < minimalniUroven) return vystup; // osetrim nasobeni bez hvezdicky a preskocim operator if (jeOperator(znak)) iVstup++; else znak = '*'; // prenesu vystupni vyraz do leveho operandu a nactu pravy operand vystup = new Vyraz(znak, vystup, nactiVstup(urovenZnaku + 1)); if (chyba != null) return null; // pokud doslo k chybe, koncim } } // Funkce, ktera prevede vstupni retezec na instance tridy Vyraz. // Navratovou hodnotou je reference na objekt, kam se retezec prevedl. // Toto je jedina verejna metoda tridy Parser. public static Vyraz stringNaVyraz(String retezec) { chyba = null; vstup = retezec; iVstup = 0; return nactiVstup(Vyraz.uSoucet); } }