рд╕реНрдХреНрд░реИрдЪ рд╕реЗ рдПрдХ рдкрд╛рд░реНрд╕рд░ рд▓рд┐рдЦрдирд╛: рдХреНрдпрд╛ рд╢реИрддрд╛рди рдЗрддрдирд╛ рднрдпрд╛рдирдХ рд╣реИ?

рдЖрдЦрд┐рд░реА рд╡рд┐рд╖рдп рдореЗрдВ, рдореИрдВрдиреЗ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХреА рдХрд┐ рдХреИрд╕реЗ рдореЗрд░реЗ рджреЛрд╕реНрдд рдФрд░ рдореИрдВрдиреЗ рдордиреЛрд░рдВрдЬрди рдХреЗ рд▓рд┐рдП .NET рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рдХреЗ рд▓рд┐рдП рдЕрдкрдиреА рдЦреБрдж рдХреА рдПрдореНрдмреЗрдбреЗрдб рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рд▓рд┐рдЦрдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рдкрд╣рд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдПрдХ рдЧрдВрднреАрд░ рдЦрд╛рдореА рдереА - рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдл # рдкрд░ рдкрд╛рд░реНрд╕рд░ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЗрд╕ рд╡рдЬрд╣ рд╕реЗ, рдмрд╣реБрдд рдЕрдзрд┐рдХ рдирд┐рд░реНрднрд░рддрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереА, рдкрд╛рд░реНрд╕рд░ рдиреЗ рдзреАрд░реЗ-рдзреАрд░реЗ рдХрд╛рдо рдХрд┐рдпрд╛, рдФрд░ рдЗрд╕рдХрд╛ рд╕рдорд░реНрдерди рдПрдХ рдЕрддреНрдпрдВрдд рдиреАрд░рд╕ рд╡реНрдпрд╡рд╕рд╛рдп рдерд╛ред

рдЬрд╛рд╣рд┐рд░ рд╣реИ, Parser рдХреЛ C # рдореЗрдВ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереА, рд▓реЗрдХрд┐рди рдЬрдм рдЖрдкрдиреЗ Parser рдХреЛ рдЦрд░реЛрдВрдЪ рд╕реЗ рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрд╛, рддреЛ рдПрдХ рджрд░реНрдЬрди рдЕрдиреНрдп рдЬрд░реВрд░реА рдЪреАрдЬреЗрдВ рдереАрдВред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдХрд╛рд░реНрдп рдХреЛ рд▓рдЧрднрдЧ рдЫрд╣ рдорд╣реАрдиреЗ рдХреЗ рд▓рд┐рдП рдлреЗрдВрдХ рджрд┐рдпрд╛ рдЧрдпрд╛ рдФрд░ рд╕реНрдердЧрд┐рдд рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рдФрд░ рднрд╛рд░реА рд▓рдЧ рд░рд╣рд╛ рдерд╛, рд▓реЗрдХрд┐рди рдЕрдВрдд рдореЗрдВ рдпрд╣ 4 рджрд┐рдиреЛрдВ рдореЗрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдХрдЯреМрддреА рдХреЗ рддрд╣рдд, рдореИрдВ рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛ рдПрдХ рдЬрдЯрд┐рд▓ рдЬрдЯрд┐рд▓ рд╡реНрдпрд╛рдХрд░рдг рдХреЗ рдкрд╛рд░реНрд╕рд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рддрд░реАрдХреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реВрдВрдЧрд╛ рдФрд░ рдЗрд╕реЗ рдорди рд╕реЗ рдирд╣реАрдВ рдЫреБрдЖ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд╕рд╛рде рд╣реА рд╕рд╛рде рдЗрд╕рдиреЗ LENS рднрд╛рд╖рд╛ рдХреЛ рдХреИрд╕реЗ рдмреЗрд╣рддрд░ рдмрдирд╛рдпрд╛ред

рд▓реЗрдХрд┐рди рд╕рдмрд╕реЗ рдкрд╣рд▓реА рдмрд╛рддред

рдкрд╣рд▓рд╛ рдкреИрдирдХреЗрдХ


рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╣рдордиреЗ рдкрд╛рд░реНрд╕рд░ рдХреЛрд░ рдХреЗ рд░реВрдк рдореЗрдВ FParsec рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред рдЗрд╕ рд╡рд┐рдХрд▓реНрдк рдХреЗ рдХрд╛рд░рдг рдЙрджреНрджреЗрд╢реНрдп рд╕реЗ рдЕрдзрд┐рдХ рдРрддрд┐рд╣рд╛рд╕рд┐рдХ рд╣реИрдВ: рдореБрдЭреЗ рд╣рд▓реНрдХреЗ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдкрд╕рдВрдж рдереЗ, рдореИрдВ рдПрдл # рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрднреНрдпрд╛рд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рдФрд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд▓реЗрдЦрдХ рдиреЗ рдмрд╣реБрдд рддреЗрдЬрд╝реА рд╕реЗ рдИрдореЗрд▓ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрдИ рд╕рд╡рд╛рд▓реЛрдВ рдХреЗ рдЬрд╡рд╛рдм рджрд┐рдПред

рд╣рдорд╛рд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдореБрдЦреНрдп рджреЛрд╖ рдмрд╛рд╣рд░реА рдирд┐рд░реНрднрд░рддрд╛рдПрдВ рдереАрдВ:


рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдХрдВрдкрд╛рдЗрд▓рд░ 3 рдЕрд╕реЗрдВрдмрд▓рд┐рдпреЛрдВ рдореЗрдВ рдЯреВрдЯ рдЧрдпрд╛: рдПрдХ рдкрд╛рд░реНрд╕рд░, рдПрдХ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдЯреНрд░реА рдФрд░ рдПрдХ рдкреНрд░рд╡реЗрд╢ рдмрд┐рдВрджреБред рдкрд╛рд░реНрд╕рд░ рдЕрд╕реЗрдВрдмрд▓реА рдиреЗ рдкреНрд░рднрд╛рд╡рд╢рд╛рд▓реА 130 kb рд▓рд┐рдпрд╛ред рдПрдХ рдПрдореНрдмреЗрдбреЗрдб рднрд╛рд╖рд╛ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рдЕрд╢реЛрднрдиреАрдп рд╣реИред

рдПрдХ рдЕрдиреНрдп рд╕рдорд╕реНрдпрд╛ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░ рд░рд╣реА рдереАред рд╕реНрдерд╛рдиреАрдп DSL рдкрд░ рдПрдХ рдЧрд▓рдд рддрд░реАрдХреЗ рд╕реЗ рджрд░реНрдЬ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рд╕рд╛рде рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд╡реНрдпрд╛рдХрд░рдг рд░рд┐рдХреЙрд░реНрдб рдПрдХ рдЕрдкреЗрдХреНрд╖рд┐рдд рддреНрд░реБрдЯрд┐ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдЕрдкреЗрдХреНрд╖рд┐рдд рдЯреЛрдХрди рд╕реВрдЪреАрдмрджреНрдз рдХрд░рддрд╛ рд╣реИ:

> let x = > :           'new'  ... 

рдпрджреНрдпрдкрд┐ рдХрд╕реНрдЯрдо рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд┐рдВрдЧ рд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди DSL рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЗрд╕рдХреЗ рд▓рд┐рдП рдЕрднрд┐рдкреНрд░реЗрдд рдирд╣реАрдВ рд╣реИред рдПрдХ рд╡реНрдпрд╛рдХрд░рдг рд╡рд┐рд╡рд░рдг рдмрджрд╕реВрд░рдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд╕рдорд░реНрдерд┐рдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред

рдПрдХ рдФрд░ рдЕрдкреНрд░рд┐рдп рдХреНрд╖рдг рдХрд╛рдо рдХреА рдЧрддрд┐ рдереАред рдХрд┐рд╕реА рднреА "рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рд╕рдмрд╕реЗ рд╕рд░рд▓ рд▓рд┐рдкрд┐" рдХреЗ "рдХреЛрд▓реНрдб рд╕реНрдЯрд╛рд░реНрдЯ" рд╕рдВрдХрд▓рди рдХреЗ рд╕рд╛рде, рдореЗрд░реА рдорд╢реАрди рдкрд░ рд▓рдЧрднрдЧ 350-380 рдорд┐рд▓реАрд╕реЗрдХрдВрдб рд▓рд┐рдпрд╛ рдЧрдпрд╛ред рдЗрд╕ рддрдереНрдп рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП рдХрд┐ рдПрдХ рд╣реА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рдХрд░рдиреЗ рдореЗрдВ рдХреЗрд╡рд▓ 5-10 рдорд┐рд▓реА рд╕реЗрдХреЗрдВрдб рд▓рдЧрддреЗ рд╣реИрдВ, рджреЗрд░реА рдЬреЗрдЖрдИрдЯреА рд╕рдВрдХрд▓рди рдХреЗ рдХрд╛рд░рдг рд╣реБрдИ рдереАред

рдореИрдВ рдПрдХрджрдо рд╕реЗ рдЖрд░рдХреНрд╖рдг рдХрд░ рджреВрдВрдЧрд╛ - рдЕрдзрд┐рдХрд╛рдВрд╢ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП, рд╡рд┐рдХрд╛рд╕ рдХрд╛ рд╕рдордп рдЕрддрд┐рд░рд┐рдХреНрдд рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдпрд╛ рдХреБрдЫ рдорд┐рд▓реАрд╕реЗрдХрдВрдб рдХреЗ рдПрдХ рдЬреЛрдбрд╝реЗ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдЬреЛ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдкрд░ рдЦрд░реНрдЪ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ, рдПрдХ рд╣рд╛рде рд╕реЗ рд▓рд┐рдЦрдиреЗ рд╡рд╛рд▓реЗ рдкрд╛рд░реНрд╕рд░ рд▓рд┐рдЦрдирд╛ рдПрдХ рд╢реИрдХреНрд╖рд┐рдХ рдпрд╛ рдЧреВрдврд╝ рд╡реНрдпрд╛рдпрд╛рдо рд╣реИред

рд╕рд┐рджреНрдзрд╛рдВрдд рдХреА рдмрд┐рдЯ


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

рдкреЗрдбрд╝ рдХреА рд╕рдВрд░рдЪрдирд╛ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЕрдЪреНрдЫреА рд╣реИ рдХрд┐ рдпрд╣ рдХрдИ рдЖрдзреБрдирд┐рдХ рдЖрднрд╛рд╕реА рдорд╢реАрдиреЛрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, JVM / .NET) рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рд╕реНрдЯреИрдХ рд╕рдВрдЧрдарди рдХреЗ рд╕рд╛рде рдЧрд╣рд░рд╛рдИ рдореЗрдВ рдЬрд╛рддреА рд╣реИред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдХреЛрдб рдкреАрдврд╝реА рдкрд░ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдкреЗрдбрд╝ рдХреЗ рддрддреНрд╡, рдкрд╛рд░реНрд╕рд░ рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рд╕рдордп-рд╕рдордп рдкрд░ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

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

  1. рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ: string -> IEnumerable<Lexem>
  2. рдкрд╛рд░реНрд╕рд░: IEnumerable<Lexem> -> IEnumerable<Node>
  3. рд╢рдмреНрджрд╛рд░реНрде рд╡рд┐рд╢реНрд▓реЗрд╖рдХ: IEnumerable<Node> -> ?

рдЪреВрдВрдХрд┐ рд╕рд┐рдореЗрдВрдЯрд┐рдХ рдПрдирд╛рд▓рд╛рдЗрдЬрд░ рд╡рд┐рд╢реБрджреНрдз рд░реВрдк рд╕реЗ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдЪреАрдЬ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕рдХрд╛ рд╡рд┐рд╡рд░рдг рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рд╣реИред рдлрд┐рд░ рднреА, рдореИрдВ рдкрд╣рд▓реЗ рджреЛ рд╡рд┐рд╢реНрд▓реЗрд╖рдгрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдЙрдкрдпреЛрдЧреА рддрд░рдХреАрдмреЗрдВ рд╕рд╛рдЭрд╛ рдХрд░реВрдБрдЧрд╛ред

рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ


рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдБ:


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

рд╕рднреА рдЯреЛрдХрди рдХреЛ рд╢реБрд░реВ рдореЗрдВ 2 рдкреНрд░рдХрд╛рд░реЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП - рд╕реНрдерд┐рд░ рдФрд░ рдЧрддрд┐рд╢реАрд▓ ред рдкрд╣рд▓реЗ рдореЗрдВ рд╡реЗ рдЯреЛрдХрди рд╢рд╛рдорд┐рд▓ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд▓рд╛рдЗрди рдореЗрдВ рд╡реНрдпрдХреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ - рдХреАрд╡рд░реНрдб рдФрд░ рдСрдкрд░реЗрдЯрд░ред рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛, рд╕рдВрдЦреНрдпрд╛, рдпрд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдЬреИрд╕реЗ рдЯреЛрдХрди рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд╕рд╛рде рд╡рд░реНрдгрди рдХрд░рдиреЗ рдореЗрдВ рдЖрд╕рд╛рди рд╣реЛрддреЗ рд╣реИрдВред

рд╕реНрдЯреИрдЯрд┐рдХ рдЯреЛрдХрди, рдмрджрд▓реЗ рдореЗрдВ, рдСрдкрд░реЗрдЯрд░реЛрдВ рдФрд░ рдХреАрд╡рд░реНрдб рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдХрд╛рд░рдг рд╣реИред рдЦреЛрдЬрд╢рдмреНрджреЛрдВ рдХрд╛ рдорд┐рд▓рд╛рди рддрднреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рдЙрдирдХрд╛ рдЕрдиреБрд╕рд░рдг рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рд╡рд░реНрдг рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ (рдпрд╛ рдЖрдЧреЗ - рдкрдВрдХреНрддрд┐ рдХреЗ рдЕрдВрдд) рдХреЗ рд▓рд┐рдП рдорд╛рдиреНрдп рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рдЕрдиреНрдпрдерд╛, рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛рдУрдВ рдХреЗ рд╕рд╛рде рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реЛрдВрдЧреА рдЬрд┐рдирдХреА рд╢реБрд░реБрдЖрдд рдХреАрд╡рд░реНрдб рд╕реЗ рдореЗрд▓ рдЦрд╛рддреА рд╣реИ: рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, "information" -> keyword(in), keyword(for), identifier(mation) ред

рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдЙрджрд╛рд╣рд░рдг
 enum LexemKind { Var, Print, Plus, Minus, Multiply, Divide, Assign, Semicolon, Identifier, Number } class LocationEntity { public int Offset; public int Length; } class Lexem : LocationEntity { public LexemKind Kind; public string Value; } class LexemDefinition<T> { public LexemKind Kind { get; protected set; } public T Representation { get; protected set; } } class StaticLexemDefinition : LexemDefinition<string> { public bool IsKeyword; public StaticLexemDefinition(string rep, LexemKind kind, bool isKeyword = false) { Representation = rep; Kind = kind; IsKeyword = isKeyword; } } class DynamicLexemDefinition : LexemDefinition<Regex> { public DynamicLexemDefinition(string rep, LexemKind kind) { Representation = new Regex(@"\G" + rep, RegexOptions.Compiled); Kind = kind; } } static class LexemDefinitions { public static StaticLexemDefinition[] Statics = new [] { new StaticLexemDefinition("var", LexemKind.Var, true), new StaticLexemDefinition("print", LexemKind.Print, true), new StaticLexemDefinition("=", LexemKind.Assign), new StaticLexemDefinition("+", LexemKind.Plus), new StaticLexemDefinition("-", LexemKind.Minus), new StaticLexemDefinition("*", LexemKind.Multiply), new StaticLexemDefinition("/", LexemKind.Divide), new StaticLexemDefinition(";", LexemKind.Semicolon), }; public static DynamicLexemDefinition[] Dynamics = new [] { new DynamicLexemDefinition("[a-zA-Z_][a-zA-Z0-9_]*", LexemKind.Identifier), new DynamicLexemDefinition("(0|[1-9][0-9]*)", LexemKind.Number), }; } class Lexer { private char[] SpaceChars = new [] { ' ', '\n', '\r', '\t' }; private string Source; private int Offset; public IEnumerable<Lexem> Lexems { get; private set; } public Lexer(string src) { Source = src; Parse(); } private void Parse() { var lexems = new List<Lexem>(); while(InBounds()) { SkipSpaces(); if(!InBounds()) break; var lex = ProcessStatic() ?? ProcessDynamic(); if(lex == null) throw new Exception(string.Format("Unknown lexem at {0}", Offset)); lexems.Add(lex); } Lexems = lexems; } private void SkipSpaces() { while(InBounds() && Source[Offset].IsAnyOf(SpaceChars)) Offset++; } private Lexem ProcessStatic() { foreach(var def in LexemDefinitions.Statics) { var rep = def.Representation; var len = rep.Length; if(Offset + len > Source.Length || Source.Substring(Offset, len) != rep) continue; if(Offset + len < Source.Length && def.IsKeyword) { var nextChar = Source[Offset + len]; if(nextChar == '_' || char.IsLetterOrDigit(nextChar)) continue; } Offset += len; return new Lexem { Kind = def.Kind, Offset = Offset, Length = len }; } return null; } private Lexem ProcessDynamic() { foreach(var def in LexemDefinitions.Dynamics) { var match = def.Representation.Match(Source, Offset); if(!match.Success) continue; Offset += match.Length; return new Lexem { Kind = def.Kind, Offset = Offset, Length = match.Length, Value = match.Value }; } return null; } private bool InBounds() { return Offset < Source.Length; } } 


рдлрд╛рдпрджреЗ:


рдиреБрдХрд╕рд╛рди:


рдкрд╛рд░реНрд╕рд░


рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдБ:


рдкрд╛рд░реНрд╕рд░ рд▓рд┐рдЦрддреЗ рд╕рдордп рдЕрдкрдиреЗ рдЬреАрд╡рди рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╡реНрдпрд╛рдХрд░рдг рдХреА рд╡реНрдпрд╡рд╕реНрдерд╛ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдПред рдХреЛрдИ рдЬрдЯрд┐рд▓ рдбрд┐рдЬрд╛рдЗрди! рд╕рднреА рдирд┐рдпрдореЛрдВ рдХреЛ 3 рдкреНрд░рдХрд╛рд░реЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:


рд╡рд┐рд╡рд░рдг рдирд┐рдпрдо рдХреЛ рдЪрд░рдгреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ: рд╣рдордиреЗ рд╡рд░реНрддрдорд╛рди рдЯреЛрдХрди рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреА рдЬрд╛рдВрдЪ рдХреА, рдЕрдЧрд▓реЗ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдпрд╛, рдФрд░ рдЗрд╕реА рддрд░рд╣ рд╢рд╛рд╕рди рдХреЗ рдЕрдВрдд рддрдХред рдкреНрд░рддреНрдпреЗрдХ рдЪреЗрдХ рдХрд┐рдП рдЧрдП рдЯреЛрдХрди рдХреЗ рд╕рд╛рде, рдЖрдк рдХреБрдЫ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ: рдПрдХ рдмреЗрдореЗрд▓ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдПрдХ рд╡рд┐рд╕реНрддреГрдд рддреНрд░реБрдЯрд┐ рджреЗрдВ, рдиреЛрдб рдореЗрдВ рдЗрд╕рдХреЗ рдореВрд▓реНрдп рдХреЛ рдмрдЪрд╛рдПрдВ, рдЖрджрд┐ред

рдПрдХ рдЧрдгрдирд╛ рдирд┐рдпрдо рдПрдХ рд▓реВрдк рд╣реИред рдореВрд▓реНрдпреЛрдВ рдХреЗ рдЕрдиреБрдХреНрд░рдо рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, C # рдореЗрдВ yield return рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЬрдирд░реЗрдЯрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд╣реИред

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

рдлрд┐рд░ рдПрдХ рдЬрд┐рдЬреНрдЮрд╛рд╕реБ рдкрд╛рдардХ рдкреВрдЫреЗрдЧрд╛:
- рдпрд╣ рдХреИрд╕рд╛ рд╣реИ, рд╡реЗ рд╕рд┐рд░реНрдл рдХреНрд░рдо рдореЗрдВ рдмреБрд▓рд╛рдП рдЬрд╛рддреЗ рд╣реИрдВ? рд▓реЗрдХрд┐рди рдкреНрд░рдореБрдЦ рдЬрд╛рдБрдЪ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛? рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕ рддрд░рд╣:
 if(CurrentLexem.Type == LexemType.Var) return parseVar(); if(CurrentLexem.Type == LexemType.For) return parseFor(); ... 

рдореИрдВ рдорд╛рдирддрд╛ рд╣реВрдВ, рдореИрдВрдиреЗ рдЕрдкрдирд╛ рдкрд╣рд▓рд╛ рдЧрдВрднреАрд░ рдкрд╛рд░реНрд╕рд░ рдЙрд╕ рддрд░рд╣ рд╕реЗ рд▓рд┐рдЦрд╛ред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдпрд╣ рдПрдХ рдмреБрд░рд╛ рд╡рд┐рдЪрд╛рд░ рд╣реИ!

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЖрдк рдХреЗрд╡рд▓ рдирд┐рд╢реНрдЪрд┐рдд рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рд╡рд░реНрдг рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред рдХрд┐рд╕реА рднреА рдпрд╛ var , рдЬрд╝рд╛рд╣рд┐рд░ рд╣реИ, рдЙрдкрдпреБрдХреНрдд рд╣реИред рд▓реЗрдХрд┐рди рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╡реНрдпрд╛рдХрд░рдг рдореЗрдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдпреЗ рдирд┐рдпрдо рд╣реИрдВ:

 assign = id_assign | member_assign | index_assign id_assign = identifier "=" expr member_assign = lvalue "." identifier "=" expr index_assign = lvalue "[" expr "]" "=" expr 

рдпрджрд┐ id_assign рд╕рд╛рде рд╕рдм рдХреБрдЫ рд╕реНрдкрд╖реНрдЯ рд╣реИ, рддреЛ рджреЛрдиреЛрдВ рдЕрдиреНрдп рдирд┐рдпрдо id_assign рд╢реБрд░реВ рд╣реЛрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХреЗ рддрд╣рдд рдХрд┐рд▓реЛрдореАрдЯрд░ рдХреА рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдЫрд┐рдкрд╛рдИ рдЬрд╛ рд╕рдХрддреА рд╣реИред рдЬрд╛рд╣рд┐рд░ рд╣реИ, рдЖрдк рдпрд╣рд╛рдВ рдХрд┐рд╕реА рднреА рдЕрдЧреНрд░рдгреА рдЬрд╛рдВрдЪ рдореЗрдВ рдирд╣реАрдВ рдЖрдПрдВрдЧреЗред

рдПрдХ рдФрд░ рд╕рдорд╕реНрдпрд╛ рдЬрд┐рдореНрдореЗрджрд╛рд░реА рдХреЗ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХрд╛ рднреНрд░рдо рд╣реИред рд╡реНрдпрд╛рдХрд░рдг рдХреЗ рдПрдХреНрд╕реНрдЯреЗрдВрд╕рд┐рдмрд▓ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП, рдирд┐рдпрдореЛрдВ рдХреЛ рдпрдерд╛рд╕рдВрднрд╡ рдПрдХ рджреВрд╕рд░реЗ рд╕реЗ рд╕реНрд╡рддрдВрддреНрд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рдмрд╛рд╣рд░реА рдирд┐рдпрдо рдХреА рдЖрдВрддрд░рд┐рдХ рд▓реЛрдЧреЛрдВ рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрддрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬрд┐рд╕рд╕реЗ рдХрдиреЗрдХреНрдЯрд┐рд╡рд┐рдЯреА рдмрдврд╝рддреА рд╣реИ рдФрд░ рд╡реНрдпрд╛рдХрд░рдг рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдХреЛ рдЬрдЯрд┐рд▓ рдХрд░рддрд╛ рд╣реИред

рддреЛ рд╣рдореЗрдВ рдЙрдиреНрдирдд рдЬрд╛рдВрдЪ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реИ? рдкреНрд░рддреНрдпреЗрдХ рдирд┐рдпрдо рдХреЛ рд╕реНрд╡рдпрдВ рдХреЗ рд▓рд┐рдП рдмрддрд╛рдПрдВ рдХрд┐ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдпрд╣ рд╕рдмрд╕реЗ рдЙрдкрдпреБрдХреНрдд рд╣реИ, рдЖрдЧреЗ рджреЗрдЦрдирд╛ рдХрд┐рддрдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред

рдКрдкрд░ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рдорд╛рди рд▓реАрдЬрд┐рдП рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдкрд╛рда рд╣реИ: a.1 = 2 :

  1. id_assign рд╡рд┐рдХрд▓реНрдк рдХреЛ id_assign рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред
  2. a рдореИрдЪ рдХреЛ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдкрд╣рдЪрд╛рдирддрд╛ a ред
  3. рдЕрдЧрд▓реА рдЕрд╡рдзрд┐ рд╣реИ, рд▓реЗрдХрд┐рди рдмрд░рд╛рдмрд░реА рдХреЗ рд╕рдВрдХреЗрдд рдХреА рдЙрдореНрдореАрдж рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЕрдиреНрдп рдирд┐рдпрдо рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рдбрд╛рд▓реА рдЧрдИ рд╣реИред
  4. рдЕрд╕рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдирд┐рдпрдо рд░рд╛рдЬреНрдп рдХреЛ рд╡рд╛рдкрд╕ рд░реЛрд▓ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЖрдЧреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реИред
  5. member_assign рд╡рд┐рдХрд▓реНрдк member_assign ред
  6. рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдФрд░ рдЕрд╡рдзрд┐ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВред рд╡реНрдпрд╛рдХрд░рдг рдореЗрдВ рдХреЛрдИ рдЕрдиреНрдп рдирд┐рдпрдо рдирд╣реАрдВ рд╣реИрдВ рдЬреЛ рдПрдХ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдФрд░ рдПрдХ рдбреЙрдЯ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рд░рд╛рдЬреНрдп рдХреЛ рд╡рд╛рдкрд╕ рд░реЛрд▓ рдХрд░рдХреЗ рдЖрдЧреЗ рдХреА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рдорддрд▓рдм рдирд╣реАрдВ рд╣реИред
  7. рдирдВрдмрд░ 1 рдПрдХ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдПрдХ рддреНрд░реБрдЯрд┐ рдбрд╛рд▓реА рдЧрдИ рд╣реИред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдХреБрдЫ рдЙрдкрдпреЛрдЧреА рддрд░реАрдХреЗ рд▓рд┐рдЦреЗрдВрдЧреЗ:

рдЫрд┐рдкрд╛ рд╣реБрдЖ рдкрд╛рда
 partial class Parser { private List<Lexem> Lexems; private int LexemId; #region Lexem handlers [DebuggerStepThrough] private bool Peek(params LexemType[] types) { var id = Math.Min(LexemId, Lexems.Length - 1); var lex = Lexems[id]; return lex.Type.IsAnyOf(types); } [DebuggerStepThrough] private Lexem Ensure(LexemType type, string msg, params object[] args) { var lex = Lexems[LexemId]; if(lex.Type != type) error(msg, args); Skip(); return lex; } [DebuggerStepThrough] private bool Check(LexemType lexem) { var lex = Lexems[LexemId]; if (lex.Type != lexem) return false; Skip(); return true; } [DebuggerStepThrough] private void Skip(int count = 1) { LexemId = Math.Min(LexemId + count, Lexems.Length - 1); } #endregion #region Node handlers [DebuggerStepThrough] private T Attempt<T>(Func<T> getter) where T : LocationEntity { var backup = LexemId; var result = Bind(getter); if (result == null) LexemId = backup; return result; } [DebuggerStepThrough] private T Ensure<T>(Func<T> getter, string msg) where T : LocationEntity { var result = Bind(getter); if (result == null) throw new Exception(msg); return result; } [DebuggerStepThrough] private T Bind<T>(Func<T> getter) where T : LocationEntity { var startId = LexemId; var start = Lexems[LexemId]; var result = getter(); if (result != null) { result.StartLocation = start.StartLocation; var endId = LexemId; if (endId > startId && endId > 0) result.EndLocation = Lexems[LexemId - 1].EndLocation; } return result; } #endregion } 

рдЙрдирдХреА рдорджрдж рд╕реЗ, рдЙрдкрд░реЛрдХреНрдд рд╡реНрдпрд╛рдХрд░рдг рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд▓рдЧрднрдЧ рддреБрдЪреНрдЫ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ:

 partial class Parser { public Node ParseAssign() { return Attempt(ParseIdAssign) ?? Attempt(ParseMemberAssign) ?? Ensure(ParseIndexAssign, "  !"); } public Node ParseIdAssign() { var id = TryGetValue(LexemType.Identifier); if (id == null) return null; if (!Check(LexemType.Assign)) return null; var expr = Ensure(ParseExpr, "  !"); return new IdAssignNode { Identifier = id, Expression = expr }; } public Node ParseMemberAssign() { var lvalue = Attempt(ParseLvalue); if (lvalue == null) return null; if (!Check(LexemType.Dot)) return null; var member = TryGetValue(LexemType.Identifier); if (member == null) return null; if (!Check(LexemType.Assign)) return null; var expr = Ensure(ParseExpr, "  !"); return new MemberAssignNode { Lvalue = lvalue, MemberName = member, Expression = expr }; } public Node ParseIndexAssign() { var lvalue = Attempt(ParseLvalue); if (lvalue == null) return null; if (!Check(LexemType.SquareBraceOpen)) return null; var index = Ensure(ParseExpr, "  !"); Ensure(LexemType.SquareBraceClose, "  !"); Ensure(LexemType.Assign, "  !"); var expr = Ensure(ParseExpr, "  !"); return new IndexAssignNode { Lvalue = lvalue, Index = index, Expression = expr }; } } 

DebuggerStepThrough рд╡рд┐рд╢реЗрд╖рддрд╛ рдбрд┐рдмрдЧрд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдмрд╣реБрдд рдорджрдж рдХрд░рддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ рдиреЗрд╕реНрдЯреЗрдб рдирд┐рдпрдореЛрдВ рдХреЗ рд╕рднреА рдХреЙрд▓ рдПрдХ рддрд░рд╣ рд╕реЗ рдпрд╛ рдХрд┐рд╕реА рдЕрдиреНрдп рддрд░реАрдХреЗ рд╕реЗ рдкреНрд░рдпрд╛рд╕ рдФрд░ рдкрд╛рд╕ рд╕реЗ рдЧреБрдЬрд░рддреЗ рд╣реИрдВ, рдЗрд╕ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рдмрд┐рдирд╛ рд╡реЗ рд▓рдЧрд╛рддрд╛рд░ рдЪрд░рдг рдЖрдИ рдореЗрдВ рдЖрдкрдХреА рдирдЬрд░ рдкрдХрдбрд╝ рд▓реЗрдВрдЧреЗ рдФрд░ рдХреЙрд▓ рд╕реНрдЯреИрдХ рдХреЛ рд░реЛрдХ рджреЗрдВрдЧреЗред

рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЗ рдлрд╛рдпрджреЗ:


рдиреБрдХрд╕рд╛рди:


рд╕рдВрдЪрд╛рд▓рдХ рдФрд░ рдкреНрд░рд╛рдердорд┐рдХрддрд╛рдПрдБ


рдмрд╛рд░-рдмрд╛рд░, рдореИрдВрдиреЗ рд╡реНрдпрд╛рдХрд░рдг рд╡рд░реНрдгрди рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдирд┐рдпрдореЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рджреЗрдЦрд╛, рдЬреЛ рд╕рдВрдЪрд╛рд▓рди рдХреА рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рджрд░реНрд╢рд╛рддреЗ рд╣реИрдВ:

 expr = expr_1 { op_1 expr_1 } expr_1 = exp2_2 { op_2 expr_2 } expr_2 = exp2_3 { op_3 expr_3 } expr_3 = int | float | identifier op_1 = "+" | "-" op_2 = "*" | "/" | "%" op_3 = "**" 

рдЕрдм рдХрд▓реНрдкрдирд╛ рдХрд░реЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЕрднреА рднреА рдмреВрд▓рд┐рдпрди рдСрдкрд░реЗрдЯрд░, рддреБрд▓рдирд╛ рдСрдкрд░реЗрдЯрд░, рд╢рд┐рдлреНрдЯ рдСрдкрд░реЗрдЯрд░, рдмрд╛рдЗрдирд░реА рдСрдкрд░реЗрдЯрд░ рдпрд╛ рдХреБрдЫ рдЙрдЪрд┐рдд рд╣реИрдВред рдЖрдкрдХреЛ рдХрд┐рддрдиреЗ рдирд┐рдпрдо рдорд┐рд▓рддреЗ рд╣реИрдВ, рдФрд░ рдпрджрд┐ рдЖрдкрдХреЛ рдмреАрдЪ рдореЗрдВ рдХрд╣реАрдВ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рдХреЗ рд╕рд╛рде рдЕрдЪрд╛рдирдХ рдирдпрд╛ рдСрдкрд░реЗрдЯрд░ рдЬреЛрдбрд╝рдирд╛ рд╣реИ рддреЛ рдЖрдкрдХреЛ рдХрд┐рддрдирд╛ рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛?

рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рдЖрдк рд╡реНрдпрд╛рдХрд░рдг рд╕реЗ рдкреНрд░рд╛рдердорд┐рдХрддрд╛рдУрдВ рдХреЗ рдкреВрд░реЗ рд╡рд┐рд╡рд░рдг рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рд╣рдЯрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдШреЛрд╖рд┐рдд рд░реВрдк рд╕реЗ рдПрдирдХреЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдЙрджрд╛рд╣рд░рдг
 expr = sub_expr { op sub_expr } sub_expr = int | float | identifier 

 partial class Parser { private static List<Dictionary<LexemType, Func<Node, Node, Node>>> Priorities = new List<Dictionary<LexemType, Func<Node, Node, Node>>> { new Dictionary<LexemType, Func<Node, Node, Node>> { { LexemType.Plus, (a, b) => new AddNode(a, b) }, { LexemType.Minus, (a, b) => new SubtractNode(a, b) } }, new Dictionary<LexemType, Func<Node, Node, Node>> { { LexemType.Divide, (a, b) => new DivideNode(a, b) }, { LexemType.Multiply, (a, b) => new MultiplyNode(a, b) }, { LexemType.Remainder, (a, b) => new RemainderNode(a, b) } }, new Dictionary<LexemType, Func<Node, Node, Node>> { { LexemType.Power, (a, b) => new PowerNode(a, b) } }, }; public NodeBase ProcessOperators(Func<Node> next, int priority = 0) { if (priority == Priorities.Count) return getter(); var node = ProcessOperators(next, priority + 1); var ops = Priorities[priority]; while (Lexems[LexemId].IsAnyOf(ops.Keys)) { foreach (var curr in ops) { if (check(curr.Key)) { node = curr.Value( node, ensure(() => ProcessOperators(next, priority + 1), " !") ); } } } return node; } } 

рдЕрдм, рдПрдХ рдирдпрд╛ рдСрдкрд░реЗрдЯрд░ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рд╕реВрдЪреА рдХреЗ рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рд▓рд╛рдЗрди рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рдЕрдиреБрдкрд╕реНрдерд┐рдд рдЙрдкрд╕рд░реНрдЧ рдСрдкрд░реЗрдЯрд░реЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рдирд╛ рдЬрд┐рдЬреНрдЮрд╛рд╕реБ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрд╕рд░рдд рдХреЗ рд░реВрдк рдореЗрдВ рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдЗрд╕рдиреЗ рд╣рдореЗрдВ рдХреНрдпрд╛ рджрд┐рдпрд╛?


рдЕрдЬреАрдм рддрд░рд╣ рд╕реЗ рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ, рд╣рд╛рде рд╕реЗ рд▓рд┐рдЦреЗ рдЧрдП рдкрд╛рд░реНрд╕рд░ рдХреЛ рдмрдирд╛рдП рд░рдЦрдирд╛ рдмрд╣реБрдд рдЖрд╕рд╛рди рд╣реЛ рдЧрдпрд╛ рд╣реИред рд╡реНрдпрд╛рдХрд░рдг рдореЗрдВ рдПрдХ рдирд┐рдпрдо рдЬреЛрдбрд╝рд╛, рдХреЛрдб рдореЗрдВ рдЙрдкрдпреБрдХреНрдд рд╕реНрдерд╛рди рдкрд╛рдпрд╛, рдЗрд╕рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЛ рдЬреЛрдбрд╝рд╛ред рдмреИрдХрдЯреНрд░реИрдХрд┐рдВрдЧ рдирд░рдХ, рдЬреЛ рдЕрдХреНрд╕рд░ рдкреБрд░рд╛рдиреЗ рдкрд╛рд░реНрд╕рд░ рдореЗрдВ рдПрдХ рдирдпрд╛ рдирд┐рдпрдо рдЬреЛрдбрд╝рддреЗ рд╕рдордп рд╣реЛрддрд╛ рдерд╛ рдФрд░ рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ рдЕрд╕рдВрдмрдВрдзрд┐рдд рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рдПрдХ рдкреВрд░реЗ рд╕рдореВрд╣ рдореЗрдВ рдЕрдЪрд╛рдирдХ рдЧрд┐рд░рд╛рд╡рдЯ рдХрд╛ рдХрд╛рд░рдг рд╣реЛрддрд╛ рд╣реИред

рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреА рдХреБрд▓, рддреБрд▓рдирд╛рддреНрдордХ рддрд╛рд▓рд┐рдХрд╛:
рдкреИрд░рд╛рдореАрдЯрд░FParsec рдкрд╛рд░реНрд╕рд░рд╢реБрджреНрдз c #
1 рд░рди рдХреЗ рд▓рд┐рдП рдкрд╛рд░рд╕рд┐рдВрдЧ рдЯрд╛рдЗрдо220 рдорд┐90 рдорд┐
рдЖрдЧреЗ рдХреЗ рд░рди рдХреЗ рд▓рд┐рдП рдкрд╛рд░рд╕рд┐рдВрдЧ рдЯрд╛рдЗрдо5 рдорд┐6 рдорд┐
рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдЖрд╡рд╢реНрдпрдХ рдЖрдХрд╛рд░800 рдХреЗрдмреА + рдПрдл # рд░рдирдЯрд╛рдЗрдо260 рдХреЗрдмреА
рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ, рдЕрдиреБрдХреВрд▓рди рдХреЛ рдЕрдВрдЬрд╛рдо рджреЗрдирд╛ рдФрд░ рдкрд╛рд░реНрд╕рд░ рд╕реЗ рдЕрдзрд┐рдХ рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдирд┐рдЪреЛрдбрд╝рдирд╛ рд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрднреА рддрдХ рдпрд╣ рдкрд░рд┐рдгрд╛рдо рдХрд╛рдлреА рд╕рдВрддреЛрд╖рдЬрдирдХ рд╣реИред

рд╡реНрдпрд╛рдХрд░рдг рдореЗрдВ рдмрджрд▓рд╛рд╡ рдХреЗ рд╕рд╛рде рд╕рд┐рд░рджрд░реНрдж рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо LENS рдореЗрдВ рдХреБрдЫ рд╕реБрдЦрдж рдЪреАрдЬреЛрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдереЗ:

рдкрд╛рд╢ рдХреЗ рд▓рд┐рдП


рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рджреГрд╢реНрдпреЛрдВ рдХреЛ рджрд░рдХрд┐рдирд╛рд░ рдХрд░рдиреЗ рдФрд░ рд╕реАрдорд╛рдУрдВ рдХреЗ рд▓рд┐рдП рджреЛрдиреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:

 var data = new [1; 2; 3; 4; 5] for x in data do println "value = {0}" x for x in 1..5 do println "square = {0}" x 

рд╕рдорд╛рд░реЛрд╣ рд░рдЪрдирд╛


рдСрдкрд░реЗрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ :> рдЖрдк рдирдП рдХрд╛рд░реНрдп рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдореМрдЬреВрджрд╛ рд▓реЛрдЧреЛрдВ рдХреЛ "рд╕реНрдЯреНрд░рд┐рдВрдЧ" рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

 let invConcat = (a:string b:string) -> b + a let invParse = incConcat :> int::Parse invParse "37" "13" // 1337 

рдЕрдирд╛рдо рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЖрдВрд╢рд┐рдХ рдЙрдкрдпреЛрдЧ рд╕рдВрднрд╡ рд╣реИ:

 fun add:int (x:int y:int) -> x + y let addTwo = int::TryParse<string> :> (x:int -> add 2 x) addTwo "40" // 42 

рд╕рд┐рдВрдЯреЗрдХреНрд╕ рдПрдиреНрд╣рд╛рдВрд╕рдореЗрдВрдЯреНрд╕



рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрд╣ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдзреАрд░реЗ-рдзреАрд░реЗ рд╡рд┐рдХрд╕рд┐рдд рд╣реЛ рд░рд╣реА рд╣реИред рдЕрднреА рднреА рдХрдИ рджрд┐рд▓рдЪрд╕реНрдк рдХрд╛рд░реНрдп рд╣реИрдВред рдЕрдЧрд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛рдИ рдЧрдИ рд╣реИ:


рдЖрдк рд╡рд┐рдВрдбреЛрдЬ рдХреЗ рд▓рд┐рдП рдПрдХрддреНрд░рд┐рдд рдбреЗрдореЛ рднреА рдбрд╛рдЙрдирд▓реЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

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


All Articles