рдпрд╣ рд▓реЗрдЦ рдПрд░реЛрди рдкреИрдЯрд░рд╕рди рджреНрд╡рд╛рд░рд╛ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдерд╛, рдЬреЛ рд╕рд┐рдПрдЯрд▓, рд╡рд╛рд╢рд┐рдВрдЧрдЯрди рдХреЗ рдПрдХ рд░реВрдмреА рдбреЗрд╡рд▓рдкрд░ рдереЗред рд╡рд╣ рд░реВрдмреА рд╡рд┐рдХрд╛рд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ 7 рд╡рд░реНрд╖реЛрдВ рд╕реЗ рднрд╛рд╡реБрдХ рд╣реИ рдФрд░ рдЗрд╕ рдЕрджреНрднреБрдд рднрд╛рд╖рд╛ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рдкреНрдпрд╛рд░ рдХреЛ рд╕рд╛рдЭрд╛ рдХрд░рдиреЗ рдореЗрдВ рдЦреБрд╢реА рд╣реЛрдЧреАредрд╕рднреА рдХреЛ рд╕рд▓рд╛рдо! рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЖрдк рдЕрдЪреНрдЫреЗ рдореВрдб рдореЗрдВ рд╣реИрдВред рдЖрдЬ, рд╕реВрд░рдЬ рдереЛрдбрд╝реА рджреЗрд░ рдХреЗ рд▓рд┐рдП рдмрд╛рджрд▓реЛрдВ рдХреЗ рдкреАрдЫреЗ рд╕реЗ рдмрд╛рд╣рд░ рдЭрд╛рдВрдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореЗрд░реЗ рдкрд╛рд╕ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рдм рдХреБрдЫ рд╣реИ!
рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рд╣рдо рд░реВрдмреА рдХреЗ рд╕рд╛рде рд╕рдВрдпреЛрдЬрди рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдХрдИ рд╕рдВрдХрд▓рди рдЙрдкрдХрд░рдг рджреЗрдЦреЗрдВрдЧреЗред рдФрд░ рд╡рд┐рд╖рдп рдореЗрдВ рдЧреЛрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ JSON рдкрд╛рд░реНрд╕рд░ рд▓рд┐рдЦреЗрдВрдЧреЗред рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдореИрдВ рдЕрд╕рдВрддреБрд╖реНрдЯ рд╡рд┐рд╕реНрдордпрд╛рджрд┐рдмреЛрдзрдХ рд╕реБрдирддрд╛ рд╣реВрдВ рдЬреИрд╕реЗ: "рдареАрдХ рд╣реИ, рд╣рд╛рд░реВрди, рдХреНрдпреЛрдВ? рд╡реЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА 1,234,567 рдЯреБрдХрдбрд╝реЗ рдирд╣реАрдВ рд▓рд┐рдЦреЗ рдЧрдП рд╣реИрдВ? тАЭрдпрд╣ рдмрд╛рдд рд╣реИ! рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ 1,234,567 рд░реВрдмреА рдЬреЙрдиреНрд╕ рдкрд╛рд░реНрд╕рд░ рд╣реИрдВ! рдФрд░ рд╣рдо JSON рд╡рд┐рд╢реНрд▓реЗрд╖рдг рднреА рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдХрд╛ рд╡реНрдпрд╛рдХрд░рдг рдПрдХ рд╣реА рдмрд╛рд░ рдореЗрдВ рдХрд╛рдо рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ, рдФрд░ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдкрд░реНрдпрд╛рдкреНрдд рд░реВрдк рд╕реЗ рд░реВрдмреА рдХреЗ рд▓рд┐рдП рд╕рдордЭрджрд╛рд░реА рд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рд╕рдВрдХрд▓рди рдЙрдкрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдЬрдЯрд┐рд▓ рд╣реИред
рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рдЖрдк рдкрдврд╝рдирд╛ рдЬрд╛рд░реА рд░рдЦреЗрдВ, рдореИрдВ рдЗрд╕ рддрдереНрдп рдкрд░ рдзреНрдпрд╛рди рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдпрд╣ JSON рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗ рдкрд░ рдХреЛрдИ рд▓реЗрдЦ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рд░реВрдмреА рдореЗрдВ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдФрд░ рд╕рдВрдХрд▓рди рдЙрдкрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реЗрдВред
рд╣рдореЗрдВ рдХреНрдпрд╛ рдЪрд╛рд╣рд┐рдП?
рдореИрдВ рд░реВрдмреА 1.9.3 рдкрд░ рдкрд░реАрдХреНрд╖рдг рдХрд░реВрдВрдЧрд╛, рд▓реЗрдХрд┐рди рдпрд╣ рдХрд┐рд╕реА рднреА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд░ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рдЖрдк рдЪреБрдирддреЗ рд╣реИрдВред рд╣рдо рдореБрдЦреНрдп рд░реВрдк рд╕реЗ
StringScanner
рдФрд░
StringScanner
рдЬреИрд╕реЗ рдЙрдкрдХрд░рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред
RACC:
рд╣рдореЗрдВ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХреЛ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд░рд╕реАрд╕реА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣ YACC рдХреЗ рд╕рдорд╛рди рдХрдИ рдорд╛рдпрдиреЛрдВ рдореЗрдВ рдПрдХ LALR рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдЬрдирд░реЗрдЯрд░ рд╣реИред рдЕрдВрддрд┐рдо рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдирд╛рдо "рдлрд┐рд░ рднреА рдПрдХ рдФрд░ рд╕рдВрдХрд▓рдХ рд╕рдВрдХрд▓рдХ" (рдПрдХ рдФрд░ рд╕рдВрдХрд▓рдХ рд╕рдВрдХрд▓рдХ) рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЪреВрдВрдХрд┐ рдпрд╣ рд░реВрдмреА рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрд╕реНрдХрд░рдг рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕рдиреЗ рдЖрд░рд╕реАрд╕реА рдХреЛ рдмрджрд▓ рджрд┐рдпрд╛ред
.y
рд░реВрдмреА рдлрд╝рд╛рдЗрд▓ рдХреЗ рд▓рд┐рдП рд╡реНрдпрд╛рдХрд░рдг рдирд┐рдпрдореЛрдВ рдХреЗ рдПрдХ рд╕реЗрдЯ (
.y
рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреЗ рд╕рд╛рде рдПрдХ рдлрд╝рд╛рдЗрд▓) рдХреЛ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рдмрджреНрдз рд╣реИ рдЬреЛ рдПрдХ рд░рд╛рдЬреНрдп рдорд╢реАрди рдХреЗ рд▓рд┐рдП рд╕рдВрдХреНрд░рдордг рдирд┐рдпрдореЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИред рдмрд╛рдж рд╡рд╛рд▓реЗ рдХреА рд╡реНрдпрд╛рдЦреНрдпрд╛ рдЖрд░рдПрд╕реА рд╕реНрдЯреЗрдЯ рдорд╢реАрди (рд░рдирдЯрд╛рдЗрдо) рджреНрд╡рд╛рд░рд╛ рдХреА рдЬрд╛рддреА рд╣реИред рд░рдирдЯрд╛рдЗрдо рд░реВрдмреА рдХреЗ рд╕рд╛рде рдЖрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдореЗрдВ рд╡рд╣ рдЯреВрд▓ рдирд╣реАрдВ рд╣реИ рдЬреЛ рдорд╢реАрди рдХреЗ рд╕реНрдЯреЗрдЯ рдЯреЗрдмрд▓ рдореЗрдВ ".y" рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреЗ рд╕рд╛рде рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддрд╛ рд╣реИред
gem install racc
рдХрд░рдХреЗ рдЗрд╕реЗ
gem install racc
ред
рдЗрд╕рдХреЗ рдмрд╛рдж, рд╣рдо ".y" рдлрд╛рдЗрд▓реЗрдВ рд▓рд┐рдЦреЗрдВрдЧреЗ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЕрдВрддрд┐рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЙрдиреНрд╣реЗрдВ рдирд╣реАрдВ рдЪрд▓рд╛ рдкрд╛рдПрдВрдЧреЗред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЙрдиреНрд╣реЗрдВ рдкрд╣рд▓реЗ рд░реВрдмреА рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рдХреЛрдб рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдлрд┐рд░ рдЗрд╕ рдХреЛрдб рдХреЛ рд╣рдорд╛рд░реЗ рдордгрд┐ рдореЗрдВ рдкреИрдХ рдХрд░реЗрдВред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдХреЗрд╡рд▓ рдордгрд┐ рдЖрд░рд╕реАрд╕реА рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВрдЧреЗ, рдФрд░ рдпрд╣ рдЕрдВрддрд┐рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реЛрдЧрд╛ред
рдЪрд┐рдВрддрд╛ рдордд рдХрд░реЛ рдЕрдЧрд░ рдпрд╣ рд╕рдм рд╕рд┐рд░ рдореЗрдВ рдлрд┐рдЯ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рдЬрдм рд╣рдо рд╕рд┐рджреНрдзрд╛рдВрдд рд╕реЗ рдЕрднреНрдпрд╛рд╕ рдХрд░рдиреЗ рдФрд░ рдХреЛрдб рд▓рд┐рдЦрдирд╛ рд╢реБрд░реВ рдХрд░реЗрдВрдЧреЗ рддреЛ рд╕рдм рдХреБрдЫ рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред
StringScanner:
StringScanner рдПрдХ рд╡рд░реНрдЧ рд╣реИ рдЬреЛ (рдЬреИрд╕рд╛ рдХрд┐ рдирд╛рдо рд╕реЗ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ) рдЖрдкрдХреЛ рд╕реНрдХреИрдирд░ рдХреЗ рд╕рд┐рджреНрдзрд╛рдВрдд рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХреНрд░рдорд┐рдХ рд░реВрдк рд╕реЗ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдпрд╣ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рд╣рдо рдХрд╣рд╛рдВ рд╣реИрдВ рдФрд░ рдЖрдкрдХреЛ рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдФрд░ рдкрд╛рддреНрд░реЛрдВ рдХреЗ рдкреНрд░рддреНрдпрдХреНрд╖ рдкрдврд╝рдиреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╢реБрд░реБрдЖрдд рд╕реЗ рдЕрдВрдд рддрдХ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рдЪрд▓реЛ рд╢реБрд░реВ рд╣реЛ рдЬрд╛рдУ! рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдПрдХ
StringScanner
рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдПрдБ рдФрд░ рдЗрд╕рдХреЗ рд╕рд╛рде рдХреБрдЫ рд╡рд░реНрдгреЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░реЗрдВ:
irb(main):001:0> require 'strscan' => true irb(main):002:0> ss = StringScanner.new 'aabbbbb' => #<StringScanner 0/7 @ "aabbb..."> irb(main):003:0> ss.scan /a/ => "a" irb(main):004:0> ss.scan /a/ => "a" irb(main):005:0> ss.scan /a/ => nil irb(main):006:0> ss => #<StringScanner 2/7 "aa" @ "bbbbb"> irb(main):007:0>
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐
StringScanner # рд╕реНрдХреИрди рдХреА рддреАрд╕рд░реА рдХреЙрд▓
nil
, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдЕрдм рдлрд┐рдЯ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИред рдФрд░ рдпрд╣ рднреА, рдЬрдм
StringScanner
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП
inspect
рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЖрдк рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рд╣реИрдВрдбрд▓рд░ рдХреА рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ (рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ
2/7
)ред
рдЖрдк
StringScanner # getch рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╣реИрдВрдбрд▓рд░ рдХреИрд░реЗрдХреНрдЯрд░-рдмрд╛рдп-рдХреИрд░реЗрдХреНрдЯрд░ рдХреЛ рднреА рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
irb(main):006:0> ss => #<StringScanner 2/7 "aa" @ "bbbbb"> irb(main):007:0> ss.getch => "b" irb(main):008:0> ss => #<StringScanner 3/7 "aab" @ "bbbb"> irb(main):009:0>
getch
рд╡рд┐рдзрд┐ рдЕрдЧрд▓реЗ рд╡рд░реНрдг рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рддреА рд╣реИ рдФрд░ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рдЖрдЧреЗ рдмрдврд╝рд╛рддреА рд╣реИред
рдЕрдм рдЬрдм рд╣рдордиреЗ рдЕрдиреБрдХреНрд░рдорд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреА рдореВрд▓ рдмрд╛рддреЗрдВ рд╕рдордЭ рд▓реА рд╣реИрдВ, рддреЛ рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдХреИрд╕реЗ рдЖрд░рдПрд╕реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдЖрд░рдПрд╕реА рдореВрд▓ рдмрд╛рддреЗрдВ
рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдХрд╣рд╛, рдЖрд░рдПрд╕реА рдПрдХ рдПрд▓рдПрдПрд▓рдЖрд░ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдЬрдирд░реЗрдЯрд░ рд╣реИред рд╣рдо рдпрд╣ рдорд╛рди рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдПрдХ рдРрд╕рд╛ рддрдВрддреНрд░ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рд╕реАрдорд┐рдд рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдирд┐рдпрдорд┐рдд рднрд╛рд╡ рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬреЛ рдмрджрд▓реЗ рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рдкрджреЛрдВ рдкрд░ рдордирдорд╛рдиреЗ рдврдВрдЧ рд╕реЗ рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдЙрдирдХреА рддреБрд▓рдирд╛ рдХреИрд╕реЗ рдХреА рдЬрд╛рддреА рд╣реИред
рдЖрдЗрдП рдПрдХ рдЙрджрд╛рд╣рд░рдг рджреЗрдЦреЗрдВред рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдо рдлрд╝реЙрд░реНрдо рдХреА рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХреЗ рд▓рд┐рдП рдЬрд╛рдБрдЪ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ:
(a|c)*abb
| рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдРрд╕реЗ рдорд╛рдорд▓реЛрдВ рдХреЛ рджрд░реНрдЬ рдХрд░реЗрдВ рдЬрдм 'рдЕ' рдпрд╛ 'рдЧ' рдХреЗ рдмрд╛рдж рд╡рд░реНрдгреЛрдВ рдХреА рдПрдХ рдордирдорд╛рдиреА рд╕рдВрдЦреНрдпрд╛ рд╣реЛрддреА рд╣реИред рдЗрд╕реЗ рдПрдХ рдЖрд░рд╕реАрдЖрд░ рд╡реНрдпрд╛рдХрд░рдг рдореЗрдВ рдЕрдиреБрд╡рд╛рдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЗрд╕ рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЛ рдЗрд╕рдХреЗ рдШрдЯрдХ рднрд╛рдЧреЛрдВ рдореЗрдВ рддреЛрдбрд╝рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВрдЧреЗ, рдФрд░ рдлрд┐рд░ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдПрдХ рд╕рд╛рде рд░рдЦреЗрдВрдЧреЗред рдкреНрд░рддреНрдпреЗрдХ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд╡реНрдпрд╛рдХрд░рдг рддрддреНрд╡ рдХреЛ рдПрдХ рдЙрддреНрдкрддреНрддрд┐ рдирд┐рдпрдо рдпрд╛ рдЙрддреНрдкрд╛рдж рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рддреЛ, рдЖрдЗрдП рдЗрд╕ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЛ рдЕрд▓рдЧ рдХрд░рддреЗ рд╣реБрдП рджреЗрдЦреЗрдВ рдХрд┐ рдЙрддреНрдкрд╛рдж рдХреИрд╕реЗ рджрд┐рдЦрддреЗ рд╣реИрдВ рдФрд░ рдЖрд░рд╕реАрд╕реА рдХрд╛ рд╡реНрдпрд╛рдХрд░рдг рдХрд┐рд╕ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рд╣реИред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдПрдХ рд╡реНрдпрд╛рдХрд░рдг рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдБред рдлрд╝рд╛рдЗрд▓ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рд░реВрдмреА рд╡рд░реНрдЧ рдХреА рдШреЛрд╖рдгрд╛ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЗрд╕рдХреЗ рдмрд╛рдж
rule
рдХреАрд╡рд░реНрдб рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рд╣рдо рдЙрддреНрдкрд╛рджреЛрдВ рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ, рдЙрд╕рдХреЗ рдмрд╛рдж
end
рдХреАрд╡рд░реНрдб, рдЙрдирдХреЗ рдЕрдВрдд рдХрд╛ рд╕рдВрдХреЗрдд рджреЗрддреЗ рд╣реИрдВ:
class Parser rule end
рдЕрдм "a | c" рдХреЗ рд▓рд┐рдП рдЙрддреНрдкрд╛рдж рдЬреЛрдбрд╝реЗрдВред рдЪрд▓реЛ рдЙрд╕реЗ
a_or_c
рдХрд╣рддреЗ рд╣реИрдВ:
class Parser rule a_or_c : 'a' | 'c' ; end
рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирд┐рдпрдо
a_or_c
, рдЬреЛ 'a' рдпрд╛ 'c' рдЕрдХреНрд╖рд░ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИред рддреБрд▓рдирд╛ рдПрдХ рдпрд╛ рдЕрдзрд┐рдХ рдмрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдЙрддреНрдкрд╛рдж рдмрдирд╛рдПрдВрдЧреЗ, рдЬрд┐рд╕реЗ рд╣рдо
a_or_cs
:
class Parser rule a_or_cs : a_or_cs a_or_c | a_or_c ; a_or_c : 'a' | 'c' ; end
рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдХрд╣рд╛,
a_or_cs
рдХрд╛ рдЙрддреНрдкрд╛рджрди рдкреНрд░рдХреГрддрд┐ рдореЗрдВ рдкреБрдирд░рд╛рд╡рд░реНрддреА рд╣реИ, рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реЛрдиреЗ
(a|c)+
ред рдЕрдЧрд▓рд╛, 'abb' рдХреЗ рд▓рд┐рдП рдЙрддреНрдкрд╛рдж рдЬреЛрдбрд╝реЗрдВ:
class Parser rule a_or_cs : a_or_cs a_or_c | a_or_c ; a_or_c : 'a' | 'c' ; abb : 'a' 'b' 'b'; end
рдФрд░ рд╕рднреА рд╕реНрдЯреНрд░рд┐рдВрдЧ рдЙрддреНрдкрд╛рджрди рдХреЛ рдкреВрд░рд╛ рдХрд░реЗрдВ:
class Parser rule string : a_or_cs abb | abb ; a_or_cs : a_or_cs a_or_c | a_or_c ; a_or_c : 'a' | 'c' ; abb : 'a' 'b' 'b'; end
рдпрд╣ рдЕрдВрддрд┐рдо рдЖрдЙрдЯрдкреБрдЯ рдЙрд╕ рдкреИрдЯрд░реНрди рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдПрдХ рдпрд╛ рдЕрдзрд┐рдХ рдЕрдХреНрд╖рд░ 'a' рдпрд╛ 'c' рдХреЗ рдмрд╛рдж 'abb' рдпрд╛ рдлреНрд░реА-рд╕реНрдЯреИрдВрдбрд┐рдВрдЧ рд╕реНрдЯреНрд░рд┐рдВрдЧ 'abb' рдореМрдЬреВрдж рд╣реИред рдпрд╣ рд╕рдм рд╣рдорд╛рд░реЗ рдореВрд▓ рдирд┐рдпрдорд┐рдд рд░реВрдк рдХреЗ рд╕рдорд╛рди рд╣реИ
(a|c)*abb
ред
рд╣рд╛рд░реВрди, рд▓реЗрдХрд┐рди рдпрд╣ рдмрд╣реБрдд рдЙрдмрд╛рдК рд╣реИ!
рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдирд┐рдпрдорд┐рдд рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рд▓рдВрдмрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдПрдХ рдкреНрд▓рд╕ рд╣реИ: рд╣рдо рдореИрдкрд┐рдВрдЧ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдХрд╣реАрдВ рднреА рд░реВрдмреА рдХреЛрдб рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рд░ рдмрд╛рд░ рдЬрдм рд╣рдо рдПрдХ рдлреНрд░реАрд╕реНрдЯреИрдВрдбрд┐рдВрдЧ рд╕реНрдЯреНрд░рд┐рдВрдЧ 'рдПрдмреАрдмреА' рдкрд░ рдЖрддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рдкреНрд░рд┐рдВрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
class Parser rule string : a_or_cs abb | abb { puts " abb, !" } ; a_or_cs : a_or_cs a_or_c | a_or_c ; a_or_c : 'a' | 'c' ; abb : 'a' 'b' 'b'; end
рдХреЛрдб рдЬрд┐рд╕реЗ рд╣рдо рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЙрд╕реЗ рдШреБрдВрдШрд░рд╛рд▓реЗ рдмреНрд░реЗрд╕рд┐рдЬрд╝ рдореЗрдВ рд╕рдВрд▓рдЧреНрди рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдЙрд╕ рдирд┐рдпрдо рдХреЗ рддреБрд░рдВрдд рдмрд╛рдж рд╕реНрдерд┐рдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рдЗрд╕рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реЛрдЧрд╛ред рдЕрдм рд╣рдо рдЕрдкрдирд╛ рд╕реНрд╡рдпрдВ рдХрд╛ JSON рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рддреИрдпрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИрдВ, рдЬреЛ рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдЕрд░реНрдЬрд┐рдд рдЬреНрдЮрд╛рди рд╕реЗ рд▓реИрд╕ рд╣реЛрдХрд░ рдШрдЯрдирд╛ рдЖрдзрд╛рд░рд┐рдд рд╣реЛрдЧрд╛ред
рдПрдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдмрдирд╛рдПрдБ
рд╣рдорд╛рд░реЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдореЗрдВ рддреАрди рдШрдЯрдХ рдСрдмреНрдЬреЗрдХреНрдЯ-рдкрд╛рд░реНрдЯреНрд╕ рд╢рд╛рдорд┐рд▓ рд╣реЛрдВрдЧреЗ: рдПрдХ рдкрд╛рд░реНрд╕рд░, рдПрдХ рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдФрд░ рдПрдХ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдкреНрд░реЛрд╕реЗрд╕рд░ред рдЖрд░рдПрд╕реА рд╡реНрдпрд╛рдХрд░рдг рдкрд░ рдирд┐рд░реНрдорд┐рдд рдПрдХ рдкрд╛рд░реНрд╕рд░ рдЗрдирдкреБрдЯ рд╕реНрдЯреНрд░реАрдо рд╕реЗ рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рд╢рд╛рдмреНрджрд┐рдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рддрдХ рдкрд╣реБрдВрдЪ рдЬрд╛рдПрдЧрд╛ред рд╣рд░ рдмрд╛рд░ рдкрд╛рд░реНрд╕рд░ рдПрдХ JSON рддрддреНрд╡ рдХреЛ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдбреЗрдЯрд╛ рд╕реНрдЯреНрд░реАрдо рд╕реЗ рдЕрд▓рдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░рддрд╛ рд╣реИ, рдпрд╣ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд╣реИрдВрдбрд▓рд░ рдХреЛ рдПрдХ рд╕рдВрдмрдВрдзрд┐рдд рдИрд╡реЗрдВрдЯ рднреЗрдЬрддрд╛ рд╣реИред рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд╣реИрдВрдбрд▓рд░ JSON рд╕реЗ рдбреЗрдЯрд╛ рдПрдХрддреНрд░ рдХрд░рдиреЗ рдФрд░ рд░реВрдмреА рдореЗрдВ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдЕрдиреБрд╡рд╛рдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред JSON рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рд╕реНрд░реЛрдд рдбреЗрдЯрд╛ рдХреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ, рдХреЙрд▓ рдХрд┐рдП рдЬрд╛рдПрдВрдЧреЗ, рдЬреИрд╕рд╛ рдХрд┐ рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдЧреНрд░рд╛рдлрд╝ рдореЗрдВ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ:

рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╡реНрдпрд╛рдкрд╛рд░ рдХреЗ рд▓рд┐рдП рдиреАрдЪреЗ рдЙрддрд░реЛред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рд╢рд╛рдмреНрджрд┐рдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░реЗрдВрдЧреЗ, рдлрд┐рд░ рд╣рдо рдкрд╛рд░реНрд╕рд░ рд╡реНрдпрд╛рдХрд░рдг рд╕реЗ рдирд┐рдкрдЯреЗрдВрдЧреЗ рдФрд░ рдЕрдВрдд рдореЗрдВ рдПрдХ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд╣реИрдВрдбрд▓рд░ рдмрдирд╛рдХрд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдкреВрд░рд╛ рдХрд░реЗрдВрдЧреЗред
рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ
рд╣рдорд╛рд░рд╛ рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдПрдХ IO рд╕реБрд╡рд┐рдзрд╛ рдкрд░ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рдпрд╣ рдЗрд╕рд╕реЗ рд╣реИ рдХрд┐ рд╣рдо рд╕реНрд░реЛрдд рдбреЗрдЯрд╛ рдкрдврд╝реЗрдВрдЧреЗред рд╣рд░ рдмрд╛рд░
next_token
рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ
next_token
рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдЗрдирдкреБрдЯ рд╕реНрдЯреНрд░реАрдо рд╕реЗ рдПрдХ рдЯреЛрдХрди рдкрдврд╝рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рд╡рд╛рдкрд╕ рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдЯреЛрдХрди рдХреА рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕реВрдЪреА рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдЧрд╛, рдЬрд┐рд╕реЗ рд╣рдордиреЗ
JSON рд╡рд┐рдирд┐рд░реНрджреЗрд╢реЛрдВ рд╕реЗ рдЙрдзрд╛рд░ рд▓рд┐рдпрд╛ рдерд╛:
- рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ (рд░реЗрдЦрд╛рдПрдВ)
- рдирдВрдмрд░ (рд╕рдВрдЦреНрдпрд╛)
- рдпрд╣ рд╕рдЪ рд╣реИ (рд╕рддреНрдп)
- рдЭреВрдареА (рдЭреВрдареА)
- рдирд▓ (рдХреЛрдИ рдореВрд▓реНрдп рдирд╣реАрдВ)
рд╕рд░рдгрд┐рдпреЛрдВ рдФрд░ рд╡рд╕реНрддреБрдУрдВ рдЬреИрд╕реЗ рдЬрдЯрд┐рд▓ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП, рдкрд╛рд░реНрд╕рд░ рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реЛрдЧрд╛ред
рдЕрдЧрд▓реЗ рджреНрд╡рд╛рд░рд╛ рд╡рд╛рдкрд╕ рдХрд┐рдП рдЧрдП рдорд╛рди next_token
:
рдЬрдм рдкрд╛рд░реНрд╕рд░ рд▓реЗрдХреНрд╕рд┐рдХрд▓ рдПрдирд╛рд▓рд╛рдЗрдЬрд╝рд░ рдХреЗ
next_token
рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдЗрд╕рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рджреЛ рддрддреНрд╡реЛрдВ рдХреА рдПрдХ рд╕рд░рдгреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХреА рдЬрд╛рддреА рд╣реИред рд╕рд░рдгреА рдХреЗ рдкрд╣рд▓реЗ рддрддреНрд╡ рдореЗрдВ рдЯреЛрдХрди рдХрд╛ рдирд╛рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рджреВрд╕рд░рд╛ рдХреБрдЫ рднреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ (рдЖрдорддреМрд░ рдкрд░ рдпрд╣ рдХреЗрд╡рд▓ рдорд┐рд▓рд╛рди рдкрд╛рда рд╣реИ)ред
nil
рд▓реМрдЯрдиреЗ
nil
рд╢рд╛рдмреНрджрд┐рдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдЕрдзрд┐рдХ рдЯреЛрдХрди рдирд╣реАрдВ рд╣реИрдВред
Tokenizer
рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ Tokenizer
:
рдЖрдЗрдП рдХреНрд▓рд╛рд╕ рдХреЛрдб рджреЗрдЦреЗрдВ рдФрд░ рджреЗрдЦреЗрдВ рдХрд┐ рдпрд╣ рдХреНрдпрд╛ рдХрд░рддрд╛ рд╣реИ:
module RJSON class Tokenizer STRING = /"(?:[^"\\]|\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4}))*"/ NUMBER = /-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/ TRUE = /true/ FALSE = /false/ NULL = /null/ def initialize io @ss = StringScanner.new io.read end def next_token return if @ss.eos? case when text = @ss.scan(STRING) then [:STRING, text] when text = @ss.scan(NUMBER) then [:NUMBER, text] when text = @ss.scan(TRUE) then [:TRUE, text] when text = @ss.scan(FALSE) then [:FALSE, text] when text = @ss.scan(NULL) then [:NULL, text] else x = @ss.getch [x, x] end end end end
рдкрд╣рд▓реЗ рдХрдИ рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдХреА рдШреЛрд╖рдгрд╛рдПрдВ рдХрд░реЗрдВ, рдЬрд┐рдирдХрд╛ рдЙрдкрдпреЛрдЧ рд╣рдо рд╕реНрдЯреНрд░рд┐рдВрдЧрд╕реЗрдВрдХреЗрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реИрдВрдбрд▓рд░ рдХреЗ рд╕рд╛рде рдорд┐рд▓рдХрд░ рдХрд░реЗрдВрдЧреЗред рд╡реЗ
json.org рд╕реЗ рд▓реА рдЧрдИ рдкрд░рд┐рднрд╛рд╖рд╛рдУрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдмрдирд╛рдП рдЧрдП рд╣реИрдВред рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдПрдХ StringScanner рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ рдЗрд╕реЗ рдмрдирд╛рддреЗ рд╕рдордп рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо IO рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдкрдврд╝рдиреЗ рдХреЛ рдЖрдордВрддреНрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдпрд╣, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдмрд╛рд╣рд░ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ IO рд╕реЗ рдбреЗрдЯрд╛ рдирд╣реАрдВ рдкрдврд╝рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрд╡рд╢реНрдпрдХрддрд╛рдиреБрд╕рд╛рд░ред
рдореБрдЦреНрдп рдХрд╛рд░реНрдп
next_token
рд╡рд┐рдзрд┐ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реИрдВрдбрд▓рд░ рдореЗрдВ рдЕрдзрд┐рдХ рдбреЗрдЯрд╛ рдирд╣реАрдВ рд╣реЛрдиреЗ рдкрд░ рдпрд╣
nil
рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдЕрдиреНрдпрдерд╛ рдпрд╣ рдкреНрд░рддреНрдпреЗрдХ рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдЧрд╛ рдЬрдм рддрдХ рдХрд┐ рдпрд╣ рд╕рд╣реА рди рдорд┐рд▓ рдЬрд╛рдПред рдпрджрд┐ рдХреЛрдИ рдорд┐рд▓рд╛рди рдкрд╛рдпрд╛ рдЧрдпрд╛ рдерд╛, рддреЛ рдпрд╣ рдЙрд╕ рдкрд╛рда рдХреЗ рд╕рд╛рде рдЯреЛрдХрди рдирд╛рдо (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП
:STRING
) рд▓реМрдЯрд╛рдПрдЧрд╛ рдЬреЛ рдкреИрдЯрд░реНрди рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИред рдпрджрд┐ рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдореЗрдВ рд╕реЗ рдХреЛрдИ рднреА рдореЗрд▓ рдирд╣реАрдВ рдЦрд╛рддрд╛ рд╣реИ, рддреЛ рдПрдХ рдЪрд░рд┐рддреНрд░ рд╣реИрдВрдбрд▓рд░ рд╕реЗ рдкрдврд╝рд╛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рд░реАрдб рд╡реИрд▓реНрдпреВ рдЯреЛрдХрди рдХреЗ рдирд╛рдо рдФрд░ рдЙрд╕рдХреЗ рдореВрд▓реНрдп рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рд╕рд╛рде рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рдПрдЧреАред
рдЖрдЗрдП JSON рдлреЙрд░реНрдореЗрдЯ рдореЗрдВ рд▓реЗрдХреНрд╕рд┐рдХрд▓ рдПрдирд╛рд▓рд╛рдЗрдЬрд╝рд░ рдХреЛ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХрд╛ рдЙрджрд╛рд╣рд░рдг рджреЗрдВ рдФрд░ рджреЗрдЦреЗрдВ рдХрд┐ рдЖрдЙрдЯрдкреБрдЯ рдореЗрдВ рд╣рдореЗрдВ рдХреМрди рд╕реЗ рдЯреЛрдХрди рдорд┐рд▓рддреЗ рд╣реИрдВ:
irb(main):003:0> tok = RJSON::Tokenizer.new StringIO.new '{"foo":null}' => #<RJSON::Tokenizer:0x007fa8529fbeb8 @ss=#<StringScanner 0/12 @ "{\"foo...">> irb(main):004:0> tok.next_token => ["{", "{"] irb(main):005:0> tok.next_token => [:STRING, "\"foo\""] irb(main):006:0> tok.next_token => [":", ":"] irb(main):007:0> tok.next_token => [:NULL, "null"] irb(main):008:0> tok.next_token => ["}", "}"] irb(main):009:0> tok.next_token => nil
рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдордиреЗ IO рдХреЗ рд╕рд╛рде рдмрддрдЦ рдЯрд╛рдЗрдкрд┐рдВрдЧ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ JSON рд╕реНрдЯреНрд░рд┐рдВрдЧ
StringIO
ред рдЗрд╕рдХреЗ рдмрд╛рдж, рдХреБрдЫ рдЯреЛрдХрди рдкрдврд╝рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХреЗ рд▓рд┐рдП рдкрд░рд┐рдЪрд┐рдд рдкреНрд░рддреНрдпреЗрдХ рдЯреЛрдХрди рдореЗрдВ рдПрдХ рдРрд╕рд╛ рдирд╛рдо рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рд╕рд░рдгреА рдХреЗ рдкрд╣рд▓реЗ рддрддреНрд╡ рдХреЗ рд╕рд╛рде рдЖрддрд╛ рд╣реИ, рдЬрдмрдХрд┐ рдЕрдЬреНрдЮрд╛рдд рдЯреЛрдХрди рдореЗрдВ рдпрд╣ рд╕реНрдерд╛рди рдПрдХ рд╡рд░реНрдг рджреНрд╡рд╛рд░рд╛ рдХрдмреНрдЬрд╛ рдХрд░ рд▓рд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд▓рд╛рдЗрди рдЯреЛрдХрди
[:STRING, "foo"]
рдФрд░ рдЕрдЬреНрдЮрд╛рдд рдЯреЛрдХрди, рд╡рд┐рд╢реЗрд╖ рд╕реНрдерд┐рддрд┐ рдореЗрдВ,
['(', '(']
ред рдЕрдВрдд рдореЗрдВ, рдЬрдм рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рдПрдЧрд╛, рддреЛ рдЖрдЙрдЯрдкреБрдЯ
nil
рд╣реЛ рдЬрд╛рдПрдЧрд╛ред
рдпрд╣ рд╢рд╛рдмреНрджрд┐рдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдкреВрд░рд╛ рдХрд░рддрд╛ рд╣реИред рдЗрдирдкреБрдЯ рдкрд░ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдХреЗ рджреМрд░рд╛рди, рдпрд╣ рдПрдХ
IO
рдСрдмреНрдЬреЗрдХреНрдЯ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдПрдХ рдПрдХрд▓
next_token
рд╡рд┐рдзрд┐ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред рдЖрдк рд╕рднреА рдкрд╛рд░реНрд╕рд░ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдкрд╛рд░реНрд╕рд░
рд╕рд┐рдВрдЯреЗрдХреНрд╕ рдореЗрдВ рдЖрдиреЗ рдХрд╛ рд╕рдордп рд╣реЛ рдЧрдпрд╛ рд╣реИред рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЪрд▓реЛ рдереЛрдбрд╝рд╛ рд░реЗрдХ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред рд╣рдореЗрдВ рдПрдХ
.y
рдлрд╝рд╛рдЗрд▓ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд░реВрдмреА-рдЖрдзрд╛рд░рд┐рдд рдлрд╝рд╛рдЗрд▓ рдкреАрдврд╝реА рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╕рд┐рд░реНрдл
rake
рд▓рд┐рдП рдиреМрдХрд░реА
рез ред
рд╣рдо рд╕рдВрдХрд▓рди рдХрд╛рд░реНрдп рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВ:
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рд░реЗрдХ-рдлрд╛рдЗрд▓ рдореЗрдВ рдПрдХ рдирд┐рдпрдо рдЬреЛрдбрд╝реЗрдВрдЧреЗ рдЬреЛ рдХрд╣рддрд╛ рд╣реИ:
" .y
рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ .rb
рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рдирд┐рдореНрди рдХрдорд╛рдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░реЗрдВ :
" rule '.rb' => '.y' do |t| sh "racc -l -o #{t.name} #{t.source}" end
рдлрд┐рд░ рд╣рдо "рд╕рдВрдХрд▓рд┐рдд" рдХрд╛рд░реНрдп рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рдЬреЛ рдЙрддреНрдкрдиреНрди
parser.rb
рдлрд╝рд╛рдЗрд▓ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИред
task :compile => 'lib/rjson/parser.rb'
рдЪреВрдБрдХрд┐ рд╡реНрдпрд╛рдХрд░рдг рдлрд╝рд╛рдЗрд▓ рдХреЛ
lib/rjson/parser.y
рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЕрдм рдЬрдм рд╣рдо
rake compile
рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рд░реЗрдХ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ
.y
рдлрд╝рд╛рдЗрд▓ рдХреЛ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреЗ рд╕рд╛рде
.rb
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░
.y
ред
рдФрд░ рдЕрдВрдд рдореЗрдВ, рд╣рдо "рдкрд░реАрдХреНрд╖рдг" рдХрд╛рд░реНрдп рдХреЛ "рд╕рдВрдХрд▓рди" рдХрд╛рд░реНрдп рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░реЗрдВрдЧреЗ, рддрд╛рдХрд┐ рдЬрдм рд╣рдо
rake test
рдЪрд▓рд╛рдПрдВ, рддреЛ рд╕рдВрдХрд▓рд┐рдд рд╕рдВрд╕реНрдХрд░рдг рд╕реНрд╡рддрдГ рдЙрддреНрдкрдиреНрди рд╣реЛ рдЬрд╛рдП:
task :test => :compile
рдЕрдм рдЖрдк
.y
рдлрд╝рд╛рдЗрд▓ рдХреЗ рд╕рдВрдХрд▓рди рдФрд░ рд╕рддреНрдпрд╛рдкрди рдкрд░ рд╕реАрдзреЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред
JSON.org рд╡рд┐рдирд┐рд░реНрджреЗрд╢рди рдкрд╛рд░реНрд╕ рдХрд░рдирд╛:
рдЕрдм рд╣рдо
json.org рд╕реЗ рдЪрд╛рд░реНрдЯреНрд╕ рдХрд╛ рдЕрдиреБрд╡рд╛рдж рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВред рд╕реНрд░реЛрдд рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдХреА рдЬрдбрд╝ рдореЗрдВ рдпрд╛ рддреЛ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдпрд╛ рдПрдХ рд╕рд░рдгреА рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЗрд╕рд▓рд┐рдП рд╣рдо рдПрдХ
document
рдЙрддреНрдкрд╛рджрди рдмрдирд╛рдПрдВрдЧреЗ рдЬреЛ рдСрдмреНрдЬреЗрдХреНрдЯ -
object
рдпрд╛ рд╕рд░рдгреА -
array
рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ:
rule document : object | array ;
рдЖрдЧреЗ рд╣рдо
array
рдХреЗ рдЙрддреНрдкрд╛рджреЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рд╕рд░рдгреА рдХреЗ рд▓рд┐рдП рдЙрддреНрдкрд╛рдж рдпрд╛ рддреЛ рдЦрд╛рд▓реА рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдЙрдирдореЗрдВ рдПрдХ рдпрд╛ рдЕрдзрд┐рдХ рдорд╛рди рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ:
array : '[' ']' | '[' values ']' ;
рдореВрд▓реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрддреНрдкрд╛рджрди рдХреЛ рдПрдХ рдорд╛рди рдХреЗ рд░реВрдк рдореЗрдВ рдкреБрдирд░рд╛рд╡рд░реНрддреА рд░реВрдк рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдпрд╛ рдХрдИ рдорд╛рди рдЕрд▓реНрдкрд╡рд┐рд░рд╛рдо рджреНрд╡рд╛рд░рд╛ рдЕрд▓рдЧ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ:
values : values ',' value | value ;
JSON рд╡рд┐рдирд┐рд░реНрджреЗрд╢рди рдореЗрдВ,
value
рдХреЛ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ, рд╕рдВрдЦреНрдпрд╛, рд╡рд╕реНрддреБ, рд╕рд░рдгреА, рд╕рд╣реА (рд╕рддреНрдп), рдЕрд╕рддреНрдп (рдЕрд╕рддреНрдп), рдпрд╛ рдЕрд╢рдХреНрдд (рдХреЛрдИ рдореВрд▓реНрдп) рдХреЗ рд░реВрдк
value
рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рдорд╛рд░реА рдкрд░рд┐рднрд╛рд╖рд╛ рд╕рдорд╛рди рд╣реЛрдЧреА, рдХреЗрд╡рд▓ рдЕрдВрддрд░ рдпрд╣ рд╣реЛрдЧрд╛ рдХрд┐ NUMBER (рд╕рдВрдЦреНрдпрд╛), TRUE (рд╕рддреНрдп) рдФрд░ FALSE (рдЧрд▓рдд) рдЬреИрд╕реЗ рддрд╛рддреНрдХрд╛рд▓рд┐рдХ рдорд╛рдиреЛрдВ рдХреЗ рд▓рд┐рдП рд╣рдо рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рд╕рдВрдмрдВрдзрд┐рдд рдЯреЛрдХрди рдирд╛рдореЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ:
value : string | NUMBER | object | array | TRUE | FALSE | NULL ;
рд╣рдо рдСрдмреНрдЬреЗрдХреНрдЯ (
object
) рдХреЗ рд▓рд┐рдП рдЙрддреНрдкрд╛рджреЛрдВ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдкрд░ рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред рдСрдмреНрдЬреЗрдХреНрдЯ рд░рд┐рдХреНрдд рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╛ рдЬреЛрдбрд╝реЗ рд╕реЗ рдорд┐рд▓рдХрд░ рдмрди рд╕рдХрддреЗ рд╣реИрдВ:
object : '{' '}' | '{' pairs '}' ;
рдПрдХ рдпрд╛ рдХрдИ рдЬреЛрдбрд╝реЗ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдЕрд▓реНрдкрд╡рд┐рд░рд╛рдо рджреНрд╡рд╛рд░рд╛ рдЕрд▓рдЧ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдлрд┐рд░ рд╕реЗ, рдкреБрдирд░рд╛рд╡рд░реНрддреА рдкрд░рд┐рднрд╛рд╖рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:
pairs : pairs ',' pair | pair ;
рдЕрдВрдд рдореЗрдВ, рдПрдХ рдЬреЛрдбрд╝реА рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ, рдЬреЛ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реИ рдФрд░ рдПрдХ рдХреЛрд▓рди рджреНрд╡рд╛рд░рд╛ рдЕрд▓рдЧ рдХреА рдЧрдИ рд╕рдВрдЦреНрдпрд╛ рд╣реИ:
pair : string ':' value ;
рдЕрдм рдЖрд░рд╕реАрд╕реА рдХреЛ рд╣рдорд╛рд░реЗ рд▓реЗрдХреНрд╕рд┐рдХрд▓ рдЯреЛрдХрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реВрдЪрд┐рдд рдХрд░реЗрдВ, рдЬреЛ рдмрд╣реБрдд рд╢реБрд░реБрдЖрдд рдореЗрдВ рдПрдХ рдкрд░рд┐рднрд╛рд╖рд╛ рдЬреЛрдбрд╝ рд░рд╣рд╛ рд╣реИ, рдФрд░ рд╣рдорд╛рд░рд╛ рдкрд╛рд░реНрд╕рд░ рддреИрдпрд╛рд░ рд╣реИ:
class RJSON::Parser token STRING NUMBER TRUE FALSE NULL rule document : object | array ; object : '{' '}' | '{' pairs '}' ; pairs : pairs ',' pair | pair ; pair : string ':' value ; array : '[' ']' | '[' values ']' ; values : values ',' value | value ; value : string | NUMBER | object | array | TRUE | FALSE | NULL ; string : STRING ; end
рдбреЙрдХреНрдпреВрдореЗрдВрдЯ рд╣реИрдВрдбрд▓рд░
рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд╣реИрдВрдбрд▓рд░ рд╣рдорд╛рд░реЗ рдкрд╛рд░реНрд╕рд░ рд╕реЗ рдШрдЯрдирд╛рдУрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдЧрд╛ред рд╡рд╣ JSON рдХреЗ рдЕрджреНрднреБрдд рдЯреБрдХрдбрд╝реЛрдВ рд╕реЗ рд╣рдорд╛рд░реА рдЕрддреБрд▓рдиреАрдп рд░реВрдмреА рд╡рд╕реНрддреБ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░реЗрдЧрд╛! рдЖрдкрдХреЗ рд╡рд┐рд╡реЗрдХ рдкрд░ рдореИрдВ рдЬрд┐рддрдиреЗ рдЗрд╡реЗрдВрдЯ рдЫреЛрдбрд╝рддрд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдореИрдВ рдЦреБрдж рдХреЛ 5 рддрдХ рд╕реАрдорд┐рдд рд░рдЦреВрдВрдЧрд╛:
start_object
- рд╡рд╕реНрддреБ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИend_object
- рд╡рд╕реНрддреБ рдХреЗ рдЕрдВрдд рдореЗрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИstart_array
- рд╕рд░рдгреА рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИend_array
- рд╕рд░рдгреА рдХреЗ рдЕрдВрдд рдореЗрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИscalar
- рдЯрд░реНрдорд┐рдирд▓ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреИрд╕реЗ рддрд╛рд░, рд╕рдЪ, рдЧрд▓рдд, рдЖрджрд┐ред
рдЗрди рдкрд╛рдВрдЪ рдШрдЯрдирд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдЗрдХрдЯреНрдард╛ рдХрд░реЗрдВрдЧреЗ рдЬреЛ рдореВрд▓ JSON рд╕рдВрд░рдЪрдирд╛ рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИред
рд╣рдо рдШрдЯрдирд╛рдУрдВ рдХрд╛ рдЕрдиреБрд╕рд░рдг рдХрд░рддреЗ рд╣реИрдВ
рд╣рдорд╛рд░рд╛ рд╣реИрдВрдбрд▓рд░ рдмрд╕ рдкрд╛рд░реНрд╕рд░ рд╕реЗ рдЖрдиреЗ рд╡рд╛рд▓реА рдШрдЯрдирд╛рдУрдВ рдкрд░ рдирдЬрд╝рд░ рд░рдЦреЗрдЧрд╛ред рдкрд░рд┐рдгрд╛рдо рдПрдХ рдкреЗрдбрд╝ рдХреА рд╕рдВрд░рдЪрдирд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╣рдо рдЕрдВрддрд┐рдо рд░реВрдмреА рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░реЗрдВрдЧреЗред
module RJSON class Handler def initialize @stack = [[:root]] end def start_object push [:hash] end def start_array push [:array] end def end_array @stack.pop end alias :end_object :end_array def scalar(s) @stack.last << [:scalar, s] end private def push(o) @stack.last << o @stack << o end end end
рдЬрдм рднреА рдкрд╛рд░реНрд╕рд░ рдХрд┐рд╕реА рдСрдмреНрдЬреЗрдХреНрдЯ рдХреА рд╢реБрд░реБрдЖрдд рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рддрд╛ рд╣реИ, рддреЛ рд╣реИрдВрдбрд▓рд░ рд╕рд╛рд╣рдЪрд░реНрдп рд╕рд░рдгреА рдХреА рд╢реБрд░реБрдЖрдд рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдЯреИрдХ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рд╣реИрд╢ рдкреНрд░рддреАрдХ рдХреЗ рд╕рд╛рде рдПрдХ рд╕реВрдЪреА рдЬреЛрдбрд╝рддрд╛ рд╣реИред рдРрд╕реА рдШрдЯрдирд╛рдПрдВ рдЬреЛ рдмрдЪреНрдЪреЗ рд╣реИрдВ, рдЙрдиреНрд╣реЗрдВ рдорд╛рддрд╛-рдкрд┐рддрд╛ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рдЬрдм рд╡рд╕реНрддреБ рдХреЗ рдЕрдВрдд рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛, рддреЛ рдорд╛рддрд╛-рдкрд┐рддрд╛ рдХреЛ рдвреЗрд░ рд╕реЗ рдкреЙрдкрдЕрдк рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рдореИрдВ рдмрд╛рд╣рд░ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рдкрд╣рд▓реА рдмрд╛рд░ рд╕рдордЭрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЪрд▓реЛ рдХреБрдЫ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЛ рджреЗрдЦреЗрдВред JSON рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдлреЙрд░реНрдо
{"foo":{"bar":null}}
рдореЗрдВ рдкрд╛рд╕ рдХрд░рдиреЗ рдкрд░, рд╣рдореЗрдВ
@stack
рд╕реНрдЯреИрдХ рдЪрд░ рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдорд┐рд▓рддрд╛ рд╣реИ:
[[:root, [:hash, [:scalar, "foo"], [:hash, [:scalar, "bar"], [:scalar, nil]]]]]
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП,
@stack
рдореЗрдВ
@stack
рдХрд╛ рдПрдХ
@stack
["foo",null,true]
, рд╣рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдорд┐рд▓рддрд╛ рд╣реИ:
[[:root, [:array, [:scalar, "foo"], [:scalar, nil], [:scalar, true]]]]
рд░реВрдмреА рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░реЗрдВ:
рдЗрд╕ рдкреНрд░рдХрд╛рд░ JSON рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдХрд╛ рдПрдХ рдордзреНрдпрд╡рд░реНрддреА рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдЗрд╕реЗ рд░реВрдмреА рдореЗрдВ рдПрдХ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдкреЗрдбрд╝ рдХреЗ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдХрд╛рд░реНрдп рд▓рд┐рдЦрддреЗ рд╣реИрдВ:
def result root = @stack.first.last process root.first, root.drop(1) end private def process type, rest case type when :array rest.map { |x| process(x.first, x.drop(1)) } when :hash Hash[rest.map { |x| process(x.first, x.drop(1)) }.each_slice(2).to_a] when :scalar rest.first end end
result
рд╡рд┐рдзрд┐
root
рдиреЛрдб рдХреЛ рд╣рдЯрд╛ рджреЗрддреА рд╣реИ рдФрд░
process
рд╡рд┐рдзрд┐ рдХреЛ рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЬрдм
process
рдПрдХ
hash
рдЪрд░рд┐рддреНрд░ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рддреА рд╣реИ, рддреЛ рдпрд╣ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдХреЙрд▓ рдХреЗ рдмрдЪреНрдЪреЛрдВ рдХреЛ
process
рд▓рд┐рдП рдПрдХ рд╕рд╣рдпреЛрдЧреА рд╕рд░рдгреА рдмрдирд╛рддреА
process
ред рдЗрд╕рдХреЗ рд╕рдорд╛рди, рд╡рд░реНрдг
array
рдХреЗ рд╕рд╛рдордиреЗ рдЖрдиреЗ рдкрд░, рд╕рд░рдгреА рдХреЗ рдмрдЪреНрдЪреЛрдВ рдкрд░ рдПрдХ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдХреЙрд▓ рдПрдХ рд╕рд░рдгреА рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рддрд╛ рд╣реИред рд╕реНрдХреЗрд▓рд░ рдорд╛рди -
scalar
рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рдмрд┐рдирд╛ рд▓реМрдЯрд╛рдП
scalar
(рдЬреЛ рдЕрдирдВрдд рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХреЛ рд░реЛрдХрддрд╛ рд╣реИ)ред рдЕрдм, рдпрджрд┐ рд╣рдо рдЕрдкрдиреЗ рд╣реИрдВрдбрд▓рд░ рд╕реЗ
result
рдХрд╣рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рдЖрдЙрдЯрдкреБрдЯ рдкрд░ рд░реВрдмреА рдСрдмреНрдЬреЗрдХреНрдЯ рдорд┐рд▓рддрд╛ рд╣реИред
рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдпрд╣ рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:
require 'rjson' input = StringIO.new '{"foo":"bar"}' tok = RJSON::Tokenizer.new input parser = RJSON::Parser.new tok handler = parser.parse handler.result
рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдВ рд╕реБрдзрд╛рд░:
рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╣рдорд╛рд░реЗ рдирд┐рдкрдЯрд╛рди рдореЗрдВ рдПрдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХрд╛рд░реНрдпрд╛рддреНрдордХ JSON рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рд╣реИред рд╕рдЪ рд╣реИ, рдПрдХ рджреЛрд╖ рдХреЗ рд╕рд╛рде - рдЗрд╕рдореЗрдВ рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдирд╣реАрдВ рд╣реИред рдЪрд▓реЛ рдЗрд╕реЗ рдмреЗрд╣рддрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд┐рдЫрд▓реЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:
module RJSON def self.load(json) input = StringIO.new json tok = RJSON::Tokenizer.new input parser = RJSON::Parser.new tok handler = parser.parse handler.result end end
рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░рд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдореВрд▓ рд░реВрдк рд╕реЗ рдПрдХ IO рдСрдмреНрдЬреЗрдХреНрдЯ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рдерд╛, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рдзрд┐ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдЗрдирдкреБрдЯ рдкрд░ рд╕реЙрдХреЗрдЯ рдпрд╛ рдлрд╝рд╛рдЗрд▓ рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ:
module RJSON def self.load_io(input) tok = RJSON::Tokenizer.new input parser = RJSON::Parser.new tok handler = parser.parse handler.result end def self.load(json) load_io StringIO.new json end end
рд╣рдо рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдереЛрдбрд╝рд╛ рдФрд░ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реЛ рдЧрдпрд╛ рд╣реИ:
require 'rjson' require 'open-uri' RJSON.load '{"foo":"bar"}'
рд╡рд┐рдЪрд╛рд░ рдЬреЛрд░ рд╕реЗ
рддреЛ, рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдкрд░ рдХрд╛рдо рдкреВрд░рд╛ рд╣реЛ рдЧрдпрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ, рд╣рдо рд╕рдВрдХрд▓рди рддрдХрдиреАрдХ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реБрдП, рдЬрд┐рд╕рдореЗрдВ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдФрд░ рд▓реЗрдХреНрд╕рд┐рдХрд▓ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреА рдореВрд▓ рдмрд╛рддреЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ, рдФрд░ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рджреБрднрд╛рд╖рд┐рдпреЛрдВ рдкрд░ рднреА рдЫреБрдЖ рдЧрдпрд╛ (рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╣рдо JSON рдХреА рд╡реНрдпрд╛рдЦреНрдпрд╛ рдХрд░рдиреЗ рдореЗрдВ рд▓рдЧреЗ рд╣реБрдП рдереЗ)ред рдЖрдкрдХреЗ рдкрд╛рд╕ рдЧрд░реНрд╡ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╣реИ!
рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХрд╛рдлреА рд▓рдЪреАрд▓рд╛ рдирд┐рдХрд▓рд╛ред рд╣рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
- рдПрдХ рд╣реИрдВрдбрд▓рд░ рд╣реИрдВрдбрд▓рд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдХреЗ рдПрдХ рдШрдЯрдирд╛ рдкреНрд░рддрд┐рдорд╛рди рдореЗрдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
- рдПрдХ рд╕рд░рд▓реАрдХреГрдд рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ рдФрд░ рдмрд╕ рдЗрдирдкреБрдЯ рдХреЗ рд▓рд┐рдП рддрд╛рд░ рдкрд╛рд╕ рдХрд░реЗрдВ
- IO рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ JSON рдлреЙрд░реНрдореЗрдЯ рдореЗрдВ рд╕реНрдЯреНрд░реАрдо рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП
рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рд▓реЗрдЦ рдЖрдкрдХреЛ рдЖрддреНрдорд╡рд┐рд╢реНрд╡рд╛рд╕ рджреЗрдЧрд╛, рдФрд░ рдЖрдк рд░реВрдмреА рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдП рдЧрдП рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдФрд░ рд╕рдВрдХрд▓рди рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдЕрдкрдиреЗ рджрдо рдкрд░ рдкреНрд░рдпреЛрдЧ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджреЗрдВрдЧреЗред рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдЕрднреА рднреА рдореЗрд░реЗ рд▓рд┐рдП рдкреНрд░рд╢реНрди рд╣реИрдВ, рддреЛ
рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рдЖрдкрдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИред
рдкреБрдирд╢реНрдЪ
рдЕрдВрдд рдореЗрдВ, рдореИрдВ рдХреБрдЫ рд╡рд┐рд╡рд░рдгреЛрдВ рдХреЛ рд╕реНрдкрд╖реНрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдореИрдВрдиреЗ рдкреНрд░рд╕реНрддреБрддрд┐ рдХреЗ рджреМрд░рд╛рди рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рдерд╛, рддрд╛рдХрд┐ рдЕрддрд┐рд░рд┐рдХреНрдд рдЕрд╕реНрдкрд╖реНрдЯрддрд╛ рдХрд╛ рдкрд░рд┐рдЪрдп рди рд╣реЛ:
- рдпрд╣рд╛рдБ рд╣рдорд╛рд░реЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХрд╛ рдЕрдВрддрд┐рдо рд╡реНрдпрд╛рдХрд░рдг рд╣реИред .Y рдлрд╝рд╛рдЗрд▓ рдХреЗ рдЖрдВрддрд░рд┐рдХ рдЕрдиреБрднрд╛рдЧ рдкрд░ рдзреНрдпрд╛рди рджреЗрдВред рдЗрд╕ рдЦрдВрдб рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рд╕рдм рдХреБрдЫ рдкрд╛рд░реНрд╕рд░ рд╡рд░реНрдЧ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдПрдЧрд╛, рдЬреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдкреАрдврд╝реА рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рд╡рд╣ рддрд░реАрдХрд╛ рд╣реИ рдЬрд┐рд╕рд╕реЗ рд╣рдо рдкрд╛рд░реНрд╕рд░ рдХреЛ рд╣реИрдВрдбрд▓рд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред
- рд╣рдорд╛рд░реЗ рдкрд╛рд░реНрд╕рд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд░реВрдмреА рдХреЛ рдЯрд░реНрдорд┐рдирд▓ JSON рдиреЛрдбреНрд╕ рдХрд╛ рд░реВрдкрд╛рдВрддрд░рдг рдХрд░рддреЗ рд╣реИрдВ ред рдЗрд╕рд▓рд┐рдП, рд╣рдо JSON рдХреЛ рджреЛ рдмрд╛рд░ рд░реВрдмреА рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддреЗ рд╣реИрдВ: рдкрд╛рд░реНрд╕рд░ рдореЗрдВ рдФрд░ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд╣реИрдВрдбрд▓рд░ рдореЗрдВред рдЙрддреНрддрд░рд╛рд░реНрджреНрдз рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИ, рдЬрдмрдХрд┐ рдкреВрд░реНрд╡ рддрд╛рддреНрдХрд╛рд▓рд┐рдХ рдореВрд▓реНрдпреЛрдВ (рд╕рдЪреНрдЪреЗ, рдЭреВрдареЗ, рдЖрджрд┐) рдХреЗ рд▓рд┐рдП рд╣реИред рдореИрдВ рдзреНрдпрд╛рди рджреЗрддрд╛ рд╣реВрдВ рдХрд┐ рдпрд╣ рдзреНрдпрд╛рди рд░рдЦрдирд╛ рдХрд╛рдлреА рдЙрдЪрд┐рдд рд╣реИ рдХрд┐ рд╕рднреА рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рдкрд╛рд░реНрд╕рд░ рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдпрд╛ рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд, рдЗрд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдмрд╛рд╣рд░ рд░рдЦрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
- рдЕрдВрдд рдореЗрдВ, рд╢рд╛рдмреНрджрд┐рдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдмрдлрд╝рд░рд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рдореИрдВрдиреЗ рдПрдХ рдЧреИрд░-рдмрдлрд░ рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рд╕реНрдХреЗрдЪ рдХрд┐рдпрд╛ рдЬреЛ рдХрд┐ рдпрд╣рд╛рдВ рд╕реЗ рд▓рд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ред рдпрд╣ рдмрд╣реБрдд рдХреНрд░реВрдб рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдПрдХ рдкрд░рд┐рдорд┐рдд рд░рд╛рдЬреНрдп рдорд╢реАрди рдХреЗ рддрд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рджрд┐рдорд╛рдЧ рдореЗрдВ рд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рд╡рд╣ рд╕рдм рд╣реИред рдЖрдкрдХрд╛ рдзреНрдпрд╛рди рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж!
1 рдЕрдВрдЧреНрд░реЗрдЬреА рд░реЗрдХ - рд░реЗрдХ
рдЕрдиреБрд╡рд╛рдж рдкрд░ рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ, рдХреГрдкрдпрд╛ рдПрдХ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдореЗрдВ рднреЗрдЬреЗрдВред