Esempio n. 1
0
        public INode Build(INodeFactory nodeFactory, PseudoList defblocks)
        {
            if (defblocks == null)
            {
                throw new ArgumentNullException(nameof(defblocks));
            }

            _nodeFactory = nodeFactory ?? throw new ArgumentNullException(nameof(nodeFactory));

            _defblocks = defblocks.ToDictionary(
                x => x.GetSingleKeywordArgument <Symbol>(":name").Name,
                x => x.AsPseudoList());

            var topBlocks = _defblocks
                            .Values
                            .Where(x => x.GetSingleArgumentAsBool(":is-top") == true)
                            .ToList();

            if (topBlocks.Count == 0)
            {
                throw new BuildingException("No top defblocks defined.");
            }

            if (topBlocks.Count > 1)
            {
                throw new BuildingException("More than one top defblock defined.");
            }

            var topBlock        = topBlocks[0];
            var topBlockContent = topBlock.GetFreeArguments();
            var result          = this.BuildContent(topBlockContent);

            return(result.Head.GetNode());
        }
        private CliExecutorArgumentDescriptor ExtractArgumentDescriptor(PseudoList subForm)
        {
            var alias           = subForm.GetSingleKeywordArgument <Symbol>(":alias").Name.ToLowerInvariant();
            var description     = subForm.GetSingleKeywordArgument <StringAtom>(":description", true)?.Value;
            var docSubstitution = subForm.GetSingleKeywordArgument <StringAtom>(":doc-subst", true)?.Value;

            IList <string> values = null;

            if (subForm.GetCarSymbolName().ToLowerInvariant() == "multi-text")
            {
                values = subForm
                         .GetAllKeywordArguments(":values")
                         .Cast <StringAtom>()
                         .Select(x => x.Value)
                         .ToList();
            }

            var isMandatory    = subForm.GetSingleArgumentAsBool(":is-mandatory") ?? false;
            var allowsMultiple = subForm.GetSingleArgumentAsBool(":allows-multiple") ?? false;

            var argumentDescriptor = new CliExecutorArgumentDescriptor(
                alias,
                values,
                isMandatory,
                allowsMultiple,
                description,
                docSubstitution);

            return(argumentDescriptor);
        }
Esempio n. 3
0
        public void AddElement_ArgumentIsValid_AddsElement()
        {
            // Arrange
            var elements = new Element[]
            {
                Nil.Instance,
                True.Instance,
                Symbol.Create("aha"),
                Symbol.Create(":key"),
            };

            var pseudoList = new PseudoList(elements);

            // Act
            var anotherSymbol = Symbol.Create("another");

            pseudoList.AddElement(anotherSymbol);

            // Assert
            var expectedList = new List <Element>(elements)
            {
                anotherSymbol
            };

            CollectionAssert.AreEqual(expectedList, pseudoList);
        }
Esempio n. 4
0
        public PseudoList Read(IList <IToken> tokens)
        {
            var list  = new PseudoList();
            var index = 0;

            this.ReadPseudoListContent(list, tokens, ref index, 0);
            return(list);
        }
        public CliExecutorDescriptorBuilder(string executorGrammar)
        {
            ILexer lexer  = new TinyLispLexer();
            var    tokens = lexer.Lexize(executorGrammar);
            ITinyLispPseudoReader reader = new TinyLispPseudoReader();

            _form = reader.Read(tokens);
        }
Esempio n. 6
0
        public void GetAllKeywordArguments_PseudoListIsNull_ThrowsArgumentNullException()
        {
            // Arrange
            PseudoList pseudoList = null;

            // Act
            var ex = Assert.Throws <ArgumentNullException>(() => pseudoList.GetAllKeywordArguments(":key"));

            // Assert
            Assert.That(ex.ParamName, Is.EqualTo("shouldBePseudoList"));
        }
Esempio n. 7
0
        public void GetMultipleFreeArgumentSets_ArgumentIsNull_ThrowsArgumentNullException()
        {
            // Arrange
            PseudoList pseudoList = null;

            // Act
            var ex = Assert.Throws <ArgumentNullException>(() => pseudoList.GetMultipleFreeArgumentSets());

            // Assert
            Assert.That(ex.ParamName, Is.EqualTo("shouldBePseudoList"));
        }
Esempio n. 8
0
        public void GetSingleKeywordArgument_ArgumentNameIsNull_ThrowsArgumentNullException()
        {
            // Arrange
            Element element = new PseudoList();

            // Act
            var ex = Assert.Throws <ArgumentNullException>(() => element.GetSingleKeywordArgument(null));

            // Assert
            Assert.That(ex.ParamName, Is.EqualTo("argumentName"));
        }
Esempio n. 9
0
        public void GetCarSymbolName_PseudoListIsEmpty_ThrowsArgumentException()
        {
            // Arrange
            var element = new PseudoList();

            // Act
            var ex = Assert.Throws <ArgumentException>(() => element.GetCarSymbolName());

            // Assert
            Assert.That(ex.Message, Does.StartWith("PseudoList is empty."));
            Assert.That(ex.ParamName, Is.EqualTo("shouldBePseudoList"));
        }
Esempio n. 10
0
        public void GetCarSymbolName_CarIsNotSymbol_ThrowsArgumentException()
        {
            // Arrange
            var element = new PseudoList(new[] { new StringAtom("some string"), });

            // Act
            var ex = Assert.Throws <ArgumentException>(() => element.GetCarSymbolName());

            // Assert
            Assert.That(ex.Message, Does.StartWith("CAR of PseudoList is not a symbol."));
            Assert.That(ex.ParamName, Is.EqualTo("shouldBePseudoList"));
        }
Esempio n. 11
0
        public void GetSingleKeywordArgument_ArgumentIsNotKeyword_ThrowsArgumentException(string badKeywordName)
        {
            // Arrange
            Element element = new PseudoList();

            // Act
            var ex = Assert.Throws <ArgumentException>(() => element.GetSingleKeywordArgument(badKeywordName));

            // Assert
            Assert.That(ex.Message, Does.StartWith($"'{badKeywordName}' is not a valid keyword."));
            Assert.That(ex.ParamName, Is.EqualTo("argumentName"));
        }
Esempio n. 12
0
        private IEnumerable <ITextClass> ParseTextClasses(PseudoList arguments)
        {
            var textClasses = new List <ITextClass>();

            foreach (var argument in arguments)
            {
                var symbolElement = (Symbol)argument;
                var textClass     = this.ResolveTextClass(symbolElement.Name);
                textClasses.Add(textClass);
            }

            return(textClasses);
        }
        private CliExecutorOptionDescriptor ExtractOptionDescriptor(PseudoList subForm)
        {
            var alias   = subForm.GetSingleKeywordArgument <Symbol>(":alias").Name.ToLowerInvariant();
            var options = subForm
                          .GetAllKeywordArguments(":values")
                          .Cast <StringAtom>()
                          .Select(x => x.Value)
                          .ToList();
            var description = subForm.GetSingleKeywordArgument <StringAtom>(":description", true)?.Value;

            var optionDescriptor = new CliExecutorOptionDescriptor(alias, options, description);

            return(optionDescriptor);
        }
Esempio n. 14
0
        public void GetMultipleFreeArgumentSets_HappyPath_ReturnsExpectedResult(string form, string expectedRepresentation)
        {
            // Arrange

            var tokens     = _lexer.Lexize(form);
            var reader     = new TinyLispPseudoReader();
            var pseudoList = reader.Read(tokens).Single().AsPseudoList();

            // Act
            var list             = pseudoList.GetMultipleFreeArgumentSets();
            var listToPseudoList = new PseudoList(list);

            // Assert
            Assert.That(listToPseudoList.ToString(), Is.EqualTo(expectedRepresentation).IgnoreCase);
        }
Esempio n. 15
0
 public NextValueManager()
 {
     this.numbers = new PseudoList <int>(kNumberRandomness);
     this.numbers.Add(1);
     this.numbers.Add(2);
     this.numbers.Add(3);
     this.numbers.GenerateList();
     this.numbers.Shuffle();
     this.special = new PseudoList <int>(1);
     this.special.Add(1);
     for (int j = 0; j < kSpecialRareness; j++)
     {
         this.special.Add(0);
     }
     this.special.GenerateList();
     this.special.Shuffle();
 }
Esempio n. 16
0
        public void Constructor_ElementsArray_CreatesExpectedInstance()
        {
            // Arrange
            var elements = new Element[]
            {
                Nil.Instance,
                True.Instance,
                Symbol.Create("aha"),
                Symbol.Create(":key"),
            };

            // Act
            var pseudoList = new PseudoList(elements);

            // Assert
            CollectionAssert.AreEqual(pseudoList, elements);
        }
Esempio n. 17
0
        public void AddElement_ArgumentIsNull_ThrowsArgumentNullException()
        {
            // Arrange
            var elements = new Element[]
            {
                Nil.Instance,
                True.Instance,
                Symbol.Create("aha"),
                Symbol.Create(":key"),
            };

            var pseudoList = new PseudoList(elements);

            // Act
            var ex = Assert.Throws <ArgumentNullException>(() => pseudoList.AddElement(null));

            // Assert
            Assert.That(ex.ParamName, Is.EqualTo("element"));
        }
        private CliExecutorKeyDescriptor ExtractKeyDescriptor(PseudoList list, int index)
        {
            var keySubForm = list[index];
            var alias      = keySubForm.GetSingleKeywordArgument <Symbol>(":alias").Name.ToLowerInvariant();
            var keys       = keySubForm
                             .GetAllKeywordArguments(":values")
                             .Cast <StringAtom>()
                             .Select(x => x.Value)
                             .ToList();
            var isMandatory    = keySubForm.GetSingleArgumentAsBool(":is-mandatory") ?? false;
            var allowsMultiple = keySubForm.GetSingleArgumentAsBool(":allows-multiple") ?? false;

            var            valueSubForm = list[index + 1];
            IList <string> values       = null;

            if (valueSubForm.GetCarSymbolName().ToLowerInvariant() == "multi-text")
            {
                values = valueSubForm
                         .GetAllKeywordArguments(":values")
                         .Cast <StringAtom>()
                         .Select(x => x.Value)
                         .ToList();
            }

            var valueDescription     = valueSubForm.GetSingleKeywordArgument <StringAtom>(":description", true)?.Value;
            var valueDocSubstitution = valueSubForm.GetSingleKeywordArgument <StringAtom>(":doc-subst", true)?.Value;

            var keyDescriptor = new CliExecutorKeyDescriptor(
                alias,
                keys,
                isMandatory,
                allowsMultiple,
                values,
                valueDescription,
                valueDocSubstitution);

            return(keyDescriptor);
        }
Esempio n. 19
0
        protected CliExecutorBase(
            string grammar,
            string version,
            bool supportsHelp)
            : base(ExtractName(grammar), version, supportsHelp)
        {
            var tinyLispLexer        = new TinyLispLexer();
            var tinyLispPseudoReader = new TinyLispPseudoReader();
            var lispTokens           = tinyLispLexer.Lexize(grammar);

            _form = tinyLispPseudoReader.Read(lispTokens);

            this.Descriptor = (new CliExecutorDescriptorBuilder(grammar)).Build();

            if (this.Name == null)
            {
                if (this.Version != null)
                {
                    throw new ArgumentException("Nameless executor cannot support version.", nameof(version));
                }

                if (this.SupportsHelp)
                {
                    throw new ArgumentException("Nameless executor cannot support help.", nameof(supportsHelp));
                }
            }

            try
            {
                var helper = new CliExecutorDescriptorBuilder(grammar);
                this.Descriptor = helper.Build();
            }
            catch (CliException)
            {
                // couldn't build descriptor
            }
        }
Esempio n. 20
0
        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);
        }
        private void CollectItems(
            PseudoList list,
            List <CliExecutorKeyDescriptor> keyList,
            List <CliExecutorArgumentDescriptor> argList,
            List <CliExecutorOptionDescriptor> optionList)
        {
            for (var i = 0; i < list.Count; i++)
            {
                var subForm    = list[i].AsPseudoList();
                var subFormCar = subForm.GetCarSymbolName().ToLowerInvariant();

                string action;

                switch (subFormCar)
                {
                case "multi-text":
                    action = subForm.GetSingleKeywordArgument <Symbol>(":action").Name.ToLowerInvariant();

                    switch (action)
                    {
                    case "key":
                        var keyDescriptor = this.ExtractKeyDescriptor(list, i);
                        keyList.Add(keyDescriptor);
                        i++;
                        break;

                    case "option":
                        var optionDescriptor = this.ExtractOptionDescriptor(subForm);
                        optionList.Add(optionDescriptor);
                        break;

                    case "argument":
                        var argumentDescriptor = this.ExtractArgumentDescriptor(subForm);
                        argList.Add(argumentDescriptor);
                        break;

                    default:
                        throw new CliException($"Unknown action: '{action}'.");
                    }

                    break;

                case "some-text":
                    action = subForm.GetSingleKeywordArgument <Symbol>(":action").Name.ToLowerInvariant();
                    if (action == "argument")
                    {
                        var argumentDescriptor = this.ExtractArgumentDescriptor(subForm);
                        argList.Add(argumentDescriptor);
                    }
                    else
                    {
                        throw new CliException($"Action '{action}' cannot be applied to node type '{subFormCar}'.");
                    }

                    break;

                case "executor":
                case "idle":
                case "fallback":
                case "end":
                    continue;

                case "alt":
                case "seq":
                case "opt":
                    CollectItems(
                        subForm.GetFreeArguments(),
                        keyList,
                        argList,
                        optionList);
                    break;

                default:
                    throw new CliException($"Unsupported node type: '{subFormCar}'.");
                }
            }
        }
Esempio n. 22
0
        public override INode CreateNode(PseudoList item)
        {
            var car = item.GetCarSymbolName().ToLowerInvariant();

            if (car == "executor")
            {
                INode executorNode;

                var executorName = item.GetSingleKeywordArgument <Symbol>(":executor-name", true)?.Name;
                if (executorName == null)
                {
                    executorNode = new IdleNode(this.NodeFamily, $"Root node for unnamed executor of type {this.GetType().FullName}");
                }
                else
                {
                    executorNode = new MultiTextNode(
                        new string[] { item.GetSingleKeywordArgument <StringAtom>(":verb").Value },
                        new ITextClass[]
                    {
                        TermTextClass.Instance,
                    },
                        true,
                        ExecutorAction,
                        this.NodeFamily,
                        $"Executor Node. Name: [{executorName}]");

                    executorNode.Properties["executor-name"] = executorName;
                }

                return(executorNode);
            }

            var node = base.CreateNode(item);

            if (node == null)
            {
                throw new CliException($"Could not build node for item '{car}'.");
            }

            if (node is FallbackNode)
            {
                return(node);
            }

            if (!(node is ActionNode))
            {
                throw new CliException($"'{typeof(ActionNode).Name}' instance was expected to be created.");
            }

            var baseResult = (ActionNode)node;

            var    action = item.GetSingleKeywordArgument <Symbol>(":action", true)?.Name?.ToLowerInvariant();
            string alias;

            switch (action)
            {
            case "key":
                baseResult.Action = KeyAction;
                alias             = item.GetSingleKeywordArgument <Symbol>(":alias").Name;
                baseResult.Properties["alias"] = alias;
                break;

            case "value":
                baseResult.Action = ValueAction;
                break;

            case "option":
                baseResult.Action = OptionAction;
                alias             = item.GetSingleKeywordArgument <Symbol>(":alias").Name;
                baseResult.Properties["alias"] = alias;
                break;

            case "argument":
                baseResult.Action = ArgumentAction;
                alias             = item.GetSingleKeywordArgument <Symbol>(":alias").Name;
                baseResult.Properties["alias"] = alias;
                break;


            default:
                throw new CliException($"Keyword ':action' is missing or invalid for item '{car}'.");
            }

            return(baseResult);
        }
Esempio n. 23
0
        public override INode CreateNode(PseudoList item)
        {
            var car = item.GetCarSymbolName().ToLowerInvariant();

            if (car == "worker")
            {
                INode workerNode;

                var workerName = item.GetSingleKeywordArgument <Symbol>(":worker-name", true)?.Name;
                if (workerName == null)
                {
                    throw new CliException("Worker name is null.");
                }
                else
                {
                    workerNode = new MultiTextNode(
                        item
                        .GetAllKeywordArguments(":verbs")
                        .Cast <StringAtom>()
                        .Select(x => x.Value)
                        .ToList(),
                        new ITextClass[]
                    {
                        TermTextClass.Instance,
                    },
                        true,
                        WorkerAction,
                        this.NodeFamily,
                        $"Worker Node. Name: [{workerName}]");

                    workerNode.Properties["worker-name"] = workerName;
                }

                return(workerNode);
            }

            var node = base.CreateNode(item);

            if (node is FallbackNode)
            {
                return(node);
            }

            if (!(node is ActionNode))
            {
                throw new CliException("ActionNode was expected to be created.");
            }

            var actionNode = (ActionNode)base.CreateNode(item);

            if (actionNode == null)
            {
                throw new CliException($"Could not build node for item '{car}'.");
            }

            var    action = item.GetSingleKeywordArgument <Symbol>(":action", true)?.Name?.ToLowerInvariant();
            string alias;

            switch (action)
            {
            case "key":
                actionNode.Action = KeyAction;
                alias             = item.GetSingleKeywordArgument <Symbol>(":alias").Name;
                actionNode.Properties["alias"] = alias;
                break;

            case "value":
                actionNode.Action = ValueAction;
                break;

            case "option":
                actionNode.Action = OptionAction;
                break;

            case "argument":
                actionNode.Action = ArgumentAction;
                alias             = item.GetSingleKeywordArgument <Symbol>(":alias").Name;
                actionNode.Properties["alias"] = alias;
                break;

            default:
                throw new CliException($"Keyword ':action' is missing for item '{car}'.");
            }

            return(actionNode);
        }
Esempio n. 24
0
        public static IList <PseudoList> GetMultipleFreeArgumentSets(this Element shouldBePseudoList)
        {
            if (shouldBePseudoList == null)
            {
                throw new ArgumentNullException(nameof(shouldBePseudoList));
            }

            var pseudoList = shouldBePseudoList as PseudoList;

            if (pseudoList == null)
            {
                throw new ArgumentException(
                          $"Argument is not of type '{typeof(PseudoList).FullName}'.",
                          nameof(shouldBePseudoList));
            }

            if (pseudoList.Count == 0)
            {
                throw new ArgumentException(
                          $"PseudoList is empty.",
                          nameof(shouldBePseudoList));
            }

            var index  = 1;
            var result = new List <PseudoList>();

            var startedWithKeyword = false;
            var startIndex         = 1;

            while (true)
            {
                if (index == pseudoList.Count)
                {
                    if (startIndex == -1)
                    {
                        // nothing to add.
                    }
                    else
                    {
                        // got free args.
                        var firstArgIndex = startIndex;

                        if (startedWithKeyword)
                        {
                            firstArgIndex++;
                        }

                        var lastArgIndex = index - 1;

                        if (firstArgIndex <= lastArgIndex)
                        {
                            var freeArgsPseudoList = new PseudoList();
                            for (var i = firstArgIndex; i <= lastArgIndex; i++)
                            {
                                freeArgsPseudoList.AddElement(pseudoList[i]);
                            }

                            result.Add(freeArgsPseudoList);
                        }
                    }

                    break;
                }

                var element = pseudoList[index];
                if (element is Keyword)
                {
                    // bumped into keyword
                    if (startIndex == -1)
                    {
                        // reset again.
                        startedWithKeyword = true;
                        index++;
                    }
                    else
                    {
                        // was started, let's check, maybe we can deliver pseudo-list of free args.
                        var delta = index - startIndex;
                        if (
                            delta == 0 ||
                            (delta == 1 && startedWithKeyword)
                            )
                        {
                            // won't consider if free.
                            // reset the entire procedure.
                            startedWithKeyword = true;
                            startIndex         = -1;
                            index++;
                        }
                        else
                        {
                            // got free args!
                            var firstArgIndex = startIndex;

                            if (startedWithKeyword)
                            {
                                firstArgIndex++;
                            }

                            var lastArgIndex = index - 1;

                            var freeArgsPseudoList = new PseudoList();
                            for (var i = firstArgIndex; i <= lastArgIndex; i++)
                            {
                                freeArgsPseudoList.AddElement(pseudoList[i]);
                            }

                            result.Add(freeArgsPseudoList);

                            startIndex = -1;
                            index++;

                            startedWithKeyword = true;
                        }
                    }
                }
                else
                {
                    // bumped into non-keyword.
                    if (startIndex == -1)
                    {
                        // let's start.
                        startIndex = index;
                        index++;
                    }
                    else
                    {
                        // was started, bumped into non-keyword again. good, let's continue.
                        index++;
                    }
                }
            }

            return(result);
        }
Esempio n. 25
0
        public static PseudoList GetAllKeywordArguments(
            this Element shouldBePseudoList,
            string argumentName,
            bool absenceIsAllowed = false)
        {
            if (shouldBePseudoList == null)
            {
                throw new ArgumentNullException(nameof(shouldBePseudoList));
            }

            var list = shouldBePseudoList as PseudoList;

            if (list == null)
            {
                throw new ArgumentException(
                          $"Argument is not of type '{typeof(PseudoList).FullName}'.",
                          nameof(shouldBePseudoList));
            }

            if (argumentName == null)
            {
                throw new ArgumentNullException(nameof(argumentName));
            }

            if (!TinyLispHelper.IsValidSymbolName(argumentName, true))
            {
                throw new ArgumentException($"'{argumentName}' is not a valid keyword.", nameof(argumentName));
            }

            var wantedKeyword = Symbol.Create(argumentName);
            var index         = list.FindFirstIndex(wantedKeyword);

            if (index == -1)
            {
                if (absenceIsAllowed)
                {
                    return(new PseudoList()); // empty
                }
                else
                {
                    throw new TinyLispException($"No argument for keyword '{argumentName}'.");
                }
            }

            index++; // move forward from keyword.
            var startIndex = index;

            while (true)
            {
                if (index == list.Count)
                {
                    break;
                }

                var element = list[index];
                if (element is Keyword)
                {
                    break;
                }

                index++;
            }

            var lastIndex = index - 1;

            var result = new PseudoList();

            for (var i = startIndex; i <= lastIndex; i++)
            {
                result.AddElement(list[i]);
            }

            return(result);
        }
Esempio n. 26
0
        private void ReadPseudoListContent(PseudoList list, IList <IToken> tokens, ref int index, int depth)
        {
            while (true)
            {
                if (index == tokens.Count)
                {
                    if (depth > 0)
                    {
                        throw new TinyLispException("Unclosed form.");
                    }
                    else
                    {
                        return;
                    }
                }

                var token = tokens[index];
                if (token is LispPunctuationToken punctuationToken)
                {
                    switch (punctuationToken.Value)
                    {
                    case Punctuation.RightParenthesis:
                        if (depth == 0)
                        {
                            throw new TinyLispException("Unexpected ')'.");
                        }
                        else
                        {
                            index++;
                            return;
                        }

                    case Punctuation.LeftParenthesis:
                        index++;
                        var innerList = new PseudoList();
                        this.ReadPseudoListContent(innerList, tokens, ref index, depth + 1);
                        list.AddElement(innerList);
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }
                else if (token is KeywordToken keywordToken)
                {
                    var element = Symbol.Create(keywordToken.Keyword);
                    list.AddElement(element);
                    index++;
                }
                else if (token is LispSymbolToken symbolToken)
                {
                    var element = Symbol.Create(symbolToken.SymbolName);
                    list.AddElement(element);
                    index++;
                }
                else if (token is TextToken textToken && textToken.Class is StringTextClass)
                {
                    var element = new StringAtom(textToken.Text);
                    list.AddElement(element);
                    index++;
                }
Esempio n. 27
0
        public virtual INode CreateNode(PseudoList item)
        {
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            try
            {
                var   car = item.GetCarSymbolName();
                INode node;

                switch (car)
                {
                case "EXACT-TEXT":
                    node = new ExactTextNode(
                        item.GetSingleKeywordArgument <StringAtom>(":value").Value,
                        this.ParseTextClasses(item.GetAllKeywordArguments(":classes")),
                        _isCaseSensitive,
                        null,
                        this.NodeFamily,
                        item.GetItemName());
                    break;

                case "SOME-TEXT":
                    node = new TextNode(
                        this.ParseTextClasses(item.GetAllKeywordArguments(":classes")),
                        null,
                        this.NodeFamily,
                        item.GetItemName());
                    break;

                case "MULTI-TEXT":
                    node = new MultiTextNode(
                        item.GetAllKeywordArguments(":values").Cast <StringAtom>().Select(x => x.Value),
                        this.ParseTextClasses(item.GetAllKeywordArguments(":classes")),
                        _isCaseSensitive,
                        null,
                        this.NodeFamily,
                        item.GetItemName());
                    break;

                case "EXACT-PUNCTUATION":
                    node = new ExactPunctuationNode(
                        item.GetSingleKeywordArgument <StringAtom>(":value").Value.Single(),
                        null,
                        this.NodeFamily,
                        item.GetItemName());
                    break;

// todo: some-number?
                case "SOME-INTEGER":
                    node = new IntegerNode(
                        null,
                        this.NodeFamily,
                        item.GetItemName());
                    break;

                case "FALLBACK":
                    var name = item.GetItemName();
                    if (name == null)
                    {
                        throw new BuildingException("Fallback node must have a name.");
                    }

                    node = new FallbackNode(
                        this.CreateFallbackPredicate(name),
                        this.NodeFamily,
                        name);

                    break;

                default:
                    return(null);
                }

                return(node);
            }
            catch (Exception ex)
            {
                throw new BuildingException($"Could not build a node from item {item}.", ex);
            }
        }