from pyparsing import *
from utils import idregex, pathregex, nest

# tokens
READ = Literal('r')
WRITE = Literal('w')
EXECUTE = Literal('x')
PERM = READ | WRITE | EXECUTE
RECURSIVE = Optional(Literal('-r '))

ID = Regex(idregex)
ROLE = ID
USER = ID
PATH = Regex(pathregex)
GT = Literal('>')

USERLIST = delimitedList(USER, delim=',')
ROLELIST = delimitedList(ROLE, delim=',')
PERMLIST = delimitedList(PERM, delim=',')

COMMENT = Optional(pythonStyleComment).suppress()

# -- BNFish -- #
USERDEF = Literal('user:') - ROLELIST - USERLIST + COMMENT
OBJECTDEF = Literal('object:') - ROLELIST - PERMLIST - RECURSIVE - PATH + COMMENT
INHERITDEF = Literal('inheritance:') - ROLE - GT - ROLELIST + COMMENT
'''mandy'''
NONEUSERDEF = Literal('free_user:') - USERLIST + COMMENT
ROLEDEF = Literal('inheritance:') - ROLE + COMMENT
PATHDEF = Literal('object:') - PATH + COMMENT
DEF = USERDEF ^ NONEUSERDEF ^ OBJECTDEF ^ INHERITDEF ^ ROLEDEF ^ PATHDEF ^ pythonStyleComment.suppress()
'''mandy'''
#DEF = USERDEF ^ OBJECTDEF ^ INHERITDEF ^ pythonStyleComment.suppress()
RBAC = OneOrMore(DEF)

# parse actions
USERDEF.setParseAction(nest)
OBJECTDEF.setParseAction(nest)
INHERITDEF.setParseAction(nest)
'''mandy'''
NONEUSERDEF.setParseAction(nest)
ROLEDEF.setParseAction(nest)
PATHDEF.setParseAction(nest)
'''mandy'''
ROLELIST.setParseAction(nest)
USERLIST.setParseAction(nest)
PERMLIST.setParseAction(nest)

def rbacparse(text):
    """Return a list of RBAC statements given a string."""
    try:
        return RBAC.parseString(text, parseAll=True)
    except (ParseException, ParseSyntaxException) as err:
        print 'ParseException:', err
        print '{0}'.format(err.line)
        print '{0}^'.format(' ' * (err.column - 1))
        raise err

if __name__ == '__main__':
    import sys
    with open(sys.argv[1], 'r') as f:
        text = f.read()
    result = rbacparse(text)
    for stmt in result:
        print stmt

