"description": "DESCRIPTION",
}
- tokens = ["STRING_LITERAL", "ID", "NUM"] + list(reserved.values())
+ tokens = ["STRING_LITERAL", "COMMENT", "ID", "NUM"] + list(reserved.values())
t_ignore_LINE_COMMENT = "//.*"
return t
# C or C++ comment (ignore)
- def t_comment(self, t):
+ def t_COMMENT(self, t):
r"(/\*(.|\n)*?\*/)|(//.*)"
t.lexer.lineno += t.value.count("\n")
+ return t
# Error handling rule
def t_error(self, t):
class Define(Processable):
type = "Define"
- def __init__(self, name, flags, block):
+ def __init__(self, name, flags, block, comment=None):
self.name = name
self.flags = flags
self.block = block
self.autoreply = False
self.autoendian = 0
self.options = {}
+ self.comment = comment
for f in flags:
if f == "dont_trace":
self.dont_trace = True
self.vla = False
self.manual_print = False
- count = 0
+ count = -1
block2 = []
block3 = []
bc_set = False
self.logger = logger
self.fields = []
self.revision = revision
+ self.last_comment = None
def _parse_error(self, msg, coord):
raise ParseError("%s: %s" % (coord, msg))
| union
| service
| paths
+ | comment
| counters"""
p[0] = p[1]
def p_define(self, p):
"""define : DEFINE ID '{' block_statements_opt '}' ';'"""
self.fields = []
- p[0] = Define(p[2], [], p[4])
+ p[0] = Define(p[2], [], p[4], self.last_comment)
def p_define_flist(self, p):
"""define : flist DEFINE ID '{' block_statements_opt '}' ';'"""
self._token_coord(p, 1),
)
else:
- p[0] = Define(p[3], p[1], p[5])
+ p[0] = Define(p[3], p[1], p[5], self.last_comment)
def p_flist(self, p):
"""flist : flag
"""
p[0] = p[1]
+ def p_comment(self, p):
+ """comment : COMMENT"""
+ self.last_comment = p[1]
+ p[0] = []
+
def p_declaration(self, p):
"""declaration : type_specifier variable_name ';'
| type_specifier variable_name '[' field_options ']' ';'
# Error rule for syntax errors
def p_error(self, p):
if p:
+ if p.type == "COMMENT":
+ self.parser.errok()
+ return
self._parse_error("before: %s" % p.value, self._coord(lineno=p.lineno))
else:
self._parse_error("At end of input", self.filename)
+ def build(self, **kwargs):
+ self.parser = yacc.yacc(module=self, **kwargs)
+
class VPPAPI:
def __init__(self, debug=False, filename="", logger=None, revision=None):
self.lexer = lex.lex(module=VPPAPILexer(filename), debug=debug)
- self.parser = yacc.yacc(
- module=VPPAPIParser(filename, logger, revision=revision),
- write_tables=False,
- debug=debug,
- )
+ self.parser = VPPAPIParser(filename, logger, revision=revision)
+ self.parser.build(write_tables=False, debug=debug)
self.logger = logger
self.revision = revision
self.filename = filename
def parse_string(self, code, debug=0, lineno=1):
self.lexer.lineno = lineno
- return self.parser.parse(code, lexer=self.lexer, debug=debug)
+ return self.parser.parser.parse(code, lexer=self.lexer, debug=debug)
def parse_fd(self, fd, debug=0):
data = fd.read()
f.crc = foldup_blocks(f.block, binascii.crc32(f.crc) & 0xFFFFFFFF)
-#
-# Main
-#
-def main():
- if sys.version_info < (
- 3,
- 5,
- ):
- log.exception(
- "vppapigen requires a supported version of python. "
- "Please use version 3.5 or greater. "
- "Using %s",
- sys.version,
- )
- return 1
-
- cliparser = argparse.ArgumentParser(description="VPP API generator")
- cliparser.add_argument("--pluginpath", default="")
- cliparser.add_argument("--includedir", action="append")
- cliparser.add_argument("--outputdir", action="store")
- cliparser.add_argument("--input")
- cliparser.add_argument(
- "--output",
- nargs="?",
- type=argparse.FileType("w", encoding="UTF-8"),
- default=sys.stdout,
- )
-
- cliparser.add_argument("output_module", nargs="?", default="C")
- cliparser.add_argument("--debug", action="store_true")
- cliparser.add_argument("--show-name", nargs=1)
- cliparser.add_argument(
- "--git-revision", help="Git revision to use for opening files"
- )
- args = cliparser.parse_args()
-
- dirlist_add(args.includedir)
- if not args.debug:
+def run_vppapigen(
+ input_file=None,
+ output=sys.stdout,
+ includedir=None,
+ debug=False,
+ show_name=None,
+ output_module="C",
+ outputdir=None,
+ pluginpath="",
+ git_revision=None,
+):
+ # reset globals
+ dirlist.clear()
+ global_types.clear()
+ seen_imports.clear()
+
+ dirlist_add(includedir)
+ if not debug:
sys.excepthook = exception_handler
# Filename
- if args.show_name:
- filename = args.show_name[0]
- elif args.input:
- filename = args.input
+ if show_name:
+ filename = show_name[0]
+ elif input_file:
+ filename = input_file
else:
filename = ""
- if args.debug:
+ if debug:
logging.basicConfig(stream=sys.stdout, level=logging.WARNING)
else:
logging.basicConfig()
# Default path
pluginpath = ""
- if not args.pluginpath:
+ if not pluginpath:
cand = []
cand.append(os.path.dirname(os.path.realpath(__file__)))
cand.append(os.path.dirname(os.path.realpath(__file__)) + "/../share/vpp/")
for c in cand:
c += "/"
- if os.path.isfile(
- "{}vppapigen_{}.py".format(c, args.output_module.lower())
- ):
+ if os.path.isfile("{}vppapigen_{}.py".format(c, output_module.lower())):
pluginpath = c
break
else:
- pluginpath = args.pluginpath + "/"
+ pluginpath = pluginpath + "/"
if pluginpath == "":
log.exception("Output plugin not found")
return 1
- module_path = "{}vppapigen_{}.py".format(pluginpath, args.output_module.lower())
+ module_path = "{}vppapigen_{}.py".format(pluginpath, output_module.lower())
try:
- plugin = SourceFileLoader(args.output_module, module_path).load_module()
+ plugin = SourceFileLoader(output_module, module_path).load_module()
except Exception as err:
log.exception("Error importing output plugin: %s, %s", module_path, err)
return 1
- parser = VPPAPI(
- debug=args.debug, filename=filename, logger=log, revision=args.git_revision
- )
+ parser = VPPAPI(debug=debug, filename=filename, logger=log, revision=git_revision)
try:
- if not args.input:
+ if not input_file:
parsed_objects = parser.parse_fd(sys.stdin, log)
else:
- parsed_objects = parser.parse_filename(args.input, log)
+ parsed_objects = parser.parse_filename(input_file, log)
except ParseError as e:
print("Parse error: ", e, file=sys.stderr)
sys.exit(1)
#
# Debug
- if args.debug:
+ if debug:
import pprint
pp = pprint.PrettyPrinter(indent=4, stream=sys.stderr)
for t in s["types"]:
pp.pprint([t.name, t.block])
- result = plugin.run(args, filename, s)
+ result = plugin.run(outputdir, filename, s)
if result:
- print(result, file=args.output)
+ if isinstance(output, str):
+ with open(output, "w", encoding="UTF-8") as f:
+ print(result, file=f)
+ else:
+ print(result, file=output)
else:
log.exception("Running plugin failed: %s %s", filename, result)
return 1
return 0
+def run_kw_vppapigen(kwargs):
+ return run_vppapigen(**kwargs)
+
+
+#
+# Main
+#
+def main():
+ if sys.version_info < (
+ 3,
+ 5,
+ ):
+ log.exception(
+ "vppapigen requires a supported version of python. "
+ "Please use version 3.5 or greater. "
+ "Using %s",
+ sys.version,
+ )
+ return 1
+
+ cliparser = argparse.ArgumentParser(description="VPP API generator")
+ cliparser.add_argument("--pluginpath", default="")
+ cliparser.add_argument("--includedir", action="append")
+ cliparser.add_argument("--outputdir", action="store")
+ cliparser.add_argument("--input")
+ cliparser.add_argument(
+ "--output",
+ nargs="?",
+ type=argparse.FileType("w", encoding="UTF-8"),
+ default=sys.stdout,
+ )
+
+ cliparser.add_argument("output_module", nargs="?", default="C")
+ cliparser.add_argument("--debug", action="store_true")
+ cliparser.add_argument("--show-name", nargs=1)
+ cliparser.add_argument(
+ "--git-revision", help="Git revision to use for opening files"
+ )
+ args = cliparser.parse_args()
+
+ return run_vppapigen(
+ includedir=args.includedir,
+ debug=args.debug,
+ outputdir=args.outputdir,
+ show_name=args.show_name,
+ input_file=args.input,
+ output_module=args.output_module,
+ pluginpath=args.pluginpath,
+ git_revision=args.git_revision,
+ output=args.output,
+ )
+
+
if __name__ == "__main__":
sys.exit(main())