doku 4
This commit is contained in:
parent
ddec1650e6
commit
b713991e4b
@ -145,13 +145,13 @@ Typy tokenů využité v~této práci jsou uvedeny v~tabulce~\ref{tab:tokens}.
|
|||||||
\label{sec:ana}
|
\label{sec:ana}
|
||||||
Následuje analýza syntaktická, během které je zadaná funkce zpracována do stromové struktury.
|
Následuje analýza syntaktická, během které je zadaná funkce zpracována do stromové struktury.
|
||||||
Existuje mnoho způsobů, jak tuto analýzu provést, mezi základní patří např.~rekurzivní sestup nebo algoritmus shunting-yard.
|
Existuje mnoho způsobů, jak tuto analýzu provést, mezi základní patří např.~rekurzivní sestup nebo algoritmus shunting-yard.
|
||||||
V~této práci je použita metoda rekurzivního sestupu, která je relativně jednoduchá a~přehledná --- program je možné
|
V~této práci je použita metoda rekurzivního sestupu, která je relativně jednoduchá a~přehledná.
|
||||||
mechanicky vytvořit z~gramatiky zpracovávaného jazyka. Mezi její další výhody patří, že se oproti
|
|
||||||
algoritmu shunting-yard dokáže lépe vypořádat s~unárními operátory.
|
|
||||||
|
|
||||||
Analyzátor rekurzivním sestupem lze obecně vytvořit z~gramatiky popisující zpracovávaný jazyk
|
Analyzátor rekurzivním sestupem lze obecně vytvořit z~gramatiky popisující zpracovávaný jazyk
|
||||||
pomocí sady funkcí, které odpovídají jednotlivým pravidlům této gramatiky.
|
pomocí sady funkcí, které odpovídají jednotlivým pravidlům této gramatiky.
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
|
||||||
Pro zpracování matematických lze sestavit gramatiku
|
Pro zpracování matematických lze sestavit gramatiku
|
||||||
|
|
||||||
\begin{verbatim}
|
\begin{verbatim}
|
||||||
@ -171,9 +171,9 @@ kde \verb|{}| značí iteraci, \verb|[]| volitelnost a~\texttt{|} jednu z~možno
|
|||||||
Výrazy v~\verb|<>| jsou neterminály, zatímco ostatní symboly jsou terminály odpovídající
|
Výrazy v~\verb|<>| jsou neterminály, zatímco ostatní symboly jsou terminály odpovídající
|
||||||
tokenům z~lexikální analýzy.
|
tokenům z~lexikální analýzy.
|
||||||
|
|
||||||
Tato gramatika je typu LL(1), což znamená, že je možné se při zpracování
|
% Tato gramatika je typu LL(1), což znamená, že je možné se při zpracování
|
||||||
vždy rozhoudnout pouze na základě jednoho symbolu ze~vstupu, což zjednodušuje
|
% vždy rozhoudnout pouze na základě jednoho symbolu ze~vstupu, což zjednodušuje
|
||||||
implementaci analyzátoru.
|
% implementaci analyzátoru.
|
||||||
|
|
||||||
V~případě, že je zadaná funkce syntakticky správná, je během této analýzy možné
|
V~případě, že je zadaná funkce syntakticky správná, je během této analýzy možné
|
||||||
vytvořit stromovou strukturu, kde bude každý uzel
|
vytvořit stromovou strukturu, kde bude každý uzel
|
||||||
@ -210,6 +210,8 @@ každého modulu je (až na výjimky) nezávislá na implementaci ostatních mod
|
|||||||
|
|
||||||
Každý modul včetně jeho rozhraní je popsán v~následujících podsekcích.
|
Každý modul včetně jeho rozhraní je popsán v~následujících podsekcích.
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
|
||||||
\subsection{Vstupní bod programu --- \texttt{main.c}}
|
\subsection{Vstupní bod programu --- \texttt{main.c}}
|
||||||
|
|
||||||
Výkon programu začíná ve~funkci \texttt{main}, která má na starosti následující úkoly:
|
Výkon programu začíná ve~funkci \texttt{main}, která má na starosti následující úkoly:
|
||||||
@ -299,11 +301,29 @@ toho její číselnou hodnotu.
|
|||||||
|
|
||||||
\subsubsection{Vytvoření uzlu}
|
\subsubsection{Vytvoření uzlu}
|
||||||
Pro vytvoření uzlu je možné použít funkce, jejichž názvy začínají \texttt{node\_create\_}:
|
Pro vytvoření uzlu je možné použít funkce, jejichž názvy začínají \texttt{node\_create\_}:
|
||||||
\texttt{node\_create\_const} (konstanta), \texttt{node\_create\_x} (proměnná), \texttt{node\_create\_add} (sčítání),
|
|
||||||
\texttt{node\_create\_sub} (odečítání), \texttt{node\_create\_mult} (násobení), \texttt{node\_create\_div} (dělení),
|
|
||||||
\texttt{node\_create\_pow} (umocnění), \texttt{node\_create\_neg} (negace), \texttt{node\_create\_fn} (funkce).
|
|
||||||
|
|
||||||
Většina těchto funkcí přijímá jako argumenty ukazatele na uzly, které se mají stát operandy vytvářeného uzlu.
|
\begin{lstlisting}
|
||||||
|
struct expr_node *node_create_const(double val);
|
||||||
|
struct expr_node *node_create_x(void);
|
||||||
|
struct expr_node *node_create_add(
|
||||||
|
struct expr_node *left, struct expr_node *right);
|
||||||
|
struct expr_node *node_create_sub(
|
||||||
|
struct expr_node *left, struct expr_node *right);
|
||||||
|
struct expr_node *node_create_mult(
|
||||||
|
struct expr_node *left, struct expr_node *right);
|
||||||
|
struct expr_node *node_create_div(
|
||||||
|
struct expr_node *left, struct expr_node *right);
|
||||||
|
struct expr_node *node_create_pow(
|
||||||
|
struct expr_node *base, struct expr_node *power);
|
||||||
|
struct expr_node *node_create_neg(
|
||||||
|
struct expr_node *unop);
|
||||||
|
struct expr_node *node_create_fn(
|
||||||
|
size_t fn_idx, struct expr_node **args);
|
||||||
|
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
Tyto funkce vrací dynamicky alokovaný uzel, který je třeba po použití uvolnit (v~případě, že se uzel stane potomkem jiného uzlu, je
|
||||||
|
automaticky uvolněn s~tímto uzlem).
|
||||||
|
|
||||||
\subsubsection{Evaluace uzlu}
|
\subsubsection{Evaluace uzlu}
|
||||||
Uzel lze vyhodnotit v~daném bodě pomocí funkce
|
Uzel lze vyhodnotit v~daném bodě pomocí funkce
|
||||||
@ -312,8 +332,8 @@ Uzel lze vyhodnotit v~daném bodě pomocí funkce
|
|||||||
const struct expr_node *node,
|
const struct expr_node *node,
|
||||||
double x, double *y);
|
double x, double *y);
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
která v~případě úspěchu vrací \texttt{EVAL\_OK} a~do \texttt{y} uloží funkční hodnotu. Pokud
|
která v~případě úspěchu vrací \texttt{EVAL\_OK} a~do \texttt{y} uloží výslednou hodnotu. Pokud
|
||||||
funkce není v tomto bodě definována, je výsledkem \texttt{EVAL\_ERROR}.
|
funkce není v~tomto bodě definována, je výsledkem \texttt{EVAL\_ERROR}.
|
||||||
|
|
||||||
\subsubsection{Uvolnění uzlu}
|
\subsubsection{Uvolnění uzlu}
|
||||||
Uzel je možné uvolnit pomocí funkce
|
Uzel je možné uvolnit pomocí funkce
|
||||||
@ -409,6 +429,8 @@ inicializuje lexikální analyzátor \texttt{lex} pro zpracování řetězce \te
|
|||||||
|
|
||||||
Deinicializace není třeba, protože při inicializaci ani činnosti tohoto modulu není prováděna žádná alokace paměti.
|
Deinicializace není třeba, protože při inicializaci ani činnosti tohoto modulu není prováděna žádná alokace paměti.
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
|
||||||
\subsubsection{Získávání tokenů}
|
\subsubsection{Získávání tokenů}
|
||||||
Aktuální token je možné získat pomocí funkce
|
Aktuální token je možné získat pomocí funkce
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
@ -416,7 +438,7 @@ Aktuální token je možné získat pomocí funkce
|
|||||||
const struct lexer *lex);
|
const struct lexer *lex);
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
která na něj vrací ukazatel.
|
která na něj vrací ukazatel.
|
||||||
Pro získání dalšího tokenu je třeba zavolat funkci
|
Pro načtení dalšího tokenu je třeba zavolat funkci
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
void lex_next(struct lexer *lex);
|
void lex_next(struct lexer *lex);
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
@ -451,7 +473,7 @@ která ji vypíše do zásobníku \texttt{eb}.
|
|||||||
|
|
||||||
\subsection{Syntaktický analyzátor --- modul \texttt{parser}}
|
\subsection{Syntaktický analyzátor --- modul \texttt{parser}}
|
||||||
Modul \texttt{parser} využívá tokeny získané lexikálním analyzátorem k~syntaktické
|
Modul \texttt{parser} využívá tokeny získané lexikálním analyzátorem k~syntaktické
|
||||||
analýze a~vytváří stromu zadaného výrazu.
|
analýze a~vytváří strom zadaného výrazu.
|
||||||
|
|
||||||
\subsubsection{Postup analýzy}
|
\subsubsection{Postup analýzy}
|
||||||
Syntantický analyzátor je implementován pomocí rekurzivního sestupu.
|
Syntantický analyzátor je implementován pomocí rekurzivního sestupu.
|
||||||
@ -467,7 +489,7 @@ se skládá z~prefixu \texttt{parse\_} a~názvu neterminálu:
|
|||||||
Pokud je tedy výrazem například sečtení tří podvýrazů, jsou vytvořeny dva uzly sčítání: operandy prvního z nich jsou dva tyto podvýrazy a operandy druhého
|
Pokud je tedy výrazem například sečtení tří podvýrazů, jsou vytvořeny dva uzly sčítání: operandy prvního z nich jsou dva tyto podvýrazy a operandy druhého
|
||||||
jsou první uzel a~třetí podvýraz. Poslední uzel je návratovou hodnotou.
|
jsou první uzel a~třetí podvýraz. Poslední uzel je návratovou hodnotou.
|
||||||
\item Funkce \texttt{parse\_term} postupuje obdobně jako \texttt{parse\_expression}, ale pro násobení a~dělení. Volá \texttt{parse\_unary}.
|
\item Funkce \texttt{parse\_term} postupuje obdobně jako \texttt{parse\_expression}, ale pro násobení a~dělení. Volá \texttt{parse\_unary}.
|
||||||
\item \texttt{parse\_unary} zjistí, zda je dalším tokenem unární operátor. V~případě, že se jedná o~mínus vytvoří uzel pro negaci,
|
\item \texttt{parse\_unary} zjistí, zda je dalším tokenem unární operátor. V~případě, že se jedná o~mínus, vytvoří uzel pro negaci,
|
||||||
jehož operandem se stane návratová hodnota \texttt{parse\_power}, jinak je tato funkce zavolána přímo.
|
jehož operandem se stane návratová hodnota \texttt{parse\_power}, jinak je tato funkce zavolána přímo.
|
||||||
\item \texttt{parse\_power} nejprve zavolá \texttt{parse\_factor} a~poté zjistí, zda následuje operátor umocnění. V~případě, že ano, vytvoří uzel pro umocnění,
|
\item \texttt{parse\_power} nejprve zavolá \texttt{parse\_factor} a~poté zjistí, zda následuje operátor umocnění. V~případě, že ano, vytvoří uzel pro umocnění,
|
||||||
jehož levým operandem je návratová hodnota \texttt{parse\_factor} a~pro zpracování pravého operandu zavolá znovu \texttt{parse\_unary}, jelikož
|
jehož levým operandem je návratová hodnota \texttt{parse\_factor} a~pro zpracování pravého operandu zavolá znovu \texttt{parse\_unary}, jelikož
|
||||||
@ -558,7 +580,7 @@ Tato funkce vypíše do souboru \texttt{file} příkazy jazyka PostScript:
|
|||||||
\subsection{Použití v~\texttt{KIV/UPG}}\label{sec:upg}
|
\subsection{Použití v~\texttt{KIV/UPG}}\label{sec:upg}
|
||||||
Moduly umožňující vyhodnocení funkcí byly využity i v~rámci semestrální práce z předmětu \texttt{KIV/UPG},
|
Moduly umožňující vyhodnocení funkcí byly využity i v~rámci semestrální práce z předmětu \texttt{KIV/UPG},
|
||||||
kde sloužily k~animaci elektrických nábojů v~čase.
|
kde sloužily k~animaci elektrických nábojů v~čase.
|
||||||
Z tohoto důvodu se v~práci nachází některé nadbytečné funkce:
|
Z tohoto důvodu se v~práci nachází některé \uv{nadbytečné} funkce:
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item Vypisování chyb do zásobníku \texttt{error\_buffer} namísto standardního výstupu, jelikož
|
\item Vypisování chyb do zásobníku \texttt{error\_buffer} namísto standardního výstupu, jelikož
|
||||||
@ -580,13 +602,13 @@ Tímto vznikne spustitelný soubor \texttt{graph.exe}.
|
|||||||
|
|
||||||
\subsection{Použití}
|
\subsection{Použití}
|
||||||
Program se spouští příkazem \texttt{graph.exe} s~následujícími argumenty:
|
Program se spouští příkazem \texttt{graph.exe} s~následujícími argumenty:
|
||||||
\begin{itemize}
|
\begin{enumerate}
|
||||||
\item Předpis funkce, která má být vykreslena.
|
\item Předpis funkce, která má být vykreslena.
|
||||||
\item Název souboru, do kterého se má graf uložit.
|
\item Název souboru, do kterého se má graf uložit.
|
||||||
\item Volitelně: Rozsah grafu ve tvaru $x_d\texttt{:}x_h\texttt{:}y_d\texttt{:}y_h$,
|
\item Volitelně: Rozsah grafu ve tvaru $x_d\texttt{:}x_h\texttt{:}y_d\texttt{:}y_h$,
|
||||||
kde $x_d$ a~$x_h$ jsou dolní a~horní mez osy $x$ a~$y_d$ a~$y_h$ jsou dolní a~horní mez osy $y$.
|
kde $x_d$ a~$x_h$ jsou dolní a~horní meze osy $x$ a~$y_d$ a~$y_h$ jsou dolní a~horní meze osy $y$.
|
||||||
V případě, že tento argument není uveden, použije se výchozí rozsah $x_d = y_d = -10$ a~$x_h = y_h = 10$.
|
V případě, že tento argument není uveden, použije se výchozí rozsah $x_d = y_d = -10$ a~$x_h = y_h = 10$.
|
||||||
\end{itemize}
|
\end{enumerate}
|
||||||
|
|
||||||
Návratová hodnota programu odopovídá některému z chybových kódů uvedených v~tabulce~\ref{tab:errors}.
|
Návratová hodnota programu odopovídá některému z chybových kódů uvedených v~tabulce~\ref{tab:errors}.
|
||||||
Při úspěšném vykreslení vznikne soubor se zadaným názvem, který bude obsahovat graf funkce ve formátu PostScript.
|
Při úspěšném vykreslení vznikne soubor se zadaným názvem, který bude obsahovat graf funkce ve formátu PostScript.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user