Τρόπος λειτουργίας
- Η λειτουργία του lex βασίζεται στην δημιουργία ενός ΜΠΑ από το αρχείο
εισόδου.
- Στη συνέχεια το ΜΠΑ μετατρέπεται σε ΝΠΑ.
- Στο αρχείο εξόδου περιέχεται κώδικας C ο οποίος υλοποιεί τη λειτουργία
του ΝΠΑ καθώς και οι αντίστοιχοι πίνακες μετάβασης.
- Για λόγους απόδοσης οι χαρακτήρες εισόδου κατανέμονται σε κλάσεις
ισοδυναμίας και αυτές σε μετακλάσεις ισοδυναμίας.
Με τον τρόπο αυτό περιορίζεται ο αριθμός των καταστάσεων.
Παράδειγμα
Αρχείο εισόδου
%option noyywrap
%%
hi printf("HI\n");
\. printf("DOT\n");
%%
main()
{
yylex();
}
Μη αιτιοκρατικό πεπερασμένο αυτόματο
Το αυτόματο αρχίζει από την κατάσταση 12.
Από κάθε κατάσταση μπορεί να οδηγηθεί σε δύο νέες καταστάσεις Κ1, Κ2.
(ε είναι το κενό σύμβολο).
συμβ. Κ1 Κ2
Κατάσταση 1 ε : 0, 0
Κατάσταση 2 ε : 0, 0
Κατάσταση 3 h : 4, 0 // Διάβασε h
Κατάσταση 4 i : 5, 0 // Διάβασε i
Κατάσταση 5 ε : 0, 0 [1] // Αναγνώρισε hi
Κατάσταση 6 ε : 1, 3
Κατάσταση 7 . : 8, 0 // Διάβασε .
Κατάσταση 8 ε : 0, 0 [2] // Αναγνώρισε .
Κατάσταση 9 ε : 6, 7
Κατάσταση 10 EOF: 11, 0
Κατάσταση 11 ε : 0, 0 [3] // Τέλος του αρχείου
Κατάσταση 12 ε : 9, 10
Κλάσεις ισοδυναμίας
\000 = -1 ' ' = 1 @ = 1 ` = 1
\001 = 1 ! = 1 A = 1 a = 1
\002 = 1 " = 1 B = 1 b = 1
\003 = 1 # = 1 C = 1 c = 1
\004 = 1 $ = 1 D = 1 d = 1
\005 = 1 % = 1 E = 1 e = 1
\006 = 1 & = 1 F = 1 f = 1
\a = 1 ' = 1 G = 1 g = 1
\b = 1 ( = 1 H = 1 h = 3
\t = 1 ) = 1 I = 1 i = 4
\n = 1 * = 1 J = 1 j = 1
\v = 1 + = 1 K = 1 k = 1
\f = 1 , = 1 L = 1 l = 1
\r = 1 - = 1 M = 1 m = 1
\016 = 1 . = 2 N = 1 n = 1
\017 = 1 / = 1 O = 1 o = 1
\020 = 1 0 = 1 P = 1 p = 1
\021 = 1 1 = 1 Q = 1 q = 1
\022 = 1 2 = 1 R = 1 r = 1
\023 = 1 3 = 1 S = 1 s = 1
\024 = 1 4 = 1 T = 1 t = 1
\025 = 1 5 = 1 U = 1 u = 1
\026 = 1 6 = 1 V = 1 v = 1
\027 = 1 7 = 1 W = 1 w = 1
\030 = 1 8 = 1 X = 1 x = 1
\031 = 1 9 = 1 Y = 1 y = 1
\032 = 1 : = 1 Z = 1 z = 1
\033 = 1 ; = 1 [ = 1 { = 1
\034 = 1 < = 1 \ = 1 | = 1
\035 = 1 = = 1 ] = 1 } = 1
\036 = 1 > = 1 ^ = 1 ~ = 1
\037 = 1 ? = 1 _ = 1 \177 = 1
Μετακλάσεις ισοδυναμίας
1 = 1
2 = 1
3 = 1
4 = 2
Αιτιοκρατικό πεπερασμένο αυτόματο
Κατάσταση # 1:
1 4
2 5 // .
3 6 // h
4 4
Κατάσταση # 2:
1 4
2 5 // .
3 6 // h
4 4
Κατάσταση # 3:
Κατάσταση # 4:
Κατάσταση # 5: // Αναγνώρισε .
Κατάσταση # 6:
4 7 // i
Κατάσταση # 7: // Αναγνώρισε hi
Παραγόμενος κώδικας σε C (τμήματα)
/* A lexical scanner generated by flex */
/* ... */
/* Πίνακες μετάβασης */
static yyconst short int yy_def[10] =
{ 0,
8, 1, 8, 8, 8, 9, 8, 0, 8
} ;
static yyconst short int yy_nxt[12] =
{ 0,
4, 5, 6, 4, 7, 8, 3, 8, 8, 8,
8
} ;
static yyconst short int yy_chk[12] =
{ 0,
1, 1, 1, 1, 9, 3, 8, 8, 8, 8,
8
} ;
/* ... */
/* Υλοποίηση του ΝΠΑ */
yy_match:
do
{
register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 9 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
*yy_state_ptr++ = yy_current_state;
++yy_cp;
}
/* ... */
/* Υλοποίηση ενεργειών χρήστη */
switch ( yy_act )
{ /* beginning of action switch */
case 1:
printf("HI\n");
break;
case 2:
printf("DOT\n");
break;
/* ... */
/* Κώδικας χρήστη */
main()
{
yylex();
}