Poznajemy generator analizatorów leksykalnych dla naszego języka programowania. Może to obejmować Flex (C/C++), Alex (Haskell), ewentualnie JFlex (Java) i inne generatory.
W programie napisanym na poprzednim laboratorium, analizator leksykalny zamieniamy na wygenerowany przy pomocy odpowiedniego generatora.
Omawiamy przykład analizatora stworzonego przy uzyciu Flexa, np.
%{
// #include "exp.tab.h" /* Definiuje leksemy, np. NUM */
#define NUM '9'
int yylval;
%}
%option noyywrap
%%
[0-9]+ {
yylval = atoi( yytext ) ;
return (int)NUM;
}
. { return (int)(yytext[0]); }
\n { return (int)'\n'; }
%%
int main() { int lexem; while(lexem=yylex()) { ... }
return 0;
}Uruchamianie:
flex -o lexer.c lexer.l
Wygenerowany plik (tu: lexer.c) zawiera funkcję yylex(), której kolejne wywołania dają kolejne leksemy (0 dla EOF jeśli nie ma innych wytycznych)
Omawiamy przykład, np.
%%
%class Scanner
%type Symbol
%unicode
%line
%{
StringBuffer string = new StringBuffer();
// Leksemy są klasy Symbol, zdefiniowanej poza tym plikiem
private Symbol symbol(int type) {
return new Symbol(type, yyline, -1);
}
private Symbol symbol(int type, Object value) {
return new Symbol(type, yyline, -1, value);
}
%}
WhiteSpace = (LineTerminator | [ \t\f])
DecIntLiteral = 0 | [1-9][0-9]*
%%
(0|[1-9][0-9]*) { return symbol(sym.NUM, new Integer(yytext())); }
{WhiteSpace} { }
. { System.out.println("Unexpected character:"+yytext());}Z tej specyfikacji JFlex wygeneruje klasę (tu: Scanner) zawierającą kod leksera. Konstruktor tej klasy bierze jako argument klasy java.io.Reader reprezentujący strumień wejściowy. Kolejne wywołania metody yylex() z tej klasy dają kolejne leksemy (null dla EOF w tym wypadku)
Omawiamy przykład, np.
{
module CalcLex(alexScanTokens) where
import CalcToken(Token(..))
}
%wrapper "basic"
$digit = 0-9
tokens :-
$white+ ; -- whitespace
"--".* ; -- comment
$digit+ {\s -> Int (read s)}
[\=\+\-\*\/\(\)] {\s -> Sym (head s)}Przykład uzycia:
$ alex CalcLex.x $ ghci CalcLex.hs GHCi, version 6.12.1... Ok, modules loaded: CalcLex, CalcTokens. *CalcLex> alexScanTokens "let x = 1 in x +x" [Let,Var "x",Sym '=',Int 1,In,Var "x",Sym '+',Var "x"]