# Path: pydsl/check.py
# def check(definition, data, *args, **kwargs):
#     """Checks if the input follows the definition"""
#     checker = checker_factory(definition)
#     return checker(data, *args, **kwargs)
# 
# Path: pydsl/parser/parser.py
# class TopDownParser(Parser):
#     """Top down parser like descent parser"""
#     def _reduce_terminal(self, symbol, data, showerrors = False):
#         from pydsl.check import check
#         from pydsl.tree import ParseTree
#         result = check(symbol.gd, [data])
#         if result:
#             return [ParseTree(0,1, symbol , data)]
#         if showerrors and not result:
#             return [ParseTree(0,1, symbol , data, valid = False)]
#         return []
# 
# Path: pydsl/tree.py
# class ParseTree(object):
# 
#     """Stores the position of the original tree"""
# 
#     def __init__(self, left, right, symbol, content, childlist=None, valid=True):
#         self.symbol = symbol
#         if not isinstance(left, int) and left is not None:
#             raise TypeError
#         if not isinstance(right, int) and right is not None:
#             raise TypeError
#         self.childlist = childlist or []
#         self.left = left
#         self.right = right
#         self.content = content
#         self.valid = valid
# 
#     def __eq__(self, other):
#         try:
#             return self.left == other.left and self.right == other.right and self.valid == other.valid and self.content == other.content 
#         except AttributeError:
#             return False
# 
#     def __bool__(self):
#         """checks if it is a null result"""
#         return self.valid
# 
#     def __nonzero__(self):
#         return self.__bool__()
# 
#     def shift(self, amount):
#         """ shifts position """
#         if self.left is not None:
#             self.left += amount
#         if self.left is not None:
#             self.right += amount
# 
#     def __len__(self):
#         if self.right is None and self.left is None:
#             return 0
#         return self.right - self.left
# 
#     def append(self, dpr):
#         """appends dpr to childlist"""
#         self.childlist.append(dpr)
# 
# Path: pydsl/exceptions.py
# class ParseError(Exception):
# 
#     def __init__(self, msg, offset):
#         self.msg = msg
#         self.offset = offset
# 
#     def __repr__(self):
#         return "ParseError(%r, %r)" % (self.msg, self.offset)
# 
#     def __str__(self):
#         return "%s at position %s" % (self.msg, self.offset + 1)


from pydsl.check import check
from pydsl.parser.parser import TopDownParser
from pydsl.tree import ParseTree
from pydsl.exceptions import ParseError
        from pydsl.grammar.symbol import TerminalSymbol
import logging
__email__ = "nesaro@gmail.com"
LOG = logging.getLogger(__name__)



class LL1RecursiveDescentParser(TopDownParser):
    def get_trees(self, data, showerrors = False): # -> list:
        """ returns a list of trees with valid guesses """
        if showerrors:
            raise NotImplementedError("This parser doesn't implement errors")
        self.data = data
        self.index = 0
        try:
            return [self.__aux_parser(self._productionset.initialsymbol)]
        except (IndexError, ParseError):
            return []

    def __aux_parser(self, symbol):
        if isinstance(symbol, TerminalSymbol):
            LOG.debug("matching symbol %s, data:%s, index:%s" % (symbol,self.data,self.index ))
            result= self.match(symbol)
            LOG.debug("symbol matched %s" % result)
            return result
        productions = self._productionset.getProductionsBySide(symbol)
        valid_firsts = []
        for production in productions:
            first_of_production = self._productionset.first_lookup(production.rightside[0])
            if check(first_of_production, [self.current]):
                valid_firsts.append(production)
        if len(valid_firsts) != 1:

# Path: pydsl/check.py
# def check(definition, data, *args, **kwargs):
#     """Checks if the input follows the definition"""
#     checker = checker_factory(definition)
#     return checker(data, *args, **kwargs)
# 
# Path: pydsl/parser/parser.py
# class TopDownParser(Parser):
#     """Top down parser like descent parser"""
#     def _reduce_terminal(self, symbol, data, showerrors = False):
#         from pydsl.check import check
#         from pydsl.tree import ParseTree
#         result = check(symbol.gd, [data])
#         if result:
#             return [ParseTree(0,1, symbol , data)]
#         if showerrors and not result:
#             return [ParseTree(0,1, symbol , data, valid = False)]
#         return []
# 
# Path: pydsl/tree.py
# class ParseTree(object):
# 
#     """Stores the position of the original tree"""
# 
#     def __init__(self, left, right, symbol, content, childlist=None, valid=True):
#         self.symbol = symbol
#         if not isinstance(left, int) and left is not None:
#             raise TypeError
#         if not isinstance(right, int) and right is not None:
#             raise TypeError
#         self.childlist = childlist or []
#         self.left = left
#         self.right = right
#         self.content = content
#         self.valid = valid
# 
#     def __eq__(self, other):
#         try:
#             return self.left == other.left and self.right == other.right and self.valid == other.valid and self.content == other.content 
#         except AttributeError:
#             return False
# 
#     def __bool__(self):
#         """checks if it is a null result"""
#         return self.valid
# 
#     def __nonzero__(self):
#         return self.__bool__()
# 
#     def shift(self, amount):
#         """ shifts position """
#         if self.left is not None:
#             self.left += amount
#         if self.left is not None:
#             self.right += amount
# 
#     def __len__(self):
#         if self.right is None and self.left is None:
#             return 0
#         return self.right - self.left
# 
#     def append(self, dpr):
#         """appends dpr to childlist"""
#         self.childlist.append(dpr)
# 
# Path: pydsl/exceptions.py
# class ParseError(Exception):
# 
#     def __init__(self, msg, offset):
#         self.msg = msg
#         self.offset = offset
# 
#     def __repr__(self):
#         return "ParseError(%r, %r)" % (self.msg, self.offset)
# 
#     def __str__(self):
#         return "%s at position %s" % (self.msg, self.offset + 1)


# Path: pydsl/parser/LL.py
from pydsl.check import check
from pydsl.parser.parser import TopDownParser
from pydsl.tree import ParseTree
from pydsl.exceptions import ParseError
        from pydsl.grammar.symbol import TerminalSymbol
import logging

__email__ = "nesaro@gmail.com"
LOG = logging.getLogger(__name__)



class LL1RecursiveDescentParser(TopDownParser):
    def get_trees(self, data, showerrors = False): # -> list:
        """ returns a list of trees with valid guesses """
        if showerrors:
            raise NotImplementedError("This parser doesn't implement errors")
        self.data = data
        self.index = 0
        try:
            return [self.__aux_parser(self._productionset.initialsymbol)]
        except (IndexError, ParseError):
            return []

    def __aux_parser(self, symbol):
        if isinstance(symbol, TerminalSymbol):
            LOG.debug("matching symbol %s, data:%s, index:%s" % (symbol,self.data,self.index ))
            result= self.match(symbol)
            LOG.debug("symbol matched %s" % result)
            return result
        productions = self._productionset.getProductionsBySide(symbol)
        valid_firsts = []
        for production in productions:
            first_of_production = self._productionset.first_lookup(production.rightside[0])
            if check(first_of_production, [self.current]):
                valid_firsts.append(production)
        if len(valid_firsts) != 1:

            raise ParseError("Expected only one valid production, found %s" % len(valid_firsts), 0)