Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # BZ2 Shell Interface Dimensions
- WIDTH, HEIGHT = 640, 480 # 1920, 1080
- ignore_missing_close_braces = True
- ignore_missing_open_braces = False
- class CFG_ParseError(Exception): pass
- def p(param):
- return ", ".join(map(repr, param))
- class Param():
- def __init__(self, value, is_quote_value = None):
- self.value = value
- self.is_quote_value = is_quote_value
- def __bool__(self):
- return len(self.value) > 0
- def append(self, data):
- self.value += data
- def convert(self):
- def isall(value, character_set):
- for c in value:
- if not c in character_set:
- return False
- return bool(value)
- if self.is_quote_value: return self.value
- elif isall(self.value, "+-1234567890"):
- return int(self.value)
- elif isall(self.value, "+-1234567890e."):
- return float(self.value)
- else:
- return None
- class Container:
- def __init__(self, name, parameters = []):
- self.name = name
- self.param = parameters
- self.parent = None
- self.attribute = [] # List of attributes ("AttributeName", [param1, param2])
- self.container = [] # List of subcontainers
- def fix_attr(self, name):
- find = name.casefold()
- if find == "Geometry".casefold():
- return name[0:4]
- elif find == "Position".casefold():
- return name[0:3]
- return name
- def get_attr(self, name, default = None):
- find = self.fix_attr(name).casefold()
- for attr in self.attribute:
- if attr[0].casefold() == find:
- return attr[1]
- return default
- def set_attr(self, name, param):
- find = name.casefold()
- for index, attr in enumerate(self.attribute):
- if attr[0].casefold() == find:
- self.attribute[index] = (self.fix_attr(name), param)
- return
- self.attribute += [(self.fix_attr(name), param)]
- def __str__(self):
- return "Container: %s(%s) - %d Attributes, %d Containers" % (
- self.name,
- p(self.param),
- len(self.attribute),
- len(self.container)
- )
- def read(cfg_path):
- progressive_debug_prints = False
- READING_NAME = 0
- READING_PARAMS = 1
- EXPECTING_COMMENT = 2
- EXPECTING_CONTAINER_OR_END = 3
- with open(cfg_path, "r") as cfg:
- valid_name = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890_"
- valid_param = "0123456789-.e"
- valid_quote = "\"'"
- skip_character = (
- " \t\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F\x10"
- "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
- )
- container = [Container("ROOT")]
- brl = 0
- state = [READING_NAME]
- name, param, quote = "", [], None
- for row, line in enumerate(cfg):
- for col, c in enumerate(line.strip()):
- # Space/tab/etc...
- if not quote and c in skip_character:
- continue
- if state[-1] == EXPECTING_COMMENT:
- # Ensure double slash, otherwise invalid.
- if c == "/":
- state.pop()
- break
- elif state[-1] == READING_NAME:
- # Add character to name value
- if c in valid_name:
- name += c
- continue
- # Comment, if it's the first piece of data
- elif c == "/" and not name:
- state.append(EXPECTING_COMMENT)
- continue
- # Beginning first parameter
- elif c == "(":
- state.append(READING_PARAMS)
- param += [Param("")]
- continue
- # Closing brace of container we are in
- elif c == "}":
- brl -= 1
- if brl >= 0:
- container.pop()
- if progressive_debug_prints:
- print("\t"*brl + "}" + "\n" + "\t"*brl)
- continue
- if ignore_missing_close_braces:
- brl = 0
- continue
- raise CFG_ParseError("%s:%d:%d: Too Many Closing Braces" % (cfg_path, row+1, col+1))
- elif state[-1] == READING_PARAMS:
- # We are currently reading quoted data (string)
- if quote:
- # Matched terminating quote
- if c == quote:
- quote = None
- continue
- # Note: We don't need to worry about \ escapes, it's not supported anyway.
- param[-1].append(c)
- continue
- # Parameter data (hopefully an integer)
- elif c in valid_param:
- param[-1].append(c)
- continue
- # Encountered quote
- elif c in valid_quote:
- # Was there already valid data before this quote encounter?
- if param[-1]:
- raise CFG_ParseError("%s:%d:%d: Unexpected Quote" % (cfg_path, row+1, col+1))
- param[-1].is_quote_value = True
- quote = c
- continue
- # Next parameter
- elif c == ",":
- param += [Param("")]
- continue
- # End of parameters
- elif c == ")":
- # Remove assumed first parameter if there were none in the cfg.
- if (len(param) == 1
- and not param[-1]
- and not param[-1].is_quote_value):
- param.pop()
- state.pop()
- state.append(EXPECTING_CONTAINER_OR_END)
- continue
- elif state[-1] == EXPECTING_CONTAINER_OR_END:
- # End of attribute
- if c == ";":
- if progressive_debug_prints:
- print("\t"*brl + "%s(%s);" % (name, ", ".join([str(x) for x in param])))
- param = [p.convert() for p in param]
- container[-1].set_attr(name, param)
- state.pop()
- name, param = "", []
- continue
- # Start of a container
- elif c == "{":
- # Add container to parent container (or root container).
- brl += 1
- if progressive_debug_prints:
- print("\t"*(brl-1) + "%s(%s) {" % (name, ", ".join([str(x) for x in param])))
- param = [p.convert() for p in param]
- container += [Container(name, param)]
- # Make current container a child of last container
- container[brl-1].container += [container[brl]]
- container[brl].parent = container[brl-1]
- state.pop()
- name, param = "", []
- continue
- print("_"*64, "\nDebug Help:", quote, brl)
- raise CFG_ParseError(
- "%s:%d:%d: %s - Unexpected Character %r" % (
- cfg_path, row+1, col+1, str(state[-1]), c
- )
- )
- # Ensure we had a matching closing brace for every opening brace.
- if brl and not ignore_missing_open_braces:
- # Note: You may disable this but it could cause silently
- # malformed results.
- raise CFG_ParseError("%s - Too Many Opening Braces" % cfg_path)
- # Return root container
- return container[0]
- def PrintConfig(cfg, brl = -1):
- if type(cfg) == str:
- cfg = read(cfg)
- # Skip root container
- if brl < 0:
- for subcfg in cfg.container:
- PrintConfig(subcfg, brl+1)
- return
- print("\t"*brl + "%s(%s) {" % (cfg.name, p(cfg.param)))
- for attr in cfg.attribute:
- print("\t"*(brl+1) + "%s(%s);" % (attr[0], p(attr[1])))
- else:
- if len(cfg.container): print("\t"*(brl+1))
- for subcfg in cfg.container:
- PrintConfig(subcfg, brl+1)
- print("\t"*brl + "}\n" + "\t"*brl)
- if __name__ == "__main__":
- PrintConfig("config/bzshell.cfg")
Add Comment
Please, Sign In to add comment