# this characters need escaping . ^ $ * + ? { } [ ] \ | ( )
import collections
import bslint.constants as const

Regex = collections.namedtuple('Token', ['regex', 'lexer_type', 'parser_type', 'indentation'])

REGEX_LIST = [
    [r"\n", const.NEW_LINE, const.NEW_LINE, const.NO_INDENTATION],
    [r"\s", None, None, const.NO_INDENTATION],

    [r"\+=", const.OPERATOR, const.OPERATOR, const.NO_INDENTATION],
    [r"-=", const.OPERATOR, const.OPERATOR, const.NO_INDENTATION],
    [r"\*=", const.OPERATOR, const.OPERATOR, const.NO_INDENTATION],
    [r"/=", const.OPERATOR, const.OPERATOR, const.NO_INDENTATION],
    [r"\\=", const.OPERATOR, const.OPERATOR, const.NO_INDENTATION],  # divide integer
    ["<<=", const.OPERATOR, const.OPERATOR, const.NO_INDENTATION],
    [">>=", const.OPERATOR, const.OPERATOR, const.NO_INDENTATION],
    ["<>", const.OPERATOR, const.COMPARISON_OPERATOR, const.NO_INDENTATION],
    [">=", const.OPERATOR, const.COMPARISON_OPERATOR, const.NO_INDENTATION],
    ["<=", const.OPERATOR, const.COMPARISON_OPERATOR, const.NO_INDENTATION],
    [">=", const.OPERATOR, const.COMPARISON_OPERATOR, const.NO_INDENTATION],
    ["=>", const.OPERATOR, const.COMPARISON_OPERATOR, const.NO_INDENTATION],
    ["=<", const.OPERATOR, const.COMPARISON_OPERATOR, const.NO_INDENTATION],

    [r">>", const.OPERATOR, const.OPERATOR, const.NO_INDENTATION],
    [r"<<", const.OPERATOR, const.OPERATOR, const.NO_INDENTATION],

    [r";", const.SEMI_COLON, const.SEMI_COLON, const.NO_INDENTATION],
    [r"@", const.AT_SYMBOL, const.AT_SYMBOL, const.NO_INDENTATION],
    [r"#", const.HASH_SYMBOL, const.HASH_SYMBOL, const.NO_INDENTATION],
    [r"\.", const.SPECIAL_OPERATOR, const.DOT, const.NO_INDENTATION],
    [r":", const.COLON, const.COLON, const.NO_INDENTATION],
    [r"\^", const.OPERATOR, const.OPERATOR, const.NO_INDENTATION],
    [r"\&", const.OPERATOR, const.OPERATOR, const.NO_INDENTATION],
    [r"\\", const.OPERATOR, const.OPERATOR, const.NO_INDENTATION],
    [r"=", const.OPERATOR, const.EQUALS, const.NO_INDENTATION],
    [r"-", const.OPERATOR, const.MINUS, const.NO_INDENTATION],
    [r"\+", const.OPERATOR, const.PLUS, const.NO_INDENTATION],
    [r"\*", const.OPERATOR, const.OPERATOR, const.NO_INDENTATION],
    [r"/", const.OPERATOR, const.OPERATOR, const.NO_INDENTATION],
    ["<", const.OPERATOR, const.COMPARISON_OPERATOR, const.NO_INDENTATION],
    [">", const.OPERATOR, const.COMPARISON_OPERATOR, const.NO_INDENTATION],

    [r"\(", const.BRACKET, const.OPEN_PARENTHESIS, const.NO_INDENTATION],
    [r"\)", const.BRACKET, const.CLOSE_PARENTHESIS, const.NO_INDENTATION],
    [r"\[", const.SQUARE_BRACKET, const.OPEN_SQUARE_BRACKET, const.NO_INDENTATION],
    [r"\]", const.SQUARE_BRACKET, const.CLOSE_SQUARE_BRACKET, const.NO_INDENTATION],
    [r"\{", const.OPEN_CURLY_BRACKET, const.OPEN_CURLY_BRACKET, const.NO_INDENTATION],
    [r"\}", const.CLOSE_CURLY_BRACKET, const.CLOSE_CURLY_BRACKET, const.NO_INDENTATION],
    [r",", const.SPECIAL_OPERATOR, const.COMMA, const.NO_INDENTATION],
    [r"(TRUE)\b", const.KEYWORD, const.VALUE, const.NO_INDENTATION],
    [r"(GETLASTRUNCOMPILEERROR)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(GETLASTRUNRUNTIMEERROR)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(GETGLOBALAA)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(ELSE IF)\b", const.KEYWORD, const.ELSE_IF, const.SPECIAL_INDENTATION],

    [r"(END IF)\b", const.KEYWORD, const.END_IF_TOKEN, const.DECREMENT_INDENTATION],
    [r"(EXIT FOR)\b", const.KEYWORD, const.EXIT, const.DECREMENT_INDENTATION],
    [r"(FOR EACH)\b", const.KEYWORD, const.FOR_EACH, const.INCREMENT_INDENTATION],
    [r"(END FOR)\b", const.KEYWORD, const.END_FOR_TOKEN, const.DECREMENT_INDENTATION],
    [r"(END WHILE)\b", const.KEYWORD, const.END_WHILE_TOKEN, const.DECREMENT_INDENTATION],
    [r"(EXIT WHILE)\b", const.KEYWORD, const.EXIT, const.DECREMENT_INDENTATION],
    [r"(END FUNCTION)\b", const.KEYWORD, const.END_FUNCTION_TOKEN, const.DECREMENT_INDENTATION],
    [r"(END SUB)\b", const.KEYWORD, const.END_SUB_TOKEN, const.DECREMENT_INDENTATION],
    [r"(LINE_NUM)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(GOTO)\b", const.KEYWORD, const.GOTO, const.NO_INDENTATION],
    [r"(CREATEOBJECT)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(ELSEIF)\b", const.KEYWORD, const.ELSE_IF, const.SPECIAL_INDENTATION],
    [r"(ENDIF)\b", const.KEYWORD, const.END_IF_TOKEN, const.DECREMENT_INDENTATION],
    [r"(ENDFOR)\b", const.KEYWORD, const.END_FOR_TOKEN, const.DECREMENT_INDENTATION],
    [r"(ENDWHILE)\b", const.KEYWORD, const.END_WHILE_TOKEN, const.DECREMENT_INDENTATION],
    [r"(EXITWHILE)\b", const.KEYWORD, const.EXIT, const.DECREMENT_INDENTATION],
    [r"(EXITFOR)\b", const.KEYWORD, const.EXIT, const.DECREMENT_INDENTATION],
    [r"(ENDFUNCTION)\b", const.KEYWORD, const.END_FUNCTION_TOKEN, const.DECREMENT_INDENTATION],
    [r"(ENDSUB)\b", const.KEYWORD, const.END_SUB_TOKEN, const.DECREMENT_INDENTATION],
    [r"(OBJFUN)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],

    [r"(Tan)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Sqr)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Sin)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Sgn)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Log)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Int)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Fix)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Exp)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Cint)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Cdbl)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Csng)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Cos)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Atn)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Abs)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Substitute)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Tr)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Val)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Stringi)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Stri)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Str)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Right)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Len)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Left)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Instr)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Chr)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Asc)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(LCase)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Ucase)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(FormatJson)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(ParseJson)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(RunGarbageCollector)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(strtoi)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(FormatDrive)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(CreateDirectory)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(DeleteDirectory)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(DeleteFile)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(MatchFiles)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(MoveFile)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(CopyFile)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(WriteAsciiFile)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(ReadAsciiFile)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(RebootSystem)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(UpTime)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(GetInterface)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Wait)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Sleep)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Eval)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Run)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Box)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(FindMemberFunction)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Rnd)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Type)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Void)\b", const.KEYWORD, const.TYPE, const.NO_INDENTATION],
    [r"(Dynamic)\b", const.KEYWORD, const.TYPE, const.NO_INDENTATION],
    [r"(Float)\b", const.KEYWORD, const.TYPE, const.NO_INDENTATION],
    [r"(Double)\b", const.KEYWORD, const.TYPE, const.NO_INDENTATION],
    [r"(Integer)\b", const.KEYWORD, const.TYPE, const.NO_INDENTATION],
    [r"(LongInteger)\b", const.KEYWORD, const.TYPE, const.NO_INDENTATION],
    [r"(String)\b", const.KEYWORD, const.TYPE, const.NO_INDENTATION],
    [r"(Boolean)\b", const.KEYWORD, const.TYPE, const.NO_INDENTATION],
    [r"(Object)\b", const.KEYWORD, const.TYPE, const.NO_INDENTATION],
    [r"(Until)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(On)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Library)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Generates)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Implements)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Event)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(Interface)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(Component)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],

    [r"(IF)\b", const.KEYWORD, const.IF, const.INCREMENT_INDENTATION],
    [r"(THEN)\b", const.KEYWORD, const.THEN, const.INCREMENT_INDENTATION],
    [r"(ELSE)\b", const.KEYWORD, const.ELSE, const.SPECIAL_INDENTATION],
    [r"(FOR)\b", const.KEYWORD, const.FOR, const.INCREMENT_INDENTATION],
    [r"(TO)\b", const.KEYWORD, const.TO, const.NO_INDENTATION],
    [r"(STEP)\b", const.KEYWORD, const.STEP, const.NO_INDENTATION],
    [r"(INVALID)\b", const.KEYWORD, const.VALUE, const.NO_INDENTATION],
    [r"(IN)\b", const.KEYWORD, const.IN, const.NO_INDENTATION],
    [r"(WHILE)\b", const.KEYWORD, const.WHILE, const.INCREMENT_INDENTATION],
    [r"(FUNCTION)\b", const.KEYWORD, const.FUNCTION, const.INCREMENT_INDENTATION],
    [r"(AS)\b", const.KEYWORD, const.AS, const.NO_INDENTATION],
    [r"(RETURN)\b", const.KEYWORD, const.RETURN, const.NO_INDENTATION],
    [r"(PRINT)\b", const.PRINT_KEYWORD, const.PRINT_KEYWORD, const.NO_INDENTATION],
    [r"(DIM)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(END)\b", const.KEYWORD, const.END_TOKEN, const.DECREMENT_INDENTATION],
    [r"(MOD)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(STOP)\b", const.KEYWORD, const.BUILT_IN_FUNCTION, const.NO_INDENTATION],
    [r"(AND)\b", const.KEYWORD, const.AND, const.NO_INDENTATION],
    [r"(BOX)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(EACH)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(EVAL)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(EXIT)\b", const.KEYWORD, const.EXIT, const.DECREMENT_INDENTATION],
    [r"(FALSE)\b", const.KEYWORD, const.VALUE, const.NO_INDENTATION],
    [r"(LET)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(NEXT)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(NOT)\b", const.KEYWORD, const.NOT, const.NO_INDENTATION],
    [r"(OR)\b", const.KEYWORD, const.OR, const.NO_INDENTATION],
    [r"(POS)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"('|rem) *(BSLINT)_(?P<command>[a-z_]+)(:(?P<param>[0-9]+))?.*", const.BSLINT_COMMAND,
     const.BSLINT_COMMAND, const.NO_INDENTATION],
    [r"('|REM\b) *(.*)", const.COMMENT, const.COMMENT, const.NO_INDENTATION],
    [r"(RUN)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(SUB)\b", const.KEYWORD, const.SUB, const.INCREMENT_INDENTATION],
    [r"(TAB)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],
    [r"(TYPE)\b", const.KEYWORD, const.KEYWORD, const.NO_INDENTATION],

    [r"\?", const.PRINT_KEYWORD, const.PRINT_KEYWORD, const.NO_INDENTATION],

    [r"(?P<value>^[a-z_][a-z0-9_]*)(?P<type>\$|%|!|#|&?)", const.ID, const.ID,
     const.NO_INDENTATION],
    ['\"(?P<value>.*?)\"', const.STRING, const.VALUE, const.NO_INDENTATION],
    [r"^\d*(\.?\d+){1}", const.NUMERIC, const.VALUE, const.NO_INDENTATION]
]

REGEXS = []
for regex in REGEX_LIST:
    REGEXS.append(Regex._make(regex))
