#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Jul  3 10:40:39 2020

@author: lune

[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"@$^:?`
"""

s = '''
forWord = {1234567890\\\\\x01\\t\\n;(){}[]}
forWordWithNum = | [1234567890] forWord $
T_word = forWord * forWordWithNum
d = [0987654321]
nums = d * d
float1 = [.] nums
float = | float1 empty $
expon1 = [eE] | [+-] empty $ nums
expon = | expon1 empty $
dec = nums float expon
bin = [0] [b] [01] * [01]
af = [0987654321abcdefABCDEF]
hex = [0] [x] af * af
T_number = | dec hex bin $
literal1 = [\\\\] [\\']
literal2 = | {\\'} literal1 empty $
T_literal = [\\'] * literal2 [\\']
T_skip = [\x01\\t] * [\x01\\t]
T_nln = [\\n;]
T_comment = [/] [/] * {\\n}
T_preproc = [#] * {\\n}
_T_DO = #ST
T_OPEN_S = [(]
T_CLOSE_S = [)]
T_OPEN_C = [{]
T_CLOSE_C = [}]
T_OPEN_I = [[]
T_CLOSE_I = []]
T_GET_ADDR = [&]
T_RIGHT_ARROW = [-] [>]
T_LAMBDA = [\\\\]
T_SEM = [,]
T_BOOL = | #true #false $
T_as = #as
T_is = #is
T_type = #type
T_with = #with
T_import = #import
T_binary = | #infixl #infixr $
T_inline = #inline
T_sugar = #sugar
T_adt = #adt
T_evalT = | #strict #lazy $
'''


#T_MINUS = [-]
#T_PLUS = [+]
#T_MULT = [*]
#T_DIVS = [/%]
#T_SHIFT = | #>> #<< $
#T_ORD = | #>=  #<=  [>] [<] $
#T_EQ = | [=] #!= $
#T_AND = #and
#T_XOR = #xor
#T_OR = #or
#T_NOT = #not

fout = open('myFL.py','w');

counter = 1
listOfTokens = []
def createLexer(s):
    global counter
    ss = s.split();
#    print(ss)
    if ss[0][0] == 'T':
        counter+=1;
        listOfTokens.append(ss[0])
    fout.write(ss[0]+' = serial([')
    d = 2
    while d < len(ss):
        def cast(k):
            ss[k] = ss[k].replace('\x01',' ')
            if ss[k][0] == '[':
                fout.write('sim(\''+ss[k][1:-1]+'\'),')
            elif ss[k][0] == '{':
                fout.write('sim(\''+ss[k][1:-1]+'\',1),')
            elif ss[k][0] == '#':
                fout.write('word(\''+ss[k][1:]+'\'),')
            elif ss[k][0] == '*':
                fout.write('rep(')
                a = cast(k+1)
                fout.write('),')
                return a
            elif ss[k][0] == '|':
                fout.write('mor([')
            elif ss[k][0] == '$':
                fout.write(']),')
            else:
                fout.write(ss[k]+',')
            return k+1
        d = cast(d)
    fout.write('])\n')
    pass

fout.write('''
import functools as f

def empty(i,s):
    return [i]
def sim(c,isIn=0):
    def parse(i,s):
        if i >= len(s):
            return []
        if isIn == 0:
            if s[i] in c:
                return [i+1]
            return []
        else:
            if s[i] in c:
                return []
            return [i+1]
    return parse
def app(a,b):
    def parser(i,s):
        t1 = map((lambda x:b(x,s)),a(i,s))
        t2 = f.reduce((lambda x,y:x+y),t1,[])
        return t2
    return parser

def par(a,b):
    def parser(i,s):
        t1 = a(i,s)
        t2 = b(i,s)
        return max(t1,t2)
    return parser

def rep(a):
    def parser(i,s):
        t1 = a(i,s)
        if t1 != [] and t1[0] > i:
            return parser(t1[0],s)
        return [i]
    return parser
def serial(s):
    if s == []:
        return empty
    elif len(s)==1:
        return s[0]
    else:
        return app(s[0],serial(s[1:]))

def mor(s):
    if s == []:
        return empty
    elif len(s)==1:
        return s[0]
    else:
        return par(s[0],mor(s[1:]))

def word(s):
    if s == '':
        return empty
    if len(s) == 1:
        return sim(s)
    return app(sim(s[0]),word(s[1:]))

tT_NONE = 0
''')
list(map(createLexer,
s[1:-1].split('\n')))

for i in range(len(listOfTokens)):
    fout.write('t'+listOfTokens[i] + ' = '+str(i+1)+'\n')

fout.write('lexerList = [\n')
for i in listOfTokens:
    fout.write(i+',')

fout.write(']\n')
fout.write('tokenIdList = [\n')
for i in listOfTokens:
    fout.write('t'+i+',')

fout.write(']\n')
fout.write('''
def lexem(i,s):
    a = list(map(lambda x:x(i,s),lexerList))
#    print(a)
    def getmax(s,n):
        if n == 0:
            return s
        elif a[n-1] == []:
            return getmax(s,n-1)
        else:
#            return (tokenIdList[n-1],a[n-1][0])
            if s[1] < a[n-1][0]:
#                print(s,(tokenIdList[n-1],a[n-1][0]))
                return getmax((tokenIdList[n-1],a[n-1][0]),n-1)
            return getmax(s,n-1)
    a,b = getmax((tT_NONE,0),len(tokenIdList))
    if b == 0:
        return ((tT_NONE,''),0)

    return ((a,s[i:b]),b)

def getAllTokens(s,i=0,l=1):
    a,b = lexem(i,s)
    a1 = (a[0],a[1],l)
    if a[0] == tT_NONE:
        return [a1]
    if '\\n' in a[1]:
        return [a1]+getAllTokens(s,b,l+1)
    return [a1]+getAllTokens(s,b,l)
      ''')


fout.close()