def _parse_base_list(self):
        """BaseList = (BASE)*"""
        tree = Tree('BaseList')

        while not self._scanner.is_end() and not self._scanner.is_next('}'):
            tree.append(self._parse_base())
        return tree
 def _parse_exp(self):
     """EXP = ITEM ([+-*/] ITEM)? """
     tree = Tree('EXP') \
         .append(self._parse_item())
     if self._scanner.is_next('OP'):
         tree.append(self._scanner.get_next('OP')) \
             .append(self._parse_item())
     return tree
    def _parse_stmt(self):
        """STMT = 'return' id | id '=' EXP | id ('++'|'--') """
        tree = Tree('STMT')
        if self._scanner.is_next('return'):
            tree.append(self._scanner.get_next('return')) \
                .append(self._parse_id())
        else:
            tree.append(self._parse_id())
            if self._scanner.is_next('ASSIGN'):
                tree.append(self._scanner.get_next('ASSIGN')) \
                    .append(self._parse_exp())
            else:
                tree.append(self._scanner.get_next('UnaryOP'))

        return tree
 def _parse_cond(self):
     """COND = EXP ('=='|'!='|'<='|'>='|'<'|'>') EXP"""
     tree = Tree('COND') \
         .append(self._parse_exp()) \
         .append(self._scanner.get_next('COND')) \
         .append(self._parse_exp())
     return tree
 def _parse_block(self):
     """BLOCK = '{' BaseList '}' """
     tree = Tree('BLOCK') \
         .append(self._scanner.get_next('{')) \
         .append(self._parse_base_list()) \
         .append(self._scanner.get_next('}'))
     return tree
    def _parse_base(self):
        """BASE = FOR | STMT ';' """
        tree = Tree('BASE')
        if self._scanner.is_next('for'):
            tree.append(self._parse_for())
        else:
            tree.append(self._parse_stmt())
            tree.append(self._scanner.get_next(';'))

        return tree
 def _parse_for(self):
     """FOR = 'for' '(' STMT ';' COND ';' STMT ')' BLOCK """
     tree = Tree('FOR') \
         .append(self._scanner.get_next('for')) \
         .append(self._scanner.get_next('(')) \
         .append(self._parse_stmt()) \
         .append(self._scanner.get_next('END')) \
         .append(self._parse_cond()) \
         .append(self._scanner.get_next('END')) \
         .append(self._parse_stmt()) \
         .append(self._scanner.get_next(')')) \
         .append(self._parse_block())
     return tree
 def _parse_item(self):
     """ITEM = id | number """
     tree = Tree('ITEM')
     if self._scanner.is_next('ID'):
         tree.append(self._parse_id())
     else:
         tree.append(self._parse_number())
     return tree
 def _parse_prog(self):
     """PROG = BaseList """
     return Tree('PROG').append(self._parse_base_list())
    def parse_tree(self, rule: BNFRule):
        tree = Tree(rule.name)
        for sub_rule in rule.sub_rules:
            first_try = True
            next_sub = False
            for token in sub_rule:
                try:
                    if token.modifier is ModifierType.none:
                        result = self.get_token(token)
                        tree.append(result,
                                    concat=token.type is RuleType.link
                                    and self.rules[token.content].type is
                                    RuleType.internal)
                    elif token.modifier is ModifierType.repeat_what_ever:
                        while True:
                            try:
                                result = self.try_get_token(token)
                            except ContextEndedError:
                                break

                            if result is None:
                                break
                            else:
                                tree.append(result,
                                            concat=token.type is RuleType.link
                                            and self.rules[token.content].type
                                            is RuleType.internal)
                    elif token.modifier is ModifierType.repeat_once_or_nothing_happened:
                        try:
                            result = self.try_get_token(token)
                        except ContextEndedError:
                            result = None
                        if result is not None:
                            tree.append(result,
                                        concat=token.type is RuleType.link
                                        and self.rules[token.content].type is
                                        RuleType.internal)
                    elif token.modifier is ModifierType.repeat_more_than_once:
                        result = self.get_token(token)
                        tree.append(result,
                                    concat=token.type is RuleType.link
                                    and self.rules[token.content].type is
                                    RuleType.internal)
                        while True:
                            try:
                                result = self.try_get_token(token)
                            except ContextEndedError:
                                break
                            if result is None:
                                break
                            else:
                                tree.append(result,
                                            concat=token.type is RuleType.link
                                            and self.rules[token.content].type
                                            is RuleType.internal)
                except (UnExceptedTokenError, ContextEndedError) as e:
                    self.last_unexpected_error = e
                    if first_try is True:
                        next_sub = True
                        break
                    else:
                        raise ParseError(e)

                # tree.append(result)
                first_try = False
            if next_sub:
                continue

            return tree
        raise self.last_unexpected_error
 def _parse_number(self):
     """number = [0-9]+"""
     tree = Tree('Number') \
         .append(self._scanner.get_next('NUMBER'))
     return tree
 def _parse_id(self):
     """id = [A-Za-z_][A-Za-z0-9_]*"""
     tree = Tree('ID') \
         .append(self._scanner.get_next('ID'))
     return tree