рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐
рдЕрдм рд▓рдЧрднрдЧ рджреЛ рд╕рд╛рд▓ рд╕реЗ рдореИрдВ OpenSource рдкреНрд░реЛрдЬреЗрдХреНрдЯ
SourceAnalyzer рдореЗрдВ рднрд╛рдЧ рд▓реЗ рд░рд╣рд╛
рд╣реВрдВ , рдФрд░ рдЕрдм Python рднрд╛рд╖рд╛ рдХреЗ рд▓рд┐рдП рдПрдХ Parser рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬреЛ рдПрдХ рдХреЙрд▓ рдЧреНрд░рд╛рдлрд╝ (рдХреЙрд▓ рдЧреНрд░рд╛рдлрд╝) рдФрд░ рдПрдХ рд╡рд░реНрдЧ рдкрд░ рдирд┐рд░реНрднрд░ рдЧреНрд░рд╛рдлрд╝ (рдХреНрд▓рд╛рд╕ рдЧреНрд░рд╛рдлрд╝ рдирд┐рд░реНрднрд░рддрд╛) рдмрдирд╛рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЕрдзрд┐рдХ рд╕рдЯреАрдХ рд░реВрдк рд╕реЗ, рдЧреНрд░рд╛рдл рдЕрдиреНрдп рдЙрдкрдХрд░рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рдкрд╛рд░реНрд╕рд░ рдХреЛ рдХреЗрд╡рд▓ рдЗрди рдЙрдкрдХрд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рддреИрдпрд╛рд░ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдкрд╛рд░реНрд╕рд░ рдкрд░ рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛рдлреА рдордиреЛрд░рдВрдЬрдХ рдереА рдФрд░ рдореИрдВ рдЖрдкрдХреЗ рд╕рд╛рде рдЕрдкрдиреЗ рдЕрдиреБрднрд╡ рдХреЛ рд╕рд╛рдЭрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛, рд╕рд╛рде рд╣реА рдЖрдкрдХреЛ рдХреБрдЫ рдРрд╕реЗ рдиреБрдХрд╕рд╛рдиреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрддрд╛рдКрдВрдЧрд╛ рдЬреЛ рд╣рдореЗрдВ рд╡рд┐рдХрд╛рд╕ рдХреЗ рдЪрд░рдг рдореЗрдВ рдорд┐рд▓реЗ рдереЗред
рд╢рдмреНрджрд╛рд╡рд▓реА
рдпрджрд┐ рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╡реНрдпрд╛рдХрд░рдг рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рдЪреБрдХреЗ рд╣реИрдВ рдФрд░ рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдХрдВрдкрд╛рдЗрд▓рд░ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рддреЛ рдЕрдЧрд▓реЗ рдкреИрд░рд╛рдЧреНрд░рд╛рдл рдореЗрдВ рдЖрдкрдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИ, рдмрд╛рдХреА рдЖрдкрдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИред
рдкрд╛рд░реНрд╕рд░ рд╡рд┐рдХрд╛рд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рджреЛ рдореБрдЦреНрдп рдШрдЯрдХреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
- рдЗрдирдкреБрдЯ рд╕реНрдЯреНрд░реАрдо рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдФрд░ рдЯреЛрдХрди рдореЗрдВ рд╡рд┐рднрд╛рдЬрди (рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╡рд┐рд╢реНрд▓реЗрд╖рдг)
- рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдирд┐рдпрдореЛрдВ рдХреЗ рдПрдХ рд╕реЗрдЯ рдХреЗ рд╕рд╛рде рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдЯреЛрдХрди (рдкрд╛рд░реНрд╕рд┐рдВрдЧ)
рдЖрдЗрдП рдереЛрдбрд╝рд╛ рдЙрджрд╛рд╣рд░рдг рджреЗрдЦреЗрдВред рдПрдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ (рдпрд╛ рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рд╕реНрдЯреНрд░реАрдо) рд╣реЛрдиреЗ рджреЗрдВ:
3 + 4 * 15
рдЗрдирдкреБрдЯ рд╕реНрдЯреНрд░реАрдо рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рдпрдо рдмрдирд╛рдПрдБ:
[1-9]* -> NUMBER + -> PLUS * -> MULT
рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╢рд╛рдмреНрджрд┐рдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рдмрд╛рдж рд╣рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ:
NUMBER(3) PLUS(+) NUMBER(4) MULT(*) NUMBER(15) EQUAL(=)
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдПрдХ рд╡реНрдпрд╛рдХрд░рдг рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ, рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рдмрд╛рдж рдореЗрдВ, рдирд┐рдпрдореЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдЖрдк рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
exp: NUMBER | exp sign exp sign: PLUS | MULT * / \ + 15 / \ 3 4
рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ,
NUMBER, MULT, PLUS
- рдкрд░рд┐рднрд╛рд╖рд╛, рдЯрд░реНрдорд┐рдирд▓реЛрдВ, рдпрд╛ рдЯреЛрдХрдиреЛрдВ рджреНрд╡рд╛рд░рд╛, рд╢рд╛рдмреНрджрд┐рдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рдЪрд░рдг рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
expr, sign
рдЯрд░реНрдорд┐рдирд▓ рдирд╣реАрдВ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рд╕рдордЧреНрд░ рдЗрдХрд╛рдЗрдпрд╛рдБ рд╣реИрдВред
рдпрд╣ рдкрд░рд┐рдЪрдп рдердХрд╛рдК рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП, рд╕рд┐рджреНрдзрд╛рдВрдд рдХреЗ рд▓рд┐рдП рдкреБрд╕реНрддрдХ рдлреНрд▓реЗрдХреНрд╕ рдПрдВрдб рдмрд╛рдЗрд╕рди рдУ'рд░реЗрд▓реА рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред
рд╡реНрдпрд╛рдХрд░рдг
рдЕрдЬрдЧрд░ рдХреЗ рд▓рд┐рдП рдкреВрд░реНрдг рд╡реНрдпрд╛рдХрд░рдг (рд╕рдВрд╕реНрдХрд░рдг 2.5.2) рдпрд╣рд╛рдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
http://docs.python.org/release/2.5.2/ref/grammar.txtрдореЗрд░рд╛ рдХрд╛рдо рдХреЗрд╡рд▓ рдХрдХреНрд╖рд╛рдУрдВ, рдХрд╛рд░реНрдпреЛрдВ рдФрд░ рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдХреА рдкрд╣рдЪрд╛рди рдХрд░рдирд╛ рдерд╛ред
рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдмреИрдХрд╕-рдиреМрд░ рдлреЙрд░реНрдо (рдЖрд░рдмреАрдПрдирдПрдл) (
рд╡рд┐рдХреА ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡реНрдпрд╛рдХрд░рдг рдХреЗ рдЖрд╡рд╢реНрдпрдХ рд╣рд┐рд╕реНрд╕реЗ рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдВрдЧреЗред
class_def = CLASS classname [inheritance] COLON suite classname = ID inheritance = LBRACE class_args_list RBRACE class_args_list = [class_arg] class_arg = dotted_name {COMMA dotted_name} dotted_name = ID {DOT ID}
рдпрд╣рд╛рдВ
[X]
рдХреА 0 рдпрд╛ 1 рдШрдЯрдирд╛ рд╣реИ,
{Y}
0 рд╣реИ рдпрд╛
{Y}
рдЕрдзрд┐рдХ рдШрдЯрдирд╛рдПрдВ рд╣реИрдВ
Y
рд╡рд░реНрдЧ рдХрд╛ рдирд╛рдо рдФрд░ рдЙрд╕рдХреА рдирд┐рд░реНрднрд░рддрд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИред рдЕрдм рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЗ рд▓рд┐рдПред
func_def = DEF funcname LBRACE [func_args_list] RBRACE COLON suite funcname = ID func_args_list = [func_arg] func_arg = (dotted_name | star_arg) {OTHER | COMMA | dotted_name | star_arg | MESSAGE} star_arg = [STAR] STAR ID
рд╡реИрд╕реЗ, рдпрд╣ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛрдб рд╕рд╣реА рд╣реЛрдЧрд╛ (рджреБрднрд╛рд╖рд┐рдпрд╛ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ), рдЕрдиреНрдпрдерд╛ рд╡реНрдпрд╛рдХрд░рдг рдХреЗ рдирд┐рдпрдореЛрдВ рдХреЛ рдЕрдзрд┐рдХ рд╕рдЦреНрддреА рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдЦреИрд░, рдЕрдм рдХреЗ рд▓рд┐рдП, рдЪрд▓реЛ рд╡реНрдпрд╛рдХрд░рдг рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рдХрд░реЗрдВ рдФрд░ рд▓реЗрдХреНрд╕рд░ (рд▓реЗрдХреНрд╕рд┐рдХрд▓ рдПрдирд╛рд▓рд╛рдЗрдЬрд╝рд░) рдкрд░ рдЬрд╛рдПрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╡реНрдпрд╛рдХрд░рдг рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдореВрд▓ рдкрд╛рдпрдерди рдХреЛрдб рдХреЛ рдЯреЛрдХрди рдореЗрдВ рддреЛрдбрд╝ рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ
рд▓реЗрдХреНрд╕рд░ рдлреНрд▓реЗрдХреНрд╕ рджреНрд╡рд╛рд░рд╛ рдЙрддреНрдкрдиреНрди рд╣реЛрддрд╛ рд╣реИред рд╕рдмрд╕реЗ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг:
%{ #include <stdio.h> %} %% start printf("START\n"); stop printf("STOP\n"); . ; /* */ %%
рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдХреЛ рдХреИрд╕реЗ рд╕рдВрдХрд▓рд┐рдд рдХрд░реЗрдВ:
% flex lexer.l && gcc lex.yy.c -o lexer -lfl
рд╡реНрдпрд╛рдХрд░рдг рдХреЗ рд▓рд┐рдП рд╡реНрдпрд╛рдХрд░рдг рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдирд╛ рд╕реАрдЦреЗрдВ:
http://rus-linux.net/lib.php?name=/MyLDP/algol/lex-yacc-howto.htmlрдареАрдХ рд╣реИ, рдЕрдм рдЯреЛрдХрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдлреИрд╕рд▓рд╛ рдХрд░рддреЗ рд╣реИрдВред рд╡реНрдпрд╛рдХрд░рдг рдореЗрдВ, рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╣реА рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИ:
CLASS, COLON, COMMA, DEF, DOT, ID, LBRACE, MESSAGE, RBRACE, OTHER, STAR
рд╣рдореЗрдВ рднреА
DEFINED
- рдЖрд░рдХреНрд╖рд┐рдд рдкрд╛рдпрдерди рд╢рдмреНрджреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рд╣рдо рдПрдХ рд▓реЗрдХреНрд╕рд░ рдмрдирд╛рддреЗ рд╣реИрдВред
рдХреЛрдб:
https://gist.github.com/2158334рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдкрд╛рд░реНрд╕рд┐рдВрдЧ: рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ, рд░рд┐рдХреНрдд рд▓рд╛рдЗрдиреЛрдВ рдФрд░ рд░рд┐рдХреНрдд рд╕реНрдерд╛рди рдХреА рдЕрдирджреЗрдЦреА рдХреА рдЬрд╛рддреА рд╣реИред рдмрд╛рдХреА рд╕рдм рдХреБрдЫ (рддрдерд╛рдХрдерд┐рдд рдЯреЛрдХрди рд╕реНрдЯреНрд░реАрдо) рдмрд╛рдЗрд╕рди рдЗрдирдкреБрдЯ рдХреЛ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рд╡рд░реНрдг рд╕реЗрдЯ рдЬреЛ рдкреИрдЯрд░реНрди рдкрд╛рддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкреИрдЯрд░реНрди
[ \t]+
) рдХреЛ
yytext
рдореЗрдВ рд░рдЦрд╛ рдЧрдпрд╛ рд╣реИред рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ,
yytext
рдПрдХ
yytext
рдкреЙрдЗрдВрдЯрд░ рд╣реИ, рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрдк рд╕рдВрдХрд▓рди рдореЗрдВ
-l
рд╕реНрд╡рд┐рдЪ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рддреЛ
yytext
рдХреЛ рдЪрд╛рд░ рд╕рд░рдгреА рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирд╛ рдЬрд╛рдПрдЧрд╛ред рдмрд╛рдЗрд╕рди рдХреЛ рдЯреЛрдХрди рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдЯреЗрдореНрдкрд▓реЗрдЯ рджреНрд╡рд╛рд░рд╛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдореВрд▓реНрдп рдХреЛ
yylval
рдореЗрдВ
yylval
(рдЕрдзрд┐рдХ рд╡рд┐рд╡рд░рдг рдХреЗ рд▓рд┐рдП, рдиреАрдЪреЗ рджреЗрдЦреЗрдВ)ред
рдпрд╣ рдмрд╛рдЗрд╕рди рдХреЗ рд▓рд┐рдП рд╡реНрдпрд╛рдХрд░рдг рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝рдиреЗ рдХрд╛ рд╕рдордп рд╣реИред
рдмрд┐рдЬреЛрди
рдмрд╛рдпрд╕рди рдХреЗ рд▓рд┐рдП рд╡реНрдпрд╛рдХрд░рдг рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдирд╛ рд╕реАрдЦреЗрдВ:
http://rus-linux.net/lib.php?name=/MyLDP/algol/lex-yacc-howto.htmlрдореИрдВ рдЖрдкрдХреЛ рдЗрд╕ рд▓реЗрдЦ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдлрд┐рд░ рд╕реЗ рдмрддрд╛ рд░рд╣рд╛ рд╣реВрдВ, рдХреНрдпреЛрдВрдХрд┐ рдЬреЛ рд▓реЛрдЧ рдмрд╛рдЗрд╕рди рдХреЗ рд▓рд┐рдП рд╡реНрдпрд╛рдХрд░рдг рдирд╣реАрдВ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рд╡реЗ рдЗрд╕ рд▓рд┐рдВрдХ рдкрд░ рд╕рд╛рдордЧреНрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЖрд╕рд╛рдиреА рд╕реЗ рд╕реАрдЦ рд╕рдХрддреЗ рд╣реИрдВред рдЦреИрд░, рдХреМрди рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рдХреИрд╕реЗ - рдорд╣рд╛рди, рдЪрд▓реЛ рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред
рдЗрд╕рд▓рд┐рдП, рд╡реНрдпрд╛рдХрд░рдг рд▓реЗрдЦ рдХреЗ рдЕрдиреБрдЪреНрдЫреЗрдж рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП, рд╣рдо рдмрд╛рдЗрд╕рди рдХреЗ рд▓рд┐рдП рдПрдХ рд╡реНрдпрд╛рдХрд░рдг рд░рдЪрдирд╛ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВрдЧреЗ:
рдХреЛрдб:
https://gist.github.com/2158315рдмрд╛рдЗрд╕рди рдирд┐рдпрдо рдореЗрдВ, рдкреНрд░рддреНрдпреЗрдХ рдЯреЛрдХрди рдХрд╛ рдПрдХ рдЕрд░реНрде рд╣реИред рд╡рд░реНрддрдорд╛рди рдирд┐рдпрдо рджреНрд╡рд╛рд░рд╛ рдПрдХрддреНрд░рд┐рдд рд╕рдореВрд╣ рдХрд╛ рдореВрд▓реНрдп
$
рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╢реЗрд╖ рдЯреЛрдХрди рдХрд╛ рдореВрд▓реНрдп
$1, $2, тАж
test_rule: token1, token2, token3; $$ $1 $2 $3
$n
рдореЗрдВ рд╕рдВрдЧреНрд░рд╣рд┐рдд рдореВрд▓реНрдп рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЬрдм
yylval
рдЯреЛрдХрди рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рддреЛ
yylval
рдХрд╛ рдореВрд▓реНрдпред
.tab.h
-d
рд╕рд╛рде рд░рдирд┐рдВрдЧ рдмрд╛рдЗрд╕рди рдлрд╝рд╛рдЗрд▓
.tab.h
рдЬреЗрдирд░реЗрдЯ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рдореЗрдВ
.tab.h
рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдЯреЛрдХрди рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреА рдореИрдХреНрд░реЛ рдкрд░рд┐рднрд╛рд╖рд╛рдПрдБ рд╣реЛрддреА рд╣реИрдВред рдкреНрд░рддреНрдпреЗрдХ рдЯреЛрдХрди рд╕рдВрдЦреНрдпрд╛
> 257
рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИред рдЗрд╕ рдлрд╝рд╛рдЗрд▓ рдХреЛ
#include "pyparser.tab.h"
рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬреЛ рд╣рдордиреЗ рдХрд┐рдпрд╛ рдерд╛:
#include "pyparser.tab.h"
ред
рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ?
yyparse
рдлрд╝рдВрдХреНрд╢рди рдХреЛ
main
рд╕реЗ
yyparse
рд╣реИ, рдЬреЛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ - рдЯреЛрдХрди рдкрдврд╝рддрд╛ рд╣реИ, рдХреБрдЫ рдХреНрд░рд┐рдпрд╛рдПрдВ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рддрд╛ рд╣реИ рдЕрдЧрд░ рдпрд╣ рдЗрдирдкреБрдЯ рдкрд╛рда (
return 0
) рдпрд╛ рд╕рд┐рдВрдЯреИрдХреНрд╕ рддреНрд░реБрдЯрд┐ (
return 1
) рдХреЗ рдЕрдВрдд рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рддрд╛ рд╣реИред
рдмрд╛рдЗрд╕рди рдХреЗ рдХрд╛рдо рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА:
http://www.linux.org.ru/books/GNU/bison/bison_7.htmlрд╣рдо рдпрд╣ рд╕рдВрдХрд▓рд┐рдд рдХрд░рдиреЗ рдФрд░ рдкрд░рдЦрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреНрдпрд╛ рд╣реИ:
% bison -d pyparser.y --verbose && flex lexer.l && g++ -c lex.yy.c pyparser.tab.c && g++ -o parser lex.yy.o pyparser.tab.o -ll -ly
рдкрд░реАрдХреНрд╖рдг рдЙрджрд╛рд╣рд░рдг:
class Foo: pass class Test(Foo): class Test2: def __init__(self): pass def foo(): pass
рдкрд░рд┐рдгрд╛рдо:
>> CLASS: Foo() >> CLASS: Test(Foo) >> CLASS: Test2() >> FUNC: __init__(self) >> FUNC: foo()
рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, рдпрд╣ рд╕рдЪ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдХрд╛рдлреА рдирд╣реАрдВ рд╣реИред рдореИрдВ рдлрд╝рдВрдХреНрд╢рди рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдореЗрдВ "рдкреВрд░рд╛ рдирд╛рдо" рджреЗрдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ, рдЬреЛ рд╣реИ:
>> CLASS: Foo() >> CLASS: Test(Foo) >> CLASS: Test2() >> FUNC: Test.Test2.__init__(self) >> FUNC: Test.Test2.foo()
рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдЖрдЧреЗ рдмрдврд╝реЗрдВ: рд╣рдо рдПрдХ рд╕реНрдЯреИрдХ рдмрдирд╛рдПрдВрдЧреЗ рдЬрд┐рд╕рдореЗрдВ рд╣рдо рд╡рд░реНрддрдорд╛рди рд╡рд░реНрдЧ рдХрд╛ рдирд╛рдо рдЬреЛрдбрд╝ рджреЗрдВрдЧреЗред рдЬреИрд╕реЗ рд╣реА рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдкрд░рд┐рднрд╛рд╖рд╛ рдорд┐рд▓рддреА рд╣реИ, рд╣рдо рдзреАрд░реЗ-рдзреАрд░реЗ рд╕реНрдЯреИрдХ рд╕реЗ рдХреНрд▓рд╛рд╕ рдХреЗ рдирд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ, рдлрд╝рдВрдХреНрд╢рди рдирд╛рдо рдХреЗ рд╕рд╛рде рдХрдВрдХреНрд░реАрдЯрд┐рдВрдЧ рдХрд░рддреЗ рд╣реИрдВред рдпрджрд┐ рдПрдХ рдирдпрд╛ рд╡рд░реНрдЧ рд╕реНрддрд░ рдореЗрдВ рдЧрд╣рд░рд╛ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЗрд╕реЗ рд╕реНрдЯреИрдХ рдореЗрдВ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рдЕрдиреНрдпрдерд╛ рд╣рдо рд╕реНрдЯреИрдХ рд╕реЗ рддрддреНрд╡реЛрдВ рдХреЛ рд╣рдЯрд╛рддреЗ рд╣реИрдВ рдЬрдм рддрдХ рдХрд┐ рд╣рдо рдиреЗрд╕реНрдЯрд┐рдВрдЧ (рдФрд░ рдПрдХ рдХрдо рдХрдо) рдХреЗ рд╡рд░реНрддрдорд╛рди рд╕реНрддрд░ рддрдХ рдирд╣реАрдВ рдкрд╣реБрдВрдЪ рдЬрд╛рддреЗ рд╣реИрдВ, рдФрд░ рд╕реНрдЯреИрдХ рдореЗрдВ рдПрдХ рдирдпрд╛ рд╡рд░реНрдЧ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред
рд╡рд┐рдЪрд╛рд░ рдФрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЖрдЧреЗ рд╣реИред
рдкрд╛рдпрдерди рд╕реБрд╡рд┐рдзрд╛рдПрдБ
рд╕реНрдкрд╖реНрдЯ рд╕рдорд╕реНрдпрд╛ рдиреЗрд╕реНрдЯрд┐рдВрдЧ рдХреЗ рд╕реНрддрд░ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдирд╛ рд╣реИред рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ, рдЗрд╕рдХреЗ рд▓рд┐рдП рдкрд╛рдпрдерди рдЯреИрдм (рдпрд╛ рд╕реНрдкреЗрд╕) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдХреБрдЫ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╡реИрд╢реНрд╡рд┐рдХ рдЪрд░ рдореЗрдВ рд╡рд░реНрддрдорд╛рди рдЗрдВрдбреЗрдВрдЯреЗрд╢рди рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдЬреЛ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдФрд░ рд▓реЗрдХреНрд╕рд░ рджреЛрдиреЛрдВ рдХреЗ рд▓рд┐рдП рд╕реБрд▓рдн рд╣реИред рдмрд╛рдЗрд╕рди рдореИрдиреБрдЕрд▓ рдХрд╛ рдХрд╣рдирд╛ рд╣реИ рдХрд┐
yylloc
рдХреЛ
yylloc
рдЧреНрд▓реЛрдмрд▓ рд╡реИрд░рд┐рдПрдмрд▓ рдореЗрдВ рдкрд╛рда рдореЗрдВ рдмрд╕ рдкрд╛рд░реНрд╕ рдХрд┐рдП рдЧрдП рдЯреЛрдХрди рдХреА рд╕реНрдерд┐рддрд┐ рдХреА рдЙрдореНрдореАрдж рд╣реИред
yylloc
рдЪрд╛рд░ рддрддреНрд╡реЛрдВ рдХреА рдПрдХ рд╕рдВрд░рдЪрдирд╛ рд╣реИ:
first_line, first_column, last_line last_column
ред
first_line
рд╣рдо рд╡рд░реНрддрдорд╛рди рд▓рд╛рдЗрди рдХреА рд╕рдВрдЦреНрдпрд╛ (рдбрд┐рдмрдЧрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реИ, рдФрд░ рдпрд╣ рдореЗрд░реЗ рдХрд╛рдо рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ) рдХреЛ
last_column
рдХрд░реЗрдЧрд╛,
last_column
рд╣рдо рдЗрдВрдбреЗрдВрдЯ рд░рдЦреЗрдВрдЧреЗред
рд╣рдо рдХреЛрдб рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдХрд░рддреЗ рд╣реИрдВред рд▓реЗрд╕рд░ рдореЗрдВ, yylloc рдЪрд░ рдХреЗ рдкреНрд░рдХрд╛рд░ рдФрд░ рд▓рд╛рдЗрди рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд▓рд┐рдП рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ:
extern YYLTYPE yylloc; #define YY_USER_INIT yylloc.first_line=1;
рдЬрдм рд╣рдо рдПрдХ рдирдИ рдкрдВрдХреНрддрд┐ рдХреЛ рдкреВрд░рд╛ рдХрд░рддреЗ рд╣реИрдВ:
yylloc.first_line++; yylloc.last_column = 0; isNewLine = true;
рдпрджрд┐ рдХреЛрдИ рд░реЗрдЦрд╛ рд░рд┐рдХреНрдд рд╕реНрдерд╛рди рд╕реЗ рд╢реБрд░реВ рд╣реЛрддреА рд╣реИ:
if (isNewLine == true && 0 == yyleng % SPACES_PER_INDENT) yylloc.last_column = yyleng / SPACES_PER_INDENT; isNewLine = false;
yyleng
- рдЯреЗрдореНрдкрд▓реЗрдЯ рджреНрд╡рд╛рд░рд╛ рдкрд╛рдпрд╛ рдЧрдпрд╛ рдЯреЛрдХрди рдХреА рд▓рдВрдмрд╛рдИред рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ,
SPACES_PER_INDENT
рдХреЛ 4 (рдорд╛рдирдХ рджреНрд╡рд╛рд░рд╛) рд╕реЗрдЯ рдХрд░реЗрдВред
рдпрджрд┐ рдкрдВрдХреНрддрд┐ рдЯреИрдм рд╡рд░реНрдг рд╕реЗ рд╢реБрд░реВ рд╣реЛрддреА рд╣реИ:
if (isNewLine == true) yylloc.last_column = yyleng; isNewLine = false;
рдЕрдм рд╣рдо рд▓рд╛рдЗрди рдХрд╛рдЙрдВрдЯ рдХреЛ рд╕рд╣реА рдХрд░реЗрдВрдЧреЗред рдЕрдЬрдЧрд░ рдореЗрдВ рдЯреНрд░рд┐рдкрд▓ рдЙрджреНрдзрд░рдг рд╣реИрдВ, рдЖрдорддреМрд░ рдкрд░ рдкреНрд░рд▓реЗрдЦрди рдкрд░ рд▓рдВрдмреА рдЯрд┐рдкреНрдкрдгреА рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрдкреЗрдХреНрд╖рд╛ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦрддреЗ рд╣реИрдВ:
static string skipMessage(string _ch){ string ch; string str = _ch; _ch = _ch[0]; bool skip = false; int count = 1; for(;;ch = yyinput()) { str += ch; if (ch == _ch){ if (count == 3) return str; else count++; } else count = 1; if ("\n" == ch || "\r" == ch) yylloc.first_line++; } }
рдпрд╣рд╛рдВ, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдХреЛрдИ рд╡реНрдпрдХреНрддрд┐ рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд╕рд╛рде рдорд┐рд▓ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдлрд┐рд░ рд▓рд╛рдЗрди рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реЛрдЧрд╛ - рд╣рдо regexp рджреНрд╡рд╛рд░рд╛ рдЦрд╛рдП рдЧрдП рд▓рд╛рдЗрдиреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реЛрдВрдЧреЗ (рдпрд╛ рд╣рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рдпрджрд┐ рд╣рд╛рдВ, рддреЛ рд╡рд┐рдзрд┐ рд▓рд┐рдЦреЗрдВ)ред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдЯрд┐рдкреНрдкрдгреА рд▓рд╛рдЗрди рдХреЛ рдЕрдирджреЗрдЦрд╛ рдХрд░рдирд╛ рди рднреВрд▓реЗрдВ:
static void skipComments(){ for(char ch = yyinput();;ch = yyinput()) { if ('\0' == ch || '\n' == ch || '\r' == ch) { yylloc.first_line++; break; } } }
рд╣рдо рд╕реНрдЯреИрдХ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреЛ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред
рдиреЗрд╕реНрдЯрд┐рдВрдЧ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдирд┐рд░реНрдзрд╛рд░рдг рдХрд░реЗрдВ
рд╣рдо рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХрд╛рд░реНрдп рдХрд░рддреЗ рд╣реИрдВред
рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП, рд╣рдо рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ:
typedef pair <string, int> meta_data;
рд╣рдордиреЗ рд╕реНрдЯреИрдХ рдкрд░
<__, >
рдХреА рдПрдХ рдЬреЛрдбрд╝реА рд▓рдЧрд╛рдИ
class_def: CLASS classname inheritance COLON suite { int indent = @1.last_column;
рд╡рд░реНрддрдорд╛рди рдЗрдВрдбреЗрдВрдЯ рд╕реЗ рдкрд╣рд▓реЗ рд╕реНрдЯреИрдХ рдХреЛ рдЦрд╛рд▓реА рдХрд░рдиреЗ рдХрд╛ рдХрд╛рд░реНрдп:
static void clean_stack( meta_stack& stack, int indent ) { while(!stack.empty()) { if( indent > stack.top().second ) break; stack.pop(); } }
рдЦреИрд░, рд╣рдо рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдкреВрд░рд╛ рдирд╛рдо рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ:
func_def: DEF funcname LBRACE func_args_list RBRACE COLON suite { string fnc_name = $2; int indent = @1.last_column; clean_stack( class_st, indent ); meta_stack tmp_class_st(class_st); while (!tmp_class_st.empty()) { fnc_name = tmp_class_st.top().first + "." + fnc_name; tmp_class_st.pop(); } }
рдирд┐рд╖реНрдХрд░реНрд╖
рдореИрдВрдиреЗ рд▓реЗрдЦ рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдирд╛ рд╢реБрд░реВ рдирд╣реАрдВ рдХрд┐рдпрд╛, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдШреЛрд╖рдгрд╛ рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд╕рдорд╛рди рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЗрд╕рдХреА рдЕрдкрдиреА рдХрдард┐рдирд╛рдЗрдпрд╛рдВ рд╣реИрдВред рдЕрдЧрд░ рд░реБрдЪрд┐ рд╣реИ - рдпрд╣рд╛рдБ github рдкрд░ рдореЗрд░реА рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рд╣реИ:
https://github.com/sagod/pyparser ред рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ, рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ рдФрд░ рдкреВрд▓ рдЕрдиреБрд░реЛрдзреЛрдВ рдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИред
рд╕рд╛рд╣рд┐рддреНрдп