diff options
Diffstat (limited to 'src/core/parser/stack')
| -rw-r--r-- | src/core/parser/stack/DocumentHandler.cpp | 383 | ||||
| -rw-r--r-- | src/core/parser/stack/DocumentHandler.hpp | 78 | ||||
| -rw-r--r-- | src/core/parser/stack/DomainHandler.cpp | 60 | ||||
| -rw-r--r-- | src/core/parser/stack/Stack.cpp | 5 | 
4 files changed, 336 insertions, 190 deletions
diff --git a/src/core/parser/stack/DocumentHandler.cpp b/src/core/parser/stack/DocumentHandler.cpp index d514701..49bf26b 100644 --- a/src/core/parser/stack/DocumentHandler.cpp +++ b/src/core/parser/stack/DocumentHandler.cpp @@ -51,20 +51,15 @@ void DocumentHandler::end() { scope().pop(); }  /* DocumentChildHandler */ -void DocumentChildHandler::preamble(Handle<Node> parentNode, -                                    std::string &fieldName, -                                    DocumentEntity *&parent, bool &inField) +void DocumentChildHandler::preamble(Rooted<Node> &parentNode, size_t &fieldIdx, +                                    DocumentEntity *&parent)  {  	// Check if the parent in the structure tree was an explicit field  	// reference. -	inField = parentNode->isa(&RttiTypes::DocumentField); -	if (inField) { -		fieldName = parentNode->getName(); +	if (parentNode->isa(&RttiTypes::DocumentField)) { +		fieldIdx = parentNode.cast<DocumentField>()->fieldIdx;  		parentNode = scope().selectOrThrow(  		    {&RttiTypes::StructuredEntity, &RttiTypes::AnnotationEntity}); -	} else { -		// If it wasn't an explicit reference, we use the default field. -		fieldName = DEFAULT_FIELD_NAME;  	}  	// Reference the parent entity explicitly. @@ -78,124 +73,235 @@ void DocumentChildHandler::preamble(Handle<Node> parentNode,  	}  } -static void createPath(const NodeVector<Node> &path, DocumentEntity *&parent, -                       size_t p0 = 1) +void DocumentChildHandler::createPath(const NodeVector<Node> &path, +                                      DocumentEntity *&parent, size_t p0)  { -	// TODO (@benjamin): These should be pushed onto the scope and poped once -	// the scope is left. Otherwise stuff may not be correclty resolved.  	size_t S = path.size();  	for (size_t p = p0; p < S; p = p + 2) { -		parent = static_cast<DocumentEntity *>( -		    parent->createChildStructuredEntity( -		                path[p].cast<StructuredClass>(), Variant::mapType{}, -		                path[p - 1]->getName(), "").get()); +		// add the field. +		Rooted<DocumentField> field{new DocumentField( +		    manager(), scope().getLeaf(), +		    parent->getDescriptor()->getFieldDescriptorIndex(), true)}; +		scope().push(field); +		// add the transparent/implicit structure element. +		Rooted<StructuredEntity> transparent = +		    parent->createChildStructuredEntity(path[p].cast<StructuredClass>(), +		                                        Variant::mapType{}, +		                                        path[p - 1]->getName(), ""); +		transparent->setLocation(location()); +		transparent->setTransparent(true); +		scope().push(transparent); +		parent = static_cast<DocumentEntity *>(transparent.get());  	} +	// add the last field. +	Rooted<DocumentField> field{new DocumentField( +	    manager(), scope().getLeaf(), +	    parent->getDescriptor()->getFieldDescriptorIndex(), true)}; +	scope().push(field);  } -static void createPath(const std::string &firstFieldName, -                       const NodeVector<Node> &path, DocumentEntity *&parent) +void DocumentChildHandler::createPath(const size_t &firstFieldIdx, +                                      const NodeVector<Node> &path, +                                      DocumentEntity *&parent)  {  	// Add the first element -	parent = static_cast<DocumentEntity *>( -	    parent->createChildStructuredEntity(path[0].cast<StructuredClass>(), -	                                        Variant::mapType{}, firstFieldName, -	                                        "").get()); +	Rooted<StructuredEntity> transparent = parent->createChildStructuredEntity( +	    path[0].cast<StructuredClass>(), firstFieldIdx); +	transparent->setLocation(location()); +	transparent->setTransparent(true); +	scope().push(transparent); +	parent = static_cast<DocumentEntity *>(transparent.get());  	createPath(path, parent, 2);  }  bool DocumentChildHandler::start(Variant::mapType &args)  { +	// extract the special "name" attribute from the input arguments. +	// the remaining attributes will be forwarded to the newly constructed +	// element. +	std::string nameAttr; +	{ +		auto it = args.find("name"); +		if (it != args.end()) { +			nameAttr = it->second.asString(); +			args.erase(it); +		} +	} +  	scope().setFlag(ParserFlag::POST_HEAD, true); -	Rooted<Node> parentNode = scope().selectOrThrow( -	    {&RttiTypes::Document, &RttiTypes::StructuredEntity, -	     &RttiTypes::AnnotationEntity, &RttiTypes::DocumentField}); +	while (true) { +		Rooted<Node> parentNode = scope().getLeaf(); + +		Rooted<StructuredEntity> entity; +		// handle the root note specifically. +		if (parentNode->isa(&RttiTypes::Document)) { +			Rooted<StructuredClass> strct = scope().resolve<StructuredClass>( +			    Utils::split(name(), ':'), logger()); +			if (strct == nullptr) { +				// if we could not resolve the name, throw an exception. +				throw LoggableException( +				    std::string("\"") + name() + "\" could not be resolved.", +				    location()); +			} +			entity = parentNode.cast<Document>()->createRootStructuredEntity( +			    strct, args, nameAttr); +		} else { +			assert(parentNode->isa(&RttiTypes::DocumentField)); -	std::string fieldName; -	DocumentEntity *parent; -	bool inField; - -	preamble(parentNode, fieldName, parent, inField); - -	// Try to find a FieldDescriptor for the given tag if we are not in a -	// field already. This does _not_ try to construct transparent paths -	// in between. -	if (!inField && parent != nullptr && -	    parent->getDescriptor()->hasField(name())) { -		Rooted<DocumentField> field{ -		    new DocumentField(parentNode->getManager(), name(), parentNode)}; -		field->setLocation(location()); -		scope().push(field); -		return true; -	} +			size_t fieldIdx; +			DocumentEntity *parent; -	// Otherwise create a new StructuredEntity -	// TODO: Consider Anchors and AnnotationEntities -	Rooted<StructuredClass> strct = -	    scope().resolve<StructuredClass>(Utils::split(name(), ':'), logger()); -	if (strct == nullptr) { -		// if we could not resolve the name, throw an exception. -		throw LoggableException( -		    std::string("\"") + name() + "\" could not be resolved.", -		    location()); -	} +			preamble(parentNode, fieldIdx, parent); -	std::string name; -	auto it = args.find("name"); -	if (it != args.end()) { -		name = it->second.asString(); -		args.erase(it); -	} +			// TODO: REMOVE +			std::string thisName = name(); +			std::string parentClassName; +			if (parent != nullptr) { +				parentClassName = parent->getDescriptor()->getName(); +			} -	Rooted<StructuredEntity> entity; -	if (parentNode->isa(&RttiTypes::Document)) { -		entity = parentNode.cast<Document>()->createRootStructuredEntity( -		    strct, args, name); -	} else { -		// calculate a path if transparent entities are needed in between. -		std::string lastFieldName = fieldName; -		if (inField) { -			Rooted<FieldDescriptor> field = -			    parent->getDescriptor()->getFieldDescriptor(fieldName); -			auto pathRes = -			    field.cast<FieldDescriptor>()->pathTo(strct, logger()); -			if (!pathRes.second) { +			/* +			 * Try to find a FieldDescriptor for the given tag if we are not in +			 * a field already. This does _not_ try to construct transparent +			 * paths in between. +			 */ +			{ +				ssize_t newFieldIdx = +				    parent->getDescriptor()->getFieldDescriptorIndex(name()); +				if (newFieldIdx != -1) { +					Rooted<DocumentField> field{new DocumentField( +					    manager(), parentNode, newFieldIdx, false)}; +					field->setLocation(location()); +					scope().push(field); +					isExplicitField = true; +					return true; +				} +			} + +			// Otherwise create a new StructuredEntity +			// TODO: Consider Anchors and AnnotationEntities +			Rooted<StructuredClass> strct = scope().resolve<StructuredClass>( +			    Utils::split(name(), ':'), logger()); +			if (strct == nullptr) { +				// if we could not resolve the name, throw an exception.  				throw LoggableException( -				    std::string("An instance of \"") + strct->getName() + -				        "\" is not allowed as child of field \"" + fieldName + -				        "\"", +				    std::string("\"") + name() + "\" could not be resolved.",  				    location());  			} -			if (!pathRes.first.empty()) { -				createPath(fieldName, pathRes.first, parent); -				lastFieldName = DEFAULT_FIELD_NAME; -			} -		} else { -			auto path = parent->getDescriptor()->pathTo(strct, logger()); -			if (path.empty()) { + +			// calculate a path if transparent entities are needed in between. +			Rooted<FieldDescriptor> field = +			    parent->getDescriptor()->getFieldDescriptors()[fieldIdx]; +			size_t lastFieldIdx = fieldIdx; +			auto pathRes = field->pathTo(strct, logger()); +			if (!pathRes.second) { +				if (scope().getLeaf().cast<DocumentField>()->transparent) { +					// if we have transparent elements above us in the structure +					// tree we try to unwind them before we give up. +					// pop the implicit field. +					scope().pop(); +					// pop the implicit element. +					scope().pop(); +					continue; +				}  				throw LoggableException(  				    std::string("An instance of \"") + strct->getName() + -				        "\" is not allowed as child of an instance of \"" + +				        "\" is not allowed as child of field \"" + +				        field->getName() + "\" of descriptor \"" +  				        parent->getDescriptor()->getName() + "\"",  				    location());  			} - -			// create all transparent entities until the last field. -			createPath(path, parent); -			if (path.size() > 1) { -				lastFieldName = DEFAULT_FIELD_NAME; +			if (!pathRes.first.empty()) { +				createPath(lastFieldIdx, pathRes.first, parent); +				lastFieldIdx = +				    parent->getDescriptor()->getFieldDescriptorIndex();  			} +			// create the entity for the new element at last. +			entity = parent->createChildStructuredEntity(strct, lastFieldIdx, +			                                             args, nameAttr); +		} +		entity->setLocation(location()); +		scope().push(entity); +		return true; +	} +} + +void DocumentChildHandler::end() +{ +	// in case of explicit fields we do not want to pop something from the +	// stack. +	if (isExplicitField) { +		return; +	} +	// pop the "main" element. +	scope().pop(); +} + +bool DocumentChildHandler::fieldStart(bool &isDefault, size_t fieldIdx) +{ +	if (isExplicitField) { +		// In case of explicit fields we do not want to create another field. +		isDefault = true; +		return fieldIdx == 0; +	} +	Rooted<Node> parentNode = scope().getLeaf(); +	assert(parentNode->isa(&RttiTypes::StructuredEntity) || +	       parentNode->isa(&RttiTypes::AnnotationEntity)); +	size_t dummy; +	DocumentEntity *parent; + +	preamble(parentNode, dummy, parent); + +	NodeVector<FieldDescriptor> fields = +	    parent->getDescriptor()->getFieldDescriptors(); + +	if (isDefault) { +		fieldIdx = fields.size() - 1; +	} else { +		if (fieldIdx >= fields.size()) { +			return false;  		} -		// create the entity for the new element at last. -		entity = parent->createChildStructuredEntity(strct, args, lastFieldName, -		                                             name); +		isDefault = fieldIdx == fields.size() - 1;  	} -	entity->setLocation(location()); -	scope().push(entity); +	// push the field on the stack. +	Rooted<DocumentField> field{ +	    new DocumentField(manager(), parentNode, fieldIdx, false)}; +	field->setLocation(location()); +	scope().push(field);  	return true;  } -void DocumentChildHandler::end() { scope().pop(); } +void DocumentChildHandler::fieldEnd() +{ +	assert(scope().getLeaf()->isa(&RttiTypes::DocumentField)); + +	// pop the field from the stack. +	scope().pop(); + +	// pop all remaining transparent elements. +	while (scope().getLeaf()->isa(&RttiTypes::StructuredEntity) && +	       scope().getLeaf().cast<StructuredEntity>()->isTransparent()) { +		// pop the transparent element. +		scope().pop(); +		// pop the transparent field. +		scope().pop(); +	} +} + +bool DocumentChildHandler::annotationStart(const Variant &className, +                                           Variant::mapType &args) +{ +	// TODO: Implement +	return false; +} + +bool DocumentChildHandler::annotationEnd(const Variant &className, +                                         const Variant &elementName) +{ +	// TODO: Implement +	return false; +}  bool DocumentChildHandler::convertData(Handle<FieldDescriptor> field,                                         Variant &data, Logger &logger) @@ -226,71 +332,40 @@ bool DocumentChildHandler::convertData(Handle<FieldDescriptor> field,  bool DocumentChildHandler::data(Variant &data)  { -	Rooted<Node> parentNode = scope().selectOrThrow( -	    {&RttiTypes::StructuredEntity, &RttiTypes::AnnotationEntity, -	     &RttiTypes::DocumentField}); - -	std::string fieldName; -	DocumentEntity *strctParent; -	bool inField; - -	preamble(parentNode, fieldName, strctParent, inField); - -	Rooted<Descriptor> desc = strctParent->getDescriptor(); -	// The parent from which we need to connect to the primitive content. -	Rooted<Node> parentClass; - -	// We distinguish two cases here: One for fields that are given. -	if (inField) { -		// Retrieve the actual FieldDescriptor -		Rooted<FieldDescriptor> field = desc->getFieldDescriptor(fieldName); -		if (field == nullptr) { -			logger().error( -			    std::string("Can't handle data because no field with name \"") + -			        fieldName + "\" exists in descriptor\"" + desc->getName() + -			        "\".", -			    location()); +	Rooted<Node> parentField = scope().getLeaf(); +	assert(parentField->isa(&RttiTypes::DocumentField)); + +	size_t fieldIdx; +	DocumentEntity *parent; + +	preamble(parentField, fieldIdx, parent); + +	Rooted<Descriptor> desc = parent->getDescriptor(); + +	// Retrieve the actual FieldDescriptor +	Rooted<FieldDescriptor> field = desc->getFieldDescriptors()[fieldIdx]; +	// If it is a primitive field directly, try to parse the content. +	if (field->isPrimitive()) { +		// Add it as primitive content. +		if (!convertData(field, data, logger())) {  			return false;  		} -		// If it is a primitive field directly, try to parse the content. -		if (field->isPrimitive()) { -			// Add it as primitive content. -			if (!convertData(field, data, logger())) { -				return false; -			} -			strctParent->createChildDocumentPrimitive(data, fieldName); -			return true; -		} -		// If it is not primitive we need to connect via transparent elements -		// and default fields. -		parentClass = field; -	} else { -		// In case of default fields we need to construct via default fields -		// and maybe transparent elements. -		parentClass = desc; +		parent->createChildDocumentPrimitive(data, fieldIdx); +		return true;  	}  	// Search through all permitted default fields of the parent class that  	// allow primitive content at this point and could be constructed via  	// transparent intermediate entities. - -	// Retrieve all default fields at this point, either from the field -	// descriptor or the structured class -	NodeVector<FieldDescriptor> defaultFields; -	if (inField) { -		defaultFields = parentClass.cast<FieldDescriptor>()->getDefaultFields(); -	} else { -		defaultFields = parentClass.cast<StructuredClass>()->getDefaultFields(); -	} - +	NodeVector<FieldDescriptor> defaultFields = field->getDefaultFields();  	// Try to parse the data using the type specified by the respective field.  	// If that does not work we proceed to the next possible field.  	std::vector<LoggerFork> forks; -	for (auto field : defaultFields) { +	for (auto primitiveField : defaultFields) {  		// Then try to parse the content using the type specification.  		forks.emplace_back(logger().fork()); -		if (!convertData(field, data, forks.back())) { +		if (!convertData(primitiveField, data, forks.back())) {  			continue;  		} @@ -298,18 +373,12 @@ bool DocumentChildHandler::data(Variant &data)  		forks.back().commit();  		// Construct the necessary path -		if (inField) { -			NodeVector<Node> path = -			    parentClass.cast<FieldDescriptor>()->pathTo(field, logger()); -			createPath(fieldName, path, strctParent); -		} else { -			auto pathRes = desc->pathTo(field, logger()); -			assert(pathRes.second); -			createPath(pathRes.first, strctParent); -		} +		NodeVector<Node> path = field->pathTo(primitiveField, logger()); +		// TODO: Create methods with indices instead of names. +		createPath(fieldIdx, path, parent);  		// Then create the primitive element -		strctParent->createChildDocumentPrimitive(data); +		parent->createChildDocumentPrimitive(data);  		return true;  	} @@ -348,4 +417,4 @@ namespace RttiTypes {  const Rtti DocumentField = RttiBuilder<ousia::parser_stack::DocumentField>(                                 "DocumentField").parent(&Node);  } -} +}
\ No newline at end of file diff --git a/src/core/parser/stack/DocumentHandler.hpp b/src/core/parser/stack/DocumentHandler.hpp index 2c474f9..5953e3a 100644 --- a/src/core/parser/stack/DocumentHandler.hpp +++ b/src/core/parser/stack/DocumentHandler.hpp @@ -76,29 +76,74 @@ public:   */  class DocumentField : public Node {  public: -	using Node::Node; +	const size_t fieldIdx; +	const bool transparent; + +	DocumentField(Manager &mgr, Handle<Node> parent, size_t fieldIdx, +	              bool transparent) +	    : Node(mgr, parent), fieldIdx(fieldIdx), transparent(transparent) +	{ +	}  };  /**   * The DocumentChildHandler class performs the actual parsing of the user   * defined elements in an Ousía document.   */ -class DocumentChildHandler : public StaticHandler { +class DocumentChildHandler : public Handler {  private: +	bool isExplicitField = false; +  	/** -	 * Code shared by both the start() and the end() method. Checks whether the -	 * parser currently is in a field and returns the name of this field. +	 * Code shared by both the start(), fieldStart() and the data() method. +	 * Checks whether the parser currently is in a field and returns the name +	 * of this field.  	 *  	 * @param parentNode is the next possible parent node (a document,  	 * a structured entity, an annotation entity or a field). -	 * @param fieldName is an output parameter to which the name of the current +	 * @param fieldIdx is an output parameter to which the index of the current  	 * field is written (or unchanged if we're not in a field).  	 * @param parent is an output parameter to which the parent document entity  	 * will be written. -	 * @param inField is set to true if we actually are in a field.  	 */ -	void preamble(Handle<Node> parentNode, std::string &fieldName, -	              DocumentEntity *&parent, bool &inField); +	void preamble(Rooted<Node> &parentNode, size_t &fieldIdx, +	              DocumentEntity *&parent); + +	/** +	 * Creates transparent elements that are stored in the given path. +	 * +	 * @param path   a NodeVector of alternating FieldDescriptors and +	 *               StructuredClasses. For each of the StructuredClasses at +	 *               index p an instance is created and added to the field at +	 *               index p-1 of the previously created instance of the +	 *               StructuredClass at index p-2. +	 * @param parent is the parent DocumentEntity for the first transparent +	 *               element. This will be reset for each created transparent +	 *               element. +	 * @param p0     is the index of the path vector of the first +	 *               StructuredClass for which an instance shall be created. +	 *               This is 1 per default. +	 */ +	void createPath(const NodeVector<Node> &path, DocumentEntity *&parent, +	                size_t p0 = 1); + +	/** +	 * Creates transparent elements that are stored in the given path. +	 * +	 * @param fieldIdx  is the index of the field for which the first instance +	 *                  shall be added. +	 * @param path      a NodeVector of alternating FieldDescriptors and +	 *                  StructuredClasses. For each of the StructuredClasses at +	 *                  index p an instance is created and added to the field at +	 *                  index p-1 of the previously created instance of the +	 *                  StructuredClass at index p-2. The first element has +	 *                  to be a StructuredClass. +	 * @param parent    is the parent DocumentEntity for the first transparent +	 *                  element. This will be reset for each created transparent +	 *                  element. +	 */ +	void createPath(const size_t &fieldIdx, const NodeVector<Node> &path, +	                DocumentEntity *&parent);  	/**  	 * Tries to convert the given data to the type that is specified in the @@ -116,12 +161,22 @@ private:  	                 Logger &logger);  public: -	using StaticHandler::StaticHandler; +	using Handler::Handler;  	bool start(Variant::mapType &args) override;  	void end() override;  	bool data(Variant &data) override; +	bool fieldStart(bool &isDefault, size_t fieldIdx) override; + +	void fieldEnd() override; + +	bool annotationStart(const Variant &className, +	                     Variant::mapType &args) override; + +	bool annotationEnd(const Variant &className, +	                   const Variant &elementName) override; +  	/**  	 * Creates a new instance of the DocumentChildHandler.  	 * @@ -146,7 +201,6 @@ extern const State Document;   */  extern const State DocumentChild;  } -  }  namespace RttiTypes { @@ -155,8 +209,6 @@ namespace RttiTypes {   */  extern const Rtti DocumentField;  } -  } -#endif /* _OUSIA_PARSER_STACK_DOCUMENT_HANDLER_HPP_ */ - +#endif /* _OUSIA_PARSER_STACK_DOCUMENT_HANDLER_HPP_ */
\ No newline at end of file diff --git a/src/core/parser/stack/DomainHandler.cpp b/src/core/parser/stack/DomainHandler.cpp index a2c8eec..ddec1ee 100644 --- a/src/core/parser/stack/DomainHandler.cpp +++ b/src/core/parser/stack/DomainHandler.cpp @@ -133,11 +133,18 @@ bool DomainFieldHandler::start(Variant::mapType &args)  	Rooted<Descriptor> parent = scope().selectOrThrow<Descriptor>(); -	Rooted<FieldDescriptor> field = parent->createFieldDescriptor( +	auto res = parent->createFieldDescriptor(  	    logger(), type, args["name"].asString(), args["optional"].asBool()); -	field->setLocation(location()); +	res.first->setLocation(location()); +	if (res.second) { +		logger().warning( +		    std::string("Field \"") + res.first->getName() + +		        "\" was declared after main field. The order of fields " +		        "was changed to make the main field the last field.", +		    *res.first); +	} -	scope().push(field); +	scope().push(res.first);  	return true;  } @@ -150,14 +157,24 @@ bool DomainFieldRefHandler::start(Variant::mapType &args)  	Rooted<Descriptor> parent = scope().selectOrThrow<Descriptor>();  	const std::string &name = args["ref"].asString(); -	scope().resolveFieldDescriptor( -	    name, parent, logger(), -	    [](Handle<Node> field, Handle<Node> parent, Logger &logger) { -		    if (field != nullptr) { -			    parent.cast<StructuredClass>()->addFieldDescriptor( -			        field.cast<FieldDescriptor>(), logger); -		    } -		}); + +	auto loc = location(); + +	scope().resolveFieldDescriptor(name, parent, logger(), +	                               [loc](Handle<Node> field, +	                                     Handle<Node> parent, Logger &logger) { +		if (field != nullptr) { +			if (parent.cast<StructuredClass>()->addFieldDescriptor( +			        field.cast<FieldDescriptor>(), logger)) { +				logger.warning( +				    std::string("Field \"") + field->getName() + +				        "\" was referenced after main field was declared. The " +				        "order of fields was changed to make the main field " +				        "the last field.", +				    loc); +			} +		} +	});  	return true;  } @@ -176,13 +193,20 @@ bool DomainPrimitiveHandler::start(Variant::mapType &args)  		fieldType = FieldDescriptor::FieldType::TREE;  	} -	Rooted<FieldDescriptor> field = parent->createPrimitiveFieldDescriptor( +	auto res = parent->createPrimitiveFieldDescriptor(  	    new UnknownType(manager()), logger(), fieldType,  	    args["name"].asString(), args["optional"].asBool()); -	field->setLocation(location()); +	res.first->setLocation(location()); +	if (res.second) { +		logger().warning( +		    std::string("Field \"") + res.first->getName() + +		        "\" was declared after main field. The order of fields " +		        "was changed to make the main field the last field.", +		    *res.first); +	}  	const std::string &type = args["type"].asString(); -	scope().resolve<Type>(type, field, logger(), +	scope().resolve<Type>(type, res.first, logger(),  	                      [](Handle<Node> type, Handle<Node> field,  	                         Logger &logger) {  		if (type != nullptr) { @@ -190,7 +214,7 @@ bool DomainPrimitiveHandler::start(Variant::mapType &args)  		}  	}); -	scope().push(field); +	scope().push(res.first);  	return true;  } @@ -254,8 +278,8 @@ bool DomainParentFieldHandler::start(Variant::mapType &args)  	                           Logger &logger) {  		    if (parent != nullptr) {  			    Rooted<FieldDescriptor> field = -			        parent.cast<Descriptor>()->createFieldDescriptor( -			            logger, type, name, optional); +			        (parent.cast<Descriptor>()->createFieldDescriptor( +			             logger, type, name, optional)).first;  			    field->addChild(strct.cast<StructuredClass>());  		    }  		}); @@ -390,4 +414,4 @@ namespace RttiTypes {  const Rtti DomainParent = RttiBuilder<ousia::parser_stack::DomainParent>(                                "DomainParent").parent(&Node);  } -} +}
\ No newline at end of file diff --git a/src/core/parser/stack/Stack.cpp b/src/core/parser/stack/Stack.cpp index 905edb4..b98cddb 100644 --- a/src/core/parser/stack/Stack.cpp +++ b/src/core/parser/stack/Stack.cpp @@ -361,9 +361,10 @@ void Stack::command(const Variant &name, const Variant::mapType &args)  		info.valid = false;  		if (validStack) {  			// Canonicalize the arguments (if this has not already been done), -			// allow additional arguments +			// allow additional arguments and numeric indices  			Variant::mapType canonicalArgs = args; -			targetState->arguments.validateMap(canonicalArgs, loggerFork, true); +			targetState->arguments.validateMap(canonicalArgs, loggerFork, true, +			                                   true);  			handler->setLogger(loggerFork);  			try {  | 
