рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░реЗрдВред рднрд╛рдЧ 1: рдкрд╛рд░реНрд╕рд░

рдЖрдкрдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИ! рдореИрдВ рдЖрдкрдХреЗ рд▓рд┐рдП рдЕрдкрдиреА рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ - рдкреАрдПрд▓ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЧрд╛рдЗрдб рдХрд╛ рдПрдХ рд╢реМрдХрд┐рдпрд╛ рдЕрдиреБрд╡рд╛рдж рдкреНрд░рд╕реНрддреБрдд рдХрд░рддрд╛ рд╣реВрдВред


рдЕрдиреБрд╡рд╛рджрдХ рд╕реЗ


рд╣рдо рдЕрдкрдиреА рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ - ╬╗ рднрд╛рд╖рд╛ (рдореВрд▓ - ╬╗anguage рдореЗрдВ) рдмрдирд╛рдПрдВрдЧреЗред рдирд┐рд░реНрдорд╛рдг рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ, рд╣рдо рдХрдИ рджрд┐рд▓рдЪрд╕реНрдк рддрдХрдиреАрдХреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рдЬреИрд╕реЗ рдХрд┐ рдкреБрдирд░рд╛рд╡рд░реНрддреА рд╡рдВрд╢, рдирд┐рдпрдВрддреНрд░рдг рд╣рд╕реНрддрд╛рдВрддрд░рдг рд╢реИрд▓реА, рдФрд░ рдмреБрдирд┐рдпрд╛рджреА рдЕрдиреБрдХреВрд▓рди рддрдХрдиреАрдХред рджреБрднрд╛рд╖рд┐рдпрд╛ рдХреЗ рджреЛ рд╕рдВрд╕реНрдХрд░рдг рдмрдирд╛рдП рдЬрд╛рдПрдВрдЧреЗ - рдирд┐рдпрдорд┐рдд рдФрд░ рд╕реАрдкреАрдПрд╕ рджреБрднрд╛рд╖рд┐рдпреЛрдВ, рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдЯреНрд░рд╛рдВрд╕-рдХрдВрдкрд╛рдЗрд▓рд░ред


рдореВрд▓ рдХреЗ рд▓реЗрдЦрдХ рдорд┐рд╣рд╛рдИ Bazon , рдкреНрд░рд╕рд┐рджреНрдз UglifyJS рдкреБрд╕реНрддрдХрд╛рд▓рдп (рдЬреЗрдПрд╕ рдХреЛрдб рдХреЛ рдХрдо рдХрд░рдиреЗ рдФрд░ рдкреНрд░рд╛рд░реВрдкрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЙрдкрдХрд░рдг) рдХреЗ рд▓реЗрдЦрдХ рд╣реИрдВред


рд╕рд╛рдордЧреНрд░реА
  1. рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░реЗрдВред рднрд╛рдЧ 1: рдкрд╛рд░реНрд╕рд░
  2. рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░реЗрдВред рднрд╛рдЧ 2: рджреБрднрд╛рд╖рд┐рдпрд╛
  3. рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░реЗрдВред рднрд╛рдЧ 3: рд╕реАрдкреАрдПрд╕ рджреБрднрд╛рд╖рд┐рдпрд╛
  4. рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░реЗрдВред рднрд╛рдЧ 4: JS рдореЗрдВ рдЯреНрд░рд╛рдВрд╕ рдХрдВрдкрд╛рдЗрд▓рд┐рдВрдЧ

рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐


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


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


рд╣рдо рдХреНрдпрд╛ рд╕реАрдЦрдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ:


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

рдЗрд╕рдХреЗ рд╕рд╛рде, рдореИрдВ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ рдХрд┐ рд▓рд┐рд╕реНрдк рдПрдХ рдорд╣рд╛рди рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреНрдпреЛрдВ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╣рдо рдЬрд┐рд╕ рднрд╛рд╖рд╛ рдкрд░ рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рд╡рд╣ рд▓рд┐рд╕реНрдк рдирд╣реАрдВ рд╣реИред рдЗрд╕рдореЗрдВ рд░рд┐рдЪ рд╕рд┐рдВрдЯреИрдХреНрд╕ (рдПрдХ рдХреНрд▓рд╛рд╕рд┐рдХ рдЗрдиреНрдлрд┐рдХреНрд╕ рдиреЛрдЯреЗрд╢рди рдЬрд┐рд╕реЗ рд╣рд░ рдХреЛрдИ рдЬрд╛рдирддрд╛ рд╣реИ), рд╕реНрдХреАрдо (рдореИрдХреНрд░реЛрдЬрд╝ рдХреЛ рдЫреЛрдбрд╝рдХрд░) рдЬреИрд╕реА рдХреБрдЫ рд╣реИред рдЕрдЪреНрдЫреА рдпрд╛ рдирд╣реАрдВ, рд▓реЗрдХрд┐рди рдореИрдХреНрд░реЛрдЬрд╝ рд▓рд┐рд╕реНрдк рдХреА рдореБрдЦреНрдп рд╡рд┐рд╢реЗрд╖рддрд╛ рд╣реИ - рдРрд╕рд╛ рдХреБрдЫ рдЬреЛ рдЕрдиреНрдп рднрд╛рд╖рд╛рдУрдВ (рд▓рд┐рд╕реНрдк рдмреЛрд▓рд┐рдпреЛрдВ рдХреЛ рдЫреЛрдбрд╝рдХрд░) рдХреЗ рд░реВрдк рдореЗрдВ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред (рд╣рд╛рдВ, рдореБрдЭреЗ SweetJS рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрддрд╛ рд╣реИ ... рдХрд░реАрдм рд╣реИ, рд▓реЗрдХрд┐рди рдРрд╕рд╛ рдирд╣реАрдВ рд╣реИред)


рд▓реЗрдХрд┐рди рдкрд╣рд▓реЗ, рдЖрдЗрдП рд╣рдорд╛рд░реА рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХрд╛ рдкрд░рд┐рдЪрдп рджреЗрдВред



╬╗ рднрд╛рд╖рд╛


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


#   println("Hello World!"); println(2 + 3 * 4); #       `lambda`  `╬╗` fib = lambda (n) if n < 2 then n else fib(n - 1) + fib(n - 2); println(fib(15)); print-range = ╬╗(a, b) # `╬╗`     ,   `lambda` if a <= b then { # `then`  ,      print(a); if a + 1 <= b { print(", "); print-range(a + 1, b); } else println(""); #   }; print-range(1, 5); 

рдЪрд░ рдирд╛рдо рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛рдУрдВ рдореЗрдВ рдЛрдг рдЪрд┐рд╣реНрди ( print-range ) рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рд╕реНрд╡рд╛рдж рдХрд╛ рдорд╛рдорд▓рд╛ рд╣реИред рдореИрдВ рд╣рдореЗрд╢рд╛ рдСрдкрд░реЗрдЯрд░реЛрдВ рдХреЗ рдЖрд╕рдкрд╛рд╕ рд░рд┐рдХреНрдд рд╕реНрдерд╛рди рд░рдЦрддрд╛ рд╣реВрдВред рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреИрдорд▓рд░рд┐рдЬрд┐рд╕реНрдЯрд░ рдФрд░ рдбреИрд╢ рдХреЛ рдЕрджреГрд╢реНрдп рд╕реНрдерд╛рди ("_") рд╕реЗ рдмреЗрд╣рддрд░ рдирд╣реАрдВ рдорд╛рдирддрд╛ред рдЬрдм рдЖрдк рдЦреБрдж рдХреБрдЫ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рддреЛ рдЖрдк рдХрд┐рддрдирд╛ рд╢рд╛рдВрдд рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред


рдирд┐рд╖реНрдХрд░реНрд╖:


 Hello World! 14 610 1, 2, 3, 4, 5 

рднрд╛рд╖рд╛ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд╕рдорд╛рди рд╣реИ, рд▓реЗрдХрд┐рди рдХреБрд▓ рдорд┐рд▓рд╛рдХрд░ рдпрд╣ рдирд╣реАрдВ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдХреЛрдИ рдмрдпрд╛рди рдирд╣реАрдВ рд╣реИрдВ, рдХреЗрд╡рд▓ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ред рдПрдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЛ рдПрдХ рдореВрд▓реНрдп рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдХрд┐рд╕реА рдЕрдиреНрдп рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдореЗрдВ рдХрд╣реАрдВ рднреА рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдХреЗ "рдЕрдиреБрдХреНрд░рдо" рдореЗрдВ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдХреЛ рдЕрд▓рдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрд░реНрдзрд╡рд┐рд░рд╛рдо рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдШреБрдВрдШрд░рд╛рд▓реЗ рдмреНрд░реЗрд╕реЗрд╕ { рдФрд░ } рдПрдХ рдЕрдиреБрдХреНрд░рдо рдмрдирд╛рддреЗ рд╣реИрдВ рдЬреЛ рд╕реНрд╡рдпрдВ рдПрдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╣реИ, рдФрд░ рдЗрд╕рдХрд╛ рдорд╛рди рдЕрдиреБрдХреНрд░рдо рд╕реЗ рдЕрдВрддрд┐рдо рдорд╛рди рд╣реИред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛рд░реНрдпрдХреНрд░рдо рд╕рд╣реА рд╣реИ:


 a = { fib(10); #    ,      fib(15) #        }; print(a); #  610 

lambda рдпрд╛ ╬╗ рдХреАрд╡рд░реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд╛рд░реНрдп рдмрдирд╛рдП рдЬрд╛рддреЗ рд╣реИрдВред рдЙрд╕рдХреЗ рдмрд╛рдж, рдХреЛрд╖реНрдардХ рдореЗрдВ рддрд░реНрдХ рдирд╛рдореЛрдВ рдХреА рдПрдХ (рд╕рдВрднрд╡рддрдГ рдЦрд╛рд▓реА) рд╕реВрдЪреА рд╣реИ, рдЬреЛ рдЕрд▓реНрдкрд╡рд┐рд░рд╛рдо рджреНрд╡рд╛рд░рд╛ рдЕрд▓рдЧ рдХреА рдЬрд╛рддреА рд╣реИред рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рд╢рд░реАрд░ рдПрдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рдЕрдиреБрдХреНрд░рдо рдореЗрдВ рд╕рдВрд▓рдЧреНрди рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ {...} ред рдпрд╣ рднреА рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рдХреЛрдИ return рдХреАрд╡рд░реНрдб рдирд╣реАрдВ рд╣реИред рдлрд╝рдВрдХреНрд╢рди рдЕрдВрддрд┐рдо рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХрд╛ рдорд╛рди рд▓реМрдЯрд╛рддрд╛ рд╣реИред


рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдХреЛрдИ var рдирд╣реАрдВред рдПрдХ рдЪрд░ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдк рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ IIFE рдХреНрдпрд╛ рдХрд╣рддреЗ рд╣реИрдВред lambda рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ, рдЪрд░ рдХреЛ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдШреЛрд╖рд┐рдд рдХрд░реЗрдВред рдЪрд░реЛрдВ рдХреЗ рд▓рд┐рдП, рджрд╛рдпрд░рд╛ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд╣реИ, рдФрд░ рдлрд╝рдВрдХреНрд╢рди рдХреНрд▓реЛрдЬрд░ рд╣реИрдВ, рдЬреИрд╕рд╛ рдХрд┐ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ [рд▓рдЧрднрдЧред рдЕрдиреБрд╡рд╛рдж: ES6 рддрдХ]ред


рднрд▓реЗ if рдПрдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╣реИред рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЯрд░реНрдирд░реА рдСрдкрд░реЗрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ:


 a = foo() ? bar() : baz(); // JavaScript a = if foo() then bar() else baz(); # ╬╗ 

then рдХреАрд╡рд░реНрдб рд╡реИрдХрд▓реНрдкрд┐рдХ рд╣реИ рдпрджрд┐ рд╢рд╛рдЦрд╛ рдПрдХ рдЕрдиреБрдХреНрд░рдо ( {...} ) рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдКрдкрд░ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред рдПрдХ рдЕрдиреНрдп рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рд╡реИрдХрд▓реНрдкрд┐рдХ рд╢рд╛рдЦрд╛ рдореМрдЬреВрдж рд╣реЛрдиреЗ рдкрд░ else рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдФрд░ рдлрд┐рд░, then рдФрд░ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЛ рд╢рд░реАрд░ рдХреЗ рд░реВрдк рдореЗрдВ рд▓реЗрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЖрдк {...} рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрдИ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдХреЛ рдПрдХ рдореЗрдВ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдпрджрд┐ else рдЕрдиреБрдкрд╕реНрдерд┐рдд рд╣реИ рдФрд░ рд╕реНрдерд┐рддрд┐ false , рддреЛ рд╕рднреА рдХрд╛ рдкрд░рд┐рдгрд╛рдо false ред рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ false рдПрдХ рдХреАрд╡рд░реНрдб рд╣реИ рдЬреЛ рдПрдХ рдорд╛рди рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдПрдХ ╬╗ рднрд╛рд╖рд╛ рдореЗрдВ рдПрдХрдорд╛рддреНрд░ рдЧрд▓рдд рдорд╛рди рд╣реИ:


 if foo() then print("OK"); 

рдЙрддреНрдкрд╛рджрди OK рдЕрдЧрд░ рдФрд░ рдХреЗрд╡рд▓ рдЕрдЧрд░ foo() рдкрд░рд┐рдгрд╛рдо false рдирд╣реАрдВ false ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╡рд╣рд╛рдБ рдХреАрд╡рд░реНрдб true , рд▓реЗрдХрд┐рди рдмрд┐рд▓реНрдХреБрд▓ рд╕рдм рдХреБрдЫ рдЬреЛ false рдирд╣реАрдВ false (рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рднреАрддрд░, рдСрдкрд░реЗрдЯрд░ === ) рд╢рд╛рдЦрд╛рдУрдВ рдореЗрдВ true рдорд╛рдирд╛ рдЬрд╛рдПрдЧрд╛ (рдирдВрдмрд░ 0 рдФрд░ рдЦрд╛рд▓реА рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕рд╣рд┐рдд "" )ред


рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ if рдореЗрдВ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рдЖрд╕рдкрд╛рд╕ рдХреЛрд╖реНрдардХ рдХреА рдХреЛрдИ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдпрджрд┐ рдЖрдк рдЙрдиреНрд╣реЗрдВ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдПрдХ рдЧрд▓рддреА рдирд╣реАрдВ рд╣реЛрдЧреА, рдХреНрдпреЛрдВрдХрд┐ ( рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╢реБрд░реВ рд╣реЛрддреА рд╣реИ, рд▓реЗрдХрд┐рди рд╡реЗ рд╕рд┐рд░реНрдл рд╕рддрд╣реА рд╣реИрдВред


рд╕рдВрдкреВрд░реНрдг рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ рддрдм рднреА рдкрд╛рд░реНрд╕ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рднрд▓реЗ рд╣реА рд╡рд╣ рдХреЛрд╖реНрдардХреЛрдВ рд╕реЗ рдШрд┐рд░рд╛ рд╣реЛ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рд┐рдП ; рдкреНрд░рддреНрдпреЗрдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рдмрд╛рджред рдЕрдВрддрд┐рдо рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдПрдХ рдЕрдкрд╡рд╛рдж рд╣реИред


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


рдЗрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рдЕрдкрдиреА рднрд╛рд╖рд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдкрд╛рд░реНрд╕рд░ рд▓рд┐рдЦреЗрдВрдЧреЗред



рдПрдПрд╕рдЯреА рдХреЗ рд▓рд┐рдП рдХреЛрдб рд░реВрдкрд╛рдВрддрд░рдг


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


рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рд╣реИрдВ:


 sum = lambda(a, b) { a + b; }; print(sum(1, 2)); 

рд╣рдорд╛рд░рд╛ рдкрд╛рд░реНрд╕рд░ рдПрдХ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдкреЗрдбрд╝ рдЙрддреНрдкрдиреНрди рдХрд░реЗрдЧрд╛:


 { type: "prog", prog: [ //  : { type: "assign", operator: "=", left: { type: "var", value: "sum" }, right: { type: "lambda", vars: [ "a", "b" ], body: { //     "prog",  ,  //     ,  //     . type: "binary", operator: "+", left: { type: "var", value: "a" }, right: { type: "var", value: "b" } } } }, //  : { type: "call", func: { type: "var", value: "print" }, args: [{ type: "call", func: { type: "var", value: "sum" }, args: [ { type: "num", value: 1 }, { type: "num", value: 2 } ] }] } ] } 

рдкрд╛рд░реНрд╕рд░ рдмрдирд╛рдиреЗ рдореЗрдВ рдореБрдЦреНрдп рдХрдард┐рдирд╛рдИ рдХреЛрдб рдХреЛ рдареАрдХ рд╕реЗ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдХрдард┐рдирд╛рдИ рд╣реИред рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реЗ рд╡рд░реНрдг рдкрдврд╝рдиреЗ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдкрд╛рд░реНрд╕рд░ рдХреЛ рдЙрдЪреНрдЪ рд╕реНрддрд░ рдкрд░ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдХреЛрдб рдЬрдЯрд┐рд▓рддрд╛ рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рджрд┐рд╢рд╛рдирд┐рд░реНрджреЗрд╢:


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

рдХреЛрдб рдХреЛ рд╕рд░рд▓ рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЗрд╕реЗ рддреАрди рднрд╛рдЧреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░реЗрдВрдЧреЗ, рдЬреЛ рдмрджрд▓реЗ рдореЗрдВ рдХрдИ рдЫреЛрдЯреЗ рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рд╣реИрдВ:




рдЪрд░рд┐рддреНрд░ рдХреА рдзрд╛рд░рд╛


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


  • peek() - рдзрд╛рд░рд╛ рд╕реЗ рдирд┐рдХрд╛рд▓реЗ рдмрд┐рдирд╛ рдЕрдЧрд▓рд╛ рд╡рд░реНрдг рд▓реМрдЯрд╛рддрд╛ рд╣реИред
  • next() - рдзрд╛рд░рд╛ рд╕реЗ рдирд┐рдХрд╛рд▓рддреЗ рд╣реБрдП, рдЕрдЧрд▓рд╛ рд╡рд░реНрдг рд▓реМрдЯрд╛рддрд╛ рд╣реИред
  • eof() - рдпрджрд┐ рдзрд╛рд░рд╛ рдореЗрдВ рдЕрдзрд┐рдХ рд╡рд░реНрдг рдирд╣реАрдВ рд╣реИрдВ рддреЛ рдпрд╣ true рд╣реИред
  • croak(msg) - рд╕рдВрджреЗрд╢ ( msg ) рдФрд░ рдзрд╛рд░рд╛ рдореЗрдВ рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рд╡рд╛рд▓реЗ рдПрдХ рдЕрдкрд╡рд╛рдж рдХреЛ рдлреЗрдВрдХрддрд╛ рд╣реИред

рдЕрдВрддрд┐рдо рдлрд╝рдВрдХреНрд╢рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рддрд╛рдХрд┐ рдЖрдк рддреНрд░реБрдЯрд┐ рдХреЗ рд╕реНрдерд╛рди рд╡рд╛рд▓реЗ рдЕрдкрд╡рд╛рдж рдХреЛ рдлреЗрдВрдХ рд╕рдХреЗрдВред


рдпрд╣рд╛рдБ рдЗрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдкреВрд░рд╛ рдХреЛрдб рд╣реИ (рдЪрд▓реЛ рдЗрд╕реЗ InputStream рдХрд╣рддреЗ рд╣реИрдВ)ред рдпрд╣ рдХрд╛рдлреА рдЫреЛрдЯрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рдЗрд╕рдХреЗ рд╕рд╛рде рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП:


 function InputStream(input) { var pos = 0, line = 1, col = 0; return { next : next, peek : peek, eof : eof, croak : croak, }; function next() { var ch = input.charAt(pos++); if (ch == "\n") line++, col = 0; else col++; return ch; } function peek() { return input.charAt(pos); } function eof() { return peek() == ""; } function croak(msg) { throw new Error(msg + " (" + line + ":" + col + ")"); } } 

рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрд╣ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд╡рд╕реНрддреБ рдирд╣реАрдВ рд╣реИ (рдЬреЛ new рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдмрдирд╛рдИ рдЧрдИ рд╣реИ)ред рдЗрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ: var stream = InputStream(string) ред


рдЕрдЧрд▓рд╛, рд╣рдо рдЕрдореВрд░реНрддрддрд╛ рдХреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕реНрддрд░ рдХреЛ рд▓рд┐рдЦреЗрдВрдЧреЗ: рдЯреЛрдХрди рдкреНрд░рд╡рд╛рд╣ (рдЯреЛрдХрди) ред



рдЯреЛрдХрди рдкреНрд░рд╡рд╛рд╣ (рдЯреЛрдХрди)


рдЯреЛрдХреЗрдирд╛рдЗрдЬрд╝рд░ (lexer) рд╡рд░реНрдгреЛрдВ рдХреА рдПрдХ рдзрд╛рд░рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдПрдХ рд╣реА рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд╕рд╛рде рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди peek() / next() рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд░рд┐рдЯрд░реНрди рдорд╛рди рдЯреЛрдХрди рд╣реЛрдВрдЧреЗред рдПрдХ рдЯреЛрдХрди рджреЛ рдЧреБрдгреЛрдВ рд╡рд╛рд▓рд╛ рдПрдХ рдкреНрд░рдХрд╛рд░ рд╣реИ: type , value ред рдпрд╣рд╛рдБ рдЯреЛрдХрди рдХреЗ рдХреБрдЫ рдЙрджрд╛рд╣рд░рдг рджрд┐рдП рдЧрдП рд╣реИрдВ:


 { type: "punc", value: "(" } // . : , ,     . . { type: "num", value: 5 } //  { type: "str", value: "Hello World!" } //  { type: "kw", value: "lambda" } //   { type: "var", value: "a" } //  { type: "op", value: "!=" } //  

рд╡реНрд╣рд╛рдЯреНрд╕рдПрдк (рд╕реНрдкреЗрд╕, рдЯреИрдм, рд▓рд╛рдЗрди рдмреНрд░реЗрдХ) рдФрд░ рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдВ рдмрд╕ рдЫреЛрдбрд╝ рджреА рдЬрд╛рддреА рд╣реИрдВред


рдПрдХ рдЯреЛрдХрди рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЕрдкрдиреА рднрд╛рд╖рд╛ рдкрд░ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓рдиреЗ рдХреА рдЬрд╝рд░реВрд░рдд рд╣реИред рд╡рд┐рдЪрд╛рд░ рдпрд╣ рд╣реИ рдХрд┐ рд╡рд░реНрддрдорд╛рди рдЪрд░рд┐рддреНрд░ ( input.peek() ) рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╣рдо рдпрд╣ рддрдп рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХреМрди рд╕рд╛ рдЯреЛрдХрди рдкрдврд╝рдирд╛ рд╣реИ:


  • рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╡реНрд╣рд╛рдЯреНрд╕рдПрдк рдХреЛ рд╕реНрдХрд┐рдк рдХрд░реЗрдВред
  • рдпрджрд┐ input.eof() , рддреЛ null рд▓реМрдЯреЗрдВред
  • рдпрджрд┐ рдпрд╣ # рд╡рд░реНрдг рд╣реИ, рддреЛ рд╕рднреА рд╡рд░реНрдгреЛрдВ рдХреЛ рдкрдВрдХреНрддрд┐ рдХреЗ рдЕрдВрдд рддрдХ рдЫреЛрдбрд╝реЗрдВ (рдФрд░ рдЕрдЧрд▓рд╛ рдЯреЛрдХрди рд▓реМрдЯрд╛рдПрдВ)ред
  • рдпрджрд┐ рдпрд╣ рдПрдХ рдЙрджреНрдзрд░рдг рдЪрд┐рд╣реНрди рд╣реИ, рддреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкрдврд╝реЗрдВред
  • рдпрджрд┐ рдпрд╣ рдПрдХ рд╕рдВрдЦреНрдпрд╛ рд╣реИ, рддреЛ рд╕рдВрдЦреНрдпрд╛ рдкрдврд╝реЗрдВред
  • рдпрджрд┐ рдпрд╣ рдПрдХ рдкрддреНрд░ рд╣реИ, рддреЛ рд╣рдо рд╢рдмреНрдж рдкрдврд╝рддреЗ рд╣реИрдВ, рдФрд░ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдпрд╛ рдХреАрд╡рд░реНрдб рд╡рд╛рдкрд╕ рдХрд░рддреЗ рд╣реИрдВред
  • рдпрджрд┐ рдпрд╣ рд╡рд┐рд╢реЗрд╖ рд╡рд░реНрдгреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИ, рддреЛ рд╕рдВрдмрдВрдзрд┐рдд рдЯреЛрдХрди рд▓реМрдЯрд╛рдПрдВред
  • рдпрджрд┐ рдпрд╣ рдСрдкрд░реЗрдЯрд░реЛрдВ рдХреЗ рдкреНрд░рддреАрдХреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИ, рддреЛ рд╣рдо рд╕рдВрдмрдВрдзрд┐рдд рдЯреЛрдХрди рд▓реМрдЯрд╛рддреЗ рд╣реИрдВред
  • рдпрджрд┐ рдЙрдкрд░реЛрдХреНрдд рдореЗрдВ рд╕реЗ рдХреЛрдИ рднреА рд▓рд╛рдЧреВ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рддреЛ input.croak() рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдЕрдкрд╡рд╛рдж рдлреЗрдВрдХ рджреЗрдВред

рд╣рдорд╛рд░реЗ рдкрд╛рд╕ tokenizer рдХрд╛ рдореБрдЦреНрдп рдХрд╛рд░реНрдп read_next рдлрд╝рдВрдХреНрд╢рди рд╣реЛрдЧрд╛:


 function read_next() { read_while(is_whitespace); if (input.eof()) return null; var ch = input.peek(); if (ch == "#") { skip_comment(); return read_next(); } if (ch == '"') return read_string(); if (is_digit(ch)) return read_number(); if (is_id_start(ch)) return read_ident(); if (is_punc(ch)) return { type : "punc", value : input.next() }; if (is_op_char(ch)) return { type : "op", value : read_while(is_op_char) }; input.croak("Can't handle character: " + ch); } 

рдпрд╣рд╛рдВ рдЖрдк рдХрдИ рдЕрддрд┐рд░рд┐рдХреНрдд рдлрд╝рдВрдХреНрд╢рди рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░ рдХреЗ рдЯреЛрдХрди read_string() , рдЬреИрд╕реЗ рдХрд┐ read_string() , read_number() , рдЖрджрд┐ ... рдЙрдиреНрд╣реЗрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рд░рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддрд╛рдХрд┐ рдХреЛрдб рд╕рд░рд▓ рдФрд░ рдЕрдзрд┐рдХ рд╕реБрдВрджрд░ рджрд┐рдЦрд╛рдИ рджреЗред


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


read_ident() рд╕рднреА рд╡рд░реНрдгреЛрдВ рдХреЛ рдПрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ is_id() рдЬреЛ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ ( is_id() ) рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдХреЛ рдкрддреНрд░, ╬╗ , рдпрд╛ _ рд╢реБрд░реВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдЗрд╕рдореЗрдВ рдПрдХ рд╣реА рд╡рд░реНрдг, рд╕рдВрдЦреНрдпрд╛ рдпрд╛ рдХреЛрдИ рднреА рд╢рд╛рдорд┐рд▓ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ: ?!-<>= ред рдпрд╣ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╣реИ рдХрд┐ foo-bar рдХреЛ рддреАрди рдЯреЛрдХрди рдХреЗ рд░реВрдк рдореЗрдВ рдирд╣реАрдВ рдкрдврд╝рд╛ рдЬрд╛рдПрдЧрд╛, рд▓реЗрдХрд┐рди рдПрдХ рдХреЗ рд░реВрдк рдореЗрдВ ( var рдЯреЛрдХрди)ред рдХреНрдпрд╛ рдпрд╣ рдЗрд╕ рддрд░рд╣ рдХреЗ is-pair? рд░реВрдк is-pair? рдирд╛рдо рдХреЗ рд╕рд╛рде рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИ is-pair? рдпрд╛ string>= (рдХреНрд╖рдорд╛ рдХрд░реЗрдВ, рдпрд╣ рдореЗрд░реЗ рдореЗрдВ рд▓рд┐рд╕реНрдкрд░ рд╣реИ)ред


рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, read_ident() рдпрд╣ рдЬрд╛рдВрдЪ рдХрд░реЗрдЧрд╛ рдХрд┐ рдХреНрдпрд╛ рдЬреНрдЮрд╛рдд рдХреАрд╡рд░реНрдб рдХреА рд╕реВрдЪреА рдореЗрдВ рдХреЛрдИ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рдпрд╣ рд╣реИ, рддреЛ рдПрдХ var -token рдХреЛ var -token рдХреЗ рдмрдЬрд╛рдп рд╡рд╛рдкрд╕ рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдХреЛрдб рдЦреБрдж рдХреЗ рд▓рд┐рдП рдмреЛрд▓рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣рд╛рдВ рд╣рдорд╛рд░реА рднрд╛рд╖рд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рддреИрдпрд╛рд░ рдЯреЛрдХрди рд╣реИ:


рдкреВрд░рд╛ рдХреЛрдб
 function TokenStream(input) { var current = null; var keywords = " if then else lambda ╬╗ true false "; return { next : next, peek : peek, eof : eof, croak : input.croak }; function is_keyword(x) { return keywords.indexOf(" " + x + " ") >= 0; } function is_digit(ch) { return /[0-9]/i.test(ch); } function is_id_start(ch) { return /[a-z╬╗_]/i.test(ch); } function is_id(ch) { return is_id_start(ch) || "?!-<>=0123456789".indexOf(ch) >= 0; } function is_op_char(ch) { return "+-*/%=&|<>!".indexOf(ch) >= 0; } function is_punc(ch) { return ",;(){}[]".indexOf(ch) >= 0; } function is_whitespace(ch) { return " \t\n".indexOf(ch) >= 0; } function read_while(predicate) { var str = ""; while (!input.eof() && predicate(input.peek())) str += input.next(); return str; } function read_number() { var has_dot = false; var number = read_while(function(ch){ if (ch == ".") { if (has_dot) return false; has_dot = true; return true; } return is_digit(ch); }); return { type: "num", value: parseFloat(number) }; } function read_ident() { var id = read_while(is_id); return { type : is_keyword(id) ? "kw" : "var", value : id }; } function read_escaped(end) { var escaped = false, str = ""; input.next(); while (!input.eof()) { var ch = input.next(); if (escaped) { str += ch; escaped = false; } else if (ch == "\\") { escaped = true; } else if (ch == end) { break; } else { str += ch; } } return str; } function read_string() { return { type: "str", value: read_escaped('"') }; } function skip_comment() { read_while(function(ch){ return ch != "\n" }); input.next(); } function read_next() { read_while(is_whitespace); if (input.eof()) return null; var ch = input.peek(); if (ch == "#") { skip_comment(); return read_next(); } if (ch == '"') return read_string(); if (is_digit(ch)) return read_number(); if (is_id_start(ch)) return read_ident(); if (is_punc(ch)) return { type : "punc", value : input.next() }; if (is_op_char(ch)) return { type : "op", value : read_while(is_op_char) }; input.croak("Can't handle character: " + ch); } function peek() { return current || (current = read_next()); } function next() { var tok = current; current = null; return tok || read_next(); } function eof() { return peek() == null; } } 

  • next() рдлрд╝рдВрдХреНрд╢рди рд╣рдореЗрд╢рд╛ read_next() рдХреЙрд▓ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдПрдХ рдЯреЛрдХрди рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдкрд╣рд▓реЗ рдкрдврд╝рд╛ рдЧрдпрд╛ рд╣реЛ ( peek() рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ)ред рдЗрд╕рдХреЗ рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ current рдЪрд░ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╡рд░реНрддрдорд╛рди рдЯреЛрдХрди рд╢рд╛рдорд┐рд▓ рд╣реИред
  • рдХреЗрд╡рд▓ рджрд╢рдорд▓рд╡ рд╕рдВрдЦреНрдпрд╛ рдирд┐рдпрдорд┐рдд рд╕рдВрдХреЗрддрди рдореЗрдВ рд╕рдорд░реНрдерд┐рдд рд╣реИрдВ (1E5, 0x, рдЖрджрд┐ рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ рд╣реИрдВ)ред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рд╣рдо рдЙрдирдХрд╛ рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдХреЗрд╡рд▓ read_number() ред
  • рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд╡рд┐рдкрд░реАрдд, рдХреЗрд╡рд▓ рд╡рд░реНрдг рдЬреЛ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдЕрдирд╕реИрдкреНрдб рдирд╣реАрдВ рдХрд┐рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрджреНрдзрд░рдг рдЪрд┐рд╣реНрди рдФрд░ рдмреИрдХрд▓реИрд╢ рд╣реИрдВред рд▓рд╛рдЗрдиреЛрдВ рдореЗрдВ рд▓рд╛рдЗрди рдмреНрд░реЗрдХ, рдЯреИрдм рдФрд░ рдХреБрдЫ рднреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рд╣рдо рдорд╛рдирдХ рд╕рдВрдпреЛрдЬрдиреЛрдВ рдЬреИрд╕реЗ \n , \t , рдЖрджрд┐ рдХреА рд╡реНрдпрд╛рдЦреНрдпрд╛ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ ... рдпрд╣ рдлрд┐рд░ рд╕реЗ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИ ( read_string() )ред

рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЖрд╕рд╛рдиреА рд╕реЗ рдПрдХ рдкрд╛рд░реНрд╕рд░ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдЙрдкрдХрд░рдг рд╣реИрдВ, рд▓реЗрдХрд┐рди рдкрд╣рд▓реЗ рдореИрдВ рдПрдПрд╕рдЯреА рд╡рд┐рд╡рд░рдг рдХреЛ рджреЗрдЦрдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреВрдВрдЧрд╛ ред



рдПрдПрд╕рдЯреА рд╡рд┐рд╡рд░рдг


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


рдЯрд╛рдЗрдкрд╕рдВрд░рдЪрдирд╛
рд╕рдВрдЦреНрдпрд╛{ type: "num", value: NUMBER }
str{ type: "str", value: STRING }
bool{ type: "bool", value: true or false }
рд╡рд░{ type: "var", value: NAME }
рд▓реИрдореНрдмреНрдбрд╛{ type: "lambda", vars: [ NAME... ], body: AST }
рдХреЙрд▓{ type: "call", func: AST, args: [ AST... ] }
рдЕрдЧрд░{ type: "if", cond: AST, then: AST, else: AST }
рдЕрд╕рд╛рдЗрди{ type: "assign", operator: "=", left: AST, right: AST }
рдмрд╛рдЗрдирд░реА{ type: "binary", operator: OPERATOR, left: AST, right: AST }
рдареЗрд▓рд╛{ type: "prog", prog: [ AST... ] }
рдЪрд▓реЛ{ type: "let", vars: [ VARS... ], body: AST }

рдЙрджрд╛рд╣рд░рдг
рд╕рдВрдЦреНрдпрд╛ ( num ):

 123.5 

 { type: "num", value: 123.5 } 

рд▓рд╛рдЗрдиреЗрдВ ( str ):

 "Hello World" 

 { type: "str", value: "Hello World!" } 

true рдФрд░ false ( bool ):

 true false 

 { type: "bool", value: true } { type: "bool", value: false } 

рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ ( var ):

 foo 

 { type: "var", value: "foo" } 

рдХрд╛рд░реНрдп ( lambda ):

 lambda (x) 10 #  ╬╗ (x) 10 

 { type: "lambda", vars: [ "x" ], body: { type: "num", value: 10 } } 

рдмрд╛рдж рдореЗрдВ рд╣рдо рдПрдХ рдирд╛рдо рдХреЗ рд╕рд╛рде рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рдкреИрд░рд╛рдореАрдЯрд░ name рдЬреЛрдбрд╝ рджреЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдкрд╛рд░реНрд╕рд░ рдХрд╛ рдкрд╣рд▓рд╛ рд╕рдВрд╕реНрдХрд░рдг рдЙрдирдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред


рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ ( call ):

 foo(a, 1) 

 { "type": "call", "func": { "type": "var", "value": "foo" }, "args": [ { "type": "var", "value": "a" }, { "type": "num", "value": 1 } ] } 

рд╢рд╛рдЦрд╛рдПрдБ ( if ):

 if foo then bar else baz 

 { "type": "if", "cond": { "type": "var", "value": "foo" }, "then": { "type": "var", "value": "bar" }, "else": { "type": "var", "value": "baz" } } 

else рдмрд┐рдирд╛:

 if foo then bar 

 { "type": "if", "cond": { "type": "var", "value": "foo" }, "then": { "type": "var", "value": "bar" } } 

рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ ( assign ):

 a = 10 

 { "type": "assign", "operator": "=", "left": { "type": "var", "value": "a" }, "right": { "type": "num", "value": 10 } } 

рдмрд╛рдЗрдирд░реА рдСрдкрд░реЗрдЯрд░ ( binary ):

 x + y * z 

 { "type": "binary", "operator": "+", "left": { "type": "var", "value": "x" }, "right": { "type": "binary", "operator": "*", "left": { "type": "var", "value": "y" }, "right": { "type": "var", "value": "z" } } } 

рдЕрдиреБрдХреНрд░рдо ( prog ):

 { a = 5; b = a * 2; a + b; } 

 { "type": "prog", "prog": [ { "type": "assign", "operator": "=", "left": { "type": "var", "value": "a" }, "right": { "type": "num", "value": 5 } }, { "type": "assign", "operator": "=", "left": { "type": "var", "value": "b" }, "right": { "type": "binary", "operator": "*", "left": { "type": "var", "value": "a" }, "right": { "type": "num", "value": 2 } } }, { "type": "binary", "operator": "+", "left": { "type": "var", "value": "a" }, "right": { "type": "var", "value": "b" } } ] } 

рдмреНрд▓реЙрдХ рдореЗрдВ рд╕рдВрд▓рдЧреНрди рдЪрд░ ( let ):

 let (a = 10, b = a * 10) { a + b; } 

 { "type": "let", "vars": [ { "name": "a", "def": { "type": "num", "value": 10 } }, { "name": "b", "def": { "type": "binary", "operator": "*", "left": { "type": "var", "value": "a" }, "right": { "type": "num", "value": 10 } } } ], "body": { "type": "binary", "operator": "+", "left": { "type": "var", "value": "a" }, "right": { "type": "var", "value": "b" } } } 

рдкрд╛рд░реНрд╕рд░ рдХрд╛ рдкрд╣рд▓рд╛ рд╕рдВрд╕реНрдХрд░рдг рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рдиреЛрдб рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░реЗрдЧрд╛, рд╣рдо рдЗрд╕реЗ рдмрд╛рдж рдореЗрдВ рдЬреЛрдбрд╝ рджреЗрдВрдЧреЗред



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


рдкрд╛рд░реНрд╕рд░ рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рдкреЗрдбрд╝ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░реЗрдЧрд╛ред


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


 function parse_lambda() { return { type: "lambda", vars: delimited("(", ")", ",", parse_varname), body: parse_expression() }; } 

рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рддрдм рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛ рдЬрдм lambda рдХреАрд╡рд░реНрдб рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЯреЛрдХрди рд╕реНрдЯреНрд░реАрдо рд╕реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдХреЗрд╡рд▓ рддрд░реНрдХреЛрдВ рдХреЗ рдирд╛рдо рд▓реЗрдиреЗ рд╣реЛрдВрдЧреЗред рд▓реЗрдХрд┐рди рдЪреВрдВрдХрд┐ рд╡реЗ рдХреЛрд╖реНрдардХ рдореЗрдВ рд╣реИрдВ рдФрд░ рдЕрд▓реНрдкрд╡рд┐рд░рд╛рдо рджреНрд╡рд╛рд░рд╛ рдЕрд▓рдЧ рдХрд┐рдП рдЧрдП рд╣реИрдВ, рд╣рдо рдЗрд╕реЗ delimited рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд░реЗрдВрдЧреЗ, рдЬреЛ рдирд┐рдореНрди рддрд░реНрдХ рд▓реЗрддрд╛ рд╣реИ: start , stop , separator , parser рдлрд╝рдВрдХреНрд╢рди, рдЬреЛ рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдХреЛ рдЕрд▓рдЧ рд╕реЗ рдкрд╛рд░реНрд╕ рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдо parse_varname рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдПрдХ рддреНрд░реБрдЯрд┐ рдХреЛ рдлреЗрдВрдХрддрд╛ рд╣реИ рдпрджрд┐ рдпрд╣ рдХреБрдЫ рдРрд╕рд╛ рдиреЛрдЯрд┐рд╕ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдПрдХ рдЪрд░ рдХреА рддрд░рд╣ рдирд╣реАрдВ рджрд┐рдЦрддрд╛ рд╣реИред рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рд╢рд░реАрд░ рдПрдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕реЗ parse_expression рд╕рд╛рде рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВред


delimited рдлрд╝рдВрдХреНрд╢рди рдирд┐рдореНрди рд╕реНрддрд░ рд╣реИ:


 function delimited(start, stop, separator, parser) { var a = [], first = true; skip_punc(start); while (!input.eof()) { if (is_punc(stop)) break; if (first) first = false; else skip_punc(separator); if (is_punc(stop)) break; //      a.push(parser()); } skip_punc(stop); return a; } 

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╣ рдФрд░ рднреА рдЕрдзрд┐рдХ рдлрд╝рдВрдХреНрд╢рдВрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ: is_punc рдФрд░ skip_punc ред рдкрд╣рд▓рд╛ рд░рд┐рдЯрд░реНрди true рдЕрдЧрд░ рд╡рд░реНрддрдорд╛рди рдЯреЛрдХрди рджрд┐рдпрд╛ рдЧрдпрд╛ рд╡рд┐рд░рд╛рдо рдЪрд┐рд╣реНрди рд╣реИ (рдЗрд╕реЗ рдирд┐рдХрд╛рд▓реЗ рдмрд┐рдирд╛), рдЬрдмрдХрд┐ skip_punc рдпрд╣ рдЬрд╛рдВрдЪ рдХрд░реЗрдЧрд╛ рдХрд┐ рдХреНрдпрд╛ рд╡рд░реНрддрдорд╛рди рдЯреЛрдХрди рджрд┐рдпрд╛ рдЧрдпрд╛ рд╡рд┐рд░рд╛рдо рдЪрд┐рд╣реНрди рд╡рд░реНрдг рд╣реИ рдФрд░ рдЗрд╕реЗ рдирд┐рдХрд╛рд▓реЗрдВ (рдпрд╛ рдЕрдиреНрдпрдерд╛ рдПрдХ рдЕрдкрд╡рд╛рдж рдлреЗрдВрдХреЗрдВ)ред


рдкреВрд░реЗ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдХрд╛рд░реНрдп рд╕рдмрд╕реЗ рд╕рд░рд▓ рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ:


 function parse_toplevel() { var prog = []; while (!input.eof()) { prog.push(parse_expression()); if (!input.eof()) skip_punc(";"); } return { type: "prog", prog: prog }; } 

рдЪреВрдБрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреЗрд╡рд▓ рднрд╛рд╡ рд╣реИрдВ, рд╣рдо рдмрд╕ parse_expression() рдХрд╣рддреЗ рд╣реИрдВ рдФрд░ рднрд╛рд╡реЛрдВ рдХреЛ рддрдм рддрдХ рдкрдврд╝рддреЗ рд╣реИрдВ рдЬрдм рддрдХ рд╣рдо рд╕рдм рдХреБрдЫ рдирд╣реАрдВ рдкрдврд╝ рд▓реЗрддреЗред skip_punc(";") рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рдХрд░рддреЗ рд╣реИрдВ ; рдкреНрд░рддреНрдпреЗрдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рдмрд╛рдж рдЕрдирд┐рд╡рд╛рд░реНрдп рд╣реИред


рдПрдХ рдФрд░ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рд╣реИ parse_if() :


 function parse_if() { skip_kw("if"); var cond = parse_expression(); if (!is_punc("{")) skip_kw("then"); var then = parse_expression(); var ret = { type: "if", cond: cond, then: then }; if (is_kw("else")) { input.next(); ret.else = parse_expression(); } return ret; } 

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


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


рдЗрд╕ рддрд░рд╣ рдХреА рдкрд╛рд░реНрд╕рд┐рдВрдЧ рд╡рд┐рдзрд┐ рдХреЛ рд░рд┐рдХрд░реНрд╕рд┐рд╡ рдбрд┐рд╕реЗрдВрдЯ рд╡рд┐рдзрд┐ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд▓рд┐рдЦрдирд╛ рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рд╣реИред


рдирд┐рдЪрд▓рд╛ рд╕реНрддрд░: parse_atom() рдФрд░ parse_expression()


parse_atom() рдлрд╝рдВрдХреНрд╢рди рд╡рд░реНрддрдорд╛рди рдЯреЛрдХрди рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдПрдХ рдЕрдиреНрдп рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ:


 function parse_atom() { return maybe_call(function(){ if (is_punc("(")) { input.next(); var exp = parse_expression(); skip_punc(")"); return exp; } if (is_punc("{")) return parse_prog(); if (is_kw("if")) return parse_if(); if (is_kw("true") || is_kw("false")) return parse_bool(); if (is_kw("lambda") || is_kw("╬╗")) { input.next(); return parse_lambda(); } var tok = input.next(); if (tok.type == "var" || tok.type == "num" || tok.type == "str") return tok; unexpected(); }); } 

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


рдЬрдм рд╡рд╣ { рджреЗрдЦрддрд╛ рд╣реИ, рддреЛ рд╡рд╣ parse_prog рдХреЗ рдЕрдиреБрдХреНрд░рдо рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП parse_prog рдХрд╣рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, parse_prog рдПрдХ рд╕рд░рд▓ рдЕрдиреБрдХреВрд▓рди рдХрд░рддрд╛ рд╣реИ: рдпрджрд┐ { рдФрд░ } рдмреАрдЪ рдХреЛрдИ рднрд╛рд╡ рдирд╣реАрдВ рд╣реИрдВ, рддреЛ рдпрд╣ false , рдпрджрд┐ рдХреЗрд╡рд▓ рдПрдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╣реИ, рддреЛ рдпрд╣ рдХреЗрд╡рд▓ рдЗрд╕реЗ рд╡рд╛рдкрд╕ рдХрд░рддрд╛ рд╣реИред рдЕрдиреНрдпрдерд╛, рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреА рдПрдХ рд╕рд░рдгреА рдХреЗ рд╕рд╛рде prog рдиреЛрдб рд╡рд╛рдкрд╕ рдЖ рдЧрдпрд╛ рд╣реИред


 //     FALSE   , //     . var FALSE = { type: "bool", value: false }; function parse_prog() { var prog = delimited("{", "}", ";", parse_expression); if (prog.length == 0) return FALSE; if (prog.length == 1) return prog[0]; return { type: "prog", prog: prog }; } 

рдФрд░ рдпрд╣рд╛рдБ parse_expression() рдлрд╝рдВрдХреНрд╢рди рд╣реИред parse_atom() рд╡рд┐рдкрд░реАрдд, рдпрд╣ рд╕рдВрднрд╡ рдХреЗ рд░реВрдк рдореЗрдВ рдХрдИ рднрд╛рд╡реЛрдВ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░реЗрдЧрд╛ред


 function parse_expression() { return maybe_call(function(){ return maybe_binary(parse_atom(), 0); }); } 

рдХрд╛рд░реНрдп maybe_*


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


maybe_call() рдлрд╝рдВрдХреНрд╢рди рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ: рдпрд╣ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ рдЬреЛ рд╡рд░реНрддрдорд╛рди рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рдпрд╣ рд╕рд╛рдордирд╛ рдХрд░рддрд╛ рд╣реИ ( рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рдмрд╛рдж, рдпрд╣ call рдореЗрдВ рдЦреБрдж рдХреЛ рд▓рдкреЗрдЯрддрд╛ рд╣реИред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдХреИрд╕реЗ delimited() рддрд░реНрдХреЛрдВ рдХреА рд╕реВрдЪреА рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рд╣реИ:


 function maybe_call(expr) { expr = expr(); return is_punc("(") ? parse_call(expr) : expr; } function parse_call(func) { return { type: "call", func: func, args: delimited("(", ")", ",", parse_expression) }; } 

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


maybe_binary(left, my_prec) рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ 1 + 2 * 3 рдЬреИрд╕реЗ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдХреЛ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд▓рдмреНрдмреЛрд▓реБрдЖрдм рдпрд╣ рд╣реИ рдХрд┐ рдЙрдиреНрд╣реЗрдВ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдСрдкрд░реЗрдЯрд░реЛрдВ рдХреА рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛:


 var PRECEDENCE = { "=": 1, "||": 2, "&&": 3, "<": 7, ">": 7, "<=": 7, ">=": 7, "==": 7, "!=": 7, "+": 10, "-": 10, "*": 20, "/": 20, "%": 20, }; 

, * "", + , , 1 + 2 * 3 (1 + (2 * 3)) ((1 + 2) * 3) .


, ( read_atom ) maybe_binary() ( ), ( my_prec ). maybe_binary , . , , .


, , , binary , , , (*):


 function maybe_binary(left, my_prec) { var tok = is_op(); if (tok) { var his_prec = PRECEDENCE[tok.value]; if (his_prec > my_prec) { input.next(); var right = maybe_binary(parse_atom(), his_prec) // (*); var binary = { type : tok.value == "=" ? "assign" : "binary", operator : tok.value, left : left, right : right }; return maybe_binary(binary, my_prec); } } return left; } 

, , , maybe_binary , ( my_prec ), , , . - , (, ), .


, , my_prec 0, binary ( assign = ).


, .


 var FALSE = { type: "bool", value: false }; function parse(input) { var PRECEDENCE = { "=": 1, "||": 2, "&&": 3, "<": 7, ">": 7, "<=": 7, ">=": 7, "==": 7, "!=": 7, "+": 10, "-": 10, "*": 20, "/": 20, "%": 20, }; return parse_toplevel(); function is_punc(ch) { var tok = input.peek(); return tok && tok.type == "punc" && (!ch || tok.value == ch) && tok; } function is_kw(kw) { var tok = input.peek(); return tok && tok.type == "kw" && (!kw || tok.value == kw) && tok; } function is_op(op) { var tok = input.peek(); return tok && tok.type == "op" && (!op || tok.value == op) && tok; } function skip_punc(ch) { if (is_punc(ch)) input.next(); else input.croak("Expecting punctuation: \"" + ch + "\""); } function skip_kw(kw) { if (is_kw(kw)) input.next(); else input.croak("Expecting keyword: \"" + kw + "\""); } function skip_op(op) { if (is_op(op)) input.next(); else input.croak("Expecting operator: \"" + op + "\""); } function unexpected() { input.croak("Unexpected token: " + JSON.stringify(input.peek())); } function maybe_binary(left, my_prec) { var tok = is_op(); if (tok) { var his_prec = PRECEDENCE[tok.value]; if (his_prec > my_prec) { input.next(); return maybe_binary({ type : tok.value == "=" ? "assign" : "binary", operator : tok.value, left : left, right : maybe_binary(parse_atom(), his_prec) }, my_prec); } } return left; } function delimited(start, stop, separator, parser) { var a = [], first = true; skip_punc(start); while (!input.eof()) { if (is_punc(stop)) break; if (first) first = false; else skip_punc(separator); if (is_punc(stop)) break; a.push(parser()); } skip_punc(stop); return a; } function parse_call(func) { return { type: "call", func: func, args: delimited("(", ")", ",", parse_expression), }; } function parse_varname() { var name = input.next(); if (name.type != "var") input.croak("Expecting variable name"); return name.value; } function parse_if() { skip_kw("if"); var cond = parse_expression(); if (!is_punc("{")) skip_kw("then"); var then = parse_expression(); var ret = { type: "if", cond: cond, then: then, }; if (is_kw("else")) { input.next(); ret.else = parse_expression(); } return ret; } function parse_lambda() { return { type: "lambda", vars: delimited("(", ")", ",", parse_varname), body: parse_expression() }; } function parse_bool() { return { type : "bool", value : input.next().value == "true" }; } function maybe_call(expr) { expr = expr(); return is_punc("(") ? parse_call(expr) : expr; } function parse_atom() { return maybe_call(function(){ if (is_punc("(")) { input.next(); var exp = parse_expression(); skip_punc(")"); return exp; } if (is_punc("{")) return parse_prog(); if (is_kw("if")) return parse_if(); if (is_kw("true") || is_kw("false")) return parse_bool(); if (is_kw("lambda") || is_kw("╬╗")) { input.next(); return parse_lambda(); } var tok = input.next(); if (tok.type == "var" || tok.type == "num" || tok.type == "str") return tok; unexpected(); }); } function parse_toplevel() { var prog = []; while (!input.eof()) { prog.push(parse_expression()); if (!input.eof()) skip_punc(";"); } return { type: "prog", prog: prog }; } function parse_prog() { var prog = delimited("{", "}", ";", parse_expression); if (prog.length == 0) return FALSE; if (prog.length == 1) return prog[0]; return { type: "prog", prog: prog }; } function parse_expression() { return maybe_call(function(){ return maybe_binary(parse_atom(), 0); }); } } 


Marijn Haverbeke, parse-js (Common Lisp), , . , , JS, .


: JavaScript. рднрд╛рдЧ 2: рджреБрднрд╛рд╖рд┐рдпрд╛

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


All Articles