chiark / gitweb /
css: deduplicate parser code in the CSS preprocessor.
authorVladimír Vondruš <mosra@centrum.cz>
Wed, 13 Jun 2018 09:17:06 +0000 (11:17 +0200)
committerVladimír Vondruš <mosra@centrum.cz>
Wed, 13 Jun 2018 09:21:05 +0000 (11:21 +0200)
No change in the output (which was desired).

css/postprocess.py

index 2aa7df309ead11dca79824ddcd51fcb66b04ef43..a0d580038faee396f8b7798c2c4e3a5c66a59d48 100755 (executable)
@@ -45,12 +45,82 @@ def postprocess(files, process_imports, out_file):
         basename, ext = os.path.splitext(files[0])
         out_file = basename + ".compiled" + ext
 
-    with open(out_file, mode='w') as out:
-        variables = {}
-        imported_files = []
-
+    variables = {}
+    imported_files = []
+    def parse(f):
+        nonlocal variables, imported_files
         not_just_variable_declarations = False
+        in_variable_declarations = False
+        in_comment = False
+        for line in f:
+            # In comment and the comment is not ending yet, ignore
+            if in_comment:
+                if comment_end_rx.match(line):
+                    in_comment = False
+                continue
+
+            # Import statement: add the file to additionally processed files
+            # unless it's disabled
+            match = import_rx.match(line)
+            if match:
+                if process_imports:
+                    imported_files += [match['file']]
+                continue
+
+            # Variable use, replace with actual value
+            # TODO: more variables on the same line?
+            match = variable_use_rx.match(line)
+            if match and match['key'] in variables:
+                out.write(match['before'])
+                out.write(variables[match['key']])
+                out.write(match['after'])
+                out.write("\n")
+                continue
+
+            # Opening brace of variable declaration block
+            match = opening_brace_rx.match(line)
+            if match:
+                in_variable_declarations = True
+                continue
+
+            # Variable declaration
+            match = variable_declaration_rx.match(line)
+            if match and in_variable_declarations:
+                variables[match['key']] = match['value']
+                continue
+
+            # Comment or empty line, ignore
+            if comment_rx.match(line):
+                continue
+
+            # Comment start line, ignore this and the next lines
+            if comment_start_rx.match(line):
+                in_comment = True
+                continue
+
+            # Closing brace of variable declaration block. If it was not just
+            # variable declarations, put the closing brace to the output as
+            # well.
+            match = closing_brace_rx.match(line)
+            if match and in_variable_declarations:
+                if not_just_variable_declarations: out.write("}\n")
+                in_variable_declarations = False
+                continue
+
+            # If inside variable declaration block, include also the opening
+            # brace and remeber to put the closing brace there as well
+            if in_variable_declarations:
+                out.write(":root {\n")
+                not_just_variable_declarations = True
+
+            # Something else, copy verbatim to the output. Strip the trailing
+            # comment, if there, to save some bytes.
+            if line.rstrip().endswith('*/'):
+                out.write(line[:line.rindex('/*')].rstrip() + '\n')
+            else:
+                out.write(line)
 
+    with open(out_file, mode='w') as out:
         # Put a helper comment and a license blob on top
         out.write("""/* Generated using `./postprocess.py {}`. Do not edit. */
 
@@ -80,105 +150,14 @@ def postprocess(files, process_imports, out_file):
 """.format(' '.join(sys.argv[1:])))
 
         # Parse the top-level file
-        with open(files[0]) as f:
-            in_variable_declarations = False
-            in_comment = False
-            for line in f:
-                # In comment and the comment is not ending yet, ignore
-                if in_comment:
-                    if comment_end_rx.match(line):
-                        in_comment = False
-                    continue
-
-                # Import statement: add the file to additionally processed
-                # files unless it's disabled
-                match = import_rx.match(line)
-                if match:
-                    if process_imports:
-                        imported_files += [match['file']]
-                    continue
-
-                # Opening brace of variable declaration block
-                match = opening_brace_rx.match(line)
-                if match:
-                    in_variable_declarations = True
-                    continue
-
-                # Variable declaration
-                match = variable_declaration_rx.match(line)
-                if match and in_variable_declarations:
-                    variables[match['key']] = match['value']
-                    continue
-
-                # Comment or empty line, ignore
-                if comment_rx.match(line):
-                    continue
-
-                # Comment start line, ignore this and the next lines
-                if comment_start_rx.match(line):
-                    in_comment = True
-                    continue
-
-                # Closing brace of variable declaration block. If it was not
-                # just variable declarations, put the closing brace to the
-                # output as well.
-                match = closing_brace_rx.match(line)
-                if match and in_variable_declarations:
-                    if not_just_variable_declarations: out.write("}\n")
-                    in_variable_declarations = False
-                    continue
-
-                # Something else, copy verbatim to the output. If inside
-                # variable declaration block, include also the opening brace
-                # and remeber to put the closing brace there as well
-                if in_variable_declarations:
-                    out.write(":root {\n")
-                    not_just_variable_declarations = True
-
-                # Strip the trailing comment, if there, to save some bytes
-                if line.rstrip().endswith('*/'):
-                    out.write(line[:line.rindex('/*')])
-                else:
-                    out.write(line)
-
-        # Now open the imported files and replace variables
+        with open(files[0]) as f: parse(f)
+
+        # Now open the imported files and parse them as well. Not doing any
+        # recursive parsing.
         for file in imported_files + files[1:]:
             out.write('\n')
 
-            with open(file) as f:
-                in_comment = False
-                for line in f:
-                    # In comment and the comment is not ending yet, ignore
-                    if in_comment:
-                        if comment_end_rx.match(line):
-                            in_comment = False
-                        continue
-
-                    # Variable use, replace with actual value
-                    # TODO: more variables on the same line?
-                    match = variable_use_rx.match(line)
-                    if match and match['key'] in variables:
-                        out.write(match['before'])
-                        out.write(variables[match['key']])
-                        out.write(match['after'])
-                        out.write("\n")
-                        continue
-
-                    # Comment or empty line, ignore
-                    if comment_rx.match(line):
-                        continue
-
-                    # Comment start line, ignore this and the next lines
-                    if comment_start_rx.match(line):
-                        in_comment = True
-                        continue
-
-                    # Something else, copy verbatim to the output. Strip the
-                    # trailing comment, if there, to save some bytes
-                    if line.rstrip().endswith('*/'):
-                        out.write(line[:line.rindex('/*')].rstrip() + '\n')
-                    else:
-                        out.write(line)
+            with open(file) as f: parse(f)
 
     return 0