Pegjs: рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдЧрдгрдирд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ (рдЬреИрд╕реЗ рд░реЗрдЧреЗрдХреНрд╕рдкреНрд╕ рдореЗрдВ)

рдХреЛ рдирд┐рд░реНрдорд┐рдд 11 рдЕрдЧре░ 2011  ┬╖  22рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: pegjs/pegjs

рдпрд╣ рдорджрджрдЧрд╛рд░ рд╣реЛрдЧрд╛ рдпрджрд┐ PEG.js рд╡реНрдпрд╛рдХрд░рдг POSIX рдореВрд▓ рд░реЗрдЧреБрд▓рд░ рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рдХреЗ рд░реЗрдВрдЬ рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рдЬреИрд╕реА рдХрд┐рд╕реА рдЪреАрдЬрд╝ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЬреИрд╕реЗ:

  • "a"\{1,7\}

a , aa , ..., aaaaaaa рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ

  • "a"\{0,1\}

рдЦрд╛рд▓реА рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ рдФрд░ a

  • "a"\{,6\}

рдЫрд╣ a 's . рддрдХ (рдФрд░ рд╕рд╣рд┐рдд) рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ

  • "a"\{6,\}

рдЫрд╣ рдпрд╛ рдЕрдзрд┐рдХ рдХреА рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ a 's

  • "a"\{3\}

рдХреЗрд╡рд▓ aaa рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ, рдЬреЛ "a"\{3,3\} . рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИ

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдореБрдЭреЗ рджреЛрд╣рд░рд╛рд╡ рдХреА рд╕рдВрдЦреНрдпрд╛ рднреА рдкрд╕рдВрдж рдЖрдПрдЧреАред рд▓реЗрдХрд┐рди рдореИрдВ рдереЛрдбрд╝рд╛ рдЕрд▓рдЧ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рд╕реБрдЭрд╛рдКрдВрдЧрд╛ред Pegasus рд▓рдЧрднрдЧ pegjs рдХреЗ рд╕рдорд╛рди рд╣реИ, рдХреЗрд╡рд▓ C# рдХреЗ рд▓рд┐рдПред рдпрд╣рд╛рдВ рджреЗрдЦреЗрдВ: https://github.com/otac0n/Pegasus/wiki/Syntax-Guide#expressions

рдФрд░ рдЙрдиреНрд╣реЛрдВрдиреЗ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛: d<3> e<2,> f<1,5>

рд╕рднреА 22 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдореИрдВ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЛ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд░реВрдВрдЧрд╛ред

рдореБрдЦреНрдп рдХрд╛рд░рдг рдпрд╣ рд╣реИ рдХрд┐ {m,n} рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХреЗ рд▓рд┐рдП PEG.js рд╡реНрдпрд╛рдХрд░рдг рдореЗрдВ рдХреЛрдИ рдЬрдЧрд╣ рдирд╣реАрдВ рд╣реИ тАФ рдмреНрд░реЗрд╕рд┐рдЬрд╝ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХрд╛рд░реНрд░рд╡рд╛рдЗрдпреЛрдВ рдХреЗ рд▓рд┐рдП рд▓рд┐рдП рдЧрдП рд╣реИрдВ рдФрд░ рдореИрдВ рдЖрдкрдХреЗ рд╕реБрдЭрд╛рд╡ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдмреИрдХрд╕реНрд▓реИрд╢ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ (рд╡реЗ рдмрджрд╕реВрд░рдд рд╣реИрдВ рдФрд░ рд╕рдВрдЧрдд рдирд╣реАрдВ рд╣реИрдВ) рдкрд░реНрд▓ рд░реЗрдЧреЗрдХреНрд╕рдкреНрд╕ рдХреЗ рд╕рд╛рде рдЬреЛ рдЕрдм рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рд╣реИрдВ рдФрд░ рдЕрдиреНрдп рдкреАрдИрдЬреА.рдЬреЗрдПрд╕ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХрд╛ рд╕реНрд░реЛрдд рднреА рд╣реИрдВ) рдпрд╛ рдЕрдиреНрдп рд╕реАрдорд╛рдВрдХрдХ (рдЬреЛ рднреНрд░рдорд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╣реЛрдВрдЧреЗ)ред

рдореЗрд░реЗ рдЕрдиреБрднрд╡ рдореЗрдВ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреА рд╕реАрдорд┐рдд рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рд╡реНрдпрд╛рдХрд░рдг рдХреЗ "рд╡реНрдпрд╛рдЦреНрдпрд╛рддреНрдордХ" рднрд╛рдЧреЛрдВ (рдирд┐рдпрдореЛрдВ рдЬреИрд╕реЗ color = "#" hexdigit hexdigit hexdigit hexdigit hexdigit hexdigit ) рдкрд░ рд╣реЛрддреА рд╣реИ рдФрд░ рдЕрдХреНрд╕рд░ рдирд╣реАрдВред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдХреЗ рдЕрдиреБрдХреНрд░рдореЛрдВ рдФрд░ рдореМрдЬреВрджрд╛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдСрдкрд░реЗрдЯрд░реЛрдВ ( * , + , ? ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдареАрдХ рд╣реИред

рдореИрдВрдиреЗ рдкреБрдирд░реНрд╡рд┐рдЪрд╛рд░ рдХрд┐рдпрд╛ рд╣реИ рдФрд░ рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдлрд┐рд░ рд╕реЗ рдЦреЛрд▓ рд░рд╣рд╛ рд╣реВрдВред рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рджреЛрд╣рд░рд╛рд╡ рдХреА рдордирдорд╛рдиреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рджреНрд╡рд╛рд░рд╛ рдмрд╣реБрдд рдЪрд╛рд╣реА рдЧрдИ рд╣реИред

рдореИрдВ regexp-рдЬреИрд╕реЗ {m,n} рд╕рд┐рдВрдЯреИрдХреНрд╕ рд╕реЗ рдмрдЪрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХреНрдпреЛрдВрдХрд┐ { рдФрд░ } рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХрд╛рд░реНрд░рд╡рд╛рдЗрдпреЛрдВ рдХреЗ рд▓рд┐рдП рд▓рд┐рдпрд╛ рдЬрд╛ рдЪреБрдХрд╛ рд╣реИ рдФрд░ рдЙрдирдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдЕрд╕реНрдкрд╖реНрдЯрддрд╛ рдкреИрджрд╛ рд╣реЛрдЧреАред рдореИрдВ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╕реЛрдЪ рд░рд╣рд╛ рд╣реВрдВ:

"foo" @ 1..10   // repeat 1 to 10 times
"foo" @ 1..     // repeat at least once
"foo" @ ..10    // repeat at most 10 times

рд╕рдмрд╕реЗ рдмрдбрд╝рд╛ рд╕рд╡рд╛рд▓ рдпрд╣ рд╣реИ рдХрд┐ рдЕрд▓рдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЪрд░рд┐рддреНрд░ рдХреНрдпрд╛ рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдП рдФрд░ рд╢реНрд░реЗрдгрд┐рдпреЛрдВ рдХреЛ рдХреИрд╕реЗ рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПред

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

"foo" 1..10   // repeat 1 to 10 times
"foo" 1..     // repeat at least once
"foo" ..10    // repeat at most 10 times

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

рдореИрдВ рдЕрд░реНрдз-рдЦреБрд▓реА рд╢реНрд░реЗрдгрд┐рдпреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реВрдВред рд╢рд╛рдпрдж + рдФрд░ - рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЙрдиреНрд╣реЗрдВ рдЗрд╕ рддрд░рд╣ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реЛрдЧрд╛:

"foo" @ 1+    // repeat at least once
"foo" @ 10-   // repeat at most 10 times

рдХреЛрдИ рд╡рд┐рдЪрд╛рд░ рдпрд╛ рдЯрд┐рдкреНрдкрдгреА?

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрдЪреНрдЫрд╛ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛ рд░рд╣реЗ рд╣реИрдВ!

рдореБрдЭреЗ рдЖрдкрдХрд╛ (рдбрд┐рдлрд╝реЙрд▓реНрдЯ) рд╕реБрдЭрд╛рд╡ рдкрд╕рдВрдж рд╣реИ:
"рдлреВ" @ 1..10 // 1 рд╕реЗ 10 рдмрд╛рд░ рджреЛрд╣рд░рд╛рдПрдВ
"рдлреВ" @ 1.. // рдХрдо рд╕реЗ рдХрдо рдПрдХ рдмрд╛рд░ рджреЛрд╣рд░рд╛рдПрдВ
"рдлреВ" @ ..10 // рдЕрдзрд┐рдХрддрдо 10 рдмрд╛рд░ рджреЛрд╣рд░рд╛рдПрдВ

рдореБрдЭреЗ рдЕрд░реНрдз-рдЦреБрд▓реА рд╢реНрд░реЗрдгрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП +/- рд╕рд┐рдВрдЯреИрдХреНрд╕ рдкрд╕рдВрдж рдирд╣реАрдВ рд╣реИ, рдбрдмрд▓-рдбреЙрдЯ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдЕрдзрд┐рдХ рд╕рд╣рдЬ рдФрд░ рдкрдардиреАрдп рдЖрдИрдПрдордУ рд╣реИред

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

рдЪреАрдпрд░реНрд╕!

рдмрд╕ рдПрдХ рддреНрд╡рд░рд┐рдд рдЯрд┐рдкреНрдкрдгреА: рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ @ рдФрд░ % # рд╕реЗ рдмреЗрд╣рддрд░ рд╡рд┐рдХрд▓реНрдк рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рд╕рд┐рдВрдЯреИрдХреНрд╕ рд╣рд╛рдЗрд▓рд╛рдЗрдЯрд░ рдЬреЛ PEG.js рд╡реНрдпрд╛рдХрд░рдг рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╡реЗ рдЬреЛ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ рд╡рд╛рдХреНрдп рд░рдЪрдирд╛ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рд╕реНрдЯреИрдХ рдУрд╡рд░рдлреНрд▓реЛ рдХрд╛ рдХреЛрдб рд╣рд╛рдЗрд▓рд╛рдЗрдЯрд░), рд╕рдВрднрд╡рддрдГ # рдХреЛ рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдХреА рд╢реБрд░реБрдЖрдд рдХреЗ рд░реВрдк рдореЗрдВ рд╡реНрдпрд╛рдЦреНрдпрд╛рдпрд┐рдд рдХрд░реЗрдЧрд╛, рдЬрд┐рд╕рд╕реЗ рдпрд╣ рджрд┐рдЦрд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ - рдХрд╖реНрдЯрдкреНрд░рдж рд░реВрдк рд╕реЗ - рдЙрд╕ рдмрд┐рдВрджреБ рд╕реЗ "рдЯрд┐рдкреНрдкрдгреА рд░рдВрдЧ" рдореЗрдВ рдИрдУрдПрд▓ рддрдХред рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рддрд░реНрдХ рдФрд░ рддрд░реНрдХ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╡рд░реАрдпрддрд╛ рдирд╣реАрдВ рд╣реИ, рдмрд▓реНрдХрд┐ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХрддрд╛ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИред

рд╣рдо {num, num} рдХреЗ рд▓рд┐рдП рдПрдХ рдЬреИрд╕реЗ рд╡рд┐рд╢реЗрд╖ рдорд╛рдорд▓реЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕реЗ? рдЬрд┐рд╕рдХрд╛ рдорддрд▓рдм рд╣реЛрдЧрд╛ рджреЛрд╣рд░рд╛рд╡, рдХреНрдпреЛрдВрдХрд┐ { , num} рдФрд░ { num, } рд╡реИрдз рдЬреЗрдПрд╕ рдХреЛрдб рдирд╣реАрдВ рд╣реИрдВ, рдФрд░ {num, num} рдФрд░ { num } рд╡реНрдпрд░реНрде рд╣реИрдВред

рдХрд╛рд░реНрд░рд╡рд╛рдИ рдЕрдиреНрдп рднрд╛рд╖рд╛рдУрдВ рдХреА рд╣реЛрдиреЗ рдкрд░ рднреА рдЙрдирдХреЗ рд╕рд╛рд░реНрдердХ рд╣реЛрдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдирд╣реАрдВ рд╣реИред

рдореБрдЭреЗ рд╕реБрдЭрд╛рдП рдЧрдП рд╡рд┐рдХрд▓реНрдкреЛрдВ рдореЗрдВ рд╕реЗ рдпреЗ рд╡рд┐рдХрд▓реНрдк рдкрд╕рдВрдж рд╣реИрдВ (рд▓реЗрдХрд┐рди рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЖрдк рдкрд░ рдирд┐рд░реНрднрд░ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЖрдк рд▓реЗрдЦрдХ рд╣реИрдВ :)):

// why we need separator, anyway? for me it looks very cool and simple to understand
"foo" 1..10   // repeat 1 to 10 times
"foo" 1..     // repeat at least once
"foo" ..10    // repeat at most 10 times

рдпрд╛

"foo"@1..10   // repeat 1 to 10 times
"foo"@1..     // repeat at least once
"foo"@..10    // repeat at most 10 times

рд▓реЗрдХрд┐рди рджреВрд╕рд░рд╛ рдХрдо рдмреЗрд╣рддрд░ рд╣реИ

x..y / ..y / x.. рд╡рд┐рдЪрд╛рд░ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд▓рдЧрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ .. рдЗрд╕рдХреЗ рд▓рд┐рдП рд▓рдЧрд╛рддрд╛рд░ рдСрдкрд░реЗрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рджрд┐рдЦрддрд╛ рд╣реИред

+/- рдореЗрд░реЗ рд▓рд┐рдП рдареАрдХ рдирд╣реАрдВ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рднреНрд░рдорд┐рдд рд╣реЛрддреЗ рд╣реИрдВ рдФрд░ .. рд╕реЗ рдКрдкрд░ рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд рдСрдкрд░реЗрдЯрд░ рдмрди рдЬрд╛рддреЗ рд╣реИрдВ (рдФрд░ + рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ)

рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдлрд┐рд░ рд╕реЗ рд╕реЛрдЪ рд░рд╣рд╛ рд╣реИред рдХреНрдпрд╛ рдпреЗ рдХрд╛рдо рдХрд░реЗрдВрдЧреЗ?

'foo'<1,5>
'foo'< ,3>
'foo'<2, >

рдЪреВрдВрдХрд┐ < рдФрд░ > рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд╡реНрдпрд╛рдХрд░рдг рджреНрд╡рд╛рд░рд╛ рдЕрдкреНрд░рдпреБрдХреНрдд рд╣реИрдВ

:+1: рдореБрдЭрд╕реЗ, рдпрд╣ рдЕрдЪреНрдЫрд╛ рд▓рдЧ рд░рд╣рд╛ рд╣реИред

рдмреЗрд╢рдХ, <,3> рдмрд░рд╛рдмрд░ рд╣реИ <0,3> , рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдиреНрдпреВрдирддрдо рд╕рдВрдЦреНрдпрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИред рдпрд╣ рдИрд╕реАрдПрдордП рдиреЗ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд░реЗрдЧреБрд▓рд░ рдПрдХреНрд╕рдкреНрд░реЗрд╢рди рдХреЗ рд▓рд┐рдП рдЬреЛ рдХрд┐рдпрд╛ рд╣реИ, рдЙрд╕рдХреЗ рдЕрдиреБрд░реВрдк рд╣реЛрдЧрд╛ред

рдореБрдЭреЗ <,> рдкрд╕рдВрдж рд╣реИред рд▓реЗрдХрд┐рди рдореИрдВ <3> <3,3> рд╕рдорд╛рди рд╣реЛрдиреЗ рдХрд╛ рднреА рд╕реБрдЭрд╛рд╡ рджреВрдВрдЧрд╛ред

рдореИрдВ рд╕рд╣рдордд рд╣реВрдВ, <> рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХреЛ рдпрдерд╛рд╕рдВрднрд╡ рдЕрдзрд┐рдХ рд╕реЗ рдЕрдзрд┐рдХ {} рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдкрд░ рд╕реАрдзреЗ рдореИрдк рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред

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

foo 1,2 fighter
bar ,3 tender
baz 4, lurhmann
qux 5 quux

рд╕рднреА рдЕрд╕рдВрджрд┐рдЧреНрдз рд╣реИрдВред

@pygy , рдПрдХ рдбрд┐рд▓реАрдореАрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рди рдХрд░рдиреЗ рдореЗрдВ рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдВрднрд╛рд╡рд┐рдд рд░реВрдк рд╕реЗ рднрд╛рд╖рд╛ рдХреЗ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреЛ рд░реЛрдХрддрд╛ рд╣реИред

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

рд╕рд╛рде рд╣реА, рд▓реЛрдЧреЛрдВ рдХреЛ рд╡реИрд╕реЗ рднреА RegExps рдореЗрдВ {1,6} рд╢реИрд▓реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрджрдд рд╣реИред

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

рдореЗрд░рд╛ рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓рд╛: IMAP рд╕рд░реНрд╡рд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдУрдВ рдореЗрдВ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдЕрдХреНрд╖рд░, рдЬреЛ {42}\r\n... рдЬреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ 42 рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдирдИ рд▓рд╛рдЗрди рдХреЗ рдмрд╛рдж рд╡рд░реНрдгреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рд╣реИ (рдпрд╣рд╛рдВ рдПрдХ рдЗрд▓рд┐рдкреНрд╕рд┐рд╕ рдХреЗ рд░реВрдк рдореЗрдВ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ)ред рдЪреВрдВрдХрд┐ IMAP рд╢рд╛рдмреНрджрд┐рдХ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдЕрдВрддрд┐рдо рд╕реАрдорд╛рдВрдХрдХ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХрд╛ рдПрдХрдорд╛рддреНрд░ рддрд░реАрдХрд╛ рд╡рд░реНрдг рдЧрдгрдирд╛ рд╣реИред

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

  = len:number message:.<len,len> .* {return message;}
number
  = n:[0-9] {return parseInt(n);}

рдкрд╛рд░реНрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП

4[__] -> ['[', '_', '_', ']']
4[___] -> ['[', '_', '_', '_']
4[_] -> Error: expected 4 chars, got 3

рдпрд╣ рдХрдИ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реИред

рдЙрд╕ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:
expression |min,max| , рдлрд┐рд░ рдЯреЗрдореНрдкрд▓реЗрдЯ рдирд┐рдпрдореЛрдВ рдХреЗ рд▓рд┐рдП рдХреЛрдг рдХреЛрд╖реНрдардХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

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

exp *     // 0 or more times
exp 1*    // at least once
exp *10   // up to 10 times
exp 1*10  // 1 to 10 times

рдирдорд╕реНрдХрд╛рд░ред рдореЗрд░реЗ рдкрд╛рд╕ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЬрдЯрд┐рд▓ рдлрд╝рд╛рдЗрд▓ рд╕реНрд╡рд░реВрдк рд╣реИред рдпрд╣ рдЖрдзрд╛ рдмрд╛рдЗрдирд░реА, рдЖрдзрд╛ ASCII рд╣реИред

рдпрд╣рд╛рдБ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рдПрдХ рд╕рд░рд▓реАрдХреГрдд рд╕рдВрд╕реНрдХрд░рдг рд╣реИ:

KK4TesRandom рдпрд╛ KK10TestATestBRandom

рддрд░реНрдХ:

<StringIndicator><StringLength><String><otherStuff>

KK рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрдХреЗрддрдХ рд╣реИред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЕрдВрдХ (рдпрд╣рд╛рдВ 4 рдФрд░ 10 ) рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреА рд▓рдВрдмрд╛рдИ рд╣реИрдВред рдлрд┐рд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реА (рдпрд╣рд╛рдВ Test рдФрд░ TestATestB )ред рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдХрд┐рд╕реА рднреА рдЕрдиреБрдорд╛рдирд┐рдд рдкреИрдЯрд░реНрди рд╕реЗ рд╕рдорд╛рдкреНрдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдореБрдЭреЗ рдореВрд▓ рд░реВрдк рд╕реЗ рд▓рдВрдмрд╛рдИ рдХреА рдЬрд╛рдирдХрд╛рд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИред рдореИрдВ рдХрд╣реВрдВрдЧрд╛ рдХрд┐ рдпрд╣ рдмрд╛рдЗрдирд░реА рдлрд╝рд╛рдЗрд▓ рд╕реНрд╡рд░реВрдкреЛрдВ рдореЗрдВ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдкреИрдЯрд░реНрди рд╣реИ, рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╡рд░реНрддрдорд╛рди рд╡реНрдпрд╛рдХрд░рдг рдХреЗ рд╕рд╛рде рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ?

рдзрдиреНрдпрд╡рд╛рджред

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

start = len:nx data:.|len| { return data; };
nx = n:$[0-9]+ { return parseInt(n, 10); };

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

рдореБрдЭреЗ рджреЛрд╣рд░рд╛рд╡ рдХреА рд╕рдВрдЦреНрдпрд╛ рднреА рдкрд╕рдВрдж рдЖрдПрдЧреАред рд▓реЗрдХрд┐рди рдореИрдВ рдереЛрдбрд╝рд╛ рдЕрд▓рдЧ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рд╕реБрдЭрд╛рдКрдВрдЧрд╛ред Pegasus рд▓рдЧрднрдЧ pegjs рдХреЗ рд╕рдорд╛рди рд╣реИ, рдХреЗрд╡рд▓ C# рдХреЗ рд▓рд┐рдПред рдпрд╣рд╛рдВ рджреЗрдЦреЗрдВ: https://github.com/otac0n/Pegasus/wiki/Syntax-Guide#expressions

рдФрд░ рдЙрдиреНрд╣реЛрдВрдиреЗ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛: d<3> e<2,> f<1,5>

рдЗрд╕рдХреЗ рд▓рд┐рдП рд▓реЛрдЧ рдХреНрдпрд╛ рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВ? рдореИрдВ рдЕрднреА рдкреАрдИрдЬреАрдЬреЗ рдореЗрдВ рдЖ рд░рд╣рд╛ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рд╢рд╛рдпрдж рдореИрдВ рдПрдХ рд╣рдереМрдбрд╝рд╛ рдХреЗ рд╕рд╛рде рдПрдХ рдкреЗрдВрдЪ рдЪрд╛рд▓реВ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдореИрдВ рд╕рд┐рд░реНрдл 1 рдФрд░ 6 рдЕрдВрдХреЛрдВ рдХреЗ рдмреАрдЪ рдорд┐рд▓рд╛рди рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ :)

рдореИрдВ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ (рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХреЗ рд▓рд┐рдП # 267 рджреЗрдЦреЗрдВ, рдЕрдВрддрд┐рдо рд╕рдорд╛рдзрд╛рди рд╕рдВрдЦреНрдпрд╛рдУрдВ, рдЪрд░ рдФрд░ рдХреЛрдб рдмреНрд▓реЙрдХ рдХреЛ рд╕реАрдорд╛рдУрдВ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ) рдФрд░ рдореИрдВ рдЬрд▓реНрдж рд╣реА рдкреИрдЧреА рдХреЗ рд▓рд┐рдП рдкреАрдЖрд░ рддреИрдпрд╛рд░ рдХрд░реВрдВрдЧрд╛ (рдкреАрдИрдЬреА.рдЬреЗрдПрд╕ рдлреЛрд░реНрдХ рдХреА рд░реАрдмреНрд░рд╛рдВрдбрд┐рдВрдЧ рдЬрд┐рд╕реЗ рдмрдирд╛рдП рд░рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ)

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

emmenko picture emmenko  ┬╖  15рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

vldmr1986 picture vldmr1986  ┬╖  12рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

mreinstein picture mreinstein  ┬╖  12рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

gatsbyz picture gatsbyz  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

mattkanwisher picture mattkanwisher  ┬╖  5рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ