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); }
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 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++; }
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); }
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); }