Algoritmus shunting-yard

Technology
12 hours ago
8
4
2
Avatar
Author
Albert Flores

Shunting yard algoritmus je metoda pro syntaktickou analýzu matematických výrazů zapsaných v infixové notaci. Algoritmus může být použit k převodu výrazů do reverzní polské notace (RPN), nebo do abstraktního syntaktického stromu (AST).

Algoritmus byl vyvinut Edsgerem Dijkstrou a pojmenován Shunting yard (česky seřaďovací nádraží), protože jeho princip se podobá seřaďovacímu nádraží.

Podobně jako interpret reverzní polské notace je shunting yard založený na používání zásobníku. Infixovou formu zápisu používá většina lidí (například 3+4 nebo 3+4*(2−1)). +more Ke konverzi do RPN je zapotřebí dvou textových proměnných (jednu pro vstup a druhou pro výstup) a jednoho zásobníku pro uchovávání operátorů které zatím nebyly vloženy do výstupu.

Ukázka jednoduché konverze

:Vstup: 3+4 # Přidej 3 do výstupní fronty (pokaždé když přečte číslo, přidá ho do výstupu) # Přidej + (nebo jeho ID) do zásobníku operátorů # Vlož 4 do výstupu # Po přečtení celého vzorce vyjmi operátory ze zásobníku a vlož je do výstupní fronty # V tomto případě je zde pouze jedno, "+" :Výstup: 3 4 +

Z této ukázky je možno vypozorovat několik pravidel: * Všechna čísla jsou okamžitě po přečtení přidána do výstupu. * Po přečtení vzorce je nutné ze zásobníku vyjmout všechny operátory a vložit je do výstupní fronty.

Detailní popis algoritmu

Dokud jsou zde tokeny ke čtení: ** Přečti token. ** Pokud je token číslo, přidej ho do výstupní fronty. +more ** Pokud je token funkce, vlož ho na zásobník. ** Pokud je token oddělovač argumentů funkce (nejčastěji čárka): *** Dokud nebude na vrcholu zásobníku levá závorka, vybírej z něj operátory a vkládej je do výstupu. Jestliže se zásobník vyprázdní a závorka nebude nalezena, oddělovač byl buď na nesprávném místě, nebo ve vstupu chybí otevírací závorka. ** Pokud je token operátor (dále jen o1), tak: *** dokud bude na vrcholu zásobníku operátor (s výjimkou závorek), o2, tak: **** pokud je o1 asociativní zleva a jeho priorita je menší nebo stejná (≤) jako priorita o2, nebo o1 je asociativní zprava a jeho priorita je nižší (2, vyjmi operátor o2 ze zásobníku a vlož ho do výstupní fronty, jinak ukonči cyklus. *** vlož operátor o1 na zásobník. ** Pokud je token levá závorka, vlož ho na zásobník. ** Pokud je token pravá závorka: *** Dokud na vrcholu zásobníku nebude levá závorka, vybírej operátory ze zásobníku a zapisuj je do výstupní fronty. *** Vyjmi ze zásobníku levou závorku, ale nevkládej jí do výstupní fronty. *** Pokud je na vrcholu zásobníku token identifikovaný jako funkce, vlož ho do výstupu. *** Pokud je zásobník prázdný a nepodařilo se najít levou závorku, jedná se o neuzavřený výraz a je vhodné oznámit chybu. * Jestliže byly zpracovány všechny tokeny ze vstupu: ** Dokud budou v zásobníku operátory: *** Jestliže operátor na vrcholu zásobníku je závorka, ve výrazu jsou neuzavřené závorky a je vhodné ohlásit chybu. *** Vyjmi operátor ze zásobníku a vlož ho do výstupní fronty. * Konec.

Časová náročnost tohoto algoritmu je lineární v závislosti na velikosti programu, protože každý token je načten pouze jednou, každá funkce a každý operátor je na zásobník vložený a vyjmutý pouze jednou a každý prvek je vložen do výstupu pouze jednou.

Detailní ukázka

3Přidej token do výstupu3
+Přidej token na zásobník3+
4Přidej token do výstupu3 4+
Přidej token na zásobník3 4+má větší prioritu než +
2Přidej token do výstupu3 4 2+
/Vyjmi ze zásobníku a vypiš3 4 2+/ a * mají stejnou prioritu
/Přidej token na zásobník3 4 2+ // má větší prioritu než +
(Přidej token na zásobník3 4 2+ / (
1Přidej token do výstupu3 4 2 * 1+ / (
-Přidej token na zásobník3 4 2 * 1+ / ( -
5Přidej token do výstupu3 4 2 * 1 5+ / ( -
)Vyjmi ze zásobníku a vypiš3 4 2 * 1 5 −+ / (Opakuj dokud nenajdeš "("
)Vyjmi ze zásobníku3 4 2 * 1 5 −+ /Zahoď nalezenou závorku
^Přidej token na zásobník3 4 2 * 1 5 −+ / ^^ má větší prioritu než /
2Přidej token do výstupu3 4 2 * 1 5 − 2+ / ^
^Přidej token na zásobník3 4 2 * 1 5 − 2+ / ^ ^^ je vyhodnoceno zprava doleva
3Přidej token do výstupu3 4 2 * 1 5 − 2 3+ / ^ ^
konecVypiš zbytek zásobníku3 4 2 * 1 5 − 2 3 ^ ^ / +

Pokud píšete interpret, výstup můžete tokenizovat a zapsat do zkompilovaného souboru k pozdější interpretaci. Konverzí z infixové notace do RPN můžete také zjednodušit vyhodnocování matematických výrazů. +more To provedete tak, jako kdybyste vyhodnocovali RPN výraz, nicméně pokud narazíte na proměnnou, jejíž hodnota je nulová a vždy když operátor má nulovou hodnotu, tak jeho hodnotu a parametry vypište na výstup (tohle je zjednodušení - problémy nastanou, pokud jsou jako parametry operátory). Pokud operátor nemá nulový parametr, jeho hodnota může být vypsána na výstup. Tato metoda očividně neobsahuje všechna možná zjednodušení - je to většinou jako optimalizace pomocí constant folding.

Reference

Externí odkazy

[url=http://www. chris-j. +moreco. uk/parsing. php]Java Applet demonstrující Shunting yard algoritmus[/url] (vyžaduje javu) * [url=https://web. archive. org/web/20090605032748/http://montcs. bloomu. edu/~bobmon/Information/RPN/infix2rpn. shtml]Infix to RPN Algorithm[/url] * [url=http://www. cs. utexas. edu/~EWD/MCReps/MR35. PDF]Originální popis Shunting yard algoritmu[/url] * [url=http://en. literateprograms. org/Shunting_yard_algorithm_%28C%29]Ukázka zdrojového kódu v C[/url].

Kategorie:Matematické zápisy Kategorie:Algoritmy syntaktické analýzy

5 min read
Share this post:
Like it 8

Leave a Comment

Please, enter your name.
Please, provide a valid email address.
Please, enter your comment.
Enjoy this post? Join Cesko.wiki
Don’t forget to share it
Top