#! /usr/bin/env python
# -*- coding: utf-8 -*-

import re

def itervars(filename, **kwargs):
    """iterates over the variables (processes, integer variables,
    clocks and channels) of the given TA filename. NOTE: EVERY VAR
    MUST BE DECLARED IN A SINGLE LINE, OTHERWISE IT WILL NOT BE
    DETECTED!

    Example usage:

    itervars(filename): gives the names of all variables
    
    itervars(filename, procs=0, clocks=0): gives the names of all
    variables but ignores processes and clocks
    """
    if not filename:
        return
    pats = {'clocks'   : r'clock',
            'chans'    : r'chan',
            'ints'     : r'int(?:\[.*\])?',
            'procs'    : r'process'}
    pat = []
    for w in pats.iterkeys():
        if w in kwargs and kwargs[w]:
                pat.append(pats[w])
        elif w not in kwargs:
            pat.append(pats[w])
    if not pat:
        return
    pat = re.compile(r"^ *(?:%s) +([^ :=;{(]+).*" % "|".join(pat))
    for line in open(filename):
        m = pat.match(line)
        if m:
            yield m.group(1)


class Pattern(object):
    """A Pattern is a set of variable names"""
    def __init__(self, filename=None, pattern=None, **kwargs):
        self.pattern = set()
        if filename:
            self.pattern = self.pattern.union(set(itervars(filename, **kwargs)))
        if pattern:
            self.pattern = self.pattern.union(set(pattern))
    def __ne__(self, p):
        return self.pattern != p.pattern
    def __gt__(self, p):
        return self.pattern.issuperset(p.pattern)
    def __eq__(self, p):
        return not self != p
    def __ge__(self, p):
        return self > p or self == p
    def __le__(self, p):
        return not p > self
    def __lt__(self, p):
        return not p >= self
    def __iter__(self):
        return iter(self.pattern)
    def __add__(self, pat):
        return Pattern(pattern=self.pattern.union(pat.pattern))
    def __sub__(self, pat):
        result = self.copy()
        if type(pat) == str:
            result.pattern.discard(pat)
        else:
            for e in pat:
                result.pattern.discard(e)
        return result
    def __len__(self):
        return len(self.pattern)
    def __str__(self):
        res = list(self.pattern)
        res.sort()
        return " ".join(res)
    def copy(self):
        return Pattern(pattern=self.pattern)


def toPattern(lst):
    pattern = set()
    for var in lst:
        pattern.add(var)
    return Pattern(pattern=pattern)
