New Lexer:
; Simple Yaml Parser by HotKeyIt
; 2010, http://www.autohotkey.com/forum/viewtopic.php?t=60670
Yaml_Add(pYaml,key1="",key2=""){
If (recursive:=InStr(key1,".")=1 ? 1 : 0)
StringTrimLeft,key1,key1,1
If InStr(key1,".")
parent:=SubStr(key1,1,InStr(key1,".",1,0)-1)
StringTrimLeft,key,key1,% InStr(key1,".",1,0)
If (parent!="" && !Yaml_Exist(pYaml,key1))
Yaml_Add(pYaml,"." parent,key)
If !Yaml_Exist(pYaml,key1){
count:=Yaml_Get(pYaml,parent!="" ? (parent "." 0) : 0)
count++
Yaml_Assign(pYaml,parent!="" ? (parent "." 0) : 0,count)
Yaml_Assign(pYaml,parent!="" ? (parent "." count) : count,key)
} else if (!recursive){
count:=Yaml_Get(pYaml,key1 "." 0)
If (count=""){
count=2
Yaml_Assign(pYaml,key1 ".1",Yaml_Get(pYaml,key1))
} else
count++
Yaml_Assign(pYaml,key1 "." 0,count)
Yaml_Assign(pYaml,key1 "." count,key2)
}
key2:=(RegExMatch(Key2,"^\s?\w+\s?$") ? key2 : "'" key2 "'")
Yaml_Assign(pYaml,key1,Yaml_Get(pYaml,key1)="" ? key2 : Yaml_Get(pYaml,key1) "," key2)
}
Yaml_Exist(pYaml,Key=""){
VarSetCapacity(var,16,0),NumPut(8, var)
If A_IsUnicode
wStr:=Key
else
VarSetCapacity(wStr, StrLen(Key)*2+1,0)
,DllCall("MultiByteToWideChar", "UInt",0, "UInt",0, "UInt",&Key, "Int",-1, "UInt",&wStr, "Int",StrLen(Key)+1)
NumPut(DllCall("oleaut32\SysAllocString","Str",wStr),var,8)
DllCall(NumGet(NumGet(pYaml+0)+48), "UInt",pYaml, "UInt",&var, "IntP",bExist)
DllCall("oleaut32\SysFreeString", "UInt",NumGet(var,8)),NumPut(0,var,8)
Return bExist
}
Yaml_Dump(pYaml,ByRef Output,key=""){
If (key=""){
Loop % Yaml_Get(pYaml,0)
{
mainkey:=Yaml_Get(pYaml,A_Index)
Output .= Yaml_Get(pYaml,mainkey ".")="" ? "" : Yaml_Get(pYaml,mainkey ".") "`n" ;"---`r`n"
value:=Yaml_Get(pYaml,mainkey)
Output .= (RegExMatch(mainkey,"^\w+$") ? mainkey : ("'" mainkey "'")) ":"
if (sub:=Yaml_Get(pYaml,mainkey "." 1)){
if !Yaml_Exist(pYaml,mainkey "." sub){
Output .= "`n"
Loop % Yaml_Get(pYaml,mainkey ".0"){
value:=Yaml_Get(pYaml,mainkey "." A_Index)
Output .= " - " (RegExMatch(value,"^\w+$") ? value : "'" value "'") "`n"
}
Continue
} else Output .= "`n"
} else Output .= " " value "`n"
Yaml_Dump(pYaml,Output,"." mainkey)
}
return Output
} else {
If (-1 < (start:=RegExMatch(key,"[^\.]")-1)){
Loop % start*2
recurse .= A_Space
StringTrimLeft,_key,key,%start%
} else _key:=key
Loop % Yaml_Get(pYaml,_key "." 0){
key1:=Yaml_Get(pYaml,_key "." A_Index)
Output .= Yaml_Get(pYaml,_key "." key1 ".")="" ? "" : Yaml_Get(pYaml,_key "." key1 ".") "`n"
value:=Yaml_Get(pYaml,_key "." key1)
Output .= recurse (RegExMatch(key1,"^\w+$") ? key1 : ("'" key1 "'")) ":"
if (sub:=Yaml_Get(pYaml,_key "." key1 ".1")){
if !Yaml_Exist(pYaml,_key "." key1 "." sub){
Output .= "`n"
Loop % Yaml_Get(pYaml,_key "." key1 ".0"){
value:=Yaml_Get(pYaml,_key "." key1 "." A_Index)
Output .= recurse " - " value "`n"
}
Continue
} else Output .= "`n"
} else Output .= " " value "`n"
Yaml_Dump(pYaml,Output, "." key "." key1)
}
}
Return output
}
Yaml_Save(pYaml,ToFile=""){
Yaml_Dump(pYaml,file)
If (ToFile!="" && FileExist(ToFile)){
StringReplace,savefile,file,`n,`r`n,A
FileMove,%ToFile%,%ToFile%.bkp.yaml
If FileExist(ToFile){
MsgBox Error Saving File
}
FileAppend,%savefile%,%ToFile%
If (ErrorLevel){
MsgBox Error Saving File
}
FileDelete,%ToFile%.bkp.yaml
If (ErrorLevel){
MsgBox Error Saving File
FileDelete,%ToFile%.bkp
FileMove,%ToFile%.bkp.yaml,%ToFile%
}
} else if (ToFile!=""){
StringReplace,savefile,file,`n,`r`n,A
FileAppend,%savefile%,%ToFile%
If (ErrorLevel){
MsgBox Error Saving File
}
}
Return file
}
Yaml_Clone(pYaml){
static CLSIDString:="{EE09B103-97E0-11CF-978F-00A02463E06F}", IIDString:="{42C642C1-97E1-11CF-978F-00A02463E06F}", StrGet:="StrGet"
If (!Init && Init:=1){ ;Initialize COM and create database
DllCall("ole32\CoInitialize", "UInt",0),VarSetCapacity(var1, 16),VarSetCapacity(var2, 16)
NumPut(8, var1),NumPut(8, var2),VarSetCapacity(CLSID, 16),VarSetCapacity(wKey, 79),VarSetCapacity(IID, 16)
If A_IsUnicode
DllCall("ole32\CLSIDFromString", "Str",CLSIDString, "Str",CLSID)
,DllCall("ole32\CLSIDFromString", "Str",IIDString, "Str",IID)
else
DllCall("MultiByteToWideChar", "UInt",0, "UInt",0, "UInt",&CLSIDString, "Int",-1, "UInt",&wKey, "Int",39)
,DllCall("ole32\CLSIDFromString", "Str",wKey, "Str",CLSID)
,DllCall("MultiByteToWideChar", "UInt",0, "UInt",0, "UInt",&IIDString, "Int",-1, "UInt",&wKey, "Int",39)
,DllCall("ole32\CLSIDFromString", "Str",wKey, "Str",IID)
}
DllCall("ole32\CoCreateInstance", "Str",CLSID, "UInt",0, "UInt",5, "Str",IID, "UIntP",_pYaml) ; CLSCTX=5
,DllCall(NumGet(NumGet(_pYaml+0)+72), "UInt",_pYaml, "Int",1)
VarSetCapacity(var1, 16),VarSetCapacity(var2, 16),NumPut(8, var1),NumPut(8, var2)
DllCall(NumGet(NumGet(pYaml+0)+80), "UInt",pYaml, "UIntP",penum) ; create key-list in penum
Loop {
If (DllCall(NumGet(NumGet(penum+0)+12), "UInt",penum, "UInt",1, "UInt",&var1, "UInt",0)) {
DllCall(NumGet(NumGet(penum+0)+8), "UInt",penum) ; END: destroy key-list
penum= ; signal end of list
ErrorLevel= ; empty
Return _pYaml
}
If A_IsUnicode
wStr:=%StrGet%(NumGet(var1,8))
else
nLen := DllCall("WideCharToMultiByte", "UInt",0, "UInt",0, "UInt",NumGet(var1,8), "Int",-1, "UInt",0, "Int",0, "UInt",0, "UInt",0)
,VarSetCapacity(wKey, nLen)
,DllCall("WideCharToMultiByte", "UInt",0, "UInt",0, "UInt",NumGet(var1,8), "Int",-1, "Str",wKey, "Int",nLen, "UInt",0, "UInt",0)
DllCall("oleaut32\SysFreeString", "UInt",NumGet(var1,8)),NumPut(0,var1,8)
Yaml_Assign(_pYaml,wKey,Yaml_Get(pYaml,wKey))
}
}
Yaml_Get(pYaml,key1=""){
static StrGet:="StrGet"
VarSetCapacity(var1, 16),VarSetCapacity(var2, 16),NumPut(8, var1),NumPut(8, var2)
If A_IsUnicode
wStr:=key1
else
VarSetCapacity(wStr, StrLen(Key1)*2+1,0)
,DllCall("MultiByteToWideChar", "UInt",0, "UInt",0, "UInt",&Key1, "Int",-1, "UInt",&wStr, "Int",StrLen(Key1)+1)
NumPut(DllCall("oleaut32\SysAllocString","Str",wStr),var1,8)
DllCall(NumGet(NumGet(pYaml+0)+48), "UInt",pYaml, "UInt",&var1, "IntP",bExist)
If bExist {
DllCall(NumGet(NumGet(pYaml+0)+36), "UInt",pYaml, "UInt",&var1, "UInt",&var2)
If (NumGet(var2,8)=0xcdcdcdcd) ;uninitialized = empty string
Return
If A_IsUnicode
Key2:=%StrGet%(NumGet(var2,8))
else
nLen := DllCall("WideCharToMultiByte", "UInt",0, "UInt",0, "UInt",NumGet(var2,8), "Int",-1, "UInt",0, "Int",0, "UInt",0, "UInt",0)
,VarSetCapacity(Key2, nLen,0)
,DllCall("WideCharToMultiByte", "UInt",0, "UInt",0, "UInt",NumGet(var2,8), "Int",-1, "Str",Key2, "Int",nLen, "UInt",0, "UInt",0)
DllCall("oleaut32\SysFreeString", "UInt",NumGet(var2,8)),NumPut(0,var2,8)
}
DllCall("oleaut32\SysFreeString", "UInt",NumGet(var1,8)),NumPut(0,var1,8)
Return Key2
}
Yaml_Set(pYaml,key1="",key2=""){
If !Yaml_Exist(pYaml,key1){
Yaml_Add(pYaml,key1,key2)
return
}
Yaml_Assign(pYaml,key1,key2)
Return
}
Yaml_Assign(pYaml,key1,key2=""){
Loop % (2){
VarSetCapacity(var%A_Index%,16,0),NumPut(8,var%A_Index%)
If A_IsUnicode
wStr:=Key%A_Index%
else
VarSetCapacity(wStr, StrLen(Key%A_Index%)*2+1,0)
,DllCall("MultiByteToWideChar", "UInt",0, "UInt",0, "UInt",&Key%A_Index%, "Int",-1, "UInt",&wStr, "Int",StrLen(Key%A_Index%)+1)
NumPut(DllCall("oleaut32\SysAllocString","Str",wStr),var%A_Index%,8)
}
DllCall(NumGet(NumGet(pYaml+0)+32), "UInt",pYaml, "UInt",&var1, "UInt",&var2) ; 8 (Set0 -> 7)
Loop 2
DllCall("oleaut32\SysFreeString", "UInt",NumGet(var%A_Index%,8)),NumPut(0,var%A_Index%,8)
}
Yaml_Insert(_pYaml,Yaml_File,MainItem0){
If FileExist(Yaml_File){
FileRead,Yaml_File_,%Yaml_File%
If (ErrorLevel){
MsgBox Error Reading File
Return
}
} else Yaml_File_:=Yaml_File
Loop,Parse,MainItem0,.
{
space.=A_Space A_Space
_depth:=A_Index-1
MainItem%_depth%:=A_LoopField
}
Loop,Parse,Yaml_File_,`n,`r
{
If A_LoopField=
Continue
if !create
Key1:="",Key2:="",Key3:="",Item:=""
If (!create){
RegExMatch(A_LoopField,"^\s+-\s(.*)$",Key)
If (Key1!=""){
count:=Yaml_Get(_pYaml,LastItem ".0")
count++
Yaml_Assign(_pYaml,LastItem "." count,Key1)
Yaml_Assign(_pYaml,LastItem ".0", count)
item:=Yaml_Get(_pYaml,LastItem)
Yaml_Assign(_pYaml,LastItem,item="" ? Key1 : item "," key1)
Continue
}
Loop 3
Key%A_Index%=
RegExMatch(A_LoopField,"^(\s*)(\w+)\s?:\s?(.*)\s?$",Key)
If (Key2=""){
Loop 3
Key%A_Index%=
RegExMatch(A_LoopField,"^(\s*)'(.+)':\s?(.*)\s?$",Key)
}
If (Key2=""){
LastLine.=Space A_LoopField "`n"
Continue
}
If (SubStr(LastLine,0)="`n")
StringTrimRight,LastLine,LastLine,1
depth:=Round(Strlen(Key1)/2,0)+_depth+1
MainItem%depth%:=Key2
Item:=MainItem0
While % ((i:=A_Index) && depth>A_Index)
Item.= "." . MainItem%i%
If !Yaml_Exist(_pYaml,Item "." key2){
MainItem:=Yaml_Get(_pYaml,Item)
count:=Yaml_Get(_pYaml,Item . ".0")
count++
Yaml_Assign(_pYaml,Item . ".0",count)
Yaml_Assign(_pYaml,Item . "." . count,key2)
Yaml_Assign(_pYaml,Item,MainItem . (MainItem="" ? "" : ",") . (RegExMatch(Key2,"^\s?\w+\s?$") ? key2 : "'" key2 "'"))
}
Item.="." . key2
Yaml_Assign(_pYaml,Item,key3)
LastItem:=Item
If LastLine!=
Yaml_Assign(_pYaml,Item . ".",LastLine),LastLine:=""
} else
Yaml_Assign(_pYaml,Item,Yaml_Get(_pYaml,Item) . A_LoopField)
If RegExMatch(Key3,"^\s*""")
create:=1
if (create && RegExMatch(A_LoopField,"""\s*$"))
create:=0
}
}
Yaml_DeleteAll(pYaml){
DllCall(NumGet(NumGet(pYaml+0)+68), "UInt",pYaml) ;delete all keys
}
Yaml_Delete(pYaml,key){
VarSetCapacity(var1,16,0),NumPut(8,var1)
If A_IsUnicode
wStr:=key
else
VarSetCapacity(wStr, StrLen(Key)*2+1,0)
,DllCall("MultiByteToWideChar", "UInt",0, "UInt",0, "UInt",&Key, "Int",-1, "UInt",&wStr, "Int",StrLen(Key)+1)
NumPut(DllCall("oleaut32\SysAllocString","Str",wStr),var1,8)
DllCall(NumGet(NumGet(pYaml+0)+64), "UInt",pYaml, "UInt",&var1)
DllCall("oleaut32\SysFreeString", "UInt",NumGet(var1,8)),NumPut(0,var1,8)
}
Yaml_Init(Yaml_File="?",pointerYaml=""){
static pYaml, CLSID,IID,Init,FileIndex
static CLSIDString:="{EE09B103-97E0-11CF-978F-00A02463E06F}", IIDString:="{42C642C1-97E1-11CF-978F-00A02463E06F}"
If (!Init && Init:=1){ ;Initialize COM and create database
DllCall("ole32\CoInitialize", "UInt",0),VarSetCapacity(var1, 16),VarSetCapacity(var2, 16)
NumPut(8, var1),NumPut(8, var2),VarSetCapacity(CLSID, 16),VarSetCapacity(wKey, 79),VarSetCapacity(IID, 16)
If A_IsUnicode
DllCall("ole32\CLSIDFromString", "Str",CLSIDString, "Str",CLSID)
,DllCall("ole32\CLSIDFromString", "Str",IIDString, "Str",IID)
else
DllCall("MultiByteToWideChar", "UInt",0, "UInt",0, "UInt",&CLSIDString, "Int",-1, "UInt",&wKey, "Int",39)
,DllCall("ole32\CLSIDFromString", "Str",wKey, "Str",CLSID)
,DllCall("MultiByteToWideChar", "UInt",0, "UInt",0, "UInt",&IIDString, "Int",-1, "UInt",&wKey, "Int",39)
,DllCall("ole32\CLSIDFromString", "Str",wKey, "Str",IID)
DllCall("ole32\CoCreateInstance", "Str",CLSID, "UInt",0, "UInt",5, "Str",IID, "UIntP",pYaml) ; CLSCTX=5
DllCall(NumGet(NumGet(pYaml+0)+72), "UInt",pYaml, "Int",0) ; Set compare mode binary (casesensitive)
}
If (Yaml_File="?"){
Loop % Yaml_Get(pYaml,0)
Yaml_Save(Yaml_Get(pYaml,Yaml_Get(pYaml,A_Index)),Yaml_Get(pYaml,A_Index))
Return
}
Loop,%Yaml_File%
Yaml_File:=A_LoopFileLongPath
If (!Yaml_Exist(_pYaml,Yaml_File) && !Yaml_Exist(pointerYaml))
DllCall("ole32\CoCreateInstance", "Str",CLSID, "UInt",0, "UInt",5, "Str",IID, "UIntP",_pYaml) ; CLSCTX=5
,DllCall(NumGet(NumGet(_pYaml+0)+72), "UInt",_pYaml, "Int",1) ; Set compare mode text (caseinsensitive)
else if (pointerYaml)
_pYaml:=pointerYaml
else
return Yaml_Get(pYaml,Yaml_File)
If FileExist(Yaml_File){
FileRead,Yaml_File_,%Yaml_File%
If (ErrorLevel){
MsgBox Error Reading File
Return
}
FileIndex++
Yaml_Assign(pYaml,0,FileIndex)
Yaml_Assign(pYaml,FileIndex,Yaml_File)
Yaml_Assign(pYaml,Yaml_File,_pYaml)
} else Yaml_File_:=Yaml_File
Loop,Parse,Yaml_File_,`n,`r
{
If A_LoopField=
Continue
if !create
Key1:="",Key2:="",Key3:="",Item:=""
If (MainItem0="" || (!create && !RegExMatch(A_LoopField,"^\s"))){
If !RegExMatch(A_LoopField,"^(\w+)\s?:\s?(.*)\s*$",MainItem)
If !RegExMatch(A_LoopField,"^'(.+)'\s?:\s?(.*)\s*$",MainItem){
Key1=
RegExMatch(A_LoopField,"^\s+-\s(.*)$",Key)
If (Key1!=""){
count:=Yaml_Get(_pYaml,MainItem0 ".0")
count++
Yaml_Assign(_pYaml,MainItem0 "." count,Key1)
Yaml_Assign(_pYaml,MainItem0 ".0", count)
item:=Yaml_Get(_pYaml,MainItem0)
Yaml_Assign(_pYaml,MainItem0,item="" ? Key1 : item "," key1)
Continue
}
LastLine.=A_LoopField "`n"
Continue
}
MainItem0:=MainItem1
ItemCount++
MainItem:=Yaml_Get(_pYaml,"") . (Yaml_Get(_pYaml,"")!="" ? "," : "") . (RegExMatch(MainItem0,"^\s?\w+\s?$") ? MainItem0 : "'" MainItem0 "'")
Yaml_Assign(_pYaml,"",MainItem)
Yaml_Assign(_pYaml,0,ItemCount)
Yaml_Assign(_pYaml,ItemCount,MainItem0)
Yaml_Assign(_pYaml,MainItem0,MainItem2)
If (SubStr(LastLine,0)="`n")
StringTrimRight,LastLine,LastLine,1
Yaml_Assign(_pYaml,MainItem0 ".",LastLine)
MainItem:="",MainItem1:="",MainItem2:="",LastLine:=""
LastItem:=MainItem0
Continue
}
If (!create){
Key1=
RegExMatch(A_LoopField,"^\s+-\s(.*)$",Key)
If (Key1!=""){
count:=Yaml_Get(_pYaml,LastItem ".0")
count++
Yaml_Assign(_pYaml,LastItem "." count,Key1)
Yaml_Assign(_pYaml,LastItem ".0", count)
item:=Yaml_Get(_pYaml,LastItem)
Yaml_Assign(_pYaml,LastItem,item="" ? Key1 : item "," key1)
Continue
}
Loop 3
Key%A_Index%=
RegExMatch(A_LoopField,"^(\s+)(\w+)\s?:\s?(.*)\s?$",Key)
If (Key2=""){
Loop 3
Key%A_Index%=
RegExMatch(A_LoopField,"^(\s+)'(.+)':\s?(.*)\s?$",Key)
}
If (Key2=""){
LastLine.=A_LoopField "`n"
Continue
}
If (SubStr(LastLine,0)="`n")
StringTrimRight,LastLine,LastLine,1
depth:=Round(Strlen(Key1)/2,0)
MainItem%depth%:=Key2
Item:=MainItem0
While % ((i:=A_Index) && depth>A_Index)
Item.= "." . MainItem%i%
If !Yaml_Exist(_pYaml,Item "." key2){
MainItem:=Yaml_Get(_pYaml,Item)
count:=Yaml_Get(_pYaml,Item . ".0")
count++
Yaml_Assign(_pYaml,Item . ".0",count)
Yaml_Assign(_pYaml,Item . "." . count,key2)
Yaml_Assign(_pYaml,Item,MainItem . (MainItem="" ? "" : ",") . (RegExMatch(Key2,"^\s?\w+\s?$") ? key2 : "'" key2 "'"))
}
Item.="." . key2
Yaml_Assign(_pYaml,Item,key3)
LastItem:=Item
If LastLine!=
Yaml_Assign(_pYaml,Item . ".",LastLine),LastLine:=""
} else
Yaml_Assign(_pYaml,Item,Yaml_Get(_pYaml,Item) . A_LoopField)
If RegExMatch(Key3,"^\s*""")
create:=1
if (create && RegExMatch(A_LoopField,"""\s*$"))
create:=0
}
Return _pYaml
}