Support relative type references in msg files

This commit is contained in:
Marko Durkovic
2021-07-08 09:18:54 +02:00
parent 3d694b20f6
commit 117a4f6348
4 changed files with 57 additions and 10 deletions
+5
View File
@@ -253,6 +253,11 @@ class VisitorIDL(Visitor): # pylint: disable=too-many-public-methods
RULES = parse_grammar(GRAMMAR_IDL)
def __init__(self):
"""Initialize."""
super().__init__()
self.typedefs = {}
def visit_specification(self, children: Any) -> Typesdict:
"""Process start symbol, return only children of modules."""
children = [x[0] for x in children if x is not None]
+9 -5
View File
@@ -89,10 +89,11 @@ def normalize_msgtype(name: str) -> str:
return str(path)
def normalize_fieldtype(field: Any, names: List[str]):
def normalize_fieldtype(typename: str, field: Any, names: List[str]):
"""Normalize field typename.
Args:
typename: Type name of field owner.
field: Field definition.
names: Valid message names.
@@ -111,9 +112,12 @@ def normalize_fieldtype(field: Any, names: List[str]):
else:
if name in dct:
name = dct[name]
elif name == 'Header':
name = 'std_msgs/msg/Header'
elif '/' not in name:
name = str(Path(typename).parent / name)
elif '/msg/' not in name:
ptype = Path(name)
name = str(ptype.parent / 'msg' / ptype.name)
name = str((path := Path(name)).parent / 'msg' / path.name)
inamedef = (Nodetype.NAME, name)
if namedef[0] == Nodetype.NAME:
@@ -159,9 +163,9 @@ class VisitorMSG(Visitor):
typelist = [children[0], *[x[1] for x in children[1]]]
typedict = dict(typelist)
names = list(typedict.keys())
for _, fields in typedict.items():
for name, fields in typedict.items():
for field in fields:
normalize_fieldtype(field, names)
normalize_fieldtype(name, field, names)
return typedict
def visit_msgdef(self, children: Any) -> Any:
+27 -5
View File
@@ -58,10 +58,22 @@ class Rule:
class RuleLiteral(Rule):
"""Rule to match string literal."""
def __init__(self, value: Any, rules: Dict[str, Rule], name: Optional[str] = None):
"""Initialize.
Args:
value: Value of this rule.
rules: Grammar containing all rules.
name: Name of this rule.
"""
super().__init__(value, rules, name)
self.value = value[1:-1].replace('\\\'', '\'')
def parse(self, text: str, pos: int) -> Tuple[int, Any]:
"""Apply rule at position."""
value: str = self.value[1:-1].replace('\\\'', '\'')
if text[pos:].startswith(value):
value = self.value
if text[pos:pos + len(value)] == value:
npos = pos + len(value)
npos = self.skip_ws(text, npos)
return npos, (self.LIT, value)
@@ -71,10 +83,21 @@ class RuleLiteral(Rule):
class RuleRegex(Rule):
"""Rule to match regular expression."""
def __init__(self, value: Any, rules: Dict[str, Rule], name: Optional[str] = None):
"""Initialize.
Args:
value: Value of this rule.
rules: Grammar containing all rules.
name: Name of this rule.
"""
super().__init__(value, rules, name)
self.value = re.compile(value[2:-1], re.M | re.S)
def parse(self, text: str, pos: int) -> Tuple[int, Any]:
"""Apply rule at position."""
pattern = re.compile(self.value[2:-1], re.M | re.S)
match = pattern.match(text, pos)
match = self.value.match(text, pos)
if not match:
return -1, []
npos = self.skip_ws(text, match.span()[1])
@@ -171,7 +194,6 @@ class Visitor: # pylint: disable=too-few-public-methods
def __init__(self):
"""Initialize."""
self.typedefs = {}
def visit(self, tree: Any) -> Any:
"""Visit all nodes in parse tree."""