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

Reply via email to