[syn] Minor refactorings in parse-syn-report.py

This was triggered by a PR to remove master/slave terminology, which
touched the "master_key" arguments of the script's _match_strings and
_match_fp_number functions.

I think this version is a little simpler to follow, and gets rid of
the problematic terminology by getting rid of the arguments entirely.

  - The _match_strings function (which only had one call site) is now
    inlined

  - The _match_fp_number no longer operates in-place on a dict and
    instead returns the stuff it extracted, which is inserted into the
    "document dict" at the call site. I've also expanded the docstring
    somewhat.

There should be no functional change. The logic in _match_fp_number
could be simplified a bit if we allowed an empty list of results for a
key with no valid matches.

Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
diff --git a/hw/syn/tools/dc/parse-syn-report.py b/hw/syn/tools/dc/parse-syn-report.py
index 97e82ed..2141fff 100755
--- a/hw/syn/tools/dc/parse-syn-report.py
+++ b/hw/syn/tools/dc/parse-syn-report.py
@@ -17,46 +17,42 @@
 CROSSCHECK_REL_TOL = 0.001
 
 
-def _match_strings(full_file, master_key, patterns, results):
-    """
-    This searches for string patterns in the full_file buffer.
-    The argument patterns needs to be a list of tuples with
-    (<error_severity>, <pattern_to_match_for>).
-    """
-    for severity, pattern in patterns:
-        results[master_key][severity] += re.findall(pattern,
-                                                    full_file,
-                                                    flags=re.MULTILINE)
-    return results
+def _match_fp_number(full_file, patterns):
+    """Extract numbers from patterns in full_file (a string)
 
+    patterns is a list of pairs, (key, pattern). Each pattern should be a
+    regular expression with exactly one capture group. Any match for group will
+    be parsed as a float.
 
-def _match_fp_number(full_file, master_key, patterns, results):
+    Returns a pair (nums, errs) where nums is a dictionary keyed by the keys in
+    patterns. The value at K is a list of floats matching patterns[K] if there
+    was more than one match. If there was exactly one match for the
+    patterns[K], the value at K is that float (rather than a singleton list).
+
+    errs is a list of error messages (caused by failed float conversions or
+    when there is no match for a pattern).
+
     """
-    This extracts numbers from the sting buffer full_file.
-    The argument patterns needs to be a list of tuples with
-    (<key>, <pattern_to_match_for>).
-    """
+    nums = {}
+    errs = []
     for key, pattern in patterns:
-        match = re.findall(pattern, full_file, flags=re.MULTILINE)
-        if len(match) == 1:
-            try:
-                results[master_key][key] = float(match[0])
-            except ValueError as err:
-                results["messages"]["flow_errors"] += ["ValueError: %s" % err]
-        elif len(match) > 0:
-            for item in match:
-                try:
-                    results[master_key][key] += [float(item)]
-                except ValueError as err:
-                    results["messages"]["flow_errors"] += [
-                        "ValueError: %s" % err
-                    ]
-        else:
-            results["messages"]["flow_errors"] += [
-                "Pattern '%s' of key '%s' not found" % (pattern, key)
-            ]
+        floats = []
+        matches = re.findall(pattern, full_file, flags=re.MULTILINE)
+        if not matches:
+            errs.append('Pattern {!r} of key {!r} not found'
+                        .format(pattern, key))
+            continue
 
-    return results
+        for match in matches:
+            try:
+                floats.append(float(match))
+            except ValueError as err:
+                errs.append('ValueError: {}'.format(err))
+
+        if floats:
+            nums[key] = floats[0] if len(floats) == 1 else floats
+
+    return (nums, errs)
 
 
 def _extract_messages(full_file, results, key):
@@ -68,8 +64,10 @@
                          ("%s_errors" % key, r"^.*command not found.*"),
                          ("%s_warnings" % key, r"^Warning: .*"),
                          ("%s_warnings" % key, r"^WARNING: .*")]
-    _match_strings(full_file, "messages", err_warn_patterns, results)
-
+    for severity, pattern in err_warn_patterns:
+        results['messages'][severity] += re.findall(pattern,
+                                                    full_file,
+                                                    flags=re.MULTILINE)
     return results
 
 
@@ -107,7 +105,10 @@
                 ("macro", r"^Macro/Black Box area: \s* (\d+\.\d+)"),
                 ("total", r"^Total cell area: \s* (\d+\.\d+)")]
 
-    results = _match_fp_number(full_file, key, patterns, results)
+    nums, errs = _match_fp_number(full_file, patterns)
+    results[key] = nums
+    results['messages']['flow_errors'] += errs
+
     # aggregate one level of sub-modules
     pattern = r"^([\.0-9A-Za-z_\[\]]+){1}(?:(?:/[\.0-9A-Za-z_\[\]]+)*)"
     for k in range(5):
@@ -293,7 +294,9 @@
                 ("leak", r"^" + results["top"] + r"\s*" + FP_NUMBER + r" \s*" +
                  FP_NUMBER + r"\s*(" + FP_NUMBER + r")")]
 
-    results = _match_fp_number(full_file, key, patterns, results)
+    nums, errs = _match_fp_number(full_file, patterns)
+    results[key] = nums
+    results['messages']['flow_errors'] += errs
 
     return results