private NodeBunch BuildCustomItem(Element item) { var links = item.GetItemLinks(); var headNode = _nodeFactory.CreateNode(item.AsPseudoList()); if (headNode == null) { throw new BuildingException("Node factory returned null."); } var tree = headNode.FetchTree(); if (tree.Count == 1) { var nodeBox = new NodeBox(headNode, links); return(new NodeBunch(nodeBox, nodeBox)); } else { var headNodeBox = new NodeBox(headNode); try { var tailNode = tree.Single(x => x.EstablishedLinks.Count == 0); var tailNodeBox = new NodeBox(tailNode, links); return(new NodeBunch(headNodeBox, tailNodeBox)); } catch (Exception ex) { throw new BuildingException("More than one tail node (the node which doesn't have links).", ex); } } }
public void DemandLink(NodeBox to) { if (_linksRequested) { throw new InvalidOperationException("Cannot demand link - links already were requested."); } if (_links.Any()) { throw new InvalidOperationException("Cannot demand link if own links are present."); } _node.EstablishLink(to._node); }
private NodeBunch BuildItem(Element item) { var car = item.GetCarSymbolName(); NodeBunch buildResult; INode node; NodeBox nodeBox; switch (car) { case "BLOCK": buildResult = this.BuildBlock(item); break; case "ALT": buildResult = this.BuildAlt(item); break; case "OPT": buildResult = this.BuildOpt(item); break; case "SEQ": buildResult = this.BuildSeq(item); break; case "IDLE": node = new IdleNode( _nodeFactory.NodeFamily, item.GetItemName()); nodeBox = new NodeBox(node, item.GetItemLinks()); buildResult = new NodeBunch(nodeBox, nodeBox); break; case "END": node = EndNode.Instance; nodeBox = new NodeBox(node); buildResult = new NodeBunch(nodeBox, nodeBox); break; default: buildResult = this.BuildCustomItem(item); break; } return(buildResult); }
private NodeBunch BuildBlock(Element item) { var blockName = item.GetSingleKeywordArgument <Symbol>(":ref").Name; var defblock = _defblocks[blockName]; var args = defblock.GetFreeArguments(); var blockEnter = new NodeBox(new IdleNode(_nodeFactory.NodeFamily, blockName)); var contentResult = this.BuildContent(args); var blockExit = new NodeBox(new IdleNode(_nodeFactory.NodeFamily, $"<exit of block> {blockName}"), item.GetItemLinks()); blockEnter.DemandLink(contentResult.Head); contentResult.Tail.RequestLink(blockExit); var result = new NodeBunch(blockEnter, blockExit); return(result); }
private NodeBunch BuildOpt(Element item) { var optName = item.GetItemName() ?? this.GetNextOptName(); var optEnter = new NodeBox(new IdleNode(_nodeFactory.NodeFamily, optName)); var optExit = new NodeBox(new IdleNode(_nodeFactory.NodeFamily, $"<exit of opt> {optName}"), item.GetItemLinks()); // short circuit! optEnter.DemandLink(optExit); var args = item.GetFreeArguments(); var contentResult = this.BuildContent(args); optEnter.DemandLink(contentResult.Head); contentResult.Tail.RequestLink(optExit); var result = new NodeBunch(optEnter, optExit); return(result); }
private NodeBunch BuildAlt(Element item) { var altName = item.GetItemName() ?? this.GetNextAltName(); var alternatives = item.GetFreeArguments(); var altEnter = new NodeBox(new IdleNode(_nodeFactory.NodeFamily, altName)); var altExit = new NodeBox(new IdleNode(_nodeFactory.NodeFamily, $"<exit of alt> {altName}"), item.GetItemLinks()); foreach (var alternative in alternatives) { var alternativeResult = this.BuildItem(alternative); altEnter.DemandLink(alternativeResult.Head); alternativeResult.Tail.RequestLink(altExit); } var result = new NodeBunch(altEnter, altExit); return(result); }
public void RequestLink(NodeBox to) { if (_node is FallbackNode) { return; // won't add any links to fallback node. } if (to == null) { throw new ArgumentNullException(nameof(to)); } if (_linksRequested) { throw new InvalidOperationException("Cannot request link - links already were requested."); } if (_links.Any()) { foreach (var link in _links) { if (link == "NEXT") { _node.EstablishLink(to._node); } else { _node.ClaimLink(link); } } } else { _node.EstablishLink(to._node); } _linksRequested = true; }
private NodeBunch BuildContent(PseudoList content) { NodeBox head = null; NodeBox tail = null; foreach (var item in content) { var result = this.BuildItem(item); if (head == null) { // first entry head = result.Head; tail = result.Tail; } else { tail.RequestLink(result.Head); tail = result.Tail; } } if (tail == null) { throw new BuildingException("Content is empty."); } if (tail.Links.Any()) { throw new BuildingException("Last item in a content must not have explicit links."); } var buildResult = new NodeBunch(head, tail); return(buildResult); }
public NodeBunch(NodeBox head, NodeBox tail) { this.Head = head ?? throw new ArgumentNullException(nameof(head)); this.Tail = tail ?? throw new ArgumentNullException(nameof(tail)); }