def parse_top(self, data, state = None): while 1: self.skip_whitespace_and_newlines() if self.at_end(): if state: raise Error(self, "Tag stack non-empty (%s) at end of data" % state) break c = self.peek_next() if c == ";": # comment line = self.read_until("\n") else: check_tag = self.seek("{}\n") if check_tag == "{": # open a tag name = self.read_until("{").strip(" {") subdata = wmldata.DataSub(name) subdata.set_meta(self.filename, self.line) self.parse_top(subdata, name) data.insert(subdata) elif check_tag == "}": self.read_until("}") name = self.read_until("\n").strip() if state.lower() == name.lower(): return raise Error(self, "Mismatched closing tag [%s], expected [%s]" % (name, state)) else: current = data while self.seek(">.=\n") == ".": name = self.read_until(".").strip(".") current = current.get_or_create_sub(name) subdata = self.parse_inside(current, self.read_next()) current.insert(subdata)
def parse_top(self, data, state=None): while 1: self.skip_whitespace_and_newlines() if self.at_end(): if state: raise Error( self, "Tag stack non-empty (%s) at end of data" % state) break c = self.read_next() if c == "#": # comment or preprocessor if self.check_for("define "): self.read_until(" ") params = [] while 1: name = self.read_until(" \n") sep = name[-1] name = name[:-1] if name: params += [name] if sep == "\n": break self.read_while(" ") text = self.read_lines_until("#enddef") if text is None: raise Error(self, "#define without #enddef") self.macros[params[0]] = self.Macro( params[0], params[1:], text, self.textdomain) if self.verbose: sys.stderr.write("New macro: %s.\n" % params[0]) elif self.check_for("undef "): self.read_until(" ") name = self.read_until("\n") name = name.rstrip() if " " in name: if self.verbose: sys.stderr.write("Stray symbols in #undef %s\n" % name) name = name.split(" ")[0] if name in self.macros: del self.macros[name] elif self.verbose: sys.stderr.write("undef'd macro '%s' did not exist\n" % name) elif self.check_for("ifdef ") or self.check_for("ifndef"): what = "#" + self.read_until(" ").rstrip() name = self.read_until(" \n") if name[-1] == " ": self.read_while(" \n") name = name[:-1] condition_failed = False if what == "#ifdef": if name in self.macros: pass else: condition_failed = True else: # what == "#ifndef" if not name in self.macros: pass else: condition_failed = True self.preprocessor_nesting.append((what, condition_failed)) # If the condition is true, we simply continue parsing. At # some point we will either hit an #else or #endif, and # things continue there. If the condition failed, we skip # over everything until we find the matching #else or # endif. if condition_failed: self.stay_in_file = True balance = 1 while balance > 0 and not self.at_end(): line = self.read_until("\n") line = line.lstrip() if line.startswith("#ifdef"): balance += 1 if line.startswith("#ifndef"): balance += 1 if line.startswith("#endif"): balance -= 1 if line.startswith("#else"): if balance == 1: balance = -1 break self.stay_in_file = False if balance == 0: self.preprocessor_nesting.pop() if balance > 0: raise Error(self, "Missing #endif for %s" % what) self.check_end() elif self.check_for("else"): if not self.preprocessor_nesting: raise Error(self, "#else without #ifdef") self.read_until("\n") # We seen an #else - that means we are at the end of a # conditional preprocessor block which has executed. So # we should now ignore everything up to the #endif. balance = 1 self.stay_in_file = True while balance > 0 and not self.at_end(): line = self.read_until("\n") line = line.lstrip() if line.startswith("#ifdef"): balance += 1 if line.startswith("#ifndef"): balance += 1 if line.startswith("#endif"): balance -= 1 self.stay_in_file = False if balance != 0: raise Error(self, "Missing #endif for #else") self.check_end() elif self.check_for("endif"): if not self.preprocessor_nesting: raise Error(self, "#endif without #ifdef") self.preprocessor_nesting.pop() self.read_until("\n") elif self.check_for("textdomain"): self.read_until(" ") self.textdomain = self.read_until("\n").strip() else: # comment line = self.read_until("\n") #comment = c + line if self.verbose: #msg = "Comment removed: %s" % comment ##sys.stderr.write(msg.encode("utf8")) pass elif c == '[': name = self.read_until("]")[:-1] if name[0] == '/': if state == name[1:]: return raise Error( self, "Mismatched closing tag [%s], expected [/%s]" % (name, state)) elif name[0] == '+': name = name[1:] try: subdata = data.dict[name][-1] self.parse_top(subdata, name) except KeyError: subdata = wmldata.DataSub(name) subdata.set_meta(self.filename, self.line) self.parse_top(subdata, name) data.insert(subdata) elif name[0] == " ": # We single this case out explicitly as the wesnoth parser # ignores it due to implementation reasons and this makes # more sense of the error message raise Error(self, "Invalid tag [%s] contains whitespace" % name) else: subdata = wmldata.DataSub(name) subdata.set_meta(self.filename, self.line) self.parse_top(subdata, name) data.insert(subdata) elif c == '{': keep_macro = self.parse_macro() if isinstance(keep_macro, wmldata.Data): data.insert(keep_macro) else: for subdata in self.parse_inside(data, c): data.insert(subdata)
if args.no_macros: wmlparser.no_macros = True if args.verbose: wmlparser.verbose = True def gt(domain, x): print "gettext: '%s' '%s'" % (domain, x) return x wmlparser.gettext = gt wmlparser.do_preprocessor_logic = True if args.execute: wmlparser.parse_text(args.execute) elif args.filename: wmlparser.parse_file(args.filename) else: wmlparser.parse_stream(sys.stdin) data = wmldata.DataSub("WML") wmlparser.parse_top(data) if args.to_json: jsonify(data, True) # For more readable results elif args.to_xml: xmlify(data, True) else: data.debug(show_contents=args.contents, use_color=args.color)