Aby wąż giętki robił to co wymyśli głowa, czyli słów kilka o analizie leksykalnej i TDD w...
-
Upload
adam-przybyla -
Category
Technology
-
view
177 -
download
2
Transcript of Aby wąż giętki robił to co wymyśli głowa, czyli słów kilka o analizie leksykalnej i TDD w...
Aby wąż giętki robił to co wymyśli głowa, czyli słów kilka o analizie leksykalnej i TDD
w Pythonie
Adam Przybyła <[email protected]>(mail i JID)
@AdamPrzybyla
(Creative Commons CC-by-nd)WrocPY - Wrocław 2013
Opis CSV w EBNFCSV file
--------
file ::= [ header ] { line }
header ::= [ { entry separator } entry ] newline
line ::= [ { entry separator } entry ] newline
entry ::= character+ | { character* " separator " } | " entry newline entry "
newline ::= \n
separator ::= ,
character ::= a|b|..|A|B|..|0|1|..
escapedQuote ::= ""
Flex i Bison● Flex – analizator leksykalny● Rozszerzona wersja programu lex● Generuje tablice przejść● Parsery LR i LL
Plik konfiguracyjny analizatora leksylalnego%%
, {return COMMA;}
\n {return NEWLINE;}
\r\n {return NEWLINE;}
[^,\n\r]+ {return ITEM;}
Kod Bisona%token COMMA NEWLINE ITEM
%%
csv_file : line_list | line_list line;
line_list : line_list line newline | line newline | line_list newline | newline;
line : line comma | line item | item | comma;
comma : COMMA ;
newline : NEWLINE;
item : ITEM ;
Program wynikowy we Bisonstatic const yytype_uint8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
Flex z kernelem● Filtr klasyfikujący ruch w sieci w kernelu● https://github.com/AdamPrzybyla/layer7-flex● Kilka razy szybsze rozwiązanie niż
oryginalne, oparte o wyrażenia regularne
Analizator leksykalny ANTLR● PCTTS● Dla leniwych● Analizator LL(*)● Przejrzysty kod● Generacja kodu Java,c#,Python,C++
Tryby pracy ANTLR● Analizator leksykalny● Tworzenie AST● Walker AST● Generowanie plików graphviz● Przetwarzanie AST● Język template
Przetwarzanie drzew AST
● Kompilator c kiedyś:● Źródło w C● C z rozwiniętymi makrami● Asembler● Plik .o + linkowanie
● Kompilator C teraz:● Kolejne modyfikacje drzew AST
Gramatyka CSV w ANTLRgrammar csv;
options { language=Python; }
file : record (NEWLINE record)* EOF ;
record : (quoted_field | unquoted_field) (COMMA (quoted_field | unquoted_field))* ;
quoted_field : DQUOTE ( CHAR | COMMA | DQUOTE DQUOTE | NEWLINE)* DQUOTE ;
unquoted_field : CHAR* ;
CHAR : '\u0000' .. '\u0009' | '\u000b' .. '\u000c' | '\u000e' .. '\u0021' | '\u0023' .. '\u002b' | '\u002d' .. '\uffff' ;
COMMA : '\u002c' ;
DQUOTE : '\u0022' ;
NEWLINE : '\u000d'? '\u000a' | '\u000d' ;
Zrozumiały kod (Python) def liczba(self, ):
w = None; p = None
try:
try:
# WrocPy.g:9:19: (p= CYFRY ) # WrocPy.g:9:21: p= CYFRY
p = self.match(self.input, CYFRY, self.FOLLOW_CYFRY_in_liczba33)
if self._state.backtracking == 0: w=p
except RecognitionException, re:
self.reportError(re)
self.recover(self.input, re)
finally:
pass
return w
Wywołanie funkcji – jak w ręcznych parserach
def mIDS(self, ):
try:
_type = IDS
_channel = DEFAULT_CHANNEL
# WrocPy.g:14:4: ( ( 'a' .. 'z' )+ ( '0' .. '9' )* )
# WrocPy.g:14:9: ( 'a' .. 'z' )+ ( '0' .. '9' )*
pass
# WrocPy.g:14:9: ( 'a' .. 'z' )+
cnt1 = 0
while True: #loop1
alt1 = 2
LA1_0 = self.input.LA(1)
Test ANTLR3 def test_liczba(self): s="1234" w=parserek(s).liczba() self.assertEqual(w.text,s)
def test_nie_liczba(self): s="A1234" w=parserek(s).liczba() self.assertFalse(w)
Definicja symboli gramatykigrammar WrocPy;options { language=Python; backtrack=true; }@members { def emitErrorMessage(self, msg): pass}liczba returns [w]: p=CYFRY {w=p};zmienna returns [w]: p=IDS {w=p};przypisanie returns [w]: p=IDS '=' p1=CYFRY {w=[p,p1]};IDS: 'a'..'z' + '0'..'9' * ;CYFRY: '0'..'9' + ;WS: .;;