Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/Tools/autotest/logger_metadata/enum_parse.py
Views: 1799
#!/usr/bin/env python12'''3AP_FLAKE8_CLEAN4'''56from __future__ import print_function78import argparse9import os10import re11import sys1213topdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../../../')14topdir = os.path.realpath(topdir)151617class EnumDocco(object):1819vehicle_map = {20"Rover": "Rover",21"Sub": "ArduSub",22"Copter": "ArduCopter",23"Plane": "ArduPlane",24"Tracker": "AntennaTracker",25"Blimp": "Blimp",26}2728def __init__(self, vehicle):29self.vehicle = vehicle30self.enumerations = []3132class EnumEntry(object):33def __init__(self, name, value, comment):34self.name = name35self.value = value36self.comment = comment3738def match_enum_line(self, line):39# attempts to extract name, value and comment from line.4041# Match: " FRED, // optional comment"42m = re.match(r"\s*([A-Z0-9_a-z]+)\s*,? *(?://[/>]* *(.*) *)?$", line)43if m is not None:44return (m.group(1), None, m.group(2))4546# Match: " FRED, /* optional comment */"47m = re.match(r"\s*([A-Z0-9_a-z]+)\s*,? *(?:/[*] *(.*) *[*]/ *)?$", line)48if m is not None:49return (m.group(1), None, m.group(2))5051# Match: " FRED = 17, // optional comment"52m = re.match(r"\s*([A-Z0-9_a-z]+)\s*=\s*([-0-9]+)\s*,?(?:\s*//[/<]*\s*(.*) *)?$",53line)54if m is not None:55return (m.group(1), m.group(2), m.group(3))5657# Match: " FRED = 17, // optional comment"58m = re.match(r"\s*([A-Z0-9_a-z]+) *= *([-0-9]+) *,?(?: */* *(.*) *)? *[*]/ *$",59line)60if m is not None:61return (m.group(1), m.group(2), m.group(3))6263# Match: " FRED = 1U<<0, // optional comment"64m = re.match(r"\s*([A-Z0-9_a-z]+) *= *[(]?1U? *[<][<] *(\d+)(?:, *// *(.*) *)?",65line)66if m is not None:67return (m.group(1), 1 << int(m.group(2)), m.group(3))6869# Match: " FRED = 0xabc, // optional comment"70m = re.match(r"\s*([A-Z0-9_a-z]+) *= *(?:0[xX]([0-9A-Fa-f]+))(?:, *// *(.*) *)?",71line)72if m is not None:73return (m.group(1), int(m.group(2), 16), m.group(3))7475'''start discarded matches - lines we understand but can't do anything76with:'''77# Match: " FRED = 17, // optional comment"78m = re.match(r"\s*([A-Z0-9_a-z]+) *= *(\w+) *,?(?: *// *(.*) *)?$",79line)80if m is not None:81return (None, None, None)82# Match: " FRED = FOO(17), // optional comment"83m = re.match(r"\s*([A-Z0-9_a-z]+) *= *(\w+) *\\( *(\w+) *\\) *,?(?: *// *(.*) *)?$",84line)85if m is not None:86return (None, None, None)8788# Match: " FRED = 1U<<0, // optional comment"89m = re.match(r"\s*([A-Z0-9_a-z]+) *= *[(]?3U? *[<][<] *(\d+)(?:, *// *(.*) *)?",90line)91if m is not None:92return (m.group(1), 1 << int(m.group(2)), m.group(3))9394# Match: "#define FRED 1 // optional comment"95m = re.match(r"#define\s*([A-Z0-9_a-z]+)\s+(-?\d+) *(// *(.*) *)?$", line)96if m is not None:97return (m.group(1), m.group(2), m.group(4))9899if m is None:100raise ValueError("Failed to match (%s)" % line)101102def enumerations_from_file(self, source_file):103def debug(x):104pass105# if source_file == "/home/pbarker/rc/ardupilot/libraries/AP_HAL/AnalogIn.h":106# debug = print107state_outside = "outside"108state_inside = "inside"109110state = state_outside111112enumerations = []113with open(source_file) as f:114enum_name = None115in_class = None116while True:117line = f.readline()118# debug(f"{state} line: {line}")119if line == "":120break121line = line.rstrip()122# print("state=%s line: %s" % (state, line))123# Skip single-line comments - unless they contain LoggerEnum tags124if re.match(r"\s*//.*", line) and "LoggerEnum" not in line:125continue126# Skip multi-line comments127if re.match(r"\s*/\*.*", line):128while "*/" not in line:129line = f.readline()130continue131if state == "outside":132if re.match("class .*;", line) is not None:133# forward-declaration of a class134continue135m = re.match(r"class *([:\w]+)", line)136if m is not None:137in_class = m.group(1)138continue139m = re.match(r"namespace *(\w+)", line)140if m is not None:141in_class = m.group(1)142continue143m = re.match(r".*enum\s*(class)? *([\w]+)\s*(?::.*_t)? *{(.*)};", line)144if m is not None:145# all one one line! Thanks!146enum_name = m.group(2)147debug("ol: %s: %s" % (source_file, enum_name))148entries_string = m.group(3)149entry_names = [x.strip() for x in entries_string.split(",")]150count = 0151entries = []152for entry in entry_names:153entries.append(EnumDocco.EnumEntry(enum_name, count, None))154count += 1155new_enumeration = EnumDocco.Enumeration(enum_name, entries)156enumerations.append(new_enumeration)157continue158159m = re.match(r".*enum\s*(class)? *([\w]+)\s*(?::.*_t)? *{", line)160if m is not None:161enum_name = m.group(2)162debug("%s: %s" % (source_file, enum_name))163entries = []164last_value = None165state = state_inside166skip_enumeration = False167continue168169# // @LoggerEnum: NAME - can be used around for #define sets170m = re.match(r".*@LoggerEnum: *([\w:]+)", line)171if m is not None:172enum_name = m.group(1)173debug("%s: %s" % (source_file, enum_name))174entries = []175last_value = None176state = state_inside177skip_enumeration = False178continue179180continue181if state == "inside":182if re.match(r"\s*enum.*$", line):183# Allow @LoggerEnum around Enum for name override184continue185if re.match(r"\s*$", line):186continue187if re.match(r"#if", line):188continue189if re.match(r"#endif", line):190continue191if re.match(r"#else", line):192continue193if re.match(r".*}\s*\w*(\s*=\s*[\w:]+)?;", line) or "@LoggerEnumEnd" in line:194# potential end of enumeration195if not skip_enumeration:196if enum_name is None:197raise Exception("WT??")198if in_class is not None:199enum_name = "::".join([in_class, enum_name])200new_enumeration = EnumDocco.Enumeration(enum_name, entries)201enumerations.append(new_enumeration)202# print("Got enum (%s)" % enum_name)203# for entry in new_enumeration.entries:204# print(" %s: %u (%s)" % (entry.name, entry.value, entry.comment))205state = state_outside206continue207(name, value, comment) = self.match_enum_line(line)208if name is None:209skip_enumeration = True210continue211debug(" name=(%s) value=(%s) comment=(%s)\n" % (name, value, comment))212if value is None:213if last_value is None:214value = 0215last_value = 0216else:217last_value += 1218value = last_value219else:220value = int(value)221last_value = value222# print("entry=%s value=%s comment=%s" % (name, value, comment))223entries.append(EnumDocco.EnumEntry(name, value, comment))224return enumerations225226class Enumeration(object):227228def __init__(self, name, entries):229# print("creating enum %s" % name)230self.name = name231self.entries = entries232233def search_for_files(self, dirs_to_search):234_next = []235for _dir in dirs_to_search:236for entry in os.listdir(_dir):237if "AP_Scripting/lua" in _dir:238continue239if "modules" in _dir:240continue241if "examples" in _dir:242continue243filepath = os.path.join(_dir, entry)244if os.path.isdir(filepath):245_next.append(filepath)246continue247(name, extension) = os.path.splitext(filepath)248if extension not in [".cpp", ".h"]:249continue250if filepath.endswith("libraries/AP_HAL/utility/getopt_cpp.h"):251continue252# Failed to match ( IOEVENT_PWM = EVENT_MASK(1),)253if filepath.endswith("libraries/AP_IOMCU/iofirmware/iofirmware.cpp"):254continue255self.files.append(filepath)256if len(_next):257self.search_for_files(_next)258259def parse_files(self):260for _file in self.files:261self.enumerations.extend(self.enumerations_from_file(_file))262263def get_enumerations(self):264self.files = []265self.search_for_files([os.path.join(topdir, x) for x in [266self.vehicle_map[self.vehicle],267"libraries"]])268self.parse_files()269return self.enumerations270271def run(self):272self.get_enumerations()273274275if __name__ == '__main__':276parser = argparse.ArgumentParser(description="Parse parameters.")277parser.add_argument("-v", "--verbose", dest='verbose', action='store_true', default=False, help="show debugging output")278parser.add_argument("--vehicle", required=True, help="Vehicle type to generate for")279280args = parser.parse_args()281282s = EnumDocco(args.vehicle)283284if args.vehicle not in s.vehicle_map:285print("Invalid vehicle (choose from: %s)" % str(s.vehicle_map.keys()))286sys.exit(1)287288s.run()289290291