рдЦреВрдВрдЯреА parser рдкреАрдврд╝реА

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



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


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


рдЗрд╕рд▓рд┐рдП, рд╣рдо рдПрдХ рд╕рд░рд▓ рд╕рдВрдХрд▓рдХ рд╕рдВрдХрд▓рдХ рдмрдирд╛ рд░рд╣реЗ рд╣реИрдВред рдореИрдВ рд╡реНрдпрд╛рдХрд░рдгрд┐рдХ рд╕рдВрдХреЗрддрди рдХреЛ рдЗрд╕ рд╣рдж рддрдХ рд╕рд░рд▓ рдХрд░ рджреВрдВрдЧрд╛ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреЗрд╡рд▓ рдирд┐рдпрдо рдФрд░ рд╡рд┐рдХрд▓реНрдк рд╣реЛрдВ; рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЦрд┐рд▓реМрдиреЗ рдХреЗ рд╡реНрдпрд╛рдХрд░рдг рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ рдкрд┐рдЫрд▓реЗ рднрд╛рдЧреЛрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдерд╛:


 statement: assignment | expr | if_statement expr: expr '+' term | expr '-' term | term term: term '*' atom | term '/' atom | atom atom: NAME | NUMBER | '(' expr ')' assignment: target '=' expr target: NAME if_statement: 'if' expr ':' statement 

рдкреВрд░реНрдг рд╕рдВрдХреЗрддрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рд╡реНрдпрд╛рдХрд░рдг рдХрд╛ рд╡рд░реНрдгрди рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 grammar: rule+ ENDMARKER rule: NAME ':' alternative ('|' alternative)* NEWLINE alternative: item+ item: NAME | STRING 

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


рдореЗрдЯрд╛-рд╡реНрдпрд╛рдХрд░рдг рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЖрд╕рд╛рди рддрд░реАрдХрд╛ рдХреЗрд╡рд▓ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ: рдирд┐рдпрдо рдХрд╛ рд╕рд╣реА рд╣рд┐рд╕реНрд╕рд╛ рддрддреНрд╡реЛрдВ рдХреА рд╕реВрдЪреА рдХреА рдПрдХ рд╕реВрдЪреА рд╣реИ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рд╕рд┐рд░реНрдл рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред (рд╡реИрд╕реЗ, рдпрджрд┐ рдкрд╣рд▓рд╛ рд╡рд░реНрдг рдПрдХ рдЙрджреНрдзрд░рдг рдЪрд┐рд╣реНрди рд╣реИ, рддреЛ рд╣рдо рдЬрд╛рдБрдЪ рдХрд░рдХреЗ NAME рдФрд░ STRING рдХреЛ рдЕрд▓рдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ)


рдирд┐рдпрдореЛрдВ рдХреЗ рд▓рд┐рдП, рдореИрдВ рд╕рд░рд▓ Rule рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ, рдФрд░ рд╕рдВрдкреВрд░реНрдг рд╡реНрдпрд╛рдХрд░рдг рдРрд╕реА рд╡рд╕реНрддреБрдУрдВ рдХреА рдПрдХ рд╕реВрдЪреА рд╣реИред рдпрд╣рд╛рдБ __eq__ рдФрд░ __eq__ рдХреЛ рдЫреЛрдбрд╝рдХрд░ Rule рд╡рд░реНрдЧ рд╣реИ:


 class Rule: def __init__(self, name, alts): self.name = name self.alts = alts 

рдФрд░ рдпрд╣рд╛рдБ GrammarParser рдХреНрд▓рд╛рд╕ рд╣реИ рдЬреЛ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ:


 class GrammarParser(Parser): def grammar(self): pos = self.mark() if rule := self.rule(): rules = [rule] while rule := self.rule(): rules.append(rule) if self.expect(ENDMARKER): return rules # <------------- final result self.reset(pos) return None def rule(self): pos = self.mark() if name := self.expect(NAME): if self.expect(":"): if alt := self.alternative(): alts = [alt] apos = self.mark() while (self.expect("|") and (alt := self.alternative())): alts.append(alt) apos = self.mark() self.reset(apos) if self.expect(NEWLINE): return Rule(name.string, alts) self.reset(pos) return None def alternative(self): items = [] while item := self.item(): items.append(item) return items def item(self): if name := self.expect(NAME): return name.string if string := self.expect(STRING): return string.string return None 

ENDMARKER рдХреЗ рдЙрдкрдпреЛрдЧ рдкрд░ рдзреНрдпрд╛рди ENDMARKER ред рд╡рд╣рд╛рдВ рдореИрдВ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рдЕрдВрддрд┐рдо рдирд┐рдпрдо рдХреЗ рдмрд╛рдж рдХреБрдЫ рднреА рдирд╣реАрдВ рд░рд╣рддрд╛ (рдФрд░ рдЕрдЧрд░ рд╡реНрдпрд╛рдХрд░рдг рдореЗрдВ рдХреЛрдИ рдЯрд╛рдЗрдкреЛ рд╣реИ рддреЛ рдРрд╕рд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ)ред рдореИрдВрдиреЗ рдЙрд╕ рд╕реНрдерд╛рди рдХреЛ рднреА рдЗрдВрдЧрд┐рдд рдХрд┐рдпрд╛ рдЬрд╣рд╛рдВ grammar() рд╡рд┐рдзрд┐ рдирд┐рдпрдореЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рджреЗрддрд╛ рд╣реИред рдмрд╛рдХреА рд╕рдм рдХреБрдЫ рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдХреЗ ToyParser рд╡рд░реНрдЧ рдХреЗ рд╕рдорд╛рди рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЙрд╕ рдкрд░ рдзреНрдпрд╛рди рдирд╣реАрдВ рджреВрдВрдЧрд╛ред рдмрд╕ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ item() рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд▓реМрдЯрд╛рддрд╛ рд╣реИ, alternative() рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреА рдПрдХ рд╕реВрдЪреА рджреЗрддрд╛ рд╣реИ, рдФрд░ rule() рдЕрдВрджрд░ рдЪрд░ alts rule() рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреА рд╕реВрдЪреА рдХреА рдПрдХ рд╕реВрдЪреА рдПрдХрддреНрд░ рдХрд░рддрд╛ рд╣реИред рдлрд┐рд░, rule() рд╡рд┐рдзрд┐ рдирд┐рдпрдо (рд╕реНрдЯреНрд░рд┐рдВрдЧ) рдХреЗ рдирд╛рдо рдХреЛ рдЬреЛрдбрд╝рддреА рд╣реИ рдФрд░ рдЗрд╕реЗ Rule рд╡рд╕реНрддреБ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддреА рд╣реИред


рдпрджрд┐ рд╣рдо рдЗрд╕ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЛ рдЕрдкрдиреЗ рдЦрд┐рд▓реМрдирд╛ рд╡реНрдпрд╛рдХрд░рдг рдкрд░ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ grammar() рд╡рд┐рдзрд┐ рдирд┐рдпрдореЛрдВ рдХреА рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕реВрдЪреА рд╡рд╛рдкрд╕ рдХрд░ рджреЗрдЧреА:


 [ Rule('statement', [['assignment'], ['expr'], ['if_statement']]), Rule('expr', [['term', "'+'", 'expr'], ['term', "'-'", 'term'], ['term']]), Rule('term', [['atom', "'*'", 'term'], ['atom', "'/'", 'atom'], ['atom']]), Rule('atom', [['NAME'], ['NUMBER'], ["'('", 'expr', "')'"]]), Rule('assignment', [['target', "'='", 'expr']]), Rule('target', [['NAME']]), Rule('if_statement', [["'if'", 'expr', "':'", 'statement']]), ] 

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


 def generate_parser_class(rules): print(f"class ToyParser(Parser):") for rule in rules: print() print(f" @memoize") print(f" def {rule.name}(self):") print(f" pos = self.mark()") for alt in rule.alts: items = [] print(f" if (True") for item in alt: if item[0] in ('"', "'"): print(f" and self.expect({item})") else: var = item.lower() if var in items: var += str(len(items)) items.append(var) if item.isupper(): print(" " + f"and ({var} := self.expect({item}))") else: print(f" " + f"and ({var} := self.{item}())") print(f" ):") print(f" " + f"return Node({rule.name!r}, [{', '.join(items)}])") print(f" self.reset(pos)") print(f" return None") 

рдпрд╣ рдХреЛрдб рдмрд╣реБрдд рдмрджрд╕реВрд░рдд рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ (рдкреНрд░рдХрд╛рд░), рдФрд░ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдореИрдВ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦреВрдВрдЧрд╛ред


for alt in rule.alts рдХреЛ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИ: рд╡рд┐рдХрд▓реНрдк рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдХреЗ рд▓рд┐рдП, рд╣рдо 3 рд╡рд┐рдХрд▓реНрдкреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдЪреБрдирддреЗ рд╣реИрдВ:


  • рдпрджрд┐ рддрддреНрд╡ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП '+' , рддреЛ рд╣рдо self.expect('+') рдЙрддреНрдкрдиреНрди рдХрд░рддреЗ рд╣реИрдВред
  • рдпрджрд┐ рддрддреНрд╡ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрдкрд░рдХреЗрд╕ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП NAME , рддреЛ рд╣рдо рдЬрдирд░реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ (name := self.expect(NAME))
  • рдЕрдиреНрдпрдерд╛, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЕрдЧрд░ рдпрд╣ expr , рддреЛ рд╣рдо рдЬрдирд░реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ (expr := self.expr())

рдпрджрд┐ рдПрдХ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдПрдХ рд╣реА рдирд╛рдо рдХреЗ рд╕рд╛рде рдХрдИ рддрддреНрд╡ рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, term '-' term ), рддреЛ рд╣рдо рджреВрд╕рд░реЗ рдореЗрдВ рдПрдХ рдЕрдВрдХ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред рдпрд╣рд╛рдВ рдПрдХ рдЫреЛрдЯреА рд╕реА рдЧрд▓рддреА рднреА рд╣реИ рдЬрд┐рд╕реЗ рдореИрдВ рдЕрдЧрд▓реЗ рдПрдкрд┐рд╕реЛрдб рдореЗрдВ рд╕рд╣реА рдХрд░реВрдВрдЧрд╛ред


рдпрд╣рд╛рдВ рдЙрдирдХреЗ рдХрд╛рдо рдХрд╛ рдереЛрдбрд╝рд╛ рд╕рд╛ рдкрд░рд┐рдгрд╛рдо рд╣реИ (рдкреВрд░реА рдХрдХреНрд╖рд╛ рдмрд╣реБрдд рдЙрдмрд╛рдК рд╣реЛрдЧреА)ред рдЕрдирд╛рд╡рд╢реНрдпрдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЪрд┐рдВрддрд╛ рди рдХрд░реЗрдВ if (True and ... ) рдХреЛрдб рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рддрд╛рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдЙрддреНрдкрдиреНрди рд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛ рд╕рдХреЗ and ред рдкрд╛рдпрдерди рдмрд╛рдЗрдЯ рдХрдВрдкрд╛рдЗрд▓рд░ рдЗрд╕рдХрд╛ рдЕрдиреБрдХреВрд▓рди рдХрд░рддрд╛ рд╣реИред


 class ToyParser(Parser): @memoize def statement(self): pos = self.mark() if (True and (assignment := self.assignment()) ): return Node('statement', [assignment]) self.reset(pos) if (True and (expr := self.expr()) ): return Node('statement', [expr]) self.reset(pos) if (True and (if_statement := self.if_statement()) ): return Node('statement', [if_statement]) self.reset(pos) return None ... 

@memoize рдбреЗрдХреЛрд░реЗрдЯрд░ рдкрд░ рдзреНрдпрд╛рди @memoize : рдореИрдВрдиреЗ рдЗрд╕реЗ рдПрдХ рдЕрдиреНрдп рд╡рд┐рд╖рдп рдкрд░ рдЖрдЧреЗ рдмрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдкреЗрд╢ рдХрд┐рдпрд╛: рдЙрддреНрдкрдиреНрди рдкрд╛рд░реНрд╕рд░ рдХреЛ рддреЗрдЬреА рд╕реЗ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП @memoize рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ред


рдпрд╣рд╛рдБ memoize() рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬреЛ рдЗрд╕ рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ:


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

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


рд░реИрдкрд░ рдкреНрд░рддреНрдпреЗрдХ рдЗрдирдкреБрдЯ рд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдП рд╡рд┐рдзрд┐ рдХреЙрд▓ рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдХреИрд╢ рдХрд░рддрд╛ рд╣реИ - рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдЗрд╕реЗ рдкреИрдХрд░реИрдЯ рдкрд╛рд░реНрд╕рд░ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ! [рд▓рдЧрднрдЧред рдкреНрд░рддрд┐ред packrat рдПрдХ "рдЪреЛрд░" рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рд╢рдмреНрдж рд░реВрд╕реА рднрд╛рд╖рд╛ рдХреЗ рд╕реНрд░реЛрддреЛрдВ рдореЗрдВ рдЕрдиреБрд╡рд╛рджрд┐рдд рдирд╣реАрдВ рд╣реИред] рдХреИрд╢реЗ рд╢рдмреНрджрдХреЛрд╢реЛрдВ рдХрд╛ рдПрдХ рд╢рдмреНрджрдХреЛрд╢ рд╣реИ, рдЬреЛ рдПрдХ Parser рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реИред рдмрд╛рд╣рд░реА рд╢рдмреНрджрдХреЛрд╢ рдХреА рдХреБрдВрдЬреА рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рд╕реНрдЯреНрд░реАрдо рдореЗрдВ рд╕реНрдерд┐рддрд┐ рд╣реИ; рдореИрдВрдиреЗ рдЗрд╕реЗ рдкреНрд░рд╛рд░рдВрдн рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП self.memos = {} рдХреЛ Parser .__ init__() рднреА рдЬреЛрдбрд╝рд╛ред рдЖрдВрддрд░рд┐рдХ рд╢рдмреНрджрдХреЛрд╢реЛрдВ рдХреЛ рдЖрд╡рд╢реНрдпрдХрддрд╛рдиреБрд╕рд╛рд░ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ; рдЙрдирдХреА рдХреБрдВрдЬрд┐рдпреЛрдВ рдореЗрдВ рдПрдХ рд╡рд┐рдзрд┐ рдФрд░ рдЙрд╕рдХреЗ рддрд░реНрдХ рд╣реЛрддреЗ рд╣реИрдВред (рд╡рд░реНрддрдорд╛рди рдбрд┐рдЬрд╛рдЗрди рдореЗрдВ рдХреЛрдИ рддрд░реНрдХ рдирд╣реАрдВ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╣рдо expect() рдХреЛ рдпрд╛рдж рдХрд░ expect() рдлрд╝рдВрдХреНрд╢рди рдЬрд┐рд╕рдореЗрдВ рдПрдХ рд╣реИ, рдЬреЛ рдХрд╛рдлреА рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ)


рдкрд╛рд░реНрд╕рд░ рд╡рд┐рдзрд┐ рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдПрдХ рдЯрдкрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рджреЛ рдореВрд▓реНрдп рд╣реИрдВ: рдкрд░рд┐рдгрд╛рдо рд╕реНрд╡рдпрдВ (рд╣рдорд╛рд░реА рдЙрддреНрдкрдиреНрди рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдпрд╣ рдорд┐рд▓рд╛рди рдирд┐рдпрдо рдХреЗ рд▓рд┐рдП Node ) рдФрд░ рдЗрдирдкреБрдЯ рд╕реНрдЯреНрд░реАрдо рдореЗрдВ рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрдХреЗрддрдХ, рдЬреЛ self.mark() рд╕реЗ рдорд┐рд▓рддрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдо рдЬреНрдЮрд╛рдкрди рдореВрд▓реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдЖрдВрддрд░рд┐рдХ рд╢рдмреНрджрдХреЛрд╢ рдореЗрдВ рд╡рд╛рдкрд╕реА рдореВрд▓реНрдп ( res ) рдФрд░ рдирдИ рд╕реНрдерд┐рддрд┐ ( endpos ) рджреЛрдиреЛрдВ рдХреЛ рдХреИрд╢ рдХрд░рддреЗ рд╣реИрдВред рдПрдХ рд╣реА рдЗрдирдкреБрдЯ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╕рдорд╛рди рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╣реА рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдкрджреНрдзрддрд┐ рдХреЗ рдмрд╛рдж рдХреЗ рдХреЙрд▓ рдкрд░, рд╣рдо рдЙрдиреНрд╣реЗрдВ рдХреИрд╢ рд╕реЗ рд▓реЗрдВрдЧреЗред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╕ рдкреЙрдЗрдВрдЯрд░ рдХреЛ self.reset() рд╕реНрдерд┐рддрд┐ рдореЗрдВ self.reset() рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ self.reset() рдФрд░ рдХреИрд╢ рдореЗрдВ рджреЗрдЦреЗрдВред


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


рдиреЛрдЯред рдкрд╛рдпрдерди рдореЗрдВ, memoize() рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдореЗрдВ рдХреИрд╢ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рдерд╛рдЧрдд рд╣реИред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛: рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдбрд┐рдмрдЧрд┐рдВрдЧ рдХреЗ рдмрд╣реБрдд рдЕрдВрдд рдореЗрдВ рдкрд╛рдпрд╛, рдкреНрд░рддреНрдпреЗрдХ Parser рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЕрдкрдирд╛ рдХреИрд╢ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЖрдк рдХреБрдВрдЬреА рдХреЗ рд░реВрдк рдореЗрдВ ( pos , func , args ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдиреЗрд╕реНрдЯреЗрдб рд╢рдмреНрджрдХреЛрд╢реЛрдВ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред


рдЕрдЧрд▓реЗ рд╣рдлреНрддреЗ рдореИрдВ рдХреЛрдб рдФрд░ рдирд┐рд╢рд╛рди рддреИрдпрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рджрд┐рдЦрд╛рдКрдВрдЧрд╛ рдХрд┐ рдХреИрд╕реЗ рдпрд╣ рд╕рдм рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрдХрдЯреНрдард╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рддреЗ рд╕рдордп рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдореИрдВ рдЕрднреА рднреА рдЯреЛрдХрди рдмрдлрд░, рдкрд╛рд░реНрд╕рд░ рдФрд░ рдХреИрд╢ рдХреЗ рд╕рд╣рдпреЛрдЧ рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдмреЗрд╣рддрд░ рддрд░реАрдХреЗ рдХреА рддрд▓рд╛рд╢ рдореЗрдВ рд╣реВрдВред рд╢рд╛рдпрдж рдореИрдВ ASCII рдореЗрдВ рдХреЗрд╡рд▓ рдкрд╛рда рдХреЗ рд░реВрдк рдореЗрдВ рдЯреНрд░реЗрд╕ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдПрдХ рдПрдирд┐рдореЗрдЯреЗрдб gif рдмрдирд╛рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛ рдЬрд╛рдПрдЧрд╛ред


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

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


All Articles