import sys, re
from UserList import UserList

### The BisonGen parser definition

class Parser(UserList):
    def __init__(self, data=None):
        UserList.__init__(self, data)
        self.last_modified = -1
        self.name = ''
        self.project = ''
        self.options = {}
        self.imports = []
        self.tokens = []
        self.grammar = None
        self.lexer = None
        return

### The grammar specification

class Grammar:
    def __init__(self, start, rules):
        self.start = start
        self.rules = rules
        return

class Rule:
    """
    A bison rule consisting of a LHS symbol and a list of RHS symbols.
    """
    def __init__(self, lineno, filename, lhs=None, rhs=None):
        self.lineno = lineno
        self.filename = filename
        # 'error' is a predefined bison token
        self.lhs = lhs or 'error'
        self.rhs = rhs or []
        self.action = {}
        return

### The lexical specification

class Lexer:
    def __init__(self, defines, states, patterns):
        self.defines = defines
        self.states = states
        self.patterns = patterns

        # Merge the unscoped patterns into the inclusive scopes.
        for scope, pattern_list in self.patterns.items():
            # Add the unscoped patterns if this is an inclusive scope
            exclusive, number = states[scope]
            if not exclusive:
                pattern_list.extend(self.patterns['INITIAL'])
        return
    
class Defines:
    def __init__(self):
        self.defines = {}
        return

    def __str__(self):
        return str(self.defines)

    def __repr__(self):
        return repr(self.defines)

    def __getitem__(self, key):
        return self.defines[key]

    def __setitem__(self, key, value):
        self.defines[key] = value

    def __len__(self):
        return len(self.defines)

    def items(self):
        return self.defines.items()


    definePattern = re.compile('\{([a-zA-Z_][\w_-]*)\}')
    def expand(self, expression):
        match = self.definePattern.search(expression)
        while match:
            e = expression[:match.start()]
            define = self.defines.get(match.group(1), '')
            expression = '%s%s%s' % (expression[:match.start()],
                                     define,
                                     expression[match.end():],
                                     )
            match = self.definePattern.search(expression)
        return expression

    def addDefine(self, name, expression):
        self.defines[name] = expression
        return

    def merge(self, other):
        self.defines.update(other.defines)
        return
    
class States:
    def __init__(self):
        self.states = {}
        return

    def addState(self, type, decl):
        if type == 'exclusive':
            flag = 1
        elif type == 'inclusive':
            flag = 0
        else:
            # unknown, return failure
            return 1

        # a valid type, now verify decl
        if self.states.has_key(decl):
            # give warning and continue on
            sys.stderr.write('start condition %s declared twice\n' % decl)
        self.states[decl] = (flag, len(self.states)+1)
        return 0

    def merge(self, other):
        for (decl, flag) in other.items():
            if self.states.has_key(decl):
                # give warning and continue on
                sys.stderr.write('start condition %s declared twice\n' % decl)
            self.states[decl] = (flag, len(self.states)+1)
        return

    def __str__(self):
        return str(self.states)

    def __repr__(self):
        return repr(self.states)

    def __getitem__(self, key):
        return self.states[key]

    def __len__(self):
        return len(self.states)

    def items(self):
        return self.states.items()

class Pattern:
    def __init__(self, lineno, filename, expression):
        self.lineno = lineno
        self.filename = filename
        self.expression = expression
        self.begin = None
        self.token = None
        self.value = None
        self.action = {}
        return
