Lex

Στην επιστήμη υπολογιστών το **lex** είναι ένα πρόγραμμα που παράγει λεκτικούς αναλυτές ("scanners" ή "lexers"). Το lex συχνά χρησιμοποιείται μαζί με τη γεννήτρια συντακτικών αναλυτών yacc. Αρχικά το lex γράφτηκε από τον Mike Lesk και τον Eric Schmidt, και αποτελεί την κλασική γεννήτρια παραγωγής λεκτικών αναλυτών σε πολλά συστήματα Unix, και ένα εργαλείο που έχει τη συμπεριφορά του περιλαμβάνεται στο πρότυπο POSIX.

Το lex διαβάζει ένα ρεύμα εισόδου (input stream) που ορίζει το λεκτικό αναλυτή και παράγει πηγαίο κώδικα που υλοποιεί το λεκτικό αναλυτή στη γλώσσα προγραμματισμού C.

Αν και παραδοσιακά αποτέλεσε κλειστό λογισμικό, είναι διαθέσιμες εκδόσεις ανοιχτού κώδικα του lex που βασίζονται στον αρχικό κώδικα της AT&T, σαν μέρος συστημάτων όπως το OpenSolaris και το Plan 9 from Bell Labs. Μια άλλη δημοφιλής έκδοση ανοιχτού κώδικα του lex είναι το flex, ο "γρήγορος λεκτικός αναλυτής" ("fast lexical analyzer").

## Δομή ενός αρχείου lex
Η δομή ενός αρχείου lex έχει σχεδιαστεί ώστε να μοιάζει με αυτήν ενός αρχείου yacc - τα αρχεία χωρίζονται σε τρεις ενότητες που διακρίνονται μεταξύ τους από γραμμές που περιέχουν μόνο δύο σύμβολα "τοις εκατό", όπως το εξής:

 *Ενότητα των ορισμών* (*Definition section*)
 %%
 *Ενότητα των κανόνων* (*Rules section*)
 %%
 *Ενότητα κώδικα C* (*C code section*)

* Στην **ενότητα των ορισμών** ορίζονται οι μακροεντολές και εισάγονται τα αρχεία επικεφαλίδας που είναι γραμμένα σε C. Μπορεί επίσης να γραφεί οποιοσδήποτε κώδικας C σε αυτό το σημείο, ο οποίος θα αντιγραφεί ως έχει στο παραγόμενο αρχείο πηγαίου κώδικα.
* Η **ενότητα των κανόνων** είναι η σημαντικότερη: αντιστοιχίζει πρότυπα (patterns) με εντολές της C . Τα πρότυπα είναι απλά κανονικές εκφράσεις. Όταν ο λεκτικός αναλυτής εντοπίσει στην είσοδό του κάποιο κείμενο που ταιριάζει με κάποιο από τα δοθέντα πρότυπα, εκτελεί τον αντίστοιχο κώδικα C. Αυτός είναι ο βασικός τρόπος με τον οποίο λειτουργεί το lex.
* Η **ενότητα κώδικα C** περιέχει εντολές C και συναρτήσεις που αντιγράφονται ως έχει στο παραγόμενο αρχείο πηγαίου κώδικα. Αυτές οι εντολές υποτίθεται ότι περιλαμβάνουν κώδικα που καλείται από τους κανόνες στην ενότητα των κανόνων. Σε μεγαλύτερα προγράμματα είναι πιο βολικό να τοποθετείται αυτός ο κώδικας σε ένα ξεχωριστό αρχείο και να γίνεται σύνδεση με αυτό στο χρόνο μεταγλώττισης.

## Παράδειγμα ενός αρχείου lex
Ακολουθεί ένα παράδειγμα ενός αρχείου lex για την έκδοση flex του lex. Αναγνωρίζει συμβολοσειρές από (ακέραιους) αριθμούς στην είσοδο και απλά τους τυπώνει.


```c
/*** Ενότητα των ορισμών ***/

%{
/* Κώδικας C που θα αντιγραφεί ως έχει */
#include <stdio.h>
%}

/* Αυτό λέει στο flex να διαβάσει μόνο ένα αρχείο εισόδου */
%option noyywrap

%%
    /*** Ενότητα των κανόνων ***/

    /* Το [0-9]+ ταιριάζει με μια συμβολοσειρά ενός η περισσότερων ψηφίων */
[0-9]+  {
            /* Το yytext είναι μια συμβολοσειρά που περιέχει το ταιριασμένο κείμενο. */
            printf("Saw an integer: %s\n", yytext);
        }

.       {   /* Αγνοεί όλους τους άλλους χαρακτήρες. */   }

%%
/*** Ενότητα κώδικα C ***/

int main(void)
{
    /* Καλεί το λεκτικό αναλυτή και στη συνέχεια τερματίζει. */
    yylex();
    return 0;
}
```


Αν αυτή η είσοδος δοθεί στο flex, θα μετατραπεί σε ένα αρχείο C, το lex.yy.c. Αυτό μπορεί να μεταγλωττιστεί σε ένα εκτελέσιμο το οποίο ταιριάζει και εμφανίζει συμβολοσειρές ακεραίων. Για παράδειγμα, για είσοδο:
 abc123z.!&*2ghj6
το πρόγραμμα θα τυπώσει:
 Saw an integer: 123
 Saw an integer: 2
 Saw an integer: 6

## Χρήση του lex με άλλα εργαλεία προγραμματισμού
### Χρήση του lex με γεννήτριες συντακτικών αναλυτών
Το lex και οι γεννήτριες συντακτικών αναλυτών, όπως το Yacc ή το Bison, συχνά χρησιμοποιούνται μαζί. Οι γεννήτριες συντακτικών αναλυτών χρησιμοποιούν μια τυπική γραμματική για να αναλύσουν συντακτικά ένα ρεύμα εισόδου, κάτι που το lex δε μπορεί να κάνει χρησιμοποιώντας απλές κανονικές εκφράσεις (το lex περιορίζεται σε απλά αυτόματα πεπερασμένων καταστάσεων). Όμως οι γεννήτριες συντακτικών αναλυτών δε μπορούν να διαβάσουν από ένα απλό ρεύμα εισόδου &ndash; χρειάζονται μια σειρά από λεκτικές μονάδες (tokens). Το lex συχνά χρησιμοποιείται για να παρέχει αυτές τις λεκτικές μονάδες στη γεννήτρια συντακτικών αναλυτών.

### Lex και make
Το make είναι ένα εργαλείο που μπορεί να χρησιμοποιηθεί για να συντηρεί προγράμματα που χρησιμοποιούν το lex. Το make θεωρεί ότι ένα αρχείο με την κατάληξη `.l` είναι αρχείο πηγαίου κώδικα lex. Η εσωτερική μακροεντολή του make `LFLAGS` μπορεί να χρησιμοποιηθεί για να ορίσει επιλογές του lex που θα κληθούν αυτόματα από το make.

## Δείτε επίσης
* Λεκτικός αναλυτής flex
* Yacc
* Ragel
* Quex

## Παραπομπές


## Εξωτερικοί σύνδεσμοι
* Το μεταεργαλείο lex  από το μάθημα 'Εισαγωγή στους μεταγλωττιστές', Δ. Σπινέλλης
* Λεκτική ανάλυση με το εργαλείο Lex, Γ. Μανής

Κατηγορία:Λογισμικό Unix
Κατηγορία:Μεταγλωττιστές
Κατηγορία:Εργαλεία προγραμματισμού Unix