
; Version: "2 Buchstaben vor Alpha - 1, 2023" Punkt 2

#include <Array.au3>

Global Const $DEBUG_ME = False

; [DONE] Array Return
; Func a()
; Return [1, 2]
; EndFunc

; [DONE] Define (zunächst ohne Variablen)
; #define MYVALUE 1 -> wird überall durch diesen Wert ersetzt. Egal was dahintersteht es wird 1:1 übernommen.
; Nicht full recursive -> man kann keine defines in defines verschachteln und erwarten dass es klappt.

; [DONE] Implicit Map definition
; Global $m['key1', 'key2', ...] = [1, 2, ...] -> das ist gut!

; [DONE] Implicit Map version 2
; Global $m['key1', ...] (ohne weiteres) -> Setzt jeden Key auf 1.

; [DONE] Forced Newline Keyword/Symbol/etc. -> Backslash Operator -> '\' bewirkt newline.
; -> Funktioniert aber nur in #defines, da AutoIt crasht sobald ein \ im richtigen Code vorkommt.

; [DONE] One Line Functions
; Global Add($a, $b) Return $a + $b


; [TODO] #cs und #ce


; [TODO] #UnDefine und #UnDefineAll -> Wenn man z.B. #define nur in einem gewissen Bereich verwenden möchte ohne sämtlichen Code außerhalb zu zerfetzen.

; [TODO] Generatives #define (ersetzt Templates/Overloading)

; [TODO] Map initializer list linebreak
; $a[1, _
; 2, 3] = [3, _
; 2, 1]
; Sollte gehen.

; [TODO] Function Overloading
; Func myFunc($a) Return $a
; Func myFunc($a, $b) Return $a + $b
; -> erstellt intern myFunc1 und myFunc2 und wählt beim Call entsprechend die richtige aus.

; [TODO] Inline (kein Byref support) -> ggf doch nicht so sinnvoll.
; Inline add($x, $y)
;   Local $q = $x * $y
; 	Return ($x + $y) * $q
; EndInline
;
; Die Funktion wird geinlined.
; z.B.
; $a = add($value1, $value2)
; wird zu:
; Local $q = $value1 * $value2
; $a = ($value1 + $value2) * $q
; -> Wird über #define(mit parametern) gemacht, aber nicht als eigenes Keyword.

; [TODO] Defer
; Local $hGFX = _GDIPlus_GraphicsCreate()
; Defer _GDIPlus_GraphicsDispose($hGFX) -> wird aufgerufen, sobald das aktuelle Scope Endet.



; [TODO] Namespaces ?
; Wäre praktisch, aber ich weiß nicht wie man das syntaktisch gut macht...





Global Enum $TYPE_NONE, $TYPE_STRING, $TYPE_COMMENTSTART, $TYPE_KEYWORD, $TYPE_PREPROCESSOR, $TYPE_UTILITYPREPROCESSOR, $TYPE_SPECIALPREPROCESSOR, _
	$TYPE_AUTOITPLUSPREPROCESSOR, $TYPE_AUTOITPLUSOPERATOR, _
	$TYPE_MACRO, $TYPE_OPERATOR, $TYPE_FUNCTION, $TYPE_VARIABLE, $TYPE_NUMBER, $TYPE_USERFUNCTION, $TYPE_INCLUDEFILE, $TYPE_EMPTY, $TYPE_NEWLINE

__AutoItPlus_Main()

Func __AutoItPlus_Main()
	If @ScriptName = 'AutoItPlus.au3' Then Exit ; We do not run ourselves... or should we.
	Local $Script[]
	__AutoItPlus_LoadFile($Script) ; Load the File this include is used in.
	__AutoItPlus_RemoveMyself($Script) ; WICHTIG! Sonst spamt man den PC mit unendlich vielen Skripten voll.
	__AutoItPlus_RemoveWhitespace($Script)
	__AutoItPlus_Tokenize($Script)
;~ 	If $DEBUG_ME Then __AutoItPlus_TokenizeDebug($Script)
	__AutoItPlus_RemoveComments($Script)
	If $DEBUG_ME Then __AutoItPlus_TokenizeDebug($Script)
;~ 	__MAP_SetKeyDistance($Script, 10)
;~ 	_MapDisplay($Script)
	__AutoItPlus_Process($Script)
;~ 	_MapDisplay($Script)

	__AutoItPlus_Detokenize($Script)
;~ 	_MapDisplay($Script)
	__AutoItPlus_Run($Script)
EndFunc

Func __AutoItPlus_Tokenize(ByRef $Script)
	Local $aLines = __MAP_SortedKeys($Script)
	For $i = 0 To UBound($aLines) - 1 Step 1
		___AutoItPlus_Tokenize($Script[$aLines[$i]])
	Next
EndFunc

Func ___AutoItPlus_TokenizeRemoveStrings(ByRef $sLine)
	; Ersetze alle Strings durch '%ZAHL%' und gib ein Array mit den Strings zurück.
	Local $aChar = StringSplit($sLine, '', 2), $bInside = False, $Strings[], $iStringIndex = 0, $sStartChar = '', $bStringFinished = False, $sNewLine = ''
	For $i = 0 To UBound($aChar) - 1 Step 1
		$bStringFinished = False
		If $aChar[$i] = "'" And ($sStartChar = '' Or $sStartChar = "'") Then
			If Not $bInside Then
				$bInside = True
				$sStartChar = "'"
			Else
				$bInside = False
				$sNewLine &= '%'
				$iStringIndex += 1
				$bStringFinished = True
				$sStartChar = ''
			EndIf
		ElseIf $aChar[$i] = '"' And ($sStartChar = '' Or $sStartChar = '"') Then
			If Not $bInside Then
				$bInside = True
				$sStartChar = '"'
			Else
				$bInside = False
				$sNewLine &= '%'
				$iStringIndex += 1
				$bStringFinished = True
				$sStartChar = ''
			EndIf
		EndIf
		If $bInside Or $bStringFinished Then
			$Strings[$iStringIndex - ($bStringFinished ? 1 : 0)] &= $aChar[$i]
		Else
			$sNewLine &= $aChar[$i]
		EndIf
	Next
	$sLine = $sNewLine
	Return $Strings
EndFunc

Func ___AutoItPlus_TokenizeEnsureSpaces(ByRef $sLine)
	; Wo müssen überall Leerzeichen sein? -> zwischen allen tokens, damit sie via StringSplit getrennt werden können.
	Local Static $aOp = ['+', '-', '*', '/', '(', ')', '[', ']', '&', '%', '?', ':', '<', '>', ',', '=', '.', ';']

	; Einfach: Operatoren
	For $i = 0 To UBound($aOp) - 1 Step 1
		$sLine = StringReplace($sLine, $aOp[$i], ' ' & $aOp[$i] & ' ', 0, 1) ; Auch mehre Spaces einfügen ist erstmal egal.
	Next
	$sLine = StringStripWS($sLine, 1 + 2 + 4) ; Links, rechts und doppelte killen.

EndFunc

Func ___AutoItPlus_Token($s, $bIsString = False)
	Local $_[]
	$_.Raw = $s
	$_.Type = $bIsString ? $TYPE_STRING : StringGetType($s)
	Return $_
EndFunc

Func ___AutoItPlus_TokenNewLine()
	Local $_[]
	$_.Raw = ''
	$_.Type = $TYPE_NEWLINE
	Return $_
EndFunc

Func ___AutoItPlus_Tokenize(ByRef $sLine)
	Local $Line[]

	; 1. Herausnehmen von Strings (ersetzen durch "%0000%" für den ersten String)
	Local $Strings = ___AutoItPlus_TokenizeRemoveStrings($sLine), $n = 0

	; 2. Leerzeichen überall ergänzen wo Operatoren sind
	___AutoItPlus_TokenizeEnsureSpaces($sLine)

	; 3. Trennung via Leerzeichen -> Ist jetzt einfach machbar, weil nichts mehr dazwischenfunkt.
	Local $aLine = StringSplit($sLine, ' ', 2)

	; 4. Handle Strings seperately
	For $i = 0 To UBound($aLine) - 1 Step 1
		If $aLine[$i] = '%' Then
			$Line[$i] = ___AutoItPlus_Token($Strings[$n], True)
			$n += 1
		Else
			$Line[$i] = ___AutoItPlus_Token($aLine[$i], False)
		EndIf
	Next

	; 5. Bitshift (not usable yet)
	If LineContainsSequence($Line, ___Array('<', '<')) Then
		Local $i = @extended
		$Line[$i]['Raw'] &= $Line[$i+1]['Raw']
		$Line[$i+1]['Raw'] = ''
		$Line[$i+1]['Type'] = $TYPE_EMPTY
	EndIf
	If LineContainsSequence($Line, ___Array('>', '>')) Then
		Local $i = @extended
		$Line[$i]['Raw'] &= $Line[$i+1]['Raw']
		$Line[$i+1]['Raw'] = ''
		$Line[$i+1]['Type'] = $TYPE_EMPTY
	EndIf

	___AutoItPlus_LineRemoveEmpty($Line)

	$sLine = $Line
	Return $Strings
EndFunc

Func LineContainsSequence(ByRef $Line, $aRaw) ; Aktuell nur für aRaw ubound 2 implementiert. VORSICHT.
	Local $bMatch
	For $i = 0 To UBound($Line) - 2 Step 1
		$bMatch = True
		For $j = 0 To UBound($aRaw) - 1 Step 1
			If $Line[$i + $j].Raw <> $aRaw[$j] Then $bMatch = false
		Next
		If $bMatch Then Return SetExtended($i, True)
	Next
	Return False
EndFunc

Func LineContains(ByRef $Line, $raw)
	Local $RawOrType = 'Raw'
	If IsInt($raw) Then $RawOrType = 'Type'
	For $i = 0 To UBound($Line) - 1 Step 1
		If $Line[$i][$RawOrType] == $raw Then Return True
	Next
	Return False
EndFunc

Func __AutoItPlus_Process(ByRef $Script)
	Local $aLines = __MAP_SortedKeys($Script), $Define[], $Insertions = 0
	For $i = 0 To UBound($aLines) - 1 Step 1
		___AutoItPlus_GetDefines($Script[$aLines[$i]], $Define)
	Next
	Local $aLines = __MAP_SortedKeys($Script)

;~ 	___Script_RearrangeLines($Script)

;~ 	_ArrayDisplay($aLines, UBound($Script))
;~ 	_MapDisplay($Define)

;~ 	ConsoleWrite(@CRLF)
	For $i = 0 To UBound($aLines) - 1 Step 1

;~ 		ConsoleWriteLine($Script[$aLines[$i]])

		$Insertions += ___AutoItPlus_InsertDefines($Script[$aLines[$i]], $Define)
	Next

	For $ii = 0 To 9 Step 1 ; 9 ist hier ein failsave... wenn es mehr als 9 aufeinander aufbauende änderungen gibt hat man ein Problem.
		Local $aLines = __MAP_SortedKeys($Script), $bChange = 0
		For $i = 0 To UBound($aLines) - 1 Step 1
			If ___AutoItPlus_Process($Script[$aLines[$i]]) Then $bChange += 1
		Next
		___Script_RearrangeLines($Script)
;~ 		ConsoleWrite('['&$ii&']' & 'numChanges: ' & $bChange & @CRLF)
		If Not $bChange Then ExitLoop
	Next

EndFunc

Func ___AutoItPlus_InsertDefines(ByRef $Line, ByRef $Define, $insertions = 0)
	Local $Keys = MapKeys($Define)
;~ 	_MapDisplay($Define)
	For $d = 0 To UBound($Keys) - 1 Step 1
		For $i = 0 To UBound($Line) - 1 Step 1
;~ 			ConsoleWrite('['&$i&']' & VarGetType($Line[$i]) & ' ' & ($Line[$i] = Null) & @CRLF)
			If $Line[$i].Raw == $Keys[$d] Then ; case sensitive
;~ 				ConsoleWrite('Replace: ' & $Line[$i].Raw & ' -> ' & $Define[$Keys[$d]].Raw & @CRLF)
				MapInsert($Line, $i, $Define[$Keys[$d]])
				Return ___AutoItPlus_InsertDefines($Line, $Define, $insertions + 1) ; rekursiv da sich die indices verschieben können.
			EndIf
		Next
	Next
	Return $insertions
EndFunc

Func MapInsert(ByRef $Map, $at, $OtherMap)
	Local $Copy[], $n = 0
	For $i = 0 To UBound($Map) - 1 Step 1
		If $i = $at Then
			For $j = 0 To UBound($OtherMap) - 1 Step 1
				$Copy[$n] = $OtherMap[$j]
				$n += 1
			Next
		Else
			$Copy[$n] = $Map[$i]
			$n += 1
		EndIf
	Next
	$Map = $copy
EndFunc

Func ___AutoItPlus_GetDefines(ByRef $Line, ByRef $Define)

	If LineLeftType($Line) = $TYPE_AUTOITPLUSPREPROCESSOR Then
		Switch LineLeft($Line)
			Case '#define'
				$Define[$Line[1].Raw] = LineTrim($Line, 2)
				If LineContains($Define[$Line[1].Raw], $Line[1].Raw) Then
					ConsoleWrite('!ERROR: #Define cannot conatin itself: ' & $Line[1].Raw & @CRLF)
					Exit
				EndIf
			Case '#enum'
				Local $Split = LineSplit(LineTrim($Line, 1), ',')
				For $i = 0 To UBound($Split) - 1 Step 1
					$Define[$Split[$i][0].Raw] = ___Map(___AutoItPlus_Token($i, False))
				Next
		EndSwitch

		; TODO eleganterer Weg um Line zu löschen.
		For $i = 0 To UBound($Line) - 1 Step 1
			$Line[$i]['Type'] = $TYPE_EMPTY
		Next
		___AutoItPlus_LineRemoveEmpty($Line)
	EndIf

EndFunc

Func ___Map($a)
	Local $_[]
	MapAppend($_, $a)
	Return $_
EndFunc

Func ___AutoItPlus_Process(ByRef $Line)

	Local $bChange = False

	; Newline
	For $i = 0 To UBound($Line) - 1 Step 1
		If $Line[$i].Type = $TYPE_AUTOITPLUSOPERATOR And $Line[$i].Raw = '\' Then
			$Line[$i] = ___AutoItPlus_TokenNewLine()
			$bChange = True
		EndIf
	Next
;~ 	Local $aSubLines = LineSplit($Line, $TYPE_NEWLINE)

;~ 	For $_i = 0 To UBound($aSubLines) - 1 Step 1
;~ 		$Line = $aSubLines[$_i]


	; TYPE_INCLUDEFILE -> Kann #Include<bla.au3> sein, oder #Include "bla.au3"
	; Pattern 1: {Preprocessor = #Include}, {String}
	If UBound($Line) > 0 And $Line[0].Raw = '#include' Then
		If LineMatchLeft($Line, ___Array($TYPE_PREPROCESSOR, $TYPE_STRING)) Then
			$Line[1]['Type'] = $TYPE_INCLUDEFILE
			$bChange = True

		ElseIf LineMatchLeft($Line, ___Array($TYPE_PREPROCESSOR, $TYPE_OPERATOR, $TYPE_USERFUNCTION, $TYPE_OPERATOR, $TYPE_USERFUNCTION, $TYPE_OPERATOR)) Then
			$Line[2]['Raw'] = $Line[1]['Raw'] & $Line[2]['Raw'] & $Line[3]['Raw'] & $Line[4]['Raw'] & $Line[5]['Raw']
			$Line[1]['Type'] = $TYPE_EMPTY
			$Line[2]['Type'] = $TYPE_INCLUDEFILE
			$Line[3]['Type'] = $TYPE_EMPTY
			$Line[4]['Type'] = $TYPE_EMPTY
			$Line[5]['Type'] = $TYPE_EMPTY
			___AutoItPlus_LineRemoveEmpty($Line)
			$bChange = True
		Else
			ConsoleWrite('! ERROR: Unknown Include Format: {')
			For $i = 0 To UBound($Line) - 1 Step 1
				ConsoleWrite($Line[$i].Raw)
			Next
			ConsoleWrite('}' & @CRLF)
		EndIf
	EndIf

	; Return []
	If UBound($Line) > 0 And $Line[0].Raw = 'return' Then
		If LineMid($Line, 1) = '[' And LineRight($Line) = ']' Then
			Local $Copy[]
			$Copy[0] = ___AutoItPlus_Token('Local', False)
			$Copy[1] = ___AutoItPlus_Token('$___tmp', False)
			$Copy[2] = ___AutoItPlus_Token('=', False)
			For $i = 1 To UBound($Line) - 1 Step 1
				$Copy[$i + 2] = $Line[$i]
			Next
			$Copy[$i + 2] = ___AutoItPlus_TokenNewLine()
			$Copy[$i + 3] = ___AutoItPlus_Token('Return', False)
			$Copy[$i + 4] = ___AutoItPlus_Token('$___tmp', False)
			$Line = $Copy
			$bChange = True
		EndIf
	EndIf

	; Global/Local $var[list] = [list] -> Das wird nur sehr rudimentär funktionieren.
	Switch LineLeft($Line)
		Case 'Local', 'Global', 'Dim'
			Switch LineMidType($Line, 1)
				Case $TYPE_VARIABLE
					Switch LineMid($Line, 2) ; $map[1, 2, 3] = [1, 2, 3]
						Case '['
							Local $initializerListEnd = ForwardMatchInitializerListEnd($Line, 3, ']', ',')
							If $initializerListEnd - 2 > 1 Then ; Map initializerlist
								If LineMid($Line, $initializerListEnd + 1) = '=' Then
									Local $left = LineGetLeft($Line, $initializerListEnd + 1) ; Hier auch lieber LineSplit verwenden.
									Local $right = LineGetRight($Line, $initializerListEnd - 1)
									$Line = ___AutoItPlus_MapInitializer($left, $right)
									$bChange = True
								Else
									Local $left = LineGetLeft($Line, $initializerListEnd + 1) ; Hier auch lieber LineSplit verwenden.
									$Line = ___AutoItPlus_MapInitializer($left)
									$bChange = True
;~ 									ConsoleWrite(@CRLF & 'initializereListEnd: ' & $initializerListEnd & @CRLF)
;~ 									ConsoleWriteLine($Line)
								EndIf
							EndIf
					EndSwitch
				Case $TYPE_USERFUNCTION ; Global UserFunction
					Switch LineMid($Line, 2)
						Case '('
							Local $initializerListEnd = ForwardMatchInitializerListEnd($Line, 3, ')', ',')
							If LineMid($Line, $initializerListEnd + 1) = 'Return' Then
								Local $Split = LineSplit($Line, 'Return')
								$Line = ___AutoItPlus_OneLineGlobalFunction($Split[0], $Split[1])
								$bChange = True
							EndIf
					EndSwitch

			EndSwitch
	EndSwitch
;~ 	$aSubLines[$_i] = $Line
;~ 	Next

;~ 	$Line = LineMerge($aSubLines)

	Return $bChange

EndFunc

Func LineMerge($aSubLines)
	Local $Line[], $subline[]
	For $i = 0 To UBound($aSubLines) - 1 Step 1
		$subline = $aSubLines[$i]
		For $j = 0 To UBound($subline) - 1 Step 1
			MapAppend($Line, $subline[$j])
		Next
		If $i < UBound($aSubLines) - 1 Then MapAppend($Line, ___AutoItPlus_TokenNewLine())
	Next
	Return $Line
EndFunc


Func ___AutoItPlus_OneLineGlobalFunction($left, $right)

	; Global Add($a, $b) Return $a + $b

	Local $NewLine[]
	MapAppend($NewLine, ___AutoItPlus_Token('Func', False))

	Local $trimLeft = LineTrim($left, 1)
	For $i = 0 To UBound($trimLeft) - 1 Step 1
		MapAppend($NewLine, $trimLeft[$i])
	Next
	MapAppend($NewLine, ___AutoItPlus_TokenNewLine())
	MapAppend($NewLine, ___AutoItPlus_Token('Return', False))
	For $i = 0 To UBound($right) - 1 Step 1
		MapAppend($NewLine, $right[$i])
	Next
	MapAppend($NewLine, ___AutoItPlus_TokenNewLine())
	MapAppend($NewLine, ___AutoItPlus_Token('EndFunc', False))

	Return $NewLine

EndFunc

Func ___AutoItPlus_MapInitializer($left, $right = Default)

	Local $varName = $left[1]

	Local $NewLine[]
	MapAppend($NewLine, $left[0])
	MapAppend($NewLine, $left[1])
	MapAppend($NewLine, ___AutoItPlus_Token('[', False))
	MapAppend($NewLine, ___AutoItPlus_Token(']', False))
	MapAppend($NewLine, ___AutoItPlus_TokenNewLine())

	$left = LineTrim($left, 3, 1)
	Local $SplitLeft = LineSplit($left, ',')
	Local $SplitRight

	If $right = Default Then
		Local $_[]
		For $i = 0 To UBound($SplitLeft) - 1 Step 1
			$_[$i] = ___Map(___AutoItPlus_Token('""', True))
		Next
		$SplitRight = $_
	Else
		$right = LineTrim($right, 1, 1)
		$SplitRight = LineSplit($right, ',')
	EndIf

	If UBound($SplitLeft) <> UBound($SplitRight) Then
		ConsoleWrite('!Error: Initializerlist left size = ' & UBound($SplitLeft) & ' right size = ' & UBound($SplitRight) & @CRLF)
	EndIf

	For $i = 0 To UBound($SplitLeft) - 1 Step 1
		MapAppend($NewLine, $varName)
		MapAppend($NewLine, ___AutoItPlus_Token('[', False))
		MapAppendLine($NewLine, $SplitLeft[$i])
		MapAppend($NewLine, ___AutoItPlus_Token(']', False))
		MapAppend($NewLine, ___AutoItPlus_Token('=', False))
		MapAppendLine($NewLine, $SplitRight[$i])
		If $i < UBound($SplitLeft) - 1 Then MapAppend($NewLine, ___AutoItPlus_TokenNewLine())
	Next

	Return $NewLine

EndFunc

Func LineTrim($Line, $iLeft = 0, $iRight = 0)
	Local $Copy[]
	For $i = $iLeft To UBound($Line) - $iRight - 1 Step 1
		$Copy[$i - $iLeft] = $Line[$i]
	Next
	Return $Copy
EndFunc

Func LineSplit(ByRef $Line, $sDelimiter = ',')
	Local $Split[], $n = 0, $Map[], $RawOrType = 'Raw'
	If IsInt($sDelimiter) Then $RawOrType = 'Type'
	For $i = 0 To UBound($Line) - 1 Step 1
		If $Line[$i][$RawOrType] = $sDelimiter Then
			$n += 1
			ContinueLoop
		EndIf
		If Not IsMap($Split[$n]) Then $Split[$n] = $Map
		MapAppend($Split[$n], $Line[$i])
	Next
	Return $Split
EndFunc


Func LineGetLeft(ByRef $Line, $iLen)
	Local $copy[]
	For $i = 0 To $iLen - 1 Step 1
		$copy[$i] = $Line[$i]
	Next
	Return $copy
EndFunc

Func LineGetRight(ByRef $Line, $iLen)
	Local $copy[], $n = 0
	For $i = UBound($Line) - $iLen To UBound($Line) - 1 Step 1
		$copy[$n] = $Line[$i]
		$n += 1
	Next
	Return $copy
EndFunc

Func ForwardMatchInitializerListEnd(ByRef $Line, $iStart, $sEndSymbol = ']', $sSeperator = ',') ; TODO -> Startsymbol damit depth auch funktioniert !
	Local $depth = 1 ; [ ist am Anfang da. Erlaubt sind nur String/Num und dann Kommata und schießlich ein ]
;~ 	ConsoleWrite(@CRLF & 'InitializerListMatching: ' & @CRLF)
	For $i = $iStart To UBound($Line) - 1 Step 1
		Switch LineMidType($Line, $i)
			Case $TYPE_STRING, $TYPE_NUMBER, $TYPE_VARIABLE
			Case $TYPE_OPERATOR
				Switch $Line[$i].Raw
					Case $sSeperator
					Case $sEndSymbol
						$depth -= 1
						If $depth = 0 Then Return $i
				EndSwitch
			Case Else
				ConsoleWrite('!ERROR: Initializerlist badly formatted: Type = ' & LineMidType($Line, $i) & ' ' & $TYPE_VARIABLE & @CRLF)
				Return $iStart ; Initializer List badly formatted
		EndSwitch
;~ 		ConsoleWrite('{' & $Line[$i].Raw & '}')
	Next
;~ 	ConsoleWrite(@CRLF)
	Return $iStart
EndFunc

Func LineLeft(ByRef $Line)
	If UBound($Line) = 0 Then Return ''
	Return $Line[0].Raw
EndFunc

Func LineMid(ByRef $Line, $i)
	If UBound($Line) > $i Then Return $Line[$i].Raw
	Return ''
EndFunc

Func LineRight(ByRef $Line)
	If UBound($Line) = 0 Then Return ''
	Return $Line[UBound($Line) - 1].Raw
EndFunc



Func LineLeftType(ByRef $Line)
	If UBound($Line) = 0 Then Return $TYPE_NONE
	Return $Line[0].Type
EndFunc

Func LineMidType(ByRef $Line, $i)
	If UBound($Line) > $i Then Return $Line[$i].Type
	Return $TYPE_NONE
EndFunc

Func LineRightType(ByRef $Line)
	If UBound($Line) = 0 Then Return $TYPE_NONE
	Return $Line[UBound($Line) - 1].Type
EndFunc




Func ___AutoItPlus_LineRemoveEmpty(ByRef $Line)
	Local $Copy[], $n = 0
	For $i = 0 To UBound($Line) - 1 Step 1
		If $Line[$i].Type <> $TYPE_EMPTY Then
			$Copy[$n] = $Line[$i]
			$n += 1
		EndIf
	Next
	$Line = $Copy
EndFunc

Func MapAppendLine(ByRef $Map, ByRef $Line)
	For $i = 0 To UBound($Line) - 1 Step 1
		MapAppend($Map, $Line[$i])
	Next
EndFunc

Func ConsoleWriteLine(ByRef $Line)
	For $i = 0 To UBound($Line) - 1 Step 1
		ConsoleWrite('{' & $Line[$i].Raw)
		Switch $Line[$i].Type
			Case $TYPE_FUNCTION
				ConsoleWrite(' FU')
			Case $TYPE_KEYWORD
				ConsoleWrite(' KY')
			Case $TYPE_MACRO
				ConsoleWrite(' MC')
			Case $TYPE_NUMBER
				ConsoleWrite(' NU')
			Case $TYPE_OPERATOR
				ConsoleWrite(' OP')
			Case $TYPE_AUTOITPLUSOPERATOR
				ConsoleWrite(' +OP')
			Case $TYPE_PREPROCESSOR
				ConsoleWrite(' PP')
			Case $TYPE_SPECIALPREPROCESSOR
				ConsoleWrite(' SP')
			Case $TYPE_AUTOITPLUSPREPROCESSOR
				ConsoleWrite(' +PP')
			Case $TYPE_STRING
				ConsoleWrite(' ST')
			Case $TYPE_USERFUNCTION
				ConsoleWrite(' UF')
			Case $TYPE_UTILITYPREPROCESSOR
				ConsoleWrite(' UP')
			Case $TYPE_VARIABLE
				ConsoleWrite(' VA')
			Case $TYPE_INCLUDEFILE
				ConsoleWrite(' IF')
			Case $TYPE_EMPTY
				ConsoleWrite(' EM')
			Case $TYPE_NEWLINE
				ConsoleWrite(' \n')
		EndSwitch
		ConsoleWrite('} ')
	Next
	ConsoleWrite(@CRLF)
EndFunc


Func __AutoItPlus_TokenizeDebug(ByRef $Script)
	Local $aLines = __MAP_SortedKeys($Script)
	For $i = 0 To UBound($aLines) - 1 Step 1
		ConsoleWriteLine($Script[$aLines[$i]])
	Next
	ConsoleWrite(@CRLF)
EndFunc


Func ___Array($a, $b = 0, $c = 0, $d = 0, $e = 0, $f = 0, $g = 0)
	Local $_ = [$a, $b, $c, $d, $e, $f, $g]
	ReDim $_[@NumParams]
	Return $_
EndFunc

Func LineMatchLeft(ByRef $Line, $aTypes)
	If UBound($aTypes) > UBound($Line) Then Return False
	For $i = 0 To UBound($aTypes) - 1 Step 1
		If $Line[$i].Type <> $aTypes[$i] Then Return False
	Next
	Return True
EndFunc

Func LineMatchRight(ByRef $Line, $aTypes)
	If UBound($aTypes) > UBound($Line) Then Return False
	Local $n = UBound($Line) - 1
	For $i = 0 To UBound($aTypes) - 1 Step 1
		If $Line[$n].Type <> $aTypes[$i] Then Return False
		$n -= 1
	Next
	Return True
EndFunc

Func ___AutoItPlus_Detokenize(ByRef $Line)
	Local $sLine = ''
	For $i = 0 To UBound($Line) - 1 Step 1
		If $Line[$i].Type = $TYPE_NEWLINE Then
			$sLine &= @CRLF
			ContinueLoop
		EndIf
		If $Line[$i].Raw = '_' Then $sLine &= ' '
		If $i > 0 And $Line[$i - 1].Type = $TYPE_KEYWORD Then $sLine &= ' '
		$sLine &= $Line[$i].Raw
		If $i < UBound($Line) - 1 And $Line[$i + 1].Type = $TYPE_KEYWORD Then $sLine &= ' '
	Next
	$Line = $sLine
EndFunc

Func ___Script_RearrangeLines(ByRef $Script)
	Local $NewScript[], $n = 0, $aKeys = __MAP_SortedKeys($Script)
	For $i = 0 To UBound($aKeys) - 1 Step 1
		If LineContains($Script[$aKeys[$i]], $TYPE_NEWLINE) Then
			Local $SubLines = LineSplit($Script[$aKeys[$i]], $TYPE_NEWLINE)
			For $j = 0 To UBound($SubLines) - 1 Step 1
				MapAppend($NewScript, $SubLines[$j])
			Next
		Else
			MapAppend($NewScript, $Script[$i])
		EndIf
	Next
	$Script = $NewScript
EndFunc

Func __AutoItPlus_Detokenize(ByRef $Script)
	Local $aLines = __MAP_SortedKeys($Script)
	For $i = 0 To UBound($aLines) - 1 Step 1
		If UBound($Script[$aLines[$i]]) > 0 Then ___AutoItPlus_Detokenize($Script[$aLines[$i]])
	Next
EndFunc

Func __AutoItPlus_RemovePreprocessorComments(ByRef $Script)
	Local $aKeys = __MAP_SortedKeys($Script), $Copy[], $iInsideCommentBlock = 0
	For $i = 0 To UBound($aKeys) - 1 Step 1
		Local $Line = $Script[$i]
		If LineLeftType($Line) = $TYPE_PREPROCESSOR And LineLeft($Line) = '#cs' Then $iInsideCommentBlock += 1
		If LineLeftType($Line) = $TYPE_PREPROCESSOR And LineLeft($Line) = '#ce' Then $iInsideCommentBlock -= 1
		If $iInsideCommentBlock = 0 And (Not (LineLeft($Line) = '#ce')) Then MapAppend($Copy, $Line)
	Next
	$Script = $Copy
EndFunc

Func __AutoItPlus_RemoveComments(ByRef $Script)

	; #cs und #ce
	__AutoItPlus_RemovePreprocessorComments($Script)





	Local $aLines = __MAP_SortedKeys($Script), $Copy[], $n = 0
	For $i = 0 To UBound($aLines) - 1 Step 1
		Local $Line = $Script[$aLines[$i]], $NewLine[], $k = 0
		For $j = 0 To UBound($Line) - 1 Step 1
			If $Line[$j].Type = $TYPE_COMMENTSTART Then ExitLoop
			$NewLine[$k] = $Line[$j]
			$k += 1
		Next
		If UBound($NewLine) > 0 Then
			$Copy[$n] = $NewLine
			$n += 1
		EndIf
	Next
	$Script = $Copy
EndFunc

Func __AutoItPlus_RemoveWhitespace(ByRef $Script)
	Local $aLines = __MAP_SortedKeys($Script), $Copy[], $n = 0
	For $i = 0 To UBound($aLines) - 1 Step 1
		If StringStripWS($Script[$aLines[$i]], 8) <> '' Then
			$Copy[$n] = $Script[$aLines[$i]]
			$n += 1
		EndIf
	Next
	$Script = $Copy
EndFunc

Func __AutoItPlus_RemoveMyself(ByRef $Script)
	Local $aLines = __MAP_SortedKeys($Script)
	For $i = 0 To UBound($aLines) - 1 Step 1 ; Aktueller Workaround. Ansich sollte man das lieber nicht so machen, aber erstmal geht das so.
		If StringInStr($Script[$aLines[$i]], '#include <AutoItPlus.au3>', 0, 1) Or _
		   StringInStr($Script[$aLines[$i]], '#include "AutoItPlus.au3"', 0, 1) Or _
		   StringInStr($Script[$aLines[$i]], "#include 'AutoItPlus.au3'", 0, 1) Then
			$Script[$aLines[$i]] = ''
		EndIf
		If StringInStr($Script[$aLines[$i]], 'Exit', 0, 1) Then
			$Script[$aLines[$i]] = ''
		EndIf
		If $Script[$aLines[$i]] = '#AutoIt3Wrapper_Run_Au3Check=n' Then $Script[$aLines[$i]] = '' ; Auch nicht die feine englische Art.

	Next
EndFunc

Func __AutoItPlus_SaveFile(ByRef $Script)
	Local $hFile = FileOpen(@ScriptFullPath & 'p', 2)
	FileWrite($hFile, __MAP_ToString($Script))
	FileClose($hFile)
EndFunc

Func __AutoItPlus_LoadFile(ByRef $Script)
	Local $hFile = FileOpen(@ScriptFullPath)
	__MAP_FromArray($Script, StringSplit(FileRead($hFile), @CRLF, 3))
	FileClose($hFile)
EndFunc

Func __AutoItPlus_Run(ByRef $Script)
	__AutoItPlus_SaveFile($Script)
	Sleep(100)
	If Not $DEBUG_ME Then __SendSciTE_Command("menucommand:420")
	Sleep(100)
	ConsoleWrite('>Running:(' & @AutoItVersion & '):' & @AutoItExe & ' "' & @ScriptFullPath & 'p"' & @CRLF)
	ConsoleWrite('+>Setting Hotkeys...--> Press Ctrl+Break to Stop. RESTART IS DIABLED WITH AutoIt+' & @CRLF)
	Local $pid = Run(@AutoItExe & ' "' & @ScriptFullPath & 'p"', @WorkingDir, Default, 1)
	ProcessWaitClose($pid)
	Exit
EndFunc




Func __MAP_ToString(ByRef $m)
	Local $aKeys = __MAP_SortedKeys($m), $s = ''
	For $i = 0 To UBound($aKeys) - 1 Step 1
		$s &= $m[$aKeys[$i]] & @CRLF
	Next
	Return $s
EndFunc

Func __MAP_SetKeyDistance(ByRef $m, $iKeyDistance = 10) ; Platz zwischen den Zeilen schaffen, damit man randalieren kann.
	Local $x[], $aKeys = __MAP_SortedKeys($m), $n = 1
	For $i = 0 To UBound($aKeys) - 1 Step 1
		$x[$n * $iKeyDistance] = $m[$aKeys[$i]]
		$n += 1
	Next
	$m = $x
EndFunc

Func __MAP_SortedKeys(ByRef $m)
	Local $a = MapKeys($m)
	_ArraySort($a)
	Return $a
EndFunc

Func __MAP_FromArray(ByRef $m, ByRef $a)
	For $i = 0 To UBound($a) - 1 Step 1
		$m[$i] = $a[$i]
	Next
EndFunc

Func _MapDisplay(ByRef $m)
	Local $aKeys = __MAP_SortedKeys($m), $a[UBound($aKeys)][2]
	For $i = 0 To UBound($aKeys) - 1 Step 1
		$a[$i][0] = $aKeys[$i]
		$a[$i][1] = $m[$aKeys[$i]]
	Next
	_ArrayDisplay($a)
EndFunc

Func __SendSciTE_Command($sString)
    Local $hWND = WinGetHandle("DirectorExtension")
    Local $vString = DllStructCreate('Char[' & StringLen($sString) + 1 & ']'), $vCOPYDATA = DllStructCreate('Ptr;DWord;Ptr')
    DllStructSetData($vString, 1, $sString)
    DllStructSetData($vCOPYDATA, 1, 1)
    DllStructSetData($vCOPYDATA, 2, StringLen($sString) + 1)
    DllStructSetData($vCOPYDATA, 3, DllStructGetPtr($vString))
    DllCall('user32.dll', 'None', 'SendMessage', 'HWnd', $hWND, 'Int', 74, 'HWnd', 0, 'Ptr', DllStructGetPtr($vCOPYDATA)) ; WM_COPYDATA
EndFunc


Func StringGetType($s)
	If StringIsCommentStart($s) Then Return $TYPE_COMMENTSTART
	If StringIsKeyword($s) Then Return $TYPE_KEYWORD
	If StringIsPreprocessor($s) Then Return $TYPE_PREPROCESSOR
	If StringIsUtilityPreprocessor($s) Then Return $TYPE_UTILITYPREPROCESSOR
	If StringIsSpecialPreprocessor($s) Then Return $TYPE_SPECIALPREPROCESSOR
	If StringIsAutoItPlusPreprocessor($s) Then Return $TYPE_AUTOITPLUSPREPROCESSOR
	If StringIsMacro($s) Then Return $TYPE_MACRO
	If StringIsOperator($s) Then Return $TYPE_OPERATOR
	If StringIsAutoItPlusOperator($s) Then Return $TYPE_AUTOITPLUSOPERATOR
	If StringIsFunction($s) Then Return $TYPE_FUNCTION
	If StringIsVariable($s) Then Return $TYPE_VARIABLE
	If StringIsNumber($s) Then Return $TYPE_NUMBER
	Return $TYPE_USERFUNCTION
EndFunc

Func StringIsNumber($s)
	If StringRegExp($s, '^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$') Then Return True
	If StringRegExp($s, '^[-+]?0[xX][0-9a-fA-F]+') Then Return True ; Braucht eigentlich kein plusminus da es aktuell noch keine unären operatoren gibt :)
	Return False
EndFunc

Func StringIsCommentStart($s)
	Return ($s = ';' Or $s = ';~')
EndFunc

Func StringIsVariable($s)
	Return StringLeft($s, 1) = '$'
EndFunc

Func StringIsFunction($s)
	Local Static $Functions = ___AutoItSyntax_Function()
	Return $Functions[StringLower($s)] ? True : False
EndFunc

Func StringIsOperator($s)
	Local Static $Operators = ___AutoItSyntax_Operator()
	Return $Operators[StringLower($s)] ? True : False
EndFunc

Func StringIsAutoItPlusOperator($s)
	Local Static $Operators = ___AutoItSyntax_AutoItPlusOperator()
	Return $Operators[StringLower($s)] ? True : False
EndFunc

Func StringIsKeyword($s)
	Local Static $Keywords = ___AutoItSyntax_Keywords()
	Return $Keywords[StringLower($s)] ? True : False
EndFunc

Func StringIsPreprocessor($s)
	Local Static $Preprocessor = ___AutoItSyntax_Preprocessor()
	Return $Preprocessor[StringLower($s)] ? True : False
EndFunc

Func StringIsAutoItPlusPreprocessor($s)
	Local Static $Preprocessor = ___AutoItSyntax_AutoItPlusPreprocessor()
	Return $Preprocessor[StringLower($s)] ? True : False
EndFunc

Func StringIsSpecialPreprocessor($s)
	Local Static $SpecialPreprocessor = ___AutoItSyntax_SpecialPreprocessor()
	Return $SpecialPreprocessor[StringLower($s)] ? True : False
EndFunc

Func StringIsUtilityPreprocessor($s)
	Local Static $UtilityPreprocessor = ___AutoItSyntax_UtilityPreprocessor()
	If Not StringInStr($s, '_', 0, 1) Then Return
	Local $a = StringSplit($s, '_', 2)
	Return $UtilityPreprocessor[StringLower($a[0])] ? True : False
EndFunc

Func StringIsMacro($s)
	Local Static $Macros = ___AutoItSyntax_Macros()
	Return $Macros[StringLower($s)] ? True : False
EndFunc

Func ___AutoItSyntax_Operator()
	Local $_[]
	$_['+'] = 1
	$_['-'] = 1
	$_['*'] = 1
	$_['/'] = 1
	$_['^'] = 1
	$_[','] = 1
	$_['&'] = 1
	$_['='] = 1
	$_['?'] = 1
	$_[':'] = 1
	$_['('] = 1
	$_[')'] = 1
	$_['['] = 1
	$_[']'] = 1
	$_['<'] = 1
	$_['>'] = 1
	$_['.'] = 1
	$_['_'] = 1 ; Alleinstehendes _ am Zeilenende
	Return $_
EndFunc

Func ___AutoItSyntax_AutoItPlusOperator()
	Local $_[]
	$_['\'] = 1 ; Forced Newline
	Return $_
EndFunc

Func ___AutoItSyntax_Function()
	Local $_[]
	$_['abs'] = 1
	$_['acos'] = 1
	$_['adlibregister'] = 1
	$_['adlibunregister'] = 1
	$_['asc'] = 1
	$_['ascw'] = 1
	$_['asin'] = 1
	$_['assign'] = 1
	$_['atan'] = 1
	$_['autoitsetoption'] = 1
	$_['autoitwingettitle'] = 1
	$_['autoitwinsettitle'] = 1
	$_['beep'] = 1
	$_['binary'] = 1
	$_['binarylen'] = 1
	$_['binarymid'] = 1
	$_['binarytostring'] = 1
	$_['bitand'] = 1
	$_['bitnot'] = 1
	$_['bitor'] = 1
	$_['bitrotate'] = 1
	$_['bitshift'] = 1
	$_['bitxor'] = 1
	$_['blockinput'] = 1
	$_['break'] = 1
	$_['call'] = 1
	$_['cdtray'] = 1
	$_['ceiling'] = 1
	$_['chr'] = 1
	$_['chrw'] = 1
	$_['clipget'] = 1
	$_['clipput'] = 1
	$_['consoleread'] = 1
	$_['consolewrite'] = 1
	$_['consolewriteerror'] = 1
	$_['controlclick'] = 1
	$_['controlcommand'] = 1
	$_['controldisable'] = 1
	$_['controlenable'] = 1
	$_['controlfocus'] = 1
	$_['controlgetfocus'] = 1
	$_['controlgethandle'] = 1
	$_['controlgetpos'] = 1
	$_['controlgettext'] = 1
	$_['controlhide'] = 1
	$_['controllistview'] = 1
	$_['controlmove'] = 1
	$_['controlsend'] = 1
	$_['controlsettext'] = 1
	$_['controlshow'] = 1
	$_['controltreeview'] = 1
	$_['cos'] = 1
	$_['dec'] = 1
	$_['dircopy'] = 1
	$_['dircreate'] = 1
	$_['dirgetsize'] = 1
	$_['dirmove'] = 1
	$_['dirremove'] = 1
	$_['dllcall'] = 1
	$_['dllcalladdress'] = 1
	$_['dllcallbackfree'] = 1
	$_['dllcallbackgetptr'] = 1
	$_['dllcallbackregister'] = 1
	$_['dllclose'] = 1
	$_['dllopen'] = 1
	$_['dllstructcreate'] = 1
	$_['dllstructgetdata'] = 1
	$_['dllstructgetptr'] = 1
	$_['dllstructgetsize'] = 1
	$_['dllstructsetdata'] = 1
	$_['drivegetdrive'] = 1
	$_['drivegetfilesystem'] = 1
	$_['drivegetlabel'] = 1
	$_['drivegetserial'] = 1
	$_['drivegettype'] = 1
	$_['drivemapadd'] = 1
	$_['drivemapdel'] = 1
	$_['drivemapget'] = 1
	$_['drivesetlabel'] = 1
	$_['drivespacefree'] = 1
	$_['drivespacetotal'] = 1
	$_['drivestatus'] = 1
	$_['envget'] = 1
	$_['envset'] = 1
	$_['envupdate'] = 1
	$_['eval'] = 1
	$_['execute'] = 1
	$_['exp'] = 1
	$_['filechangedir'] = 1
	$_['fileclose'] = 1
	$_['filecopy'] = 1
	$_['filecreatentfslink'] = 1
	$_['filecreateshortcut'] = 1
	$_['filedelete'] = 1
	$_['fileexists'] = 1
	$_['filefindfirstfile'] = 1
	$_['filefindnextfile'] = 1
	$_['fileflush'] = 1
	$_['filegetattrib'] = 1
	$_['filegetencoding'] = 1
	$_['filegetlongname'] = 1
	$_['filegetpos'] = 1
	$_['filegetshortcut'] = 1
	$_['filegetshortname'] = 1
	$_['filegetsize'] = 1
	$_['filegettime'] = 1
	$_['filegetversion'] = 1
	$_['fileinstall'] = 1
	$_['filemove'] = 1
	$_['fileopen'] = 1
	$_['fileopendialog'] = 1
	$_['fileread'] = 1
	$_['filereadline'] = 1
	$_['filereadtoarray'] = 1
	$_['filerecycle'] = 1
	$_['filerecycleempty'] = 1
	$_['filesavedialog'] = 1
	$_['fileselectfolder'] = 1
	$_['filesetattrib'] = 1
	$_['filesetend'] = 1
	$_['filesetpos'] = 1
	$_['filesettime'] = 1
	$_['filewrite'] = 1
	$_['filewriteline'] = 1
	$_['floor'] = 1
	$_['ftpsetproxy'] = 1
	$_['funcname'] = 1
	$_['guicreate'] = 1
	$_['guictrlcreateavi'] = 1
	$_['guictrlcreatebutton'] = 1
	$_['guictrlcreatecheckbox'] = 1
	$_['guictrlcreatecombo'] = 1
	$_['guictrlcreatecontextmenu'] = 1
	$_['guictrlcreatedate'] = 1
	$_['guictrlcreatedummy'] = 1
	$_['guictrlcreateedit'] = 1
	$_['guictrlcreategraphic'] = 1
	$_['guictrlcreategroup'] = 1
	$_['guictrlcreateicon'] = 1
	$_['guictrlcreateinput'] = 1
	$_['guictrlcreatelabel'] = 1
	$_['guictrlcreatelist'] = 1
	$_['guictrlcreatelistview'] = 1
	$_['guictrlcreatelistviewitem'] = 1
	$_['guictrlcreatemenu'] = 1
	$_['guictrlcreatemenuitem'] = 1
	$_['guictrlcreatemonthcal'] = 1
	$_['guictrlcreateobj'] = 1
	$_['guictrlcreatepic'] = 1
	$_['guictrlcreateprogress'] = 1
	$_['guictrlcreateradio'] = 1
	$_['guictrlcreateslider'] = 1
	$_['guictrlcreatetab'] = 1
	$_['guictrlcreatetabitem'] = 1
	$_['guictrlcreatetreeview'] = 1
	$_['guictrlcreatetreeviewitem'] = 1
	$_['guictrlcreateupdown'] = 1
	$_['guictrldelete'] = 1
	$_['guictrlgethandle'] = 1
	$_['guictrlgetstate'] = 1
	$_['guictrlread'] = 1
	$_['guictrlrecvmsg'] = 1
	$_['guictrlregisterlistviewsort'] = 1
	$_['guictrlsendmsg'] = 1
	$_['guictrlsendtodummy'] = 1
	$_['guictrlsetbkcolor'] = 1
	$_['guictrlsetcolor'] = 1
	$_['guictrlsetcursor'] = 1
	$_['guictrlsetdata'] = 1
	$_['guictrlsetdefbkcolor'] = 1
	$_['guictrlsetdefcolor'] = 1
	$_['guictrlsetfont'] = 1
	$_['guictrlsetgraphic'] = 1
	$_['guictrlsetimage'] = 1
	$_['guictrlsetlimit'] = 1
	$_['guictrlsetonevent'] = 1
	$_['guictrlsetpos'] = 1
	$_['guictrlsetresizing'] = 1
	$_['guictrlsetstate'] = 1
	$_['guictrlsetstyle'] = 1
	$_['guictrlsettip'] = 1
	$_['guidelete'] = 1
	$_['guigetcursorinfo'] = 1
	$_['guigetmsg'] = 1
	$_['guigetstyle'] = 1
	$_['guiregistermsg'] = 1
	$_['guisetaccelerators'] = 1
	$_['guisetbkcolor'] = 1
	$_['guisetcoord'] = 1
	$_['guisetcursor'] = 1
	$_['guisetfont'] = 1
	$_['guisethelp'] = 1
	$_['guiseticon'] = 1
	$_['guisetonevent'] = 1
	$_['guisetstate'] = 1
	$_['guisetstyle'] = 1
	$_['guistartgroup'] = 1
	$_['guiswitch'] = 1
	$_['hex'] = 1
	$_['hotkeyset'] = 1
	$_['httpsetproxy'] = 1
	$_['httpsetuseragent'] = 1
	$_['hwnd'] = 1
	$_['inetclose'] = 1
	$_['inetget'] = 1
	$_['inetgetinfo'] = 1
	$_['inetgetsize'] = 1
	$_['inetread'] = 1
	$_['inidelete'] = 1
	$_['iniread'] = 1
	$_['inireadsection'] = 1
	$_['inireadsectionnames'] = 1
	$_['inirenamesection'] = 1
	$_['iniwrite'] = 1
	$_['iniwritesection'] = 1
	$_['inputbox'] = 1
	$_['int'] = 1
	$_['isadmin'] = 1
	$_['isarray'] = 1
	$_['isbinary'] = 1
	$_['isbool'] = 1
	$_['isdeclared'] = 1
	$_['isdllstruct'] = 1
	$_['isfloat'] = 1
	$_['isfunc'] = 1
	$_['ishwnd'] = 1
	$_['isint'] = 1
	$_['iskeyword'] = 1
	$_['ismap'] = 1
	$_['isnumber'] = 1
	$_['isobj'] = 1
	$_['isptr'] = 1
	$_['isstring'] = 1
	$_['log'] = 1
	$_['mapappend'] = 1
	$_['mapexists'] = 1
	$_['mapkeys'] = 1
	$_['mapremove'] = 1
	$_['memgetstats'] = 1
	$_['mod'] = 1
	$_['mouseclick'] = 1
	$_['mouseclickdrag'] = 1
	$_['mousedown'] = 1
	$_['mousegetcursor'] = 1
	$_['mousegetpos'] = 1
	$_['mousemove'] = 1
	$_['mouseup'] = 1
	$_['mousewheel'] = 1
	$_['msgbox'] = 1
	$_['number'] = 1
	$_['objcreate'] = 1
	$_['objcreateinterface'] = 1
	$_['objevent'] = 1
	$_['objevent'] = 1
	$_['objget'] = 1
	$_['objname'] = 1
	$_['onautoitexitregister'] = 1
	$_['onautoitexitunregister'] = 1
	$_['opt'] = 1
	$_['ping'] = 1
	$_['pixelchecksum'] = 1
	$_['pixelgetcolor'] = 1
	$_['pixelsearch'] = 1
	$_['processclose'] = 1
	$_['processexists'] = 1
	$_['processgetstats'] = 1
	$_['processlist'] = 1
	$_['processsetpriority'] = 1
	$_['processwait'] = 1
	$_['processwaitclose'] = 1
	$_['progressoff'] = 1
	$_['progresson'] = 1
	$_['progressset'] = 1
	$_['ptr'] = 1
	$_['random'] = 1
	$_['regdelete'] = 1
	$_['regenumkey'] = 1
	$_['regenumval'] = 1
	$_['regread'] = 1
	$_['regwrite'] = 1
	$_['round'] = 1
	$_['run'] = 1
	$_['runas'] = 1
	$_['runaswait'] = 1
	$_['runwait'] = 1
	$_['send'] = 1
	$_['sendkeepactive'] = 1
	$_['seterror'] = 1
	$_['setextended'] = 1
	$_['shellexecute'] = 1
	$_['shellexecutewait'] = 1
	$_['shutdown'] = 1
	$_['sin'] = 1
	$_['sleep'] = 1
	$_['soundplay'] = 1
	$_['soundsetwavevolume'] = 1
	$_['splashimageon'] = 1
	$_['splashoff'] = 1
	$_['splashtexton'] = 1
	$_['sqrt'] = 1
	$_['srandom'] = 1
	$_['statusbargettext'] = 1
	$_['stderrread'] = 1
	$_['stdinwrite'] = 1
	$_['stdioclose'] = 1
	$_['stdoutread'] = 1
	$_['string'] = 1
	$_['stringaddcr'] = 1
	$_['stringcompare'] = 1
	$_['stringformat'] = 1
	$_['stringfromasciiarray'] = 1
	$_['stringinstr'] = 1
	$_['stringisalnum'] = 1
	$_['stringisalpha'] = 1
	$_['stringisascii'] = 1
	$_['stringisdigit'] = 1
	$_['stringisfloat'] = 1
	$_['stringisint'] = 1
	$_['stringislower'] = 1
	$_['stringisspace'] = 1
	$_['stringisupper'] = 1
	$_['stringisxdigit'] = 1
	$_['stringleft'] = 1
	$_['stringlen'] = 1
	$_['stringlower'] = 1
	$_['stringmid'] = 1
	$_['stringregexp'] = 1
	$_['stringregexpreplace'] = 1
	$_['stringreplace'] = 1
	$_['stringreverse'] = 1
	$_['stringright'] = 1
	$_['stringsplit'] = 1
	$_['stringstripcr'] = 1
	$_['stringstripws'] = 1
	$_['stringtoasciiarray'] = 1
	$_['stringtobinary'] = 1
	$_['stringtrimleft'] = 1
	$_['stringtrimright'] = 1
	$_['stringupper'] = 1
	$_['tan'] = 1
	$_['tcpaccept'] = 1
	$_['tcpclosesocket'] = 1
	$_['tcpconnect'] = 1
	$_['tcplisten'] = 1
	$_['tcpnametoip'] = 1
	$_['tcprecv'] = 1
	$_['tcpsend'] = 1
	$_['tcpshutdown'] = 1
	$_['tcpstartup'] = 1
	$_['timerdiff'] = 1
	$_['timerinit'] = 1
	$_['tooltip'] = 1
	$_['traycreateitem'] = 1
	$_['traycreatemenu'] = 1
	$_['traygetmsg'] = 1
	$_['trayitemdelete'] = 1
	$_['trayitemgethandle'] = 1
	$_['trayitemgetstate'] = 1
	$_['trayitemgettext'] = 1
	$_['trayitemsetonevent'] = 1
	$_['trayitemsetstate'] = 1
	$_['trayitemsettext'] = 1
	$_['traysetclick'] = 1
	$_['trayseticon'] = 1
	$_['traysetonevent'] = 1
	$_['traysetpauseicon'] = 1
	$_['traysetstate'] = 1
	$_['traysettooltip'] = 1
	$_['traytip'] = 1
	$_['ubound'] = 1
	$_['udpbind'] = 1
	$_['udpclosesocket'] = 1
	$_['udpopen'] = 1
	$_['udprecv'] = 1
	$_['udpsend'] = 1
	$_['udpshutdown'] = 1
	$_['udpstartup'] = 1
	$_['vargettype'] = 1
	$_['winactivate'] = 1
	$_['winactive'] = 1
	$_['winclose'] = 1
	$_['winexists'] = 1
	$_['winflash'] = 1
	$_['wingetcaretpos'] = 1
	$_['wingetclasslist'] = 1
	$_['wingetclientsize'] = 1
	$_['wingethandle'] = 1
	$_['wingetpos'] = 1
	$_['wingetprocess'] = 1
	$_['wingetstate'] = 1
	$_['wingettext'] = 1
	$_['wingettitle'] = 1
	$_['winkill'] = 1
	$_['winlist'] = 1
	$_['winmenuselectitem'] = 1
	$_['winminimizeall'] = 1
	$_['winminimizeallundo'] = 1
	$_['winmove'] = 1
	$_['winsetontop'] = 1
	$_['winsetstate'] = 1
	$_['winsettitle'] = 1
	$_['winsettrans'] = 1
	$_['winwait'] = 1
	$_['winwaitactive'] = 1
	$_['winwaitclose'] = 1
	$_['winwaitnotactive'] = 1
	Return $_
EndFunc

Func ___AutoItSyntax_Macros()
	Local $_[]
	$_['@appdatacommondir'] = 1
	$_['@appdatadir'] = 1
	$_['@autoitexe'] = 1
	$_['@autoitpid'] = 1
	$_['@autoitversion'] = 1
	$_['@autoitx64'] = 1
	$_['@com_eventobj'] = 1
	$_['@commonfilesdir'] = 1
	$_['@compiled'] = 1
	$_['@computername'] = 1
	$_['@comspec'] = 1
	$_['@cpuarch'] = 1
	$_['@cr'] = 1
	$_['@crlf'] = 1
	$_['@desktopcommondir'] = 1
	$_['@desktopdepth'] = 1
	$_['@desktopdir'] = 1
	$_['@desktopheight'] = 1
	$_['@desktoprefresh'] = 1
	$_['@desktopwidth'] = 1
	$_['@documentscommondir'] = 1
	$_['@error'] = 1
	$_['@exitcode'] = 1
	$_['@exitmethod'] = 1
	$_['@extended'] = 1
	$_['@favoritescommondir'] = 1
	$_['@favoritesdir'] = 1
	$_['@gui_ctrlhandle'] = 1
	$_['@gui_ctrlid'] = 1
	$_['@gui_dragfile'] = 1
	$_['@gui_dragid'] = 1
	$_['@gui_dropid'] = 1
	$_['@gui_winhandle'] = 1
	$_['@homedrive'] = 1
	$_['@homepath'] = 1
	$_['@homeshare'] = 1
	$_['@hotkeypressed'] = 1
	$_['@hour'] = 1
	$_['@ipaddress1'] = 1
	$_['@ipaddress2'] = 1
	$_['@ipaddress3'] = 1
	$_['@ipaddress4'] = 1
	$_['@kblayout'] = 1
	$_['@lf'] = 1
	$_['@localappdatadir'] = 1
	$_['@logondnsdomain'] = 1
	$_['@logondomain'] = 1
	$_['@logonserver'] = 1
	$_['@mday'] = 1
	$_['@min'] = 1
	$_['@mon'] = 1
	$_['@msec'] = 1
	$_['@muilang'] = 1
	$_['@mydocumentsdir'] = 1
	$_['@numparams'] = 1
	$_['@osarch'] = 1
	$_['@osbuild'] = 1
	$_['@oslang'] = 1
	$_['@osservicepack'] = 1
	$_['@ostype'] = 1
	$_['@osversion'] = 1
	$_['@programfilesdir'] = 1
	$_['@programscommondir'] = 1
	$_['@programsdir'] = 1
	$_['@scriptdir'] = 1
	$_['@scriptfullpath'] = 1
	$_['@scriptlinenumber'] = 1
	$_['@scriptname'] = 1
	$_['@sec'] = 1
	$_['@startmenucommondir'] = 1
	$_['@startmenudir'] = 1
	$_['@startupcommondir'] = 1
	$_['@startupdir'] = 1
	$_['@sw_disable'] = 1
	$_['@sw_enable'] = 1
	$_['@sw_hide'] = 1
	$_['@sw_lock'] = 1
	$_['@sw_maximize'] = 1
	$_['@sw_minimize'] = 1
	$_['@sw_restore'] = 1
	$_['@sw_show'] = 1
	$_['@sw_showdefault'] = 1
	$_['@sw_showmaximized'] = 1
	$_['@sw_showminimized'] = 1
	$_['@sw_showminnoactive'] = 1
	$_['@sw_showna'] = 1
	$_['@sw_shownoactivate'] = 1
	$_['@sw_shownormal'] = 1
	$_['@sw_unlock'] = 1
	$_['@systemdir'] = 1
	$_['@tab'] = 1
	$_['@tempdir'] = 1
	$_['@tray_id'] = 1
	$_['@trayiconflashing'] = 1
	$_['@trayiconvisible'] = 1
	$_['@username'] = 1
	$_['@userprofiledir'] = 1
	$_['@wday'] = 1
	$_['@windowsdir'] = 1
	$_['@workingdir'] = 1
	$_['@yday'] = 1
	$_['@year'] = 1
	Return $_
EndFunc

Func ___AutoItSyntax_Preprocessor()
	Local $_[]
	$_['#ce'] = 1
	$_['#comments-end'] = 1
	$_['#comments-start'] = 1
	$_['#cs'] = 1
	$_['#include'] = 1
	$_['#include-once'] = 1
	$_['#notrayicon'] = 1
	$_['#onautoitstartregister'] = 1
	$_['#requireadmin'] = 1
	Return $_
EndFunc

Func ___AutoItSyntax_SpecialPreprocessor()
	Local $_[]
	$_['#endregion'] = 1
	$_['#forcedef'] = 1
	$_['#forceref'] = 1
	$_['#ignorefunc'] = 1
	$_['#pragma'] = 1
	$_['#region'] = 1
	Return $_
EndFunc

Func ___AutoItSyntax_UtilityPreprocessor()
	Local $_[]
	$_['#autoit3wrapper'] = 1
	$_['#au3stripper'] = 1
	$_['#tidy'] = 1
	Return $_
EndFunc

Func ___AutoItSyntax_AutoItPlusPreprocessor()
	Local $_[]
	$_['#define'] = 1
	$_['#enum'] = 1
	Return $_
EndFunc

Func ___AutoItSyntax_Keywords()
	Local $_[]
	$_['and'] = 1
	$_['byref'] = 1
	$_['case'] = 1
	$_['const'] = 1
	$_['continuecase'] = 1
	$_['continueloop'] = 1
	$_['default'] = 1
	$_['dim'] = 1
	$_['do'] = 1
	$_['else'] = 1
	$_['elseif'] = 1
	$_['endfunc'] = 1
	$_['endif'] = 1
	$_['endselect'] = 1
	$_['endswitch'] = 1
	$_['endwith'] = 1
	$_['enum'] = 1
	$_['exit'] = 1
	$_['exitloop'] = 1
	$_['false'] = 1
	$_['for'] = 1
	$_['func'] = 1
	$_['global'] = 1
	$_['if'] = 1
	$_['in'] = 1
	$_['local'] = 1
	$_['next'] = 1
	$_['not'] = 1
	$_['null'] = 1
	$_['or'] = 1
	$_['redim'] = 1
	$_['return'] = 1
	$_['select'] = 1
	$_['static'] = 1
	$_['step'] = 1
	$_['switch'] = 1
	$_['then'] = 1
	$_['to'] = 1
	$_['true'] = 1
	$_['until'] = 1
	$_['volatile'] = 1
	$_['wend'] = 1
	$_['while'] = 1
	$_['with '] = 1
	Return $_
EndFunc

