def visitForBlock(self, element: Element) -> ResultType: """ Handle for loop block. """ Error.assertHasAttr(element=element, attr="value1") Error.assertHasAttr(element=element, attr="iterable") Error.assertHasSequence(element=element, sequence="nested") value1 = element.getAttr("value1").value value2 = element.getAttrValue("value2") sequence = element.getNestedSequence(kind="nested") assert sequence block: ResultType = [] # Loop through the elements iterable = self.resolveName(name=element.getAttr("iterable").value) if value2 is None: for value in iterable: self.substitutions.register(element=element, key=value1, value=value) block += self._visit(sequence=sequence) self.substitutions.unregister(value1) else: iterablePair = iterable.items() if isinstance( iterable, dict) else enumerate(iterable) for key, value in iterablePair: self.substitutions.register(element=element, key=value1, value=key) self.substitutions.register(element=element, key=value2, value=value) block += self._visit(sequence=sequence) self.substitutions.unregister(value2) self.substitutions.unregister(value1) return block
def readValue(self, element: Element) -> typing.Any: """ Read a value from an element. """ Error.assertHasAttr(element=element, attr="value") Error.assertHasAttr(element=element, attr="type") valueType = element.getAttr("type").value value = element.getAttr("value").value if valueType == "name": return self.resolveName(value) elif valueType == "number": return float(value) elif valueType == "string": return value elif valueType == "true": return True elif valueType == "false": return False Error.handleFromElement(element=element, message="Unsupported value type.")
def elementToEntity(element: Element, extension: typing.Optional[typing.Dict[str, typing.Type[EntityType]]] = None) -> EntityType: """ Instantiate an entity from an element. """ Error.assertHasAttr(element=element, attr="category") category = element.getAttr("category").value if extension and category in extension: return extension[category](element=element) if category not in CATEGORY_TO_ENTITY: Error.handleFromElement(element=element, message="Unexpected element category: {}".format(category)) return CATEGORY_TO_ENTITY[category](element=element)
def visitMacro(self, element: Element) -> None: """ Handle macro definition block. """ Error.assertHasSequence(element=element, sequence="argument") Error.assertHasSequence(element=element, sequence="nested") Error.assertHasAttr(element=element, attr="name") name = element.getAttr("name").value Error.assertTrue( element=element, attr="name", condition=(name not in self.substitutions), message= "Name conflict with macro and an already existing name: '{}'.". format(name)) # Register the macro self.substitutions.register( element=element, key=name, value=lambda *args: self.processMacro(element, *args))
def visitElement(self, element: Element, result: typing.List[str], nested: typing.Optional[typing.List[str]]) -> typing.List[str]: if element.isAttr("type"): entity = Type(element=element, kind="type", underlyingType="fqn_type", template="template_resolved" if self.isResolved else "template", argumentTemplate="argument_template_resolved" if self.isResolved else None, const="const") output = self.visitType(entity=entity, nested=[] if nested is None else nested, parameters=entity.parametersTemplateResolved) else: Error.assertHasAttr(element=element, attr="value") Error.assertTrue(element=element, condition=not nested, message="Value cannot have nested entities.") output = self.visitValue(value=element.getAttr("value").value, comment=element.getAttrValue("comment")) result.append(output) return result
def visitElement(self, element: Element, result: ResultType) -> ResultType: """ Go through all elements and dispatch the action. """ Error.assertHasAttr(element=element, attr="category") category = element.getAttr("category").value try: # Raw content if category == "content": Error.assertHasAttr(element=element, attr="content") string = element.getAttr("content").value result.append(string) # Substitution elif category == "substitution": self.visitSubstitution(element=element, result=result) # Comments elif category == "comment": pass # End statement elif category == "end": # Reset the else flag here to make sure nested if without else do not trigger. self.followElse = False # For loop block elif category == "for": block = self.visitForBlock(element=element) self.appendBlock(element=element, result=result, block=block) # If block elif category == "if": Error.assertHasAttr(element=element, attr="condition") conditionStr = element.getAttr("condition").value block = self.visitIfBlock(element=element, conditionStr=conditionStr) self.appendBlock(element=element, result=result, block=block) # Else block elif category == "else": block = [] if self.followElse: conditionStr = element.getAttrValue("condition", "True") # type: ignore block = self.visitIfBlock(element=element, conditionStr=conditionStr) self.appendBlock(element=element, result=result, block=block) # Macro block elif category == "macro": self.visitMacro(element=element) elif category == "include": block = self.visitInclude(element=element) self.appendBlock(element=element, result=result, block=block) else: raise Exception("Unsupported category: '{}'.".format(category)) # Propagate processed exception to the top layer except ExceptionParser as e: raise e except Exception as e: Error.handleFromElement(element=element, message=str(e)) return result
def visitElement(self, element: Element, result: typing.List[str]) -> typing.List[str]: Error.assertHasAttr(element=element, attr="name") result.append(element.getAttr("name").value) return result