def parse(self, s):
global_comp = None<EOL>if self._parse_global:<EOL><INDENT>m = re.match(r'<STR_LIT>', s)<EOL>if m is not None:<EOL><INDENT>global_comp = m.group(<NUM_LIT:1>)<EOL>s = m.group(<NUM_LIT:2>)<EOL><DEDENT><DEDENT>expect_operator = False<EOL>direction = None<EOL>left = []<EOL>right = []<EOL>current_side = left<EOL>saved_token = None<EOL>def tokenize():<EOL><INDENT>for match in re.finditer(self._scanner, s):<EOL><INDENT>for i, group in enumerate(match.groups()):<EOL><INDENT>if group is not None:<EOL><INDENT>token = self._tokens[i][<NUM_LIT:1>]<EOL>span = match.start(), match.end()<EOL>if token is None:<EOL><INDENT>raise ParseError(<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'.format(group), span=span)<EOL><DEDENT>yield self._tokens[i][<NUM_LIT:1>], group, span<EOL>break<EOL><DEDENT><DEDENT><DEDENT><DEDENT>for token, value, span in tokenize():<EOL><INDENT>if saved_token is not None and (<EOL>token in (_ReactionToken.Plus,<EOL>_ReactionToken.Arrow,<EOL>_ReactionToken.End)):<EOL><INDENT>compound = parse_compound(saved_token, global_comp)<EOL>current_side.append((compound, <NUM_LIT:1>))<EOL>expect_operator = True<EOL>saved_token = None<EOL><DEDENT>if token == _ReactionToken.Plus:<EOL><INDENT>if not expect_operator:<EOL><INDENT>raise ParseError('<STR_LIT>'.format(value),<EOL>span=span)<EOL><DEDENT>expect_operator = False<EOL><DEDENT>elif token == _ReactionToken.Arrow:<EOL><INDENT>if direction is not None:<EOL><INDENT>raise ParseError(<EOL>'<STR_LIT>'.format(value),<EOL>span=span)<EOL><DEDENT>if not expect_operator and len(left) > <NUM_LIT:0>:<EOL><INDENT>raise ParseError('<STR_LIT>'.format(value),<EOL>span=span)<EOL><DEDENT>expect_operator = False<EOL>direction = self._arrows[value]<EOL>current_side = right<EOL><DEDENT>elif token == _ReactionToken.Group:<EOL><INDENT>if expect_operator:<EOL><INDENT>raise ParseError('<STR_LIT>'.format(<EOL>value), span=span)<EOL><DEDENT>if saved_token is not None:<EOL><INDENT>raise ParseError('<STR_LIT>'.format(<EOL>value), span=span)<EOL><DEDENT>saved_token = value<EOL><DEDENT>elif token == _ReactionToken.Quoted:<EOL><INDENT>if expect_operator:<EOL><INDENT>raise ParseError('<STR_LIT>'.format(<EOL>value), span=span)<EOL><DEDENT>if saved_token is not None:<EOL><INDENT>try:<EOL><INDENT>count = parse_compound_count(saved_token)<EOL><DEDENT>except ValueError as e:<EOL><INDENT>raise_from(ParseError(<EOL>'<STR_LIT>'.format(<EOL>saved_token),<EOL>span=span), e)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>count = <NUM_LIT:1><EOL><DEDENT>compound = parse_compound(value, global_comp)<EOL>current_side.append((compound, count))<EOL>expect_operator = True<EOL>saved_token = None<EOL><DEDENT>elif token == _ReactionToken.Other:<EOL><INDENT>if expect_operator:<EOL><INDENT>raise ParseError('<STR_LIT>'.format(<EOL>value), span=span)<EOL><DEDENT>if saved_token is not None:<EOL><INDENT>try:<EOL><INDENT>count = parse_compound_count(saved_token)<EOL><DEDENT>except ValueError as e:<EOL><INDENT>raise_from(ParseError(<EOL>'<STR_LIT>'.format(<EOL>saved_token),<EOL>span=span), e)<EOL><DEDENT>compound = parse_compound(value, global_comp)<EOL>current_side.append((compound, count))<EOL>expect_operator = True<EOL>saved_token = None<EOL><DEDENT>else:<EOL><INDENT>saved_token = value<EOL><DEDENT><DEDENT><DEDENT>if direction is None:<EOL><INDENT>raise ParseError('<STR_LIT>')<EOL><DEDENT>return Reaction(direction, left, right)<EOL>
Parse reaction string.