Author: elias
Date: Sun Mar 23 16:35:10 2008
New Revision: 25022
URL: http://svn.gna.org/viewcvs/wesnoth?rev=25022&view=rev
Log:
Added logic processing (#ifdef/#ifndef) to the python WML preprocessor (until
now it would just parse both branches and add them to the output tree, as
that's what campgen needed).
Modified:
trunk/data/tools/wesnoth/wmldata.py
trunk/data/tools/wesnoth/wmlparser.py
Modified: trunk/data/tools/wesnoth/wmldata.py
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/data/tools/wesnoth/wmldata.py?rev=25022&r1=25021&r2=25022&view=diff
==============================================================================
--- trunk/data/tools/wesnoth/wmldata.py (original)
+++ trunk/data/tools/wesnoth/wmldata.py Sun Mar 23 16:35:10 2008
@@ -225,6 +225,11 @@
else:
self.dict[data.name] = [data]
+ def append(self, other):
+ """Append all elements of other."""
+ for item in other.data:
+ self.insert(item)
+
def insert(self, data):
"""Inserts a sub-element."""
self.data += [data]
Modified: trunk/data/tools/wesnoth/wmlparser.py
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/data/tools/wesnoth/wmlparser.py?rev=25022&r1=25021&r2=25022&view=diff
==============================================================================
--- trunk/data/tools/wesnoth/wmlparser.py (original)
+++ trunk/data/tools/wesnoth/wmlparser.py Sun Mar 23 16:35:10 2008
@@ -7,6 +7,12 @@
"""Module implementing a WML parser."""
class Error(Exception):
+ """
+ This is a custom exception the parser throws on errors. It can display
+ the position of the error as a tree of all files and macros leading to
+ the error, with line numbers.
+ """
+
def __init__(self, parser, text):
self.text = "%s:%d: %s" % (parser.filename, parser.line, text)
for i in range(len(parser.texts)):
@@ -17,6 +23,10 @@
return self.text
class Parser:
+ """
+ The main parser class. An instance of this is needed for parsing.
+ """
+
class Macro:
"""Class to hold one single macro."""
def __init__(self, name, params, text):
@@ -38,6 +48,7 @@
user_dir is used for resolving {~filepath} and [EMAIL PROTECTED]
See http://www.wesnoth.org/wiki/PreprocessorRef
"""
+
self.data_dir = data_dir
self.user_dir = user_dir
@@ -55,6 +66,12 @@
self.macro_not_found_callback = None
self.no_macros = False
+
+ # If set, we actually do preprocessor logic with #ifdef and so on.
+ # Otherwise, they get included in the parse tree as nodes.
+ self.do_preprocessor_logic = False
+ # Internal flag while inside a non-parsed block
+ self.just_parse = False
# If set, included files are only parsed when under the given
directory.
self.only_expand_pathes = []
@@ -260,6 +277,10 @@
if macro[-1] != "}":
raise Error(self, "Unclosed macro")
return
+
+ if self.just_parse:
+ # We do not execute any macros or file inclusions.
+ return None
preserve = macro
macro = macro[:-1] # Get rid of final }
@@ -502,7 +523,7 @@
j += 1
return data
- def parse_top(self, data, state = None):
+ def parse_top(self, data, state = None, dont_parse_else = False):
while 1:
self.skip_whitespace_and_newlines()
if self.at_end():
@@ -523,35 +544,66 @@
if text == None:
raise Error(self, "#define without #enddef")
return
- self.macros[params[0]] = self.Macro(params[0], params[1:],
text)
+ if not self.just_parse:
+ self.macros[params[0]] = self.Macro(
+ params[0], params[1:], text)
+ 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")
self.macros[name] = None
- elif self.check_for("ifdef "):
- self.read_until(" ")
+ 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]
+
subdata = wmldata.DataIfDef(name, [], "then")
- self.parse_top(subdata, "#ifdef")
- data.insert(subdata)
- elif self.check_for("ifndef "):
- self.read_until(" ")
- name = self.read_until(" \n")
- if name[-1] == " ": self.read_while(" \n")
- name = name[:-1]
- subdata = wmldata.DataIfDef(name, [], "then")
- self.parse_top(subdata, "#ifndef")
- data.insert(subdata)
+
+ dont_parse_else = False
+ if self.do_preprocessor_logic:
+ dont_parse_else = True
+ prev = self.just_parse
+ if what == "#ifdef":
+ if not name in self.macros:
+ self.just_parse = True
+ dont_parse_else = prev
+ elif what == "#ifndef":
+ if name in self.macros:
+ self.just_parse = True
+ dont_parse_else = prev
+
+ self.parse_top(subdata, what, dont_parse_else)
+
+ if self.do_preprocessor_logic:
+ self.just_parse = prev
+ if self.just_parse == False:
+ elses = subdata.get_ifdefs("else")
+ if dont_parse_else:
+ if elses:
+ subdata.remove(elses[0])
+ data.append(subdata)
+ else:
+ if elses:
+ data.append(elses[0])
+ else:
+ data.insert(subdata)
elif self.check_for("else"):
+
self.read_until("\n")
if state != "#ifdef" and state != "#ifndef":
raise Error(self, "#else without #ifdef")
subdata = wmldata.DataIfDef("else", [], "else")
+
+ if self.do_preprocessor_logic:
+ self.just_parse = dont_parse_else
self.parse_top(subdata, "#else")
+
data.insert(subdata)
return
@@ -632,6 +684,8 @@
if options.verbose:
wmlparser.verbose = True
+
+ wmlparser.do_preprocessor_logic = True
if options.execute:
wmlparser.parse_text(options.execute)
_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits