рд╡рд╛рдо рдкреБрдирд░рд╛рд╡рд░реНрддреА рдЦреВрдВрдЯреА рд╡реНрдпрд╛рдХрд░рдг

рдореИрдВрдиреЗ рдХрдИ рдмрд╛рд░ рдПрдХ рдареЛрдХрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдмрд╛рдИрдВ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛, рдФрд░ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХрд╛ рд╕рдордп рд╣реИред рдореБрдЦреНрдп рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдПрдХ рдмрд╛рдИрдВ рдкреБрдирд░рд╛рд╡рд░реНрддреА рд╡рдВрд╢ рдХреЗ рд╕рд╛рде рдПрдХ рдкрд╛рд░реНрд╕рд░ рдПрдХ рд╕реНрдЯреИрдХ рдЕрддрд┐рдкреНрд░рд╡рд╛рд╣ рдХреЗ рдХрд╛рд░рдг рддреБрд░рдВрдд рджреБрд░реНрдШрдЯрдирд╛рдЧреНрд░рд╕реНрдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред



рдЗрд╕ рдХрд╛рд▓реНрдкрдирд┐рдХ рд╡реНрдпрд╛рдХрд░рдг рдирд┐рдпрдо рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:


expr: expr '+' term | term 

рдЕрдЧрд░ рд╣рдордиреЗ рд╡реНрдпрд╛рдХрд░рдг рдХреЗ рдЗрд╕ рдЯреБрдХрдбрд╝реЗ рдХреЛ рд╡рд╛рдо-рдкреБрдирд░рд╛рд╡рд░реНрддреА рдкрд╛рд░реНрд╕рд░ рдкрджреНрдзрддрд┐ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛, рддреЛ рд╣рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдореЗрдВ рд╕реЗ рдХреБрдЫ рдорд┐рд▓реЗрдЧрд╛:


 def expr(): if expr() and expect('+') and term(): return True if term(): return True return False 

рдЗрд╕ рдкреНрд░рдХрд╛рд░, expr() рдХреЗ рд▓рд┐рдП рдПрдХ рдХреЙрд▓ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ expr() рдХреЗ рд▓рд┐рдП рдПрдХ рдХреЙрд▓ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рдПрдХ рдХреЙрд▓ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ ... рдпрд╣ рдХреЗрд╡рд▓ рдПрдХ рд░реЗрдХ рдУрд╡рд░рдлреНрд▓реЛ рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдПрдХ RecursionError рдЕрдкрд╡рд╛рдж рдХреЗ рд░реВрдк рдореЗрдВ рд╡реНрдпрдХреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред


рдкрд╛рд░рдВрдкрд░рд┐рдХ рд╕рдорд╛рдзрд╛рди рд╡реНрдпрд╛рдХрд░рдг рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдирд╛ рд╣реИред рдкрд┐рдЫрд▓реЗ рднрд╛рдЧреЛрдВ рдореЗрдВ, рдореИрдВрдиреЗ рдРрд╕рд╛ рд╣реА рдХрд┐рдпрд╛ред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдКрдкрд░ рджрд┐рдП рдЧрдП рд╡реНрдпрд╛рдХрд░рдг рдирд┐рдпрдо рдХреЛ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:


 expr: term '+' expr | term 

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдкрд╛рд░реНрд╕ рдЯреНрд░реА рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рдЪрд░рдг рдореЗрдВ, рдЗрд╕рдХрд╛ рдЖрдХрд╛рд░ рдЕрд▓рдЧ рд╣реЛрдЧрд╛ред рдпрд╣ рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрд░реНрдмрд╛рдж рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдЕрдЧрд░ рд╣рдордиреЗ рд╡реНрдпрд╛рдХрд░рдг рдореЗрдВ '-' рдСрдкрд░реЗрдЯрд░ рдХреЛ рдЬреЛрдбрд╝рд╛ рд╣реИ (рдЪреВрдВрдХрд┐ a - (b - c) рд╕рдорд╛рди (a - b) - c ) рдХреЗ рд╕рдорд╛рди рдирд╣реАрдВ рд╣реИред рдпрд╣ рдЖрдорддреМрд░ рдкрд░ рд╕рдореВрд╣ рдФрд░ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдЬреИрд╕реЗ рдЕрдзрд┐рдХ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдкреАрдИрдЬреА рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рд╣рдо рдЙрдкрд░реЛрдХреНрдд рдирд┐рдпрдо рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ:


 expr: term ('+' term)* 

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рд╣реИ рдХрд┐ рд╡рд░реНрддрдорд╛рди рдкрд╛рдпрдерди рд╡реНрдпрд╛рдХрд░рдг рдХреЛ рдкреИрдЬрди рдкрд╛рд░реНрд╕рд░ рдХреЗ рд▓рд┐рдП рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ (рдЬрд┐рд╕рдореЗрдВ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдирд┐рдпрдореЛрдВ рдХреЗ рд╕рд╛рде рд╕рдорд╛рди рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВ)ред


рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдХ рдЫреЛрдЯреА рд╕реА рд╕рдорд╕реНрдпрд╛ рд╣реИ: рдЪреВрдВрдХрд┐ '+' рдФрд░ '-' (рдЬреИрд╕реЗ рдкрд╛рдпрдерди) рдореЗрдВ рдСрдкрд░реЗрдЯрд░ рдЬреНрдпрд╛рджрд╛рддрд░ рдмрд╛рдЗрдирд░реА рд╣реЛрддреЗ рд╣реИрдВ, рдЬрдм рд╣рдо a + b + c рдЬреИрд╕реА a + b + c рдЪреАрдЬрд╝ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдХреЗ рдкрд░рд┐рдгрд╛рдо рд╕реЗ рдЧреБрдЬрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИ (рдЬреЛ рдореВрд▓ рд░реВрдк рд╕реЗ рдПрдХ рд╡рд╛рдордкрдВрдереА-рдкреБрдирд░рд╛рд╡рд░реНрддреА рдкреЗрдбрд╝ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП ['a', '+', 'b', '+', 'c'] (рдЬреЛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧреА [['a', '+', 'b'] , '+', 'c'] )ред


рдореВрд▓ рдмрд╛рдИрдВ рдкреБрдирд░рд╛рд╡рд░реНрддреА рд╡реНрдпрд╛рдХрд░рдг рд╡рд╛рдВрдЫрд┐рдд рд╕рдВрдЧрддрд┐ рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕рдВрдХреЗрдд рджреЗрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕ рд░реВрдк рдореЗрдВ рд╕реАрдзреЗ рдкрд╛рд░реНрд╕рд░ рдЙрддреНрдкрдиреНрди рдХрд░рдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред рдФрд░ рд╣рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ! рдПрдХ рдкрд╛рдардХ рдиреЗ рдЧрдгрд┐рддреАрдп рдкреНрд░рдорд╛рдг рдХреЗ рд╕рд╛рде рдПрдХ рдЕрдЪреНрдЫреА рдЪрд╛рд▓ рдмрддрд╛рдИ рдЬрд┐рд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЖрд╕рд╛рди рдерд╛ред рдЕрдм рдореИрдВ рд╕рдордЭрд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ред


рдЖрдЗрдП рдЗрдирдкреБрдЯ foo + bar + baz рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЛ рджреЗрдЦреЗрдВред рдЬрд┐рд╕ рдкреЗрдбрд╝ рдХреЛ рд╣рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд╡рд╣ (foo + bar) + baz рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИред рдпрд╣ expr() рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рддреАрди рдмрд╛рдИрдВ-рдкреБрдирд░рд╛рд╡рд░реНрддреА рдХреЙрд▓ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ: рдПрдХ рд╢реАрд░реНрд╖-рд╕реНрддрд░реАрдп рдСрдкрд░реЗрдЯрд░ '+' (рдЬреЛ рдХрд┐, рджреВрд╕рд░рд╛) рд╕реЗ рдореЗрд▓ рдЦрд╛рддреА рд╣реИ; рдПрдХ рдФрд░ - рдЖрдВрддрд░рд┐рдХ рдСрдкрд░реЗрдЯрд░ '+' (рдпрд╛рдиреА рдкрд╣рд▓рд╛); рдФрд░ рддреАрд╕рд░рд╛ рджреВрд╕рд░рд╛ рд╡рд┐рдХрд▓реНрдк (рдпрд╛рдиреА, term ) рдХрд╛ рд╡рд┐рдХрд▓реНрдк рд╣реИред


рдЪреВрдВрдХрд┐ рдореИрдВ рд╡рд┐рд╢реЗрд╖ рдЙрдкрдХрд░рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЖрд░реЗрдЦреЛрдВ рдХреЛ рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдЕрдЪреНрдЫрд╛ рдирд╣реАрдВ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рдореИрдВ ASCII рдХрд▓рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдпрд╣рд╛рдВ рджрд┐рдЦрд╛рдКрдВрдЧрд╛:


 expr------------+------+ | \ \ expr--+------+ '+' term | \ \ | expr '+' term | | | | term | | | | | 'foo' 'bar' 'baz' 

рд╡рд┐рдЪрд╛рд░ рдпрд╣ рд╣реИ рдХрд┐ expr() рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ, рд╣рдореЗрдВ рдПрдХ "рдУрд░реЗрдХрд▓" рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдЬреЛ рд╣рдореЗрдВ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдкрд╣рд▓рд╛ рд╡рд┐рдХрд▓реНрдк рдЪреБрдирдирд╛ рд╣реИ (рдЕрд░реНрдерд╛рдд, exprive call to expr() ) рдпрд╛ рджреВрд╕рд░рд╛ (рд╡рд╣ рд╣реИ, term() рдХреЙрд▓)ред expr() рдХреЗ рдкрд╣рд▓реЗ рдХреЙрд▓ рдкрд░ expr() рдСрд░реЗрдХрд▓ рдХреЛ рд╣рдореЗрдВ рдкрд╣рд▓реЗ рд╡рд┐рдХрд▓реНрдк ( expr() ) рдХрд╛ рдкрд╛рд▓рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣рдирд╛ рдЪрд╛рд╣рд┐рдП; рджреВрд╕рд░реЗ (рдкреБрдирд░рд╛рд╡рд░реНрддреА) рдХреЙрд▓ рдореЗрдВ - рдЗрд╕реА рддрд░рд╣, рд▓реЗрдХрд┐рди рддреАрд╕рд░реЗ рдореЗрдВ рд╣рдореЗрдВ term() рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрдХреЗрдд рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдПред рдХреЛрдб рдореЗрдВ, рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛:


 def expr(): if oracle() and expr() and expect('+') and term(): return True if term(): return True return False 

рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рдУрд░реЗрдХрд▓ рдХреЛ рдХреИрд╕реЗ рд▓рд┐рдЦрдирд╛ рд╣реИ? рдЖрдЗрдП рджреЗрдЦреЗрдВ ... рд╣рдо рдХреЙрд▓ рд╕реНрдЯреИрдХ рдореЗрдВ (рдмрд╛рдПрдВ-рдкреБрдирд░рд╛рд╡рд░реНрддреА) expr() рдХреЙрд▓ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдирд┐рдореНрди рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдореЗрдВ '+' рдСрдкрд░реЗрдЯрд░реЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд╕рд╛рде рддреБрд▓рдирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрджрд┐ рдХреЙрд▓ рд╕реНрдЯреИрдХ рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ рдХреА рд╕рдВрдЦреНрдпрд╛ рд╕реЗ рдЕрдзрд┐рдХ рдЧрд╣рд░рд╛ рд╣реИ, рддреЛ рдУрд░реЗрдХрд▓ рдХреЛ рдЧрд▓рдд (рд╣рдореЗрдВ рдЪреБрдирдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд░рдирд╛) рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдореИрдВ sys._getframe() рд╕рд╛рде sys._getframe() рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрдВрддрдЬрд╛рд░ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛, рд▓реЗрдХрд┐рди рдПрдХ рдмреЗрд╣рддрд░ рддрд░реАрдХрд╛ рд╣реИ: рдЪрд▓реЛ рдХреЙрд▓ рд╕реНрдЯреИрдХ рдлреНрд▓рд┐рдк рдХрд░реЗрдВ!


рд╡рд┐рдЪрд╛рд░ рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдПрдХ рдХреЙрд▓ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд╣рд╛рдВ рдУрд░реЗрдХрд▓ рдЧрд▓рдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдкрд░рд┐рдгрд╛рдо рдХреЛ рдмрдЪрд╛рддрд╛ рд╣реИред рдпрд╣ рд╣рдореЗрдВ рдЕрдиреБрдХреНрд░рдо expr() -> term() -> 'foo' ред (рдЗрд╕реЗ рдкреНрд░рд╛рд░рдВрднрд┐рдХ term рд▓рд┐рдП рдПрдХ рдкрд╛рд░реНрд╕ рдЯреНрд░реА рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, 'foo' , 'foo' ред рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб рдХреЗрд╡рд▓ True , рд▓реЗрдХрд┐рди рд▓реЗрдЦреЛрдВ рдХреА рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЗ рджреВрд╕рд░реЗ рднрд╛рдЧ рдореЗрдВ рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рд╣реА рджрд┐рдЦрд╛рдпрд╛ рдХрд┐ рдкрд╛рд░реНрд╕ рдЯреНрд░реА рдХреЛ рдХреИрд╕реЗ рд╡рд╛рдкрд╕ рдХрд┐рдпрд╛ рдЬрд╛рдПред) рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рдСрд░реЗрдХрд▓ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕реЗ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдмрд╕ рдкрд╣рд▓реА рдХреЙрд▓ рдкрд░ False рд▓реМрдЯреЗрдВ - рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдХреЛрдИ рд╕реНрдЯреИрдХ рдЪреЗрдХрд┐рдВрдЧ рдпрд╛ рдкреАрдпрд░рд┐рдВрдЧ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред


рдлрд┐рд░ рд╣рдо expr() рдлрд┐рд░ рд╕реЗ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдЗрд╕ рдмрд╛рд░ oracle True рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди expr() рдХреЗ рд▓рд┐рдП рдмрд╛рдИрдВ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдХреЙрд▓ рдХреЗ рдмрдЬрд╛рдп рд╣рдо рдкрд┐рдЫрд▓реЗ рдХреЙрд▓ рд╕реЗ рд╕рд╣реЗрдЬреЗ рдЧрдП рдкрд░рд┐рдгрд╛рдо рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдФрд░ рдЪреВрдВрдХрд┐ рдЕрдкреЗрдХреНрд╖рд┐рдд рдСрдкрд░реЗрдЯрд░ '+' рдФрд░ рдЕрдЧрд▓рд╛ рдЙрдкрдпреБрдХреНрдд рдЯреЛрдХрди рднреА рдореМрдЬреВрдж рд╣реИрдВ, рдЗрд╕рд╕реЗ рд╣рдореЗрдВ foo + bar рд▓рд┐рдП рдПрдХ рдкрд╛рд░реНрд╕ рдЯреНрд░реА рдорд┐рд▓реЗрдЧрд╛ред


рдПрдХ рдмрд╛рд░ рдлрд┐рд░ рд╣рдо рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЛ рджреЛрд╣рд░рд╛рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рд╕реЗ рд╕рдм рдХреБрдЫ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ: рдЗрд╕ рдмрд╛рд░ рд╣рдореЗрдВ рдкреВрд░реНрдг рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рдПрдХ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдЯреНрд░реА рдорд┐рд▓рддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдмрд╛рдПрдВ-рдкреБрдирд░рд╛рд╡рд░реНрддреА ( (foo + bar) + baz ) рд╣реИред


рдлрд┐рд░ рд╣рдо рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЛ рдлрд┐рд░ рд╕реЗ рджреЛрд╣рд░рд╛рддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдЗрд╕ рдмрд╛рд░, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдУрд░реЗрдХрд▓ True , рдФрд░ рдкрд┐рдЫрд▓реА рдХреЙрд▓ рдХрд╛ рд╕рд╣реЗрдЬрд╛ рдЧрдпрд╛ рдкрд░рд┐рдгрд╛рдо рднреА рдЙрдкрд▓рдмреНрдз рд╣реИ, рдФрд░ рдХреЛрдИ '+' рдСрдкрд░реЗрдЯрд░ рдирд╣реАрдВ рд╣реИ, рдФрд░ рдкрд╣рд▓рд╛ рд╡реИрдХрд▓реНрдкрд┐рдХ рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдо рджреВрд╕рд░реЗ рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рд╕рдлрд▓ рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдХреЗрд╡рд▓ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╢рдмреНрдж ( 'foo' ) рдкрд╛рддрд╛ рд╣реИред рдпрд╣ рдкрд░рд┐рдгрд╛рдо рдкрд╣рд▓реЗ рд╡рд┐рдХрд▓реНрдк рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЦрд░рд╛рдм рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕ рд╕реНрддрд░ рдкрд░ рд╣рдо рд╕рдмрд╕реЗ рд▓рдВрдмреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг (рдпрд╛рдиреА (foo + bar) + baz ) рдХреЛ рд░реЛрдХрддреЗ рд╣реИрдВ рдФрд░ рдмрдЪрд╛рддреЗ рд╣реИрдВред


рдЗрд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рдХреЛрдб рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдкрд╣рд▓реА рдмрд╛рд░ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд┐рдпрд╛ рддрд╛рдХрд┐ expr() рдХреЙрд▓ рдХреЛ expr() рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд▓реЗрдлреНрдЯ-рд░рд┐рдХрд░реНрд╕рд┐рд╡ рдХреЙрд▓ рдХреЗ рд╕рд╛рде рдорд┐рд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХреЗред рдЪрд▓реЛ рдЗрд╕реЗ oracle_expr() ред рдХреЛрдб:


 def expr(): if oracle_expr() and expect('+') and term(): return True if term(): return True return False 

рдЕрдЧрд▓рд╛, рд╣рдо рдПрдХ рдЖрд╡рд░рдг рд▓рд┐рдЦреЗрдВрдЧреЗ рдЬреЛ рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рддрд░реНрдХ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ рдЪрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ (рдЪрд┐рдВрддрд╛ рди рдХрд░реЗрдВ, рдореБрдЭреЗ рдмрд╛рдж рдореЗрдВ рдЗрд╕рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдорд┐рд▓ рдЬрд╛рдПрдЧрд╛)ред oracle_expr() рдлрд╝рдВрдХреНрд╢рди рд╡реИрд╢реНрд╡рд┐рдХ рдЪрд░ рдХреЛ рдкрдврд╝реЗрдЧрд╛, рдФрд░ рдЖрд╡рд░рдг рдЗрд╕реЗ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░реЗрдЧрд╛:


 saved_result = None def oracle_expr(): if saved_result is None: return False return saved_result def expr_wrapper(): global saved_result saved_result = None parsed_length = 0 while True: new_result = expr() if not new_result: break new_parsed_length = <calculate size of new_result> if new_parsed_length <= parsed_length: break saved_result = new_result parsed_length = new_parsed_length return saved_result 

рдХреЛрдб, рдЬрд╝рд╛рд╣рд┐рд░ рд╣реИ, рднрдпрд╛рдирдХ рд╣реИ, рд▓реЗрдХрд┐рди рдХрдо рд╕реЗ рдХрдо рдпрд╣ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХрд╛ рд╕рд╛рд░ рдмрддрд╛рддрд╛ рд╣реИред рдЖрдЗрдП рдЗрд╕реЗ рд░рд┐рдлрд▓реЗрдХреНрдЯрд░ рдХрд░реЗрдВ рддрд╛рдХрд┐ рд╣рдо рдЗрд╕ рдкрд░ рдЧрд░реНрд╡ рдХрд░ рд╕рдХреЗрдВред


рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╕рдордЭ (рдЬреЛ рдореЗрд░рд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдореИрдВ рд╢рд╛рдпрдж рдпрд╣ рдиреЛрдЯрд┐рд╕ рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдкрд╣рд▓рд╛ рд╡реНрдпрдХреНрддрд┐ рдирд╣реАрдВ рд╣реВрдВ) рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ рдЪрд░ рдХреЗ рдмрдЬрд╛рдп рд╕рдВрд╕реНрдорд░рдг рдХреИрд╢ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рдореЗрдВ рд╣рдо рдХреЙрд▓ рд╕реЗ рдХреЙрд▓ рдкрд░ рд░рд┐рдЬрд▓реНрдЯ рд╕реНрдЯреЛрд░ рдХрд░реЗрдВрдЧреЗред рддреЛ рд╣рдо рдПрдХ рдЕрд▓рдЧ рдлрд╝рдВрдХреНрд╢рди oracle_expr() рдЫреБрдЯрдХрд╛рд░рд╛ oracle_expr() , рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдорд╛рдирдХ рдХреЙрд▓ рдЙрддреНрдкрдиреНрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ expr() рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рдмрд╛рдИрдВ рдУрд░ рдпрд╛ рджрд╛рдИрдВ рдУрд░ рдПрдХ рдкреБрдирд░рд╛рд╡рд░реНрддреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╣реИред


рддреЛ, рд╣рдореЗрдВ рдПрдХ рдЕрд▓рдЧ @memoize_left_rec рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреЗрд╡рд▓ рдмрд╛рдПрдВ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдирд┐рдпрдореЛрдВ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ oracle_expr() рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ, oracle_expr() рдХреИрд╢ рд╕реЗ рд╕рдВрдЧреНрд░рд╣реАрдд рдорд╛рди рдХреЛ oracle_expr() , рдФрд░ рдЗрд╕рдореЗрдВ рдПрдХ рд▓реВрдк рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рдХрдИ рдмрд╛рд░ expr() рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ, рдЬрдм рддрдХ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдирдП рдкрд░рд┐рдгрд╛рдо рдкрд┐рдЫрд▓реЗ рдПрдХ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рдХреЗ рдХрднреА рд▓рдВрдмреЗ рд╣рд┐рд╕реНрд╕реЗ рдХреЗ рд╕рд╛рде рддреБрд▓рдиреАрдп рди рд╣реЛред рдФрд░, рдЬрд╝рд╛рд╣рд┐рд░ рд╣реИ, рдЪреВрдВрдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдЗрдирдкреБрдЯ рд╕реНрдерд┐рддрд┐ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рд╡рд┐рдзрд┐ рдЕрд▓рдЧ рд╕реЗ рдХреИрд╢ рдХреА рдЬрд╛рддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдмреИрдХрдЯреНрд░реИрдХрд┐рдВрдЧ рдпрд╛ рдХреБрдЫ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдирд┐рдпрдореЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЪрд┐рдВрддрд┐рдд рдирд╣реАрдВ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдЬрд┐рд╕ рдЦрд┐рд▓реМрдирд╛ рд╡реНрдпрд╛рдХрд░рдг рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛, рдЙрд╕рдХреЗ рд▓рд┐рдП expr рдФрд░ term рджреЛрдиреЛрдВ рдкреБрдирд░рд╛рд╡рд░реНрддреА рд╣реИрдВ)ред


рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рдХрд╛ рдПрдХ рдФрд░ рд▓рд╛рдн рдЬреЛ рдореИрдВрдиреЗ рддреАрд╕рд░реЗ рднрд╛рдЧ рдореЗрдВ рдмрдирд╛рдпрд╛ рд╣реИ, рд╡рд╣ рдпрд╣ рдЬрд╛рдВрдЪрдирд╛ рдЖрд╕рд╛рди рдмрдирд╛рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдирдпрд╛ рдкрд░рд┐рдгрд╛рдо рдкреБрд░рд╛рдиреЗ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рд▓рдВрдмрд╛ рд╣реИ: mark() рд╡рд┐рдзрд┐ рдЗрдирдкреБрдЯ рдЯреЛрдХрди рдХреА рд╕рд░рдгреА рдореЗрдВ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЛ рд╡рд╛рдкрд╕ рд▓реМрдЯрд╛рддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдмрд╕ parsed_length рдмрдЬрд╛рдп рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


рдореИрдВ рдЗрд╕ рдмрд╛рдд рдХрд╛ рдкреНрд░рдорд╛рдг рдЫреЛрдбрд╝ рджреЗрддрд╛ рд╣реВрдВ рдХрд┐ рдпрд╣ рдПрд▓реНрдЧреЛрд░рд┐рдердо рд╣рдореЗрд╢рд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЪрд╛рд╣реЗ рд╡рд╣ рд╡реНрдпрд╛рдХрд░рдг рдХрд┐рддрдирд╛ рд╣реА рдкрд╛рдЧрд▓ рдХреНрдпреЛрдВ рди рд╣реЛред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдореИрдВрдиреЗ рдЗрд╕реЗ рдкрдврд╝рд╛ рднреА рдирд╣реАрдВ рдерд╛ред рдореИрдВ рджреЗрдЦрддрд╛ рд╣реВрдВ рдХрд┐ рдпрд╣ рд╕рд░рд▓ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЬреИрд╕реЗ рдХрд┐ рдореЗрд░реЗ рдЦрд┐рд▓реМрдирд╛ рд╡реНрдпрд╛рдХрд░рдг рдореЗрдВ expr , рд╕рд╛рде рд╣реА рдХреБрдЫ рдФрд░ рдЬрдЯрд┐рд▓ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╡реИрдХрд▓реНрдкрд┐рдХ рдореЗрдВ рд╡реИрдХрд▓реНрдкрд┐рдХ рддрддреНрд╡реЛрдВ рдХреЗ рдкреАрдЫреЗ рдЫрд┐рдкреА рд╣реБрдИ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рдпрд╛ рдХрдИ рдирд┐рдпрдореЛрдВ рдХреЗ рдмреАрдЪ рдкрд╛рд░рд╕реНрдкрд░рд┐рдХ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ)ред рд╕рдмрд╕реЗ рдХрдард┐рди рд╕реНрдерд┐рддрд┐ рдЬрд┐рд╕реЗ рдореИрдВ рдкрд╛рдпрдерди рд╡реНрдпрд╛рдХрд░рдг рдореЗрдВ рдпрд╛рдж рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ, рдЕрднреА рднреА рдЗрд╕ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рджреНрд╡рд╛рд░рд╛ рд╣рд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рд╕рд┐рд░реНрдл рдкреНрд░рдореЗрдп рдФрд░ рдЗрд╕реЗ рд╕рд╛рдмрд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд▓реЛрдЧреЛрдВ рдкрд░ рднрд░реЛрд╕рд╛ рдХрд░рддрд╛ рд╣реВрдВред


рдЪрд▓реЛ рдпреБрджреНрдз рдХреЛрдб рд▓рд┐рдЦрддреЗ рд╣реИрдВред


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдкрд╛рд░реНрд╕рд░ рдЬрдирд░реЗрдЯрд░ рдХреЛ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдХреМрди рд╕реЗ рдирд┐рдпрдо рдкреБрдирд░рд╛рд╡рд░реНрддреА рд╣реИрдВред рдпрд╣ рдЧреНрд░рд╛рдл рд╕рд┐рджреНрдзрд╛рдВрдд рдореЗрдВ рдПрдХ рд╣рд▓ рд╕рдорд╕реНрдпрд╛ рд╣реИред рдореИрдВ рдпрд╣рд╛рдБ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдирд╣реАрдВ рджрд┐рдЦрд╛рдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдБ, рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдореИрдВ рдЗрд╕реЗ рдФрд░ рднреА рд╕рд░рд▓ рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдБред рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рд╡реНрдпрд╛рдХрд░рдг рдореЗрдВ рдХреЗрд╡рд▓ рдмрд╛рдПрдВ-рдкреБрдирд░рд╛рд╡рд░реНрддреА рдирд┐рдпрдо рд╕реАрдзреЗ рдмрд╛рдПрдВ-рдкреБрдирд░рд╛рд╡рд░реНрддреА рд╣реЛрддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ рд╣рдорд╛рд░реЗ рдЦрд┐рд▓реМрдирд╛ рд╡реНрдпрд╛рдХрд░рдг рдореЗрдВ expr ред рдлрд┐рд░, рдмрд╛рдИрдВ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдмрд╕ рдПрдХ рд╡рд┐рдХрд▓реНрдк рдХреА рддрд▓рд╛рд╢ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬреЛ рд╡рд░реНрддрдорд╛рди рдирд┐рдпрдо рдХреЗ рдирд╛рдо рд╕реЗ рд╢реБрд░реВ рд╣реЛрдЧрд╛:


 def is_left_recursive(rule): for alt in rule.alts: if alt[0] == rule.name: return True return False 

рдЕрдм рд╣рдо рдкрд╛рд░реНрд╕рд░ рдЬрдирд░реЗрдЯрд░ рдХреЛ рдмрджрд▓ рджреЗрдВрдЧреЗ рддрд╛рдХрд┐ рдмрд╛рдПрдВ-рдкреБрдирд░рд╛рд╡рд░реНрддреА рдирд┐рдпрдореЛрдВ рдХреЗ рд▓рд┐рдП рдпрд╣ рдПрдХ рдФрд░ рдбреЗрдХреЛрд░реЗрдЯрд░ рдЙрддреНрдкрдиреНрди рдХрд░реЗред рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рддреАрд╕рд░реЗ рднрд╛рдЧ рдореЗрдВ, рд╣рдордиреЗ @memoize рдореЗрдВ рд╕рднреА рдкрд╛рд░реНрд╕рд░ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ @memoize ред рдЕрдм рд╣рдо рдЬрдирд░реЗрдЯрд░ рдореЗрдВ рдПрдХ рдЫреЛрдЯрд╛ рдмрджрд▓рд╛рд╡ рдХрд░реЗрдВрдЧреЗ, рддрд╛рдХрд┐ рдмрд╛рдПрдВ-рдкреБрдирд░рд╛рд╡рд░реНрддреА рдирд┐рдпрдореЛрдВ рдХреЗ рд▓рд┐рдП рд╣рдо @memoize_left_rec рдЙрдкрдпреЛрдЧ @memoize_left_rec , рдФрд░ рдлрд┐рд░ memoize_left_rec рдбреЗрдХреЛрд░реЗрдЯрд░ рдореЗрдВ рдЬрд╛рджреВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдВред рдмрд╛рдХреА рдЬрдирд░реЗрдЯрд░ рдФрд░ рдЕрдиреНрдп рдХреЛрдб рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ! (рд╣рд╛рд▓рд╛рдВрдХрд┐ рдореБрдЭреЗ рд╡рд┐рдЬрд╝реБрдЕрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдХреЛрдб рдХреЗ рд╕рд╛рде рдЯрд┐рдВрдХрд░ рдХрд░рдирд╛ рдкрдбрд╝рд╛)


рд╕рдВрджрд░реНрдн рдХреЗ рд▓рд┐рдП, рдпрд╣рд╛рдБ рдореВрд▓ @memoize рдбреЗрдХреЛрд░реЗрдЯрд░ @memoize , рднрд╛рдЧ 3 рд╕реЗ рдХреЙрдкреА рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ self рдПрдХ Parser рдЙрджрд╛рд╣рд░рдг рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдПрдХ memo рд╡рд┐рд╢реЗрд╖рддрд╛ рд╣реИ (рдПрдХ рдЦрд╛рд▓реА рд╢рдмреНрджрдХреЛрд╢ рдХреЗ рд╕рд╛рде рдЖрд░рдВрднреАрдХреГрдд) рдФрд░ mark() рдФрд░ reset() рддрд░реАрдХреЗ рдЬреЛ рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВред tokenizer:


 def memoize(func): def memoize_wrapper(self, *args): pos = self.mark() memo = self.memos.get(pos) if memo is None: memo = self.memos[pos] = {} key = (func, args) if key in memo: res, endpos = memo[key] self.reset(endpos) else: res = func(self, *args) endpos = self.mark() memo[key] = res, endpos return res return memoize_wrapper 

рдЗрдирдкреБрдЯ рд╕реНрдЯреНрд░реАрдо рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдП @memoize рдбреЗрдХреЛрд░реЗрдЯрд░ рдкрд┐рдЫрд▓реЗ рдХреЙрд▓ рдХреЛ рдпрд╛рдж рдХрд░рддрд╛ рд╣реИ - рдЗрдирдкреБрдЯ рдЯреЛрдХрди рдХреЗ (рдЖрд▓рд╕реА) рд╕рд░рдгреА рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ memo рд╢рдмреНрджрдХреЛрд╢ рд╣реИред memoize_wrapper рдХреА рдкрд╣рд▓реА рдЪрд╛рд░ рдкрдВрдХреНрддрд┐рдпрд╛рдБ рд╕рд╣реА memo рд╢рдмреНрджрдХреЛрд╢ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдкрд┐рдд memoize_wrapper ред


рдФрд░ рдпрд╣рд╛рдБ @memoize_left_rec ред рдХреЗрд╡рд▓ else рд╢рд╛рдЦрд╛ рдКрдкрд░ @memoize рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╕реЗ рдереЛрдбрд╝реА рднрд┐рдиреНрди рд╣реИ:


 def memoize_left_rec(func): def memoize_left_rec_wrapper(self, *args): pos = self.mark() memo = self.memos.get(pos) if memo is None: memo = self.memos[pos] = {} key = (func, args) if key in memo: res, endpos = memo[key] self.reset(endpos) else: # Prime the cache with a failure. memo[key] = lastres, lastpos = None, pos # Loop until no longer parse is obtained. while True: self.reset(pos) res = func(self, *args) endpos = self.mark() if endpos <= lastpos: break memo[key] = lastres, lastpos = res, endpos res = lastres self.reset(lastpos) return res return memoize_left_rec_wrapper 

рдпрд╣ рд╢рд╛рдпрдж рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ рдХрд┐ рдпрд╣ expr() рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рдХреИрд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдЧрд╛:


  @memoize_left_rec def expr(self): pos = self.mark() if ((expr := self.expr()) and self.expect('+') and (term := self.term())): return Node('expr', [expr, term]) self.reset(pos) if term := self.term(): return Node('term', [term]) self.reset(pos) return None 

рдкрд╛рд░реНрд╕рд┐рдВрдЧ foo + bar + baz рдХреЗ рдЙрджрд╛рд╣рд░рдг рдкрд░ред


рдЬрдм рднреА рдЖрдк expr() рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдХреЙрд▓ рдбреЗрдХреЛрд░реЗрдЯрд░ рджреНрд╡рд╛рд░рд╛ "рд╣реБрдХ" рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдкрд┐рдЫрд▓реЗ рдХреЙрд▓ рдХреА рддрд▓рд╛рд╢ рдХрд░ рд░рд╣рд╛ рд╣реИред рдкрд╣рд▓реА рдХреЙрд▓ рдкрд░, рд╣рдо else рд╢рд╛рдЦрд╛ рдореЗрдВ рдкрд╣реБрдБрдЪрддреЗ рд╣реИрдВ, рдЬрд╣рд╛рдБ рд╣рдо рдмрд╛рд░-рдмрд╛рд░ рд╕рдЬрд╛рдП рдЧрдП рдлрдВрдХреНрд╢рди expr() рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВред рдЬрд╛рд╣рд┐рд░ рд╣реИ, рд╣рдо рдлрд┐рд░ рд╕реЗ рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЗ рдкрд╛рд╕ рдкрд╣реБрдВрдЪреЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдЗрд╕ рдмрд╛рд░ рдХреИрд╢ рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХреБрдЫ рдореВрд▓реНрдп рд╣реИ, рдЗрд╕рд▓рд┐рдП рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдмрд╛рдзрд┐рдд рд╣реИред


рдЖрдЧреЗ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ? рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдХреИрд╢ рдорд╛рди рдХреА рдЧрдгрдирд╛ рдЗрд╕ рд▓рд╛рдЗрди рдкрд░ рдХреА рдЬрд╛рддреА рд╣реИ:


  # Prime the cache with a failure. memo[key] = lastres, lastpos = None, pos 

рдпрд╣ рдЗрд╕ рддрдереНрдп рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рд╕рдЬрд╛рдпрд╛ рдЧрдпрд╛ expr() None рджреЗрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдмрд╛рдж рдкрд╣рд▓рд╛ if expr() рдЧрд┐рд░рддрд╛ рд╣реИ (рдЬрдм expr: = self.expr() )ред рдпрд╣реА рд╣реИ, рд╣рдо рджреВрд╕рд░реЗ рдкрд░ рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВ if , рдЬреЛ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ (рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, 'foo' ) term рдкрд╣рдЪрд╛рдирддрд╛ рд╣реИ рдФрд░ Node рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджреЗрддрд╛ рд╣реИред рд╣рдо рдХрд╣рд╛рдБ рд╕реЗ рд╡рд╛рдкрд╕ рдЖ рд░рд╣реЗ рд╣реИрдВ? рдбреЗрдХреЛрд░реЗрдЯрд░ рдореЗрдВ while рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рд╣рдо рдПрдХ рдирдП рдкрд░рд┐рдгрд╛рдо ( Node рдЙрджрд╛рд╣рд░рдг) рдХреЗ рд╕рд╛рде рд╕рдВрд╕реНрдорд░рдг рдХреИрд╢ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдЕрдЧрд▓рд╛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдЪрд▓рд╛рддреЗ рд╣реИрдВред


expr() рдлрд┐рд░ рд╕реЗ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕ рд╕рдордп рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯреЗрдб рдкреБрдирд░рд╛рд╡рд░реНрддреА рдХреЙрд▓ Node (рд╢рдмреНрдж) рдХрд╛ рдХреИрд╢реНрдб рдЙрджрд╛рд╣рд░рдг рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА expect('+') ред рд╕рдм рдХреБрдЫ рдХреНрд░рдо рдореЗрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЕрдм рд╣рдо рдкрд╣рд▓реЗ '+' рдСрдкрд░реЗрдЯрд░ рдкрд░ рд╣реИрдВред рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рдПрдХ рд╢рдмреНрдж рдЦреЛрдЬрддреЗ рд╣реИрдВ рдЬреЛ рд╕рдлрд▓ рднреА рд╣реЛрддрд╛ рд╣реИ ( 'bar' рдкрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ)ред


рддреЛ рдЕрдм expr() , рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкрд╣рдЪрд╛рдиреЗ рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ foo + bar , while рд▓реМрдЯрддрд╛ рд╣реИ, рдЬреЛ рдПрдХ рд╣реА рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реИ: рдпрд╣ рд╕рдВрд╕реНрдорд░рдг рдХреИрд╢ рдХреЛ рдПрдХ рдирдП (рд▓рдВрдмреЗ) рдкрд░рд┐рдгрд╛рдо рдХреЗ рд╕рд╛рде рдЕрдкрдбреЗрдЯ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЕрдЧрд▓рд╛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИред


рдпрд╣ рдЦреЗрд▓ рдлрд┐рд░ рджреЛрд╣рд░рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдлрд┐рд░ рд╕реЗ, рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯреЗрдб рдкреБрдирд░рд╛рд╡рд░реНрддреА рдХреЙрд▓ expr() рдХреИрд╢ рд╕реЗ рдПрдХ рдирдпрд╛ рдкрд░рд┐рдгрд╛рдо (рдЗрд╕ рдмрд╛рд░ foo + bar ) рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ, рдФрд░ рд╣рдо рдПрдХ рдФрд░ '+' (рджреВрд╕рд░рд╛) рдФрд░ рджреВрд╕рд░рд╛ term ( 'baz' ) рджреЗрдЦрдиреЗ рдХреА рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдПрдХ Node (foo + bar) + baz рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдЗрд╕реЗ while рд▓реМрдЯрд╛рддреЗ рд╣реИрдВ, рдЬреЛ рдЗрд╕реЗ рдХреИрд╢ рдореЗрдВ рдбрд╛рд▓рддрд╛ рд╣реИ рдФрд░ рдлрд┐рд░ рд╕реЗ рджреЛрд╣рд░рд╛рддрд╛ рд╣реИред


рд▓реЗрдХрд┐рди рдЕрдм рд╣рдо рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреА рдПрдХ рдФрд░ рд╢рд╛рдЦрд╛ рдХреЗ рд╕рд╛рде рдЬрд╛рдПрдВрдЧреЗред рд╣рдо рдПрдХ рдФрд░ '+' рд╕реЗ рдорд┐рд▓рдиреЗ рдХреА рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рдирд╣реАрдВ рдкрд╛рддреЗ рд╣реИрдВ! рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдпрд╣ рдХреЙрд▓ expr() рдЕрдкрдиреЗ рджреВрд╕рд░реЗ рд╡рд┐рдХрд▓реНрдк рдкрд░ рд▓реМрдЯрддрд╛ рд╣реИ, рдФрд░ рдХреЗрд╡рд▓ term рджреЗрддрд╛ рд╣реИред рдЬрдм рдпрд╣ while рд╕реЗ рдкрд╣рд▓реЗ рдкреЙрдк рдЕрдк while , рддреЛ рдпрд╣ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдкрд░рд┐рдгрд╛рдо рдЕрдВрддрд┐рдо рд╕реЗ рдХрдо рд╣реИред рддреЛ рдпрд╣ рдмрд╛рдзрд┐рдд рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдПрдХ рд▓рдВрдмрд╛ рдкрд░рд┐рдгрд╛рдо рджреЗрддрд╛ рд╣реИ ( (foo + bar) + baz ) рдЬрд┐рд╕рдиреЗ expr() рдХреЙрд▓ рд╢реБрд░реВ рдХрд┐рдпрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, statement() рдХреЙрд▓ рдпрд╣рд╛рдБ рдирд╣реАрдВ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ)ред


рддреЛ, рдпрд╣ рд╡рд╣ рдЬрдЧрд╣ рд╣реИ рдЬрд╣рд╛рдВ рдЖрдЬ рдХреА рдХрд╣рд╛рдиреА рд╕рдорд╛рдкреНрдд рд╣реЛрддреА рд╣реИ: рд╣рдордиреЗ рдкреАрдИрдЬреА рдкрд╛рд░реНрд╕рд░ рдореЗрдВ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдмрд╛рдИрдВ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ред рдЕрдЧрд▓реЗ рд╣рдлреНрддреЗ рдореИрдВ рд╡реНрдпрд╛рдХрд░рдг рдореЗрдВ "рдХрд╛рд░реНрдпреЛрдВ" рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░рдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛ рд░рд╣рд╛ рд╣реВрдВ, рдЬреЛ рд╣рдореЗрдВ рдЗрд╕ рд╡рд┐рдХрд▓реНрдк рдХреЗ рд▓рд┐рдП рдкрд╛рд░реНрд╕рд░ рд╡рд┐рдзрд┐ рджреНрд╡рд╛рд░рд╛ рд▓реМрдЯрд╛рдП рдЧрдП рдкрд░рд┐рдгрд╛рдо рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ (рдмрдЬрд╛рдп рд╣рдореЗрд╢рд╛ рдПрдХ Node рдЙрджрд╛рд╣рд░рдг рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП)ред


рдпрджрд┐ рдЖрдк рдХреЛрдб рдХреЗ рд╕рд╛рде рдЦреЗрд▓рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ GitHub рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рджреЗрдЦреЗрдВ ред (рдореИрдВрдиреЗ рдмрд╛рдИрдВ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рдЬрд╝реБрдЕрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдХреЛрдб рднреА рдЬреЛрдбрд╝рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдЗрд╕рд╕реЗ рдмрд╣реБрдд рдЦреБрд╢ рдирд╣реАрдВ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдЗрд╕реЗ рдпрд╣рд╛рдВ рд▓рд┐рдВрдХ рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИред)


рдЗрд╕ рд▓реЗрдЦ рдХреЗ рд▓рд┐рдП рд▓рд╛рдЗрд╕реЗрдВрд╕ рдФрд░ рдХреЛрдб рдХрд╛ рд╣рд╡рд╛рд▓рд╛ рджрд┐рдпрд╛: CC BY-NC-SA 4.0

Source: https://habr.com/ru/post/hi471986/


All Articles