예제 #1
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);
        }
예제 #2
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"));
        }
예제 #3
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++;
                }
예제 #4
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);
        }
예제 #5
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);
        }