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()