def match(self, lexer: Lexer, debug: int = 0, partial=True):

        if debug:
            print(' ' * (debug - 1) +
                  f'### Group {self.name}.match(), calling super\'s match()')

        tree = Ast(self.name, lexer.current_position(), grammars=[])
        if lexer.current_token is None\
            or lexer.current_token.spelling == '_EOF':
            if self.repeat[0] == 0:
                return tree
            return None

        lexer.anchor()
        repetition = 0
        if self.repeat[1] == -1:
            # can repeat for infinite times: grammar* | grammar+ | grammar{a,}
            while True:
                nodes = super().match(lexer, debug)
                if nodes is None:
                    break
                tree.extend(nodes)
                repetition += 1
                if lexer.current_token is None:
                    break
        else:
            # repeat for limited times: grammar{a, b} | grammar{a} | [grammar]
            while True:
                if repetition >= self.repeat[1]:
                    break
                nodes = super().match(lexer, debug)
                if nodes is None:
                    break
                tree.extend(nodes)
                repetition += 1
                if lexer.current_token is None:
                    break

        if repetition < self.repeat[0]:
            # if actual repetition is smaller than minimum times

            if debug:
                print(
                    ' ' * (debug - 1) +
                    f'--- Group {self.name}.match() FAILED in minimal repetition)'
                )

            lexer.backward()

            if debug:
                print(
                    f'<<< lexer backwarded, current token: {lexer.current_token}'
                )

            return None

        if debug:
            print(' ' * (debug - 1) + f'+++ Group {self.name}.match() SUCCESS')
        lexer.release_anchor()
        return tree
Exemple #2
0
    def match(self, lexer: Lexer, debug: int = 0, partial=True):
        """
        try to match lexer's current token with a production list in
        productions

        return AST instance: match SUCCESS with a production list in
        productions
        return None: match FAILED with whole productions
        """
        tree = Ast(self.name, lexer.current_position(), grammars=[])
        recursive_productions = []
        for production_list in self.productions:
            lexer.anchor()
            if debug:
                print(' ' * (
                    debug - 1) + f'### {self.name}.match() with production_list: {production_list}')
            # productions: [[G1, G2], [G3, G4], ...] <-> G1 G2 | G3 G4 | ...
            #
            # try to match all tokes with a production_list, mark the tracker
            # case 1: matched & break loop
            # case 2: unmatched, try next production_list in productions until
            # loop ends and function returns `None`
            success = self.build_ast(tree, lexer, production_list,
                                     recursive_productions,
                                     debug) if debug else self.build_ast(tree,
                                                                         lexer,
                                                                         production_list,
                                                                         recursive_productions)
            if success is True or success is None:
                # success case or Epsilon case
                if debug:
                    print(
                        ' ' * (debug - 1) + f'+++ {self.name}.match() SUCCESS')
                break
            else:
                # failed case
                continue
        else:
            if debug:
                print(' ' * (debug - 1) + f'--- {self.name}.match() FAILED')
            return None

        # one production_list is fully matched, pop anchor stack by one
        lexer.release_anchor()

        if lexer.current_token is None or tree.children or partial:
            return tree
        return None