# Path: pydsl/parser/parser.py
# class BottomUpParser(Parser):
#     """ leaf to root parser"""
#     def __init__(self, bnfgrammar):
#         self._lexer = lexer_factory(bnfgrammar.alphabet, ascii_encoding)
#         super().__init__(bnfgrammar)
# 
# Path: pydsl/grammar/symbol.py
# class NonTerminalSymbol(str, Symbol):
#     def __init__(self, name):
#         Symbol.__init__(self)
# 
#     def __str__(self):
#         return "<NonTS: " + self + ">"
# 
#     def __hash__(self):
#         return str.__hash__(self)
# 
#     def __eq__(self, other):
#         if not isinstance(other, NonTerminalSymbol):
#             return False
#         return str.__eq__(self,other)
# 
# class TerminalSymbol(Symbol):
# 
#     def __init__(self, gd):
#         if not isinstance(gd, Grammar):
#             raise TypeError("Expected Grammar, got %s" % (gd,))
#         Symbol.__init__(self)
#         if not gd:
#             raise Exception
#         self.gd = gd
# 
#     def __hash__(self):
#         return hash(self.gd)
# 
#     def check(self, data):# ->bool:
#         """Checks if input is recognized as this symbol"""
#         return check(self.gd, data)
# 
#     def first(self):
#         return self.gd.first
# 
#     def __eq__(self, other):
#         """StringTerminalSymbol are equals if definition and names are equal"""
#         try:
#             return self.gd == other.gd
#         except AttributeError:
#             return False
# 
#     def __str__(self):
#         return "<TS: " + str(self.gd) + ">"
# 
# class EndSymbol(Symbol):
#     _instance = None
#     def __new__(cls):
#         if cls._instance is None:
#             cls._instance = super(EndSymbol, cls).__new__(cls)
#         return cls._instance
# 
#     def __hash__(self):
#         assert(EndSymbol._instance is not None)
#         return hash(id(self._instance))
# 
#     def __eq__(self, other):
#         result = isinstance(other, EndSymbol) or EndSymbol == other
#         return result
# 
#     def __bool__(self):
#         return False
# 
#     def __str__(self):
#         return "$"
# 
# class Symbol(object):
#     pass
# 
# Path: pydsl/grammar/BNF.py
# class Production(object):
# 
#     def __init__(self, leftside, rightside):
#         # Left side must have at least one non terminal symbol
#         for element in rightside:
#             if not isinstance(element, Symbol):
#                 raise TypeError
#         self.leftside = tuple(leftside)
#         self.rightside = tuple(rightside)
# 
#     def __str__(self):
#         leftstr = " ".join([x for x in self.leftside])
#         rightstr = " ".join([str(x) for x in self.rightside])
#         return leftstr + "::=" + rightstr
# 
#     def __eq__(self, other):
#         try:
#             if len(self.leftside) != len(other.leftside):
#                 return False
#             if len(self.rightside) != len(other.rightside):
#                 return False
#             if not list_eq(self.leftside, other.leftside):
#                 return False
#             if not list_eq(self.rightside, other.rightside):
#                 return False
#         except AttributeError:
#             return False
#         return True
# 
#     def __hash__(self):
#         return hash(self.leftside) & hash(self.rightside)
# 
# Path: pydsl/grammar/definition.py
# class Grammar(object):
# 
#     def __init__(self, base_alphabet = None):
#         self.__base_alphabet = base_alphabet
# 
#     def enum(self):
#         """Generates every possible accepted string"""
#         raise NotImplementedError
# 
#     @property
#     def first(self):
#         """Alphabet that matches every possible first element.
#         the returned value is a subset of the base_alphabet"""
#         return self.alphabet
# 
#     @property
#     def minsize(self):# -> int:
#         """Returns the minimum size in alphabet tokens"""
#         return 0
# 
#     @property
#     def maxsize(self):
#         """Returns the max size in alphabet tokens"""
#         return None
# 
#     @property
#     def alphabet(self):
#         if not self.__base_alphabet:
#             raise AttributeError
#         return self.__base_alphabet


import logging
    import copy
from pydsl.parser.parser import BottomUpParser
from pydsl.grammar.symbol import NonTerminalSymbol, TerminalSymbol, EndSymbol, Symbol
from pydsl.grammar.BNF import Production
from pydsl.grammar.definition import Grammar
from collections import Iterable, defaultdict
        from pydsl.check import check
    def __eq__(self, anotherset):
        """Tests on itemlist equality"""
        if not isinstance(anotherset, LR0ItemSet):
            raise TypeError
        if len(self.itemlist) != len(anotherset.itemlist):
            return False
        for element in self.itemlist:
            if element not in anotherset.itemlist:
                return False
        return True

    def append_item(self, item):
        """Append new item to set"""
        if not isinstance(item, LR0Item):
            raise TypeError
        self.itemlist.append(item)

    def append_transition(self, symbol, targetset):
        """Appends a transition"""
        if symbol in self.transitions:
            return
        self.transitions[symbol] = targetset

    def has_transition(self, symbol):
        return symbol in self.transitions

    def get_transition(self, symbol):
        """gets a transition"""
        return self.transitions[symbol]


# Path: pydsl/parser/parser.py
# class BottomUpParser(Parser):
#     """ leaf to root parser"""
#     def __init__(self, bnfgrammar):
#         self._lexer = lexer_factory(bnfgrammar.alphabet, ascii_encoding)
#         super().__init__(bnfgrammar)
# 
# Path: pydsl/grammar/symbol.py
# class NonTerminalSymbol(str, Symbol):
#     def __init__(self, name):
#         Symbol.__init__(self)
# 
#     def __str__(self):
#         return "<NonTS: " + self + ">"
# 
#     def __hash__(self):
#         return str.__hash__(self)
# 
#     def __eq__(self, other):
#         if not isinstance(other, NonTerminalSymbol):
#             return False
#         return str.__eq__(self,other)
# 
# class TerminalSymbol(Symbol):
# 
#     def __init__(self, gd):
#         if not isinstance(gd, Grammar):
#             raise TypeError("Expected Grammar, got %s" % (gd,))
#         Symbol.__init__(self)
#         if not gd:
#             raise Exception
#         self.gd = gd
# 
#     def __hash__(self):
#         return hash(self.gd)
# 
#     def check(self, data):# ->bool:
#         """Checks if input is recognized as this symbol"""
#         return check(self.gd, data)
# 
#     def first(self):
#         return self.gd.first
# 
#     def __eq__(self, other):
#         """StringTerminalSymbol are equals if definition and names are equal"""
#         try:
#             return self.gd == other.gd
#         except AttributeError:
#             return False
# 
#     def __str__(self):
#         return "<TS: " + str(self.gd) + ">"
# 
# class EndSymbol(Symbol):
#     _instance = None
#     def __new__(cls):
#         if cls._instance is None:
#             cls._instance = super(EndSymbol, cls).__new__(cls)
#         return cls._instance
# 
#     def __hash__(self):
#         assert(EndSymbol._instance is not None)
#         return hash(id(self._instance))
# 
#     def __eq__(self, other):
#         result = isinstance(other, EndSymbol) or EndSymbol == other
#         return result
# 
#     def __bool__(self):
#         return False
# 
#     def __str__(self):
#         return "$"
# 
# class Symbol(object):
#     pass
# 
# Path: pydsl/grammar/BNF.py
# class Production(object):
# 
#     def __init__(self, leftside, rightside):
#         # Left side must have at least one non terminal symbol
#         for element in rightside:
#             if not isinstance(element, Symbol):
#                 raise TypeError
#         self.leftside = tuple(leftside)
#         self.rightside = tuple(rightside)
# 
#     def __str__(self):
#         leftstr = " ".join([x for x in self.leftside])
#         rightstr = " ".join([str(x) for x in self.rightside])
#         return leftstr + "::=" + rightstr
# 
#     def __eq__(self, other):
#         try:
#             if len(self.leftside) != len(other.leftside):
#                 return False
#             if len(self.rightside) != len(other.rightside):
#                 return False
#             if not list_eq(self.leftside, other.leftside):
#                 return False
#             if not list_eq(self.rightside, other.rightside):
#                 return False
#         except AttributeError:
#             return False
#         return True
# 
#     def __hash__(self):
#         return hash(self.leftside) & hash(self.rightside)
# 
# Path: pydsl/grammar/definition.py
# class Grammar(object):
# 
#     def __init__(self, base_alphabet = None):
#         self.__base_alphabet = base_alphabet
# 
#     def enum(self):
#         """Generates every possible accepted string"""
#         raise NotImplementedError
# 
#     @property
#     def first(self):
#         """Alphabet that matches every possible first element.
#         the returned value is a subset of the base_alphabet"""
#         return self.alphabet
# 
#     @property
#     def minsize(self):# -> int:
#         """Returns the minimum size in alphabet tokens"""
#         return 0
# 
#     @property
#     def maxsize(self):
#         """Returns the max size in alphabet tokens"""
#         return None
# 
#     @property
#     def alphabet(self):
#         if not self.__base_alphabet:
#             raise AttributeError
#         return self.__base_alphabet


# Path: pydsl/parser/LR0.py
import logging
    import copy
from pydsl.parser.parser import BottomUpParser
from pydsl.grammar.symbol import NonTerminalSymbol, TerminalSymbol, EndSymbol, Symbol
from pydsl.grammar.BNF import Production
from pydsl.grammar.definition import Grammar
from collections import Iterable, defaultdict
        from pydsl.check import check

    def __eq__(self, anotherset):
        """Tests on itemlist equality"""
        if not isinstance(anotherset, LR0ItemSet):
            raise TypeError
        if len(self.itemlist) != len(anotherset.itemlist):
            return False
        for element in self.itemlist:
            if element not in anotherset.itemlist:
                return False
        return True

    def append_item(self, item):
        """Append new item to set"""
        if not isinstance(item, LR0Item):
            raise TypeError
        self.itemlist.append(item)

    def append_transition(self, symbol, targetset):
        """Appends a transition"""
        if symbol in self.transitions:
            return
        self.transitions[symbol] = targetset

    def has_transition(self, symbol):
        return symbol in self.transitions

    def get_transition(self, symbol):
        """gets a transition"""
        return self.transitions[symbol]


class LR0Parser(BottomUpParser):