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

# tokens
RECURSIVE = Optional(Literal('-r '))
NON_OPT_RECURSIVE = Literal('-r ')

ID = Regex(idregex)
CLEARANCE = ID
CATEGORY = ID
USER = ID
PATH = Regex(pathregex)
COL = Literal(':')

CLEARANCELIST = delimitedList(CLEARANCE, delim='>')
CATEGORYLIST = delimitedList(CATEGORY, delim=',')
# dirty hack
OPT_CATEGORYLIST = Optional(CATEGORYLIST).setParseAction(lambda x: x if len(x) else [[None]])
USERLIST = delimitedList(USER, delim=',')


CLEARANCEDOT = CLEARANCE - Literal('.') - CLEARANCE
CLEARANCESPEC = CLEARANCEDOT ^ CLEARANCE

COMMENT = Optional(pythonStyleComment).suppress()

# -- BNFish -- #
CLEARANCEDEF = Literal('clearances:') - CLEARANCELIST + COMMENT
CATEGORYDEF = Literal('categories:') - CATEGORYLIST + COMMENT
ASSIGNMENT = Literal('assign:') - CLEARANCESPEC - COL - OPT_CATEGORYLIST - RECURSIVE - PATH + COMMENT
USERDEF = Literal('users:') - CLEARANCESPEC - COL - CATEGORYLIST - USERLIST + COMMENT
DEF = CLEARANCEDEF ^ CATEGORYDEF ^ ASSIGNMENT ^ USERDEF ^ pythonStyleComment.suppress()
MLS = OneOrMore(DEF)

CLEARANCEDEF.setParseAction(nest)
CATEGORYDEF.setParseAction(nest)
ASSIGNMENT.setParseAction(nest)
USERDEF.setParseAction(nest)

CLEARANCELIST.setParseAction(nest)
CATEGORYLIST.setParseAction(nest)
USERLIST.setParseAction(nest)
CLEARANCESPEC.setParseAction(nest)

def mlsparse(text):
    try:
        return MLS.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 = mlsparse(text)
    for stmt in result:
        print stmt

