%% This is a LaTeX document. Hey, Emacs, -*- latex -*- , get it? \documentclass[12pt,a4paper]{article} \usepackage[a4paper,margin=2cm]{geometry} \usepackage[francais]{babel} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} %\usepackage{ucs} \usepackage{times} % A tribute to the worthy AMS: \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \usepackage{amsthm} % \usepackage{mathrsfs} \usepackage{wasysym} \usepackage{url} % \usepackage{graphics} \usepackage[usenames,dvipsnames]{xcolor} %\usepackage{tikz} %\usetikzlibrary{arrows,automata,positioning} \usepackage[hyperindex=false]{hyperref} % \theoremstyle{definition} \newtheorem{comcnt}{Tout} \newcommand\thingy{% \refstepcounter{comcnt}\smallbreak\noindent\textbf{\thecomcnt.} } \newcommand\exercice{% \refstepcounter{comcnt}\bigbreak\noindent\textbf{Exercice~\thecomcnt.}} \renewcommand{\qedsymbol}{\smiley} % \newcommand{\liff}{\mathrel{\Longleftrightarrow}\relax} % \DeclareUnicodeCharacter{00A0}{~} \DeclareUnicodeCharacter{03B5}{$\varepsilon$} % \DeclareMathSymbol{\tiret}{\mathord}{operators}{"7C} \DeclareMathSymbol{\traitdunion}{\mathord}{operators}{"2D} \DeclareSymbolFont{roman}{OT1}{cmr}{m}{n} \DeclareMathSymbol{\ldquote}{\mathopen}{roman}{"5C} \DeclareMathSymbol{\rdquote}{\mathopen}{roman}{"22} \DeclareMathSymbol{\endash}{\mathbin}{roman}{"7B} % % \DeclareFontFamily{U}{manual}{} \DeclareFontShape{U}{manual}{m}{n}{ <-> manfnt }{} \newcommand{\manfntsymbol}[1]{% {\fontencoding{U}\fontfamily{manual}\selectfont\symbol{#1}}} \newcommand{\dbend}{\manfntsymbol{127}}% Z-shaped \newcommand{\danger}{\noindent\hangindent\parindent\hangafter=-2% \hbox to0pt{\hskip-\hangindent\dbend\hfill}} % \newcommand{\spaceout}{\hskip1emplus2emminus.5em} \newif\ifcorrige \corrigetrue \newenvironment{corrige}% {\ifcorrige\relax\else\setbox0=\vbox\bgroup\fi% \smallbreak\noindent{\underbar{\textit{Corrigé.}}\quad}} {{\hbox{}\nobreak\hfill\checkmark}% \ifcorrige\relax\else\egroup\fi\par} % % % \begin{document} \ifcorrige \title{TP \texttt{JavaCC} — Corrigé} \else \title{TP \texttt{JavaCC}} \fi \author{David A. Madore} \maketitle \centerline{\textbf{INF105}} {\footnotesize \immediate\write18{sh ./vc > vcline.tex} \begin{center} Git: \input{vcline.tex} \end{center} \immediate\write18{echo ' (stale)' >> vcline.tex} \par} \pretolerance=8000 \tolerance=50000 % % % JavaCC est un programme permettant de créer automatiquement un analyseur syntaxique (=parseur, \textit{parser} en anglais) pour un langage décrit sous forme de grammaire hors contexte. Le principe est le suivant : on écrit un fichier \texttt{.jj} qui contient un mélange de description du langage (sous forme de productions dans une syntaxe évoquant les expressions régulières) et de code Java à exécuter lorsque ces différentes productions sont rencontrées. Le programme \texttt{javacc} convertit ce fichier \texttt{.jj} en un fichier \texttt{.java} qui contient le code de l'analyseur (on peut ensuite compiler ce fichier avec \texttt{javac} comme n'importe quel code Java). La documentation de JavaCC est accessible en ligne sur \url{http://javacc.java.net/doc/docindex.html} mais il est probablement plus simple d'apprendre par imitation. Sur \url{http://perso.enst.fr/~madore/inf105/Calculatrice.jj} (à télécharger, ou à recopier depuis \texttt{\char`\~madore/Calculatrice.jj} dans les salles de TP) on trouvera le code d'une calculatrice très simple écrit en JavaCC. On peut compiler et lancer ce code (après l'avoir recopié) en lançant successivement : \noindent \indent\texttt{\char`\~madore/bin/javacc Calculatrice.jj}\\ \indent\texttt{javac Calculatrice.java}\\ \indent\texttt{java Calculatrice} On peut alors taper des expressions arithmétiques telles que \texttt{3+4} ou \texttt{2*6} (terminer chaque calcul en tapant Enter, et terminer le programme en tapant Control-D). Vérifier que cela fonctionne correctement. Initialement, la grammaire de la calculatrice dans $\texttt{Calculatrice.jj}$ est donnée par : \[ \begin{array}{rcl} \mathit{expression} & \rightarrow & \mathit{element} \; ( \ldquote\hbox{\texttt{+}}\rdquote \mathit{element} \,|\, \ldquote\hbox{\texttt{-}}\rdquote \mathit{element} \,|\, \ldquote\hbox{\texttt{*}}\rdquote \mathit{element} \,|\, \ldquote\hbox{\texttt{/}}\rdquote \mathit{element} ){*}\\ \mathit{element} & \rightarrow & \mathit{Number}\\ \mathit{Number} & \rightarrow & [\ldquote\mathtt{0}\rdquote\endash\ldquote\mathtt{9}\rdquote]{+} \; (\ldquote\mathtt{.}\rdquote \; [\ldquote\mathtt{0}\rdquote\endash\ldquote\mathtt{9}\rdquote]*)? \end{array} \] (1) Que se passe-t-il quand on demande de calculer \texttt{3+4*5} à la calculatrice ? Pourquoi ? Modifier la grammaire pour avoir une priorité correcte des opérations (\texttt{*} et \texttt{/} doivent être prioritaires sur \texttt{+} et \texttt{-}, et en particulier \texttt{3+4*5} doit renvoyer $23$). Pour cela, on peut par exemple introduire un nouveau nonterminal $\mathit{terme}$ représentant un terme d'une somme ou différence, et qui est lui-même formé de produits ou quotients. Tester la calculatrice ainsi modifiée. (2) La calculatrice ne gère pas les parenthèses : ajouter cette fonctionnalité et tester. Par exemple, \texttt{(3+5)/(2*2)} doit revoyer $2$. Pour cela, on pourra ajouter une nouvelle production pour $\mathit{element}$ correspondant à une $\mathit{expression}$ entourée de parenthèses. (3) La calculatrice ne gère pas le $-$ unaire (pour indiquer l'opposé d'un nombre) : ajouter cette fonctionnalité et tester. Par exemple, \texttt{-3*-6} doit renvoyer $18$, et \texttt{-1-2} doit renvoyer $-3$. Vérifier que le moins unaire marche aussi devant les parenthèses (\texttt{-(2+3)} doit renvoyer $-5$). On pourra aussi ajouter le $+$ unaire (qui ne change pas le nombre). Pour cela, on pourra introduire un nouveau nonterminal $\mathit{unaire}$ représentant un élément éventuellement précédé d'un $-$ (ou d'un $+$) unaire. (4) La calculatrice ne gère pas l'opération puissance : introduire celle-ci sous la notation du caractère ``\texttt{\char"5E}'' (accent circonflexe) : attention, on veut que l'opération \texttt{\char"5E} soit prioritaire sur toutes les autres (addition, soustraction, multiplication, division, et opérations unaires), et on veut qu'elle soit associative \emph{à droite}, c'est-à-dire par exemple que \texttt{2\char"5E\relax 3\char"5E\relax 2} doit calculer $2^{3^2} = 2^9 = 512$. La méthode Java permettant de calculer $a^b$ s'écrit \texttt{Math.pow(a,b)}. Tester notamment les calculs suivants : $\hbox{\texttt{2\char"5E\relax 3\char"5E\relax 2}} \rightsquigarrow 512$ ; $\hbox{\texttt{-1\char"5E\relax 2}} \rightsquigarrow -1$ ; $\hbox{\texttt{(-1)\char"5E\relax 2}} \rightsquigarrow 1$ ; $\hbox{\texttt{2\char"5E\relax -1}} \rightsquigarrow 0.5$ ; $\hbox{\texttt{2*3\char"5E\relax 2*3}} \rightsquigarrow 54$. % % % \end{document}