Open user menu
Files
gr_parser.src
//This implementation deviates from RFC 7159 - The JavaScript Object Notation (JSON) Data Interchange Format <https://tools.ietf.org/html/rfc7159> in the following ways:
//Section 6 (Numbers):
// Leading zeros are allowed
// Infinity, -Infinity, NaN are considered valid numbers
//Section 7 (Strings):
// Escaping characters is not implemented
// Literal double quote is represented as "" in a string
//usage:
//json = new JSON
//string = json.to_string(object)
//object = json.to_object(string)
JSON = {}
JSON.JSON_QUOTE = """"
JSON.JSON_WHITESPACE = [char(9), char(10), char(13), char(32)] //[TAB, LF, CR, Space]
JSON.JSON_SYNTAX = [",",":","[","]","{","}"]
JSON.NUMBER_SYNTAX = ["-","+","E","e","."]
JSON.NULL = null
JSON.sLexString=function(string)
if string[0] == self.JSON_QUOTE then
string = string[1:]
else
return [self.NULL, string]
end if
json_string = ""
strlen = string.len
if strlen > 0 then
i = 0
while i < strlen
if string[i] == "\" and string[i+1] == self.JSON_QUOTE then
i = i + 2
json_string = json_string + self.JSON_QUOTE
continue
end if
if string[i] == self.JSON_QUOTE then
i = i + 1
return [json_string, string[i:]]
end if
json_string = json_string + string[i]
i = i + 1
end while
end if
exit("<color=#ff0000>JSON string lexer error: Expected end-of-string quote")
end function
JSON.sLexNumber=function(string)
strlen = string.len
if strlen > 8 and string[:9] == "-Infinity" then
return ["-Infinity".val, string[9:]]
else if strlen > 7 and string[:8] == "Infinity" then
return ["Infinity".val, string[8:]]
else if strlen > 2 and string[:3] == "NaN" then
return ["NaN".val, string[3:]]
end if
json_number = ""
for c in string
if (c.code > 47 and c.code < 58) or self.NUMBER_SYNTAX.indexOf(c) != null then
json_number = json_number + c
else
break
end if
end for
number = json_number.val
if number == 0 and json_number != "0" then return [self.NULL, string]
return [number, string[json_number.len:]]
end function
JSON.sLexBool=function(string)
strlen=string.len
if strlen > 3 and string[:4] == "true" then return [true, string[4:]]
if strlen > 4 and string[:5] == "false" then return [false, string[5:]]
return [self.NULL, string]
end function
JSON.sLexNull=function(string)
if string.len > 3 and string[:4] == "null" then return [true, string[4:]]
return [false, string]
end function
JSON.sLexWhitespace=function(string)
if self.JSON_WHITESPACE.indexOf(string[0]) != null then
return [string[0], string[1:]]
end if
return [self.NULL, string]
end function
JSON.sLexSyntax=function(string)
if self.JSON_SYNTAX.indexOf(string[0]) != null then
return [string[0], string[1:]]
end if
return [self.NULL, string]
end function
JSON.sLex=function(string)
tokens = []
while string
res = self.sLexString(string)
if res[0] != null then
tokens.push({"token":"string","value":res[0]})
string=res[1]
continue
end if
res = self.sLexNumber(string)
if res[0] != null then
tokens.push({"token":"number","value":res[0]})
string=res[1]
continue
end if
res = self.sLexBool(string)
if res[0] != null then
tokens.push({"token":"bool","value":res[0]})
string=res[1]
continue
end if
res = self.sLexNull(string)
if res[0] == true then
tokens.push({"token":"null","value":self.NULL})
string=res[1]
continue
end if
res = self.sLexSyntax(string)
if res[0] != null then
tokens.push({"token":"syntax","value":res[0]})
string=res[1]
continue
end if
res = self.sLexWhitespace(string)
if res[0] != null then
string=res[1]
continue
end if
exit("<color=#ff0000>JSON lexer error: Unexpected character: "+string[0])
end while
return tokens
end function
JSON.sParseList=function(tokens)
if tokens[0] == {"token":"syntax","value":"]"} then return [[], tokens[1:]]
json_list = []
while tokens
res = self.sParse(tokens)
json_list.push(res[0])
tokens = res[1]
if tokens[0] == {"token":"syntax","value":"]"} then
return [json_list, tokens[1:]]
else if tokens[0] != {"token":"syntax","value":","} then
exit("<color=#ff0000>JSON parser error: Expected comma after object in list")
end if
tokens = tokens[1:]
end while
exit("<color=#ff0000>JSON list parser error: Expected end-of-list bracket")
end function
JSON.sParseMap=function(tokens)
if tokens[0] == {"token":"syntax","value":"}"} then return [{}, tokens[1:]]
json_map = {}
while tokens
if tokens[0].token == "string" or tokens[0].token == "number" then
json_key = tokens[0].value
tokens = tokens[1:]
else
exit("<color=#ff0000>JSON map parser error: Expected string or number key, got: "+tokens[0])
end if
if tokens[0] != {"token":"syntax","value":":"} then
exit("<color=#ff0000>JSON map parser error: Expected "":"" after key in map, got: "+tokens[0])
end if
res = self.sParse(tokens[1:])
json_map[json_key]=res[0]
tokens=res[1]
if tokens[0] == {"token":"syntax","value":"}"} then
return [json_map, tokens[1:]]
else if tokens[0] != {"token":"syntax","value":","} then
exit("<color=#ff0000>JSON map parser error: Expected "","" after pair in map, got: "+tokens[0])
end if
tokens = tokens[1:]
end while
exit("<color=#ff0000>JSON map parser error: Expected end-of-map brace")
end function
JSON.sParse=function(tokens)
if tokens then
if tokens[0] == {"token":"syntax","value":"["} then
return self.sParseList(tokens[1:])
else if tokens[0] == {"token":"syntax","value":"{"} then
return self.sParseMap(tokens[1:])
end if
return [tokens[0].value, tokens[1:]]
end if
return null
end function
JSON.oParseList=function(list)
list_string = "["
listlen = list.len
if listlen then
if listlen > 1 then
for i in range(0,listlen-2)
list_string = list_string + self.to_string(list[i]) + ","
end for
end if
list_string = list_string + self.to_string(list[-1])
end if
return list_string + "]"
end function
JSON.oParseMap=function(map)
map_string = "{"
mapkeys = map.indexes
maplen = mapkeys.len
if maplen then
if maplen > 1 then
for i in range(0,maplen-2)
if typeof(mapkeys[i]) == "string" then
map_string = map_string + """" + mapkeys[i] + """" + ":" + self.to_string(map[mapkeys[i]]) + ","
else
map_string = map_string + mapkeys[i] + ":" + self.to_string(map[mapkeys[i]]) + ","
end if
end for
end if
if typeof(mapkeys[-1]) == "string" then
map_string = map_string + """" + mapkeys[-1] + """" + ":" + self.to_string(map[mapkeys[-1]])
else
map_string = map_string + mapkeys[-1] + ":" + self.to_string(map[mapkeys[-1]])
end if
end if
return map_string + "}"
end function
JSON.to_object=function(string)
return self.sParse(self.sLex(string))[0]
end function
JSON.to_string=function(object)
if typeof(object) == "string" then
return """" + object.replace("""", "\""") + """"
else if typeof(object) == "number" then
return str(object)
else if object == null then
return null
else if typeof(object) == "list" then
return self.oParseList(object)
else
return self.oParseMap(object)
end if
end function
// --------------------------------------
// pretty much try and error to find every character escaped the by json parser
escape_list = []
escape_list.push({"escaped": char(92)+"...n", "unscaped": char(10)})
escape_list.push({"escaped": char(92)+"t", "unscaped": char(9)})
escape_list.push({"escaped": char(92)+"u003e", "unscaped": char(62)})
escape_list.push({"escaped": char(92)+"u003c", "unscaped": char(60)})
escape_list.push({"escaped": char(92)+"u0026", "unscaped": char(38)})
unescape = function(string)
for set in escape_list
string = string.replace(set["escaped"], set["unscaped"])
end for
return string
end function
escape = function(string)
for set in escape_list
string = string.replace(set["unscaped"], set["escaped"])
end for
return string
end function
get_folder_table = function(folder, table=null, parent="")
if table == null then table = {}
index = table.len
obj = {"parent": parent, "type": "folder", "name": folder.name}
table[str(index)] = obj
parent = str(index)
index = index + 1
scripts = folder.get_files
folders = folder.get_folders
for script in scripts
obj = {"parent": parent, "type": "script", "name": script.name, "content": escape(script.get_content)}
table[str(index)] = obj
index = index + 1
end for
for folder in folders
get_folder_table(folder, table, parent)
end for
return table
end function
computer = get_shell.host_computer
root_path = current_path
root_folder = computer.File(root_path)
import_folder = function()
json = new JSON
root_folder_name = user_input("(optional, you can press enter to skip and use the root folder name provided in the import string)\nroot folder name: \n")
export_string = user_input("export string: \n")
table = json.to_object(export_string)
file_table = {}
for value in table.values
key = table.indexOf(value)
file_name = value["name"].replace(" ", "_")
if value["parent"] == "" then
parent_folder = root_folder
if root_folder_name != "" then file_name = root_folder_name
file_path = parent_folder.path + "/" + file_name
if computer.File(file_path) then computer.File(file_path).delete //clear
else
parent_folder = file_table[value["parent"]]["file"]
file_path = parent_folder.path + "/" + file_name
end if
if value["type"] == "folder" then
f_out = computer.create_folder(parent_folder.path, file_name)
if f_out != 1 then
print(file_path)
exit(f_out)
end if
file = computer.File(file_path)
else if value["type"] == "script" then
f_out = computer.touch(parent_folder.path, file_name)
if f_out != 1 then
print(file_path)
exit(f_out)
end if
file = computer.File(file_path)
file.set_content(unescape(value["content"]))
end if
file_table[key] = {"parent": value["parent"], "file": file}
print(file_path + " " + value["type"] +" created")
end for
end function
export_folder = function()
full_path = user_input("full path of the folder:\n")
folder = computer.File(full_path)
export_obj = get_folder_table(folder)
print("\n\nthis is your export string:\n\n")
json = new JSON
export_string = json.to_string(export_obj)
print(export_string)
end function
print("<b>grey repo parser (www.greyrepo.xyz/posts/folder-parser)</b>\nactions:\n[1] import project\n[2] export a local folder")
input = user_input("select action:\n")
if input == "1" then import_folder()
if input == "2" then export_folder()