ΠΟΛΥΤΕΧΝΕΙΟ ΚΡΗΤΗΣ Τµήµα Ηλεκτρονικών Μηχανικών και Μηχανικών Υπολογιστών ΠΛΗ 401 ΘΕΩΡΙΑ ΥΠΟΛΟΓΙΣΜΟΥ Εργασία Προγραµµατισµού ιδάσκων Μιχαήλ Γ. Λαγουδάκης Επιµέλεια εργασίας Σπύρος Αργυρόπουλος Χειµερινό Εξάµηνο 2007-2008 σελ. 1/15
1. Εισαγωγή Η εργασία προγραµµατισµού του µαθήµατος «ΠΛΗ 401 - Θεωρία Υπολογισµού» έχει ως στόχο τη βαθύτερη κατανόηση της χρήσης και εφαρµογής θεωρητικών εργαλείων, όπως οι κανονικές εκφράσεις και οι γραµµατικές χωρίς συµφραζόµενα, στο πρόβληµα της µεταγλώττισης (compilation) γλωσσών προγραµµατισµού. Συγκεκριµένα, η εργασία αφορά στη σχεδίαση και υλοποίηση των αρχικών σταδίων ενός µεταγλωττιστή (compiler) για τη φανταστική γλώσσα FhP, η οποία περιγράφεται αναλυτικά παρακάτω. Για την υλοποίηση της εργασίας θα χρησιµοποιήσετε τη γλώσσα C και τα εργαλεία flex και bison τα οποία είναι διαθέσιµα ως ελεύθερο λογισµικό. Η εργασία θα περιλαµβάνει δύο τµήµατα: 1. Υλοποίηση λεκτικού αναλυτή για την γλώσσα FhP µε χρήση flex 2. Υλοποίηση συντακτικού αναλυτή για τη γλώσσα FhP µε χρήση bison Η προθεσµία παράδοσης της εργασίας είναι η Τρίτη 18 εκεµβρίου 2007, 11:59µµ. Παρατηρήσεις 1. Η εργασία θα εκπονηθεί από οµάδες φοιτητών το πολύ δύο ατόµων. Τα ονόµατα των οµάδων και οι αντίστοιχοι αριθµοί µητρώου πρέπει να δηλωθούν µέχρι το τέλος Νοεµβρίου µε email σας στο theory@intelligence.tuc.gr. 2. Για την εκπόνηση της εργασίας µπορούν να χρησιµοποιηθούν υπολογιστές του Εργαστηρίου Συστηµάτων Λογισµικού (softnet) ή εναλλακτικά υπολογιστές του Μηχανογραφικού Κέντρου και προσωπικοί υπολογιστές. Για λογαριασµούς πρόσβασης στο softnet απευθυνθείτε στον κ. Αργυρόπουλο. Μπορείτε επίσης να χρησιµοποιήσετε τους δικούς σας υπολογιστές στο σπίτι είτε σε περιβάλλον Linux είτε σε Windows (µέσω CygWin). 3. Η παράδοση της εργασίας θα γίνει ηλεκτρονικά µέσα από την ιστοσελίδα του µαθήµατος. Το παραδοτέο αρχείο (.zip,.tar,.rar) θα πρέπει να φέρει τα επώνυµα της οµάδας στο filename (π.χ. Argyropoulos_Lagoudakis.zip). 4. Εκτός από τον κώδικα, το παραδοτέο σας θα πρέπει να περιλαµβάνει και µια συνοπτική αναφορά (δακτυλογραφηµένη, PDF µορφή) που θα εξηγεί τις τεχνικές που χρησιµοποιήθηκαν και τις ιδιαιτερότητες της εργασίας σας. 5. Η αξιολόγηση της εργασίας θα γίνει ατοµικά και θα περιλαµβάνει εξέταση καλής λειτουργίας του παραδοτέου προγράµµατος καθώς και προφορική εξέταση στο χώρο του Εργαστηρίου Συστηµάτων Λογισµικού (softnet) στις 20 και 21 εκεµβρίου σε ώρες που θα ανακοινωθούν. Είναι αποκλειστικά δική σας ευθύνη να εξασφαλίσετε τη σωστή λειτουργία του παραδοτέου προγράµµατος στους υπολογιστές του εργαστηρίου. 6. Οι ηµεροµηνίες παράδοσης είναι αυστηρές και οι εκπρόθεσµες εργασίες δε θα γίνονται δεκτές. Μη παράδοση της εργασίας οδηγεί σε απώλεια του αντιστοίχου ποσοστού από τον τελικό βαθµό του µαθήµατος. σελ. 2/15
2. Η γλώσσα προγραµµατισµού FhP Η γλώσσα FhP βασίζεται στη γλώσσα PHP. Λόγω οµοιοτήτων της FhP µε την PHP, η περιγραφή τονίζει κυρίως σηµεία όπου οι δύο γλώσσες διαφέρουν. Σε περιπτώσεις πιθανής ασάφειας µπορείτε να ανατρέξετε στην περιγραφή της PHP. Κάθε πρόγραµµα σε γλώσσα FhP είναι ένα σύνολο από λεκτικές µονάδες, οι οποίες είναι διατεταγµένες µε βάση κάποιους συντακτικούς κανόνες, όπως περιγράφονται παρακάτω. 2.1 Λεκτικές Μονάδες Οι λεκτικές µονάδες της γλώσσας FhP χωρίζονται στις παρακάτω κατηγορίες: Τις λέξεις κλειδιά, οι οποίες είναι οι παρακάτω: if else while for do switch case continue default return exit break integer int float real double boolean bool string echo print function true false and or xor Ειδικά για τις λέξεις κλειδιά, τα πεζά γράµµατα θεωρούνται ίδια µε τα αντίστοιχα κεφαλαία, εποµένως για παράδειγµα η λέξη κλειδί else θα πρέπει να µπορεί να αναγνωριστεί και σαν Else ή ELSe ή ElsE κ.τ.λ. Τα αναγνωριστικά (ονόµατα µεταβλητών και συναρτήσεων), τα οποία αποτελούνται από ένα πεζό ή κεφαλαίο γράµµα του λατινικού αλφαβήτου, πιθανώς ακολουθούµενο από µια σειρά πεζών ή κεφαλαίων γραµµάτων, δεκαδικών ψηφίων ή χαρακτήρων υπογράµµισης (underscore). Tα αναγνωριστικά δεν πρέπει να συµπίπτουν µε τις λέξεις κλειδιά που αναφέρθηκαν παραπάνω. Παραδείγµατα: x y1 angle my_value Distance_02 Οι ακέραιες σταθερές χωρίς πρόσηµο, που αποτελούνται από ένα ή περισσότερα δεκαδικά ψηφία χωρίς περιττά µηδενικά στην αρχή. Παραδείγµατα: 0 42 1284200 3 100001 Οι πραγµατικές σταθερές χωρίς πρόσηµο, που αποτελούνται από ένα ακέραιο µέρος, ένα κλασµατικό µέρος και ένα προαιρετικό εκθετικό µέρος. Το ακέραιο µέρος αποτελείται από ένα ή περισσότερα δεκαδικά ψηφία χωρίς περιττά µηδενικά. Το κλασµατικό µέρος αποτελείται από το χαρακτήρα της υποδιαστολής (.) ακολουθούµενο από ένα ή περισσότερα δεκαδικά ψηφία. Τέλος, το εκθετικό µέρος αποτελείται από το πεζό ή κεφαλαίο γράµµα E, ένα προαιρετικό πρόσηµο + ή - και ένα ή περισσότερα δεκαδικά ψηφία και πάλι χωρίς περιττά µηδενικά. Παραδείγµατα: 42.0 4.2e1 0.420E+2 42000.0e-3 σελ. 3/15
Οι λογικές σταθερές (boolean), που αποτελούνται από τις λέξεις-τιµές true ή false. Οι σταθερές συµβολοσειρές (strings), που αποτελούνται είτε από µια ακολουθία κοινών χαρακτήρων µέσα απλά εισαγωγικά, είτε από µια ακολουθία κοινών χαρακτήρων ή ακολουθιών διαφυγής µέσα σε διπλά εισαγωγικά. Οι σταθερές συµβολοσειρές δεν µπορούν να εκτείνονται σε περισσότερες από µια γραµµές του προγράµµατος. Οι ακολουθίες διαφυγής ξεκινούν µε το χαρακτήρα \ (backslash) και περιγράφονται στον Πίνακα 1. Παραδείγµατα: abc "Route 66" "Hello world!\n" "Item:\t\"Laser Printer\"\nPrice:\t142\$\n" Χαρακτήρας Περιγραφή \n χαρακτήρας αλλαγής γραµµής (line feed) \t χαρακτήρας στηλοθέτησης (TAB) \\ χαρακτήρας \ (backslash) \' χαρακτήρας ' (απλό εισαγωγικό) \" χαρακτήρας " (διπλό εισαγωγικό) \$ χαρακτήρας $ (δολάριο) Πίνακας 1. Ακολουθίες διαφυγής (escape sequences) Τους τελεστές, οι οποίοι είναι οι παρακάτω: = > <!= >= <= + - * / % ++ -- += -= *= /= %= &&! ==. and or xor Τους διαχωριστές, οι οποίοι είναι οι παρακάτω: { ; ( ) :, [ ]? Τις γραµµές εξωτερικού κώδικα, οι οποίες είναι ξεχωριστές γραµµές κώδικα στο αρχείο του προγράµµατος που δεν βρίσκονται ανάµεσα στα tags έναρξης και τερµατισµού της FhP (, ). Εκτός από τις λεκτικές µονάδες που προαναφέρθηκαν, ένα πρόγραµµα FhP µπορεί επίσης να περιέχει τα παρακάτω, τα οποία αγνοούνται (δηλαδή τα αναγνωρίζετε αλλά δεν κάνετε τίποτα για αυτά): Κενούς χαρακτήρες, δηλαδή ακολουθίες αποτελούµενες από κενά διαστήµατα (space), χαρακτήρες στηλοθέτησης (tab), χαρακτήρες αλλαγής γραµµής (line feed) ή χαρακτήρες επιστροφής στην αρχή της γραµµής (carriage return). Σχόλια, τα οποία αρχίζουν µε την ακολουθία χαρακτήρων /* και τερµατίζονται µε την πρώτη µετέπειτα εµφάνιση της ακολουθίας χαρακτήρων */. Κατά συνέπεια, τα σχόλια δεν επιτρέπεται να είναι φωλιασµένα. Στο εσωτερικό τους επιτρέπεται η εµφάνιση οποιουδήποτε χαρακτήρα. σελ. 4/15
Σχόλια γραµµής, το οποία αρχίζουν µε την ακολουθία χαρακτήρων // και εκτείνονται ως το τέλος της τρέχουσας γραµµής. 2.2 Συντακτική οµή Ένα πρόγραµµα FhP µπορεί να βρίσκεται µέσα σε ένα αρχείο.fhp και να αποτελείται από τα παρακάτω: ηλώσεις συναρτήσεων Εντολές εν υπάρχει κανένας περιορισµός στην σειρά µε την οποία εµφανίζονται αυτά. Για παράδειγµα, ένα πρόγραµµα θα µπορεί να έχει στην αρχή µια σειρά εντολών, στη συνέχεια δηλώσεις συναρτήσεων, µετά ξανά εντολές, ξανά συναρτήσεις, κ.ο.κ. Μέσα στο αρχείο.fhp µπορούν να υπάρχουν µηδέν ή περισσότερα µη συνεχόµενα τµήµατα προγράµµατος σε FhP. Κάθε τµήµα βρίσκεται ανάµεσα στα tags και (tags έναρξης και τερµατισµού της FhP). Όλα τα υπόλοιπα περιεχόµενα του αρχείου απλά θα προωθούνται ως γραµµές εξωτερικού κώδικα χωρίς να ελέγχονται για σύνταξη. Όλα τα τµήµατα προγράµµατος σε FhP αποτελούν µια ενότητα η οποία ακολουθεί συγκεκριµένους συντακτικούς κανόνες. εν επιτρέπεται η ύπαρξη φωλιασµένων tags έναρξης και τερµατισµού. Παράδειγµα: if ($true_or_false) { <p>the value of $true_or_false is true.</p> else { <p>the value of $true_or_false is false.</p> Παρακάτω περιγράφονται αναλυτικά όλα τα δοµικά συστατικά που µπορεί να περιλαµβάνονται σε ένα πρόγραµµα της γλώσσας FhP. 2.2.1 Τύποι δεδοµένων Η FhP υποστηρίζει τέσσερις βασικούς τύπους δεδοµένων: integer: ακέραιοι αριθµοί boolean: λογικές τιµές string: χαρακτήρες float: πραγµατικοί αριθµοί 2.2.2 Μεταβλητές εν υπάρχουν δηλώσεις µεταβλητών. Η αναγνώρισή τους γίνεται αυτόµατα τη στιγµή που θα χρησιµοποιηθούν για πρώτη φορά. Οι µεταβλητές της γλώσσας FhP είναι της µορφής: σελ. 5/15
$<αναγνωριστικό_όνοµα_µεταβλητής> Ο τύπος κάθε µεταβλητής καθορίζεται από τον τύπο των δεδοµένων που θα της καταχωρήσουµε αλλά το θέµα αυτό δε θα µας απασχολήσει σε αυτή την εργασία. Το όνοµα της µεταβλητής είναι case-sensitive. Παραδείγµατα µεταβλητών είναι: $i = 0; /* µεταβλητή τύπου integer */ $y = 4.2; /* µεταβλητή τύπου float */ $c = "This is a string \n"; /* µεταβλητή τύπου string */ $f = false; /* µεταβλητή τύπου boolean */ Εκτός από τους βασικούς τύπους, η FhP υποστηρίζει επίσης µονοδιάστατους ή πολυδιάστατους πίνακες. εν υπάρχει δήλωση πινάκων. Τα στοιχεία των πινάκων της γλώσσας είναι της µορφής: $<αναγνωριστικό_όνοµα>[<δείκτης1>][<δείκτης2>]...[<δείκτηςν>] Οι δείκτες µπορούν να είναι: - Θετικός ακέραιος - Μεταβλητή - Έκφραση Παραδείγµατα στοιχείων πινάκων είναι: $matrix[1][5] $y[$k][($k+2)*$n] 2.2.3 Συναρτήσεις Κάθε συνάρτηση είναι µια δοµική µονάδα που αποτελείται από την επικεφαλίδα ακολουθούµενη από το σώµα της. Στην επικεφαλίδα αναφέρεται η λέξη κλειδί function, το όνοµα της συνάρτησης και οι τυπικές της παράµετροι µέσα σε παρενθέσεις. Οι παρενθέσεις είναι υποχρεωτικές ακόµα και αν µία συνάρτηση δεν έχει τυπικές παραµέτρους. Το σώµα µιας συνάρτησης περικλείεται µέσα σε άγκιστρα {. Το σώµα µιας συνάρτησης µπορεί να αποτελείται από δηλώσεις συναρτήσεων και εντολές χωρίς περιορισµό στη σειρά µε την οποία εµφανίζονται. Αν η συνάρτηση επιστρέφει τιµή τότε το σώµα της θα πρέπει να περιέχει τουλάχιστον την εντολή επιστροφής return. Οι εντολές περιγράφονται στην ενότητα 2.2.5. Ακολουθεί παράδειγµα συνάρτησης µε σώµα: function foo ($arg_1, $arg_2,..., $arg_n) { echo "Example function.\n"; return $retval; 2.2.4 Εκφράσεις και Τελεστές Οι εκφράσεις (expressions) είναι το πιο σηµαντικό κοµµάτι µιας γλώσσας προγραµµατισµού. Οι πιο βασικές µορφές εκφράσεων είναι οι σταθερές και οι µεταβλητές. Πιο σύνθετες µορφές εκφράσεων είναι αυτές που προκύπτουν µε τη χρήση των τελεστών. Οι τελεστές της FhP διακρίνονται σε τελεστές µε ένα όρισµα και τελεστές µε δύο ορίσµατα. Από τους πρώτους, ορισµένοι γράφονται πριν το όρισµα (prefix) και σελ. 6/15
ορισµένοι µετά (postfix), ενώ οι δεύτεροι γράφονται πάντα µεταξύ των ορισµάτων (infix). Η αποτίµηση των ορισµάτων των τελεστών µε δυο ορίσµατα γίνεται από αριστερά προς τα δεξιά. Στον Πίνακα 2 ορίζεται η προτεραιότητα και η προσεταιριστικότητα των τελεστών της FhP. Προηγούνται οι τελεστές που εµφανίζονται πιο ψηλά στον πίνακα. Όσοι τελεστές βρίσκονται στο ίδιο κελί έχουν την ίδια προτεραιότητα. Τελεστές Περιγραφή Ορίσµατα Θέση Προσεταιριστικότητα! Λογική άρνηση 1 prefix ++ -- Αύξηση, µείωση 1 prefix, postfix + - Πρόσηµα 1 prefix (int) (float) (string) (boolean) Τύποι cast 1 prefix * / % Πολλαπλασιαστικοί τελεστές 2 infix, αριστερή + -. Προσθετικοί τελεστές 2 infix, αριστερή == > < <= >=!= Σχεσιακοί τελεστές 2 infix, χωρίς σύνδεση &&, and Λογική σύζευξη 2 infix, αριστερή, or Λογική διάζευξη 2 infix, αριστερή xor Λογική αποκλειστική διάζευξη 2 infix, αριστερή = += -= /= %= *= Τελεστές ανάθεσης 2 infix, δεξιά Πίνακας 2. Προτεραιότητα και προσεταιριστικότητα των τελεστών της FhP Παραδείγµατα σωστών εκφράσεων: -$a // αντίθετος της µεταβλητής $a $a + $b * $b / $a // αριθµητική έκφραση ($b = 4) + 5 // τελεστές ανάθεσης µε αριθµητικούς ($a < $b) && ($c!= $d) // τελεστές λογικοί µε σχεσιακούς $a + ($c!= $d) // τελεστές αριθµητικοί µε σχεσιακούς $b = $a. "World!" // συνένωση - παράθεση συµβολοσειρών $a + $b[1][$k][($k+1)*2] // αριθµητική έκφραση µε πίνακα σελ. 7/15
2.2.5 Εντολές Οι εντολές που υποστηρίζει η γλώσσα FhP είναι οι ακόλουθες (κάθε απλή εντολή της γλώσσας FhP τερµατίζει µε το διαχωριστικό ;): Η κενή εντολή (;) που δεν κάνει καµία ενέργεια. Η εντολή ανάθεσης $l = e;, όπου $l είναι µία µεταβλητή και e µια έκφραση όπως ορίζεται και στην PHP. Υποστηρίζονται δύο είδη εντολών ανάθεσης: - Απλή εντολή ανάθεσης, π.χ. $i = $k + 2; - Εντολή ανάθεσης µε χρήση casting, π.χ. $i = (integer) $k; Τα επιτρεπόµενα casts είναι τα: (int), (integer) - cast σε integer (bool), (boolean) - cast σε boolean (float), (double), (real) - cast σε float (string) - cast σε string Η σύνθετη εντολή, που αποτελείται από µια σειρά έγκυρων εντολών ανάµεσα σε άγκιστρα {. Η εντολή ελέγχου if ( e ) s 1 else s 2 όπου e είναι µια έκφραση και τα s 1, s 2 είναι έγκυρες (απλές ή σύνθετες) εντολές. Το τµήµα else είναι προαιρετικό. H εντολή ελέγχου switch ( e ) { ; case e 1 : s 1 case e n : s n default : s d όπου e, e 1,, e n είναι εκφράσεις, s 1,, s n, s d είναι σειρές από έγκυρες απλές εντολές χωρίς άγκιστρα { και n 0. Η εντολή βρόχου while ( e ) s όπου e είναι µια έκφραση και το s είναι έγκυρη εντολή. Η εντολή βρόχου for ( e1; e2; e3 ) s. Οι εκφράσεις e1,e2,e3 είναι προαιρετικές και τo s πρέπει να είναι έγκυρη εντολή. H εντολή διακοπής break;, που προκαλεί την άµεση έξοδο από τον πιο εσωτερικό βρόχο, όπως ακριβώς και στη PHP. H εντολή διακοπής exit e;, που προκαλεί την άµεση έξοδο από το πρόγραµµα και επιστρέφει στο standard output την τιµή της έκφρασης e ως µήνυµα για τον λόγο εξόδου. Είναι σωστή η χρήση της εντολής διακοπής exit; χωρίς την έκφραση e στην περίπτωση που δεν επιστρέφεται κάποιο µήνυµα εξόδου. σελ. 8/15
H εντολή συνέχειας continue; προκαλεί την συνέχεια του βρόχου µέσα στον οποίο βρίσκεται, όπως ακριβώς και στη PHP. Η εντολή επιστροφής return e; τερµατίζει την εκτέλεση της τρέχουσας συνάρτησης και επιστρέφει την τιµή της έκφρασης e ως αποτέλεσµα της συνάρτησης. Είναι σωστή η χρήση της εντολής επιστροφής return; χωρίς την έκφραση e στην περίπτωση που η συνάρτηση δεν επιστρέφει κάποια τιµή. Η εντολή κλήσης µιας συνάρτησης f(e 1,..,e n );, όπου f είναι το όνοµα της συνάρτησης και e 1,..,e n είναι εκφράσεις που αντιστοιχούν στα δηλωθέντα ορίσµατα. 2.2.6 Προκαθορισµένες συναρτήσεις Η FhP υποστηρίζει ένα σύνολο προκαθορισµένων συναρτήσεων, οι οποίες βρίσκονται στη διάθεση του προγραµµατιστή. Παρακάτω, δίνονται οι επικεφαλίδες τους: print( e ); ή print e; echo( e ); ή echo e; ; Παραδείγµατα print("hello World"); echo "Hello World"; print $foo; echo($foo); print($f1, $f2); // Λάθος συντακτικό!! 2.2.7 Γραµµές εξωτερικού κώδικα Η FhP υποστηρίζει την παρεµβολή γραµµών εξωτερικού κώδικα, οι οποίες αναγνωρίζονται σαν ξεχωριστές λεκτικές µονάδες και προωθούνται στο standard output χωρίς να ελέγχεται η εσωτερική της δοµή. Οι γραµµές εξωτερικού κώδικα µπορούν να πάρουν τη θέση οποιαδήποτε απλής εντολής χωρίς όµως να χρειάζεται ο τερµατισµός τους µε το διαχωριστικό ;. (Στην παρούσα εργασία δεν µας ενδιαφέρει ο τρόπος που εκτελούνται οι γραµµές εξωτερικού κώδικα). 3. Αναλυτική περιγραφή εργασίας 3.1 Τα εργαλεία Για να ολοκληρώσετε επιτυχώς την εργασία του µαθήµατος χρειάζεται να γνωρίζετε καλά προγραµµατισµό σε C, flex και bison. Τα εργαλεία flex και bison έχουν αναπτυχθεί στα πλαίσια του προγράµµατος GNU και µπορείτε να τα βρείτε σε όλους τους κόµβους του διαδικτύου που διαθέτουν λογισµικό GNU (π.χ. www.gnu.org). Περισσότερες πληροφορίες και σύνδεσµοι σχετικοί µε τα δύο αυτά εργαλεία υπάρχουν στην ιστοσελίδα του µαθήµατος (www.intelligence.tuc.gr/~theory). σελ. 9/15
Στο λειτουργικό Linux (οποιαδήποτε διανοµή) τα εργαλεία αυτά είναι ενσωµατωµένα, οπότε δεν χρειάζεται να κατεβάσετε ή να εγκαταστήσετε κάτι! Τα εγχειρίδια των εργαλείων µπορείτε να τα κατεβάσετε από τη σελίδα του µαθήµατος. Οι οδηγίες χρήσης που δίνονται παρακάτω έχουν δοκιµαστεί στη διανοµή Linux του εργαστηρίου, πιθανόν όµως να υπάρχουν µικροδιαφορές σε άλλα συστήµατα. 3.2 Τρόπος προσέγγισης της εργασίας Για τη δική σας διευκόλυνση στην κατανόηση των εργαλείων που θα χρησιµοποιήσετε καθώς και του τρόπου µε τον οποίο τα εργαλεία αυτά συνεργάζονται, προτείνουµε την υλοποίηση της εργασίας του µαθήµατος σε δύο φάσεις. 3.2.1 1 η φάση: Λεκτική ανάλυση Το αποτέλεσµα της λεκτικής ανάλυσης θα είναι ένα πρόγραµµα το οποίο θα παίρνει σαν είσοδο ένα πρόγραµµα της γλώσσας FhP και θα αναγνωρίζει τις λεκτικές µονάδες (tokens) στο αρχείο αυτό. Η έξοδός του θα είναι µία λίστα από τα tokens που διάβασε και ο χαρακτηρισµός τους. Για παράδειγµα, για είσοδο $i = $k + 2; η έξοδος του προγράµµατός σας θα πρέπει να είναι token ID: $i token EQUAL: = token ID: $k token ADDOP: + token INT: 2 token SEMICOLON: ; Σε περίπτωση µη αναγνωρίσιµης λεκτικής µονάδας θα πρέπει να τυπώνεται κατάλληλο µήνυµα λάθους και να τερµατίζει η λεκτική ανάλυση. Για να φτιάξετε ένα λεκτικό αναλυτή θα χρησιµοποιήσετε το εργαλείο flex και τον compiler gcc. ώστε man flex στη γραµµή εντολής για να δείτε το manual του flex. Τα αρχεία µε κώδικα του flex έχουν προέκταση.l. Για να κάνετε compile και να τρέξετε τον κώδικά σας ακολουθήστε τις οδηγίες που δίνονται παρακάτω. 1. Γράψτε τον κώδικα flex σε ένα αρχείο µε προέκταση.l, π.χ. mylexer.l. 2. Κάντε compile, γράφοντας flex mylexer.l στη γραµµή εντολής. 3. ώστε ls για να δείτε το αρχείο lex.yy.c που παράγεται από τον flex. 4. Κάντε compile το lex.yy.c µε την εντολή gcc -o mycompiler lex.yy.c lfl 5. Αν δεν έχετε λάθη στο mylexer.l, παράγεται το εκτελέσιµο mycompiler. 6. Τρέξτε το µε./mycompiler < example.fhp, για το πρόγραµµα example.fhp. Κάθε φορά που αλλάζετε το mylexer.l θα πρέπει να κάνετε όλη την διαδικασία: flex mylexer.l gcc -o mycompiler lex.yy.c -lfl./mycompiler < example.fhp Εποµένως είναι καλή ιδέα να φτιάξετε ένα script για να κάνει όλα τα παραπάνω. σελ. 10/15
3.2.2 2 η φάση: Συντακτική ανάλυση Το αποτέλεσµα της συντακτικής ανάλυσης θα είναι ένα πρόγραµµα το οποίο θα παίρνει σαν είσοδο ένα αρχείο της γλώσσας FhP και θα αναγνωρίζει αν αυτό το πρόγραµµα ακολουθεί τους συντακτικούς κανόνες της FhP. Στην έξοδο θα αναπαράγει τα αποτελέσµατα της λεκτικής ανάλυσης (λίστα από λεκτικές µονάδες και κατηγορίες και πιθανά λεκτικά λάθη) και στο τέλος ένα µήνυµα ότι το πρόγραµµα που δόθηκε είναι συντακτικά σωστό ή διαφορετικά ο αριθµός γραµµής όπου διαγνώσθηκε το πρώτο λάθος, το περιεχόµενο της γραµµής µε το λάθος και προαιρετικά ένα κατατοπιστικό µήνυµα διάγνωσης. Για παράδειγµα, για τη λανθασµένη είσοδο... $i = $k + 2... η έξοδος του προγράµµατός σας θα πρέπει να είναι Syntax error in line 56: $i = $k + 2 ή Syntax error in line 56: $i = $k + 2 (semicolon expected) (όπου line 56 είναι ο αριθµός της γραµµής µέσα στο αρχείο συµπεριλαµβανοµένων των γραµµών σχολίων ή εξωτερικού κώδικα.) Για να φτιάξετε ένα συντακτικό αναλυτή θα χρησιµοποιήσετε το εργαλείο bison και τον compiler gcc. ώστε man bison για να δείτε το manual του bison. Τα αρχεία µε κώδικα του bison έχουν προέκταση.y. Για να κάνετε compile και να τρέξετε τον κώδικά σας ακολουθήστε τις οδηγίες που δίνονται παρακάτω. 1. Υποθέτουµε ότι έχετε ήδη έτοιµο τον λεκτικό αναλυτή στο mylexer.l. 2. Γράψτε τον κώδικα bison σε αρχείο µε προέκταση.y, π.χ. myanalyzer.y. 3. Για να ενώσετε το flex µε το bison πρέπει να κάνετε τα εξής: a. Βάλτε τα αρχεία mylexer.l και myanalyzer.y στο ίδιο directory. b. Βγάλτε την συνάρτηση main από το flex αρχείο και φτιάξτε µια main στο bison αρχείο. Για αρχή το µόνο που χρειάζεται να κάνει η καινούρια main είναι να καλεί µια φορά την µακροεντολή του bison yyparse(). H yyparse() τρέχει επανειληµµένα την yylex() και προσπαθεί να αντιστοιχίσει κάθε token που επιστρέφει o λεκτικός αναλυτής στη γραµµατική που έχετε γράψει στο συντακτικό αναλυτή. Επιστρέφει 0 για επιτυχή τερµατισµό και 1 για λανθασµένο τερµατισµό. c. Αφαιρέστε τα defines που είχατε κάνει για τα tokens στο flex ή σε κάποιο άλλο.h αρχείο. Αυτά θα δηλωθούν τώρα στο bison αρχείο ένα σε κάθε γραµµή µε την εντολή %token. Όταν κάνετε compile to myanalyzer.y θα δηµιουργείται αυτόµατα και ένα αρχείο µε όνοµα myanalyzer.tab.h. To αρχείο αυτό θα πρέπει να το κάνετε include στο αρχείο mylexer.l και έτσι ο flex θα καταλαβαίνει τα ίδια tokens µε τoν bison. 4. Κάντε compile bison -d myanalyzer.y flex mylexer.l gcc -o mycompiler lex.yy.c myanalyzer.tab.c -lfl./mycompiler <test.fhp σελ. 11/15
Προσοχή! Πρέπει πρώτα να κάνετε compile το myanalyzer.y και µετά το mylexer.l γιατί το myanalyzer.tab.h γίνεται include στο mylexer.l. Κάθε φορά που αλλάζετε το mylexer.l και myanalyzer.y θα πρέπει να κάνετε όλη την διαδικασία. Είναι καλή ιδέα να φτιάξετε ένα script για όλα τα παραπάνω. 3.3 Παραδοτέο Το παραδοτέο για την εργασία του µαθήµατος θα περιέχει τα παρακάτω αρχεία: mylexer.l: To αρχείο flex. myanalyzer.y: To αρχείο bison. team.txt: Τα ονόµατα σας µε τους αριθµούς µητρώου. grammar.txt: Η γραµµατική χωρίς συµφραζόµενα που χρησιµοποιήσατε. report.pdf: Συνοπτική (δακτυλογραφηµένη) αναφορά που θα εξηγεί τις τεχνικές που χρησιµοποιήσατε και τις ιδιαιτερότητες της εργασίας σας. correctx.fhp, X=1,2,3: Σωστά (λεκτικά και συντακτικά) προγράµµατα της γλώσσας FhP (προαιρετικό). wrongx.fhp, X=1,2,3: Λανθασµένα (λεκτικά ή συντακτικά) προγράµµατα της FhP (προαιρετικό). Είναι δική σας ευθύνη να αναδείξετε τη δουλειά σας µέσα από αντιπροσωπευτικά προγράµµατα της γλώσσας FhP. Κατά τη διάρκεια της εξέτασης της εργασίας σας θα γίνουν τα εξής: Μεταγλώττιση των παραδοτέων προγραµµάτων: Ανεπιτυχής µεταγλώττιση θα σηµαίνει µεγάλη µείωση στον τελικό βαθµό της εργασίας σας. Έλεγχος εκτελέσιµου τόσο στα παραδείγµατα προγραµµάτων του Παραρτήµατος όσο και σε άλλα άγνωστα σε σας παραδείγµατα: Η καλή εκτέλεση αυτών των παραδειγµάτων θα επηρεάσει σηµαντικά το τελικό βαθµό της εργασίας σας. Έλεγχος εκτελέσιµου µε τα παραδείγµατα προγραµµάτων σε FhP που έχετε δώσει εσείς: Μόνο σε περίπτωση που θέλετε να αναδείξετε κάτι από τη δουλειά σας. Ερωτήσεις σχετικά µε την υλοποίηση και τα παραδοτέα κείµενα. Θα πρέπει να είστε σε θέση να εξηγήσετε θέµατα σχεδιασµού, επιλογών και τρόπων υλοποίησης. 4. Επίλογος Στη διάρκεια του εξαµήνου θα δοθούν διευκρινίσεις όπου χρειάζεται. Για ερωτήσεις µπορείτε να απευθύνεστε στον κ. Αργυρόπουλο. Γενικές απορίες καλό είναι να αποστέλλονται στη λίστα του µαθήµατος για να τις βλέπουν και οι συνάδελφοί σας. Καλή επιτυχία! σελ. 12/15
ΠΑΡΑΡΤΗΜΑ 1. Παραδείγµατα προγραµµάτων της FhP 1.1 Hello World! <html> <head> <title>fhp Test</title> </head> <body> echo "<p>hello World</p>"; </body> </html> Προτεινόµενο αποτέλεσµα λεκτικής συντακτικής ανάλυσης: Token EXTERNAL_CODE_LINE:<html> Token EXTERNAL_CODE_LINE:<head> Token EXTERNAL_CODE_LINE:<title>PHP Test</title> Token EXTERNAL_CODE_LINE:</head> Token EXTERNAL_CODE_LINE:<body> Token RESERVED_FUNCTION:echo Token STRING: <p>hello World</p> Token SEMICOLON:; Token EXTERNAL_CODE_LINE:</body> Token EXTERNAL_CODE_LINE:</html> Your program is syntactically correct! 1.2 Πρώτοι αριθµοί Το παρακάτω παράδειγµα προγράµµατος στη γλώσσα FhP είναι ένα πρόγραµµα που υπολογίζει τους πρώτους αριθµούς µεταξύ 1 και n, όπου το n καθορίζεται από το χρήστη. Λαµβάνεται υπόψη ότι οι αριθµοί 2 και 3 είναι πρώτοι, και στη συνέχεια εξετάζονται µόνο οι αριθµοί της µορφής 6k±1, όπου k ακέραιος αριθµός. function prime($n){ if ($n < 0) $result = prime(-$n); else if ($n < 2) $result = false; else if ($n == 2) $result = true; else if ($n % 2 == 0) $result = false; else { $i = 3; $isprime = true; while ( $isprime && $i <= $n / 2 ) { $isprime = ($n % $i!=0); $i = $i+2; σελ. 13/15
$result = $isprime; return $result; $limit = readinteger(); $counter = 0; if ($limit >= 2) { $counter = $counter + 1; echo('2 '); if ($limit >= 3) { $counter = $counter + 1; echo('3 '); $number = 6; while ($number <= $limit) { if (prime($number-1)) { $counter = $counter + 1; echo number-1; echo ' '; if (($number!= $limit) && prime($number+1){ $counter = $counter + 1; echo $number+1; echo ' '; $number = $number + 6; echo("\ntotal: "); echo $counter; 1.3 Άλλο παράδειγµα $check = "test"; $check.= $filename; if ($test == $check) { print("<html><body>"); print("you are already registered."); print("</body></html>"); else { $rated = "test"; $rated.= $filename; setcookie(test, $rated, time()+86400); <HTML><BODY><br> You are a new user so I recorded your id. </BODY></HTML> $status = getuserstatus($u); σελ. 14/15
switch ( $status ) { case '0' : case '1' : updatesystem(0); break; case '2' : updatesystem(0); break; default : echo "No Permissions"; 1.4 Παράδειγµα µε συντακτικό λάθος 1 <html> 2 <head> 3 <title>fhp Test</title> 4 </head> 5 <body> 6 7 // Missing parenthesis. 8 echo ("<p>hello World</p>"; 9 10 </body> 11 </html> Προτεινόµενο αποτέλεσµα λεκτικής συντακτικής ανάλυσης: Token EXTERNAL_CODE_LINE:<html> Token EXTERNAL_CODE_LINE:<head> Token EXTERNAL_CODE_LINE:<title>PHP Test</title> Token EXTERNAL_CODE_LINE:</head> Token EXTERNAL_CODE_LINE:<body> Syntax error in line 8: echo ("<p>hello World</p>; ή Syntax error in line 8: echo ("<p>hello World</p>; (Missing parenthesis) σελ. 15/15