public Shell(IAbstractEditor editor) { _editor = editor; _editor.TextChanged += HandleTextChanged; _text = new TextWithChanges(_editor); _selectedTreeStack = new CowList<ParseTree>(); _chordBuffer = new Queue<Synpl.EditorAbstraction.Key>(); _structureModeAction = "m"; _inStructureMode = false; }
public void Setup() { _cowList1 = new CowList<int>(); _cowList1.Add(3); _cowList1.Add(4); _cowList1.Add(2); List<string> storage = new List<string>(); storage.Add("Ana"); storage.Add("are"); storage.Add("mere"); storage.Add("."); _cowList2 = new CowList<string>(storage); }
public ParseTreeList(int startPosition, int endPosition, CowList<ParseTree> members, Synpl.Core.Parser parser, ParseTree parent, TextWithChanges text) : base(startPosition, endPosition, members, parser, parent, text, "() (list)") { }
public ParseTree(int startPosition, int endPosition, CowList<ParseTree> subTrees, Parser parser, ParseTree parent, TextWithChanges text, string label) { _startPosition = startPosition; _endPosition = endPosition; _subTrees = subTrees; _parser = parser; _parent = parent; _text = text; _label = label; foreach (ParseTree node in _subTrees) { node._parent = this; } }
public static void ParseGlobal(CowList<Token> tokens, TextWithChanges text, out ParseTree parseTree, out CowList<Token> remainingTokens) { CowList<ParseTree> trees = new CowList<ParseTree>(); remainingTokens = tokens; while (remainingTokens.Count > 0) { ParseTree tree; ParseLocal(remainingTokens, text, out tree, out remainingTokens); trees.Add(tree); } if (trees.Count == 0) { throw new ParseException("No tokens in stream."); } parseTree = new ParseTreeList(tokens[0].StartPosition, trees.Last.EndPosition, trees, SexpParser.GetInstance(ParseType.Global), null, text); }
public void TestEquals() { CowList<int> equalList = new CowList<int>(); equalList.Add(3); equalList.Add(4); equalList.Add(2); Assert.AreEqual(equalList, _cowList1); }
private ParseTree Reparse(CowList<CharWithPosition> code) { CowList<Token> tokens = _parser.TokenizerFunc(code); ParseTree reparsedSelf; CowList<Token> tokensRest; _parser.ParserFunc(tokens, _text, out reparsedSelf, out tokensRest); if (tokensRest.Count > 0) { throw new ParseException("Extra tokens in stream."); } int index = GetIndexInParent(); if (index != -1) { _parent.SubTrees[index] = reparsedSelf; reparsedSelf._parent = _parent; _parent = null; } reparsedSelf.AdjustCoordinates(this); return reparsedSelf.GetRoot(); }
public ParseTree GetNodeAtPath(CowList<int> path) { if (path.Count == 0) { return this; } int head = path[0]; if (head >= 0 && head < _subTrees.Count) { return _subTrees[head].GetNodeAtPath(path.Tail); } return null; }
// Restores a position saved by GetEditorPositionAsPath private void SetEditorPositionFromPath(CowList<int> path, int offset) { if (path == null || _parseTree == null) { return; } ParseTree currentNode = _parseTree.GetNodeAtPath(path); if (currentNode != null) { _editor.CursorOffset = currentNode.StartPosition + offset; } }
public void RemoveSliceWithChanges(int start, int end, bool sendToEditor) { if (_editor != null && sendToEditor) { _editor.DeleteText(start, end - start, true); } int oldStart = ConvertActualPositionToOld(start); int oldEnd = ConvertActualPositionToOld(end, true); CowList<TextChange> newChanges = new CowList<TextChange>(); foreach (TextChange change in _changes) { if (change.Position < oldStart) { newChanges.Add(change); } } int offset = -(oldEnd - oldStart); foreach (TextChange change in _changes) { if (change.Position >= oldEnd) { newChanges.Add(change.Moved(offset)); } } _changes = newChanges; _text = _text.Remove(oldStart, oldEnd - oldStart); }
public void InsertSliceWithChanges(int position, TextWithChanges slice, bool sendToEditor) { if (_editor != null && sendToEditor) { CowList<CharWithPosition> sliceText = slice.GetCurrentSlice(0, slice.GetActualLength()); StringBuilder sb = new StringBuilder(); foreach (CharWithPosition cwp in sliceText) { sb.Append(cwp.Char); } _editor.InsertText(position, sb.ToString(), true); } int oldPosition = ConvertActualPositionToOld(position); CowList<TextChange> newChanges = new CowList<TextChange>(); // Select changes before the insert position. int i; for (i = 0; i < _changes.Count; i++) { if (_changes[i].Position < oldPosition) { newChanges.Add(_changes[i]); } else { break; } } // Add changes from the inserted slice. foreach (TextChange change in slice._changes) { newChanges.Add(change.Moved(oldPosition)); } // Add changes that were after the insert position. for (; i < _changes.Count; i++) { newChanges.Add(_changes[i].Moved(slice._text.Length)); } _changes = newChanges; _text = _text.Substring(0, oldPosition) + slice._text + _text.Substring(oldPosition); }
public CowList<CharWithPosition> GetOldSlice(int start, int end) { int oldStart = ConvertActualPositionToOld(start); int oldEnd = ConvertActualPositionToOld(end, true); CowList<TextChange> relevantChanges = new CowList<TextChange>(); foreach (TextChange change in _changes) { if (change.IsBetween(oldStart, oldEnd)) { relevantChanges.Add(change); } } CowList<CharWithPosition> result = new CowList<CharWithPosition>(); int k = 0; int runningIndex = start; for (int i = oldStart; i < oldEnd && i < _text.Length; i++) { bool isDeletion = false; if (k < relevantChanges.Count) { if (relevantChanges[k].Position == i) { if (relevantChanges[k].IsDeletion) { isDeletion = true; k++; } else { runningIndex += 1; k++; continue; } } } result.Add(new CharWithPosition(runningIndex, _text[i])); if (!isDeletion) { runningIndex += 1; } } return result; }
public CowList<CharWithPosition> GetCurrentSlice(int start, int end) { int oldStart = ConvertActualPositionToOld(start); int oldEnd = ConvertActualPositionToOld(end, true); CowList<TextChange> deletes = new CowList<TextChange>(); foreach (TextChange change in _changes) { if (change.IsDeletion && change.IsBetween(oldStart, oldEnd)) { deletes.Add(change); } } CowList<CharWithPosition> result = new CowList<CharWithPosition>(); int k = 0; int runningIndex = start; for (int i = oldStart; i < oldEnd && i < _text.Length; i++) { if (k < deletes.Count) { if (deletes[k].Position == i) { k ++; continue; } } result.Add(new CharWithPosition(runningIndex, _text[i])); runningIndex++; } return result; }
// TODO: Add unit test. public CowList<int> GetChangesActualPositionsBetween(int start, int end) { CowList<int> result = new CowList<int>(); int offset = 0; foreach (TextChange tc in _changes) { if (tc.IsDeletion) { offset --; } if (tc.Position + offset > end) { break; } if (tc.Position + offset >= start) { result.Add(tc.Position + offset); } } return result; }
public void TestConstructorLiteral() { CowList<int> literal = new CowList<int>(3, 4, 2); Assert.AreEqual(_cowList1, literal); }
public void SetText(string text) { _changes = new CowList<TextChange>(); _text = text; }
private static CowList<ParseTree> MakeList(ParseTree item) { CowList<ParseTree> result = new CowList<ParseTree>(); result.Add(item); return result; }
public void ValidateSlice(int start, int end) { int oldStart = ConvertActualPositionToOld(start); int oldEnd = ConvertActualPositionToOld(end, true); CowList<TextChange> changesBefore = new CowList<TextChange>(); foreach (TextChange change in _changes) { if (change.Position < oldStart) { changesBefore.Add(change); } } CowList<TextChange> deletesBetween = new CowList<TextChange>(); foreach (TextChange change in _changes) { if (change.IsDeletion && change.IsBetween(oldStart, oldEnd)) { deletesBetween.Add(change); } } int offset = - deletesBetween.Count; CowList<TextChange> changesAfter = new CowList<TextChange>(); foreach (TextChange change in _changes) { if (change.Position >= oldEnd) { changesAfter.Add(change.Moved(offset)); } } _changes = changesBefore; _changes.AddRange(changesAfter); int runningOffset = 0; foreach (TextChange delete in deletesBetween) { int pos = delete.Position + runningOffset; _text = _text.Remove(pos, 1); runningOffset -= 1; } }
// This function is used to save the current position of the cursor in a // way that's restorable after a pretty print or transform. // It stores the path to the node the cursor is on, along with the offset of the // cursor position relative to the start position of that node. // // Obviously, this works only for transformations that rearrange text, not for transformations // that change the parse tree structure. Transformations of the tree structure must be re-applied // on the <path> vector before calling SetEditorPositionAsPath. private void GetEditorPositionAsPath(out CowList<int> path, out int offset) { path = null; offset = 0; if (_parseTree == null) { return; } CowList<ParseTree> pathToPosition = _parseTree.GetPathForPosition(_editor.CursorOffset); if (pathToPosition.Count == 0) { return; } ParseTree currentTree = pathToPosition.Last; path = currentTree.GetPath(); offset = _editor.CursorOffset - currentTree.StartPosition; }
public TextWithChanges() { _changes = new CowList<TextChange>(); _text = String.Empty; }
private void UpdateSelection(ParseTree newRoot, CowList<int> path) { if (newRoot != null) { _selectedTreeStack.Clear(); _parseTree = newRoot; _selectedTreeStack.Add(_parseTree.GetNodeAtPath(path)); SelectInEditor(); } }
public TextWithChanges(IAbstractEditor editor) { _changes = new CowList<TextChange>(); _editor = editor; _text = _editor.GetText(0, _editor.Length); }
public CowList<ParseTree> GetPathForPosition(int position) { if (!Contains(position)) { return new CowList<ParseTree>(); } CowList<ParseTree> result = new CowList<ParseTree>(); result.Add(this); foreach (ParseTree subTree in _subTrees) { if (position < subTree.StartPosition) { break; } if (subTree.Contains(position)) { result.AddRange(subTree.GetPathForPosition(position)); break; } } return result; }
public static void ParseLocal(CowList<Token> tokens, TextWithChanges text, out ParseTree parseTree, out CowList<Token> remainingTokens) { if (tokens.Count == 0) { throw new ParseException("No tokens in stream."); } switch ((TokenTypes)tokens[0].Kind) { case TokenTypes.Quote: ParseTree quotedTree; ParseLocal(tokens.Tail, text, out quotedTree, out remainingTokens); parseTree = new ParseTreeQuote(tokens[0].StartPosition, quotedTree.EndPosition, quotedTree, SexpParser.GetInstance(ParseType.Sexp), null, text); return; case TokenTypes.OpenParen: CowList<ParseTree> members = new CowList<ParseTree>(); CowList<Token> iterTokens = tokens.Tail; while (iterTokens.Count > 0 && (TokenTypes)iterTokens[0].Kind != TokenTypes.CloseParen) { ParseTree member; CowList<Token> nextIterTokens; ParseLocal(iterTokens, text, out member, out nextIterTokens); iterTokens = nextIterTokens; members.Add(member); } if (iterTokens.Count == 0) { throw new ParseException("No tokens left in stream, expected a ')'."); } remainingTokens = iterTokens.Tail; parseTree = new ParseTreeList(tokens[0].StartPosition, iterTokens[0].EndPosition, members, SexpParser.GetInstance(ParseType.Sexp), null, text); return; case TokenTypes.CloseParen: throw new ParseException("Unexpected ')'."); case TokenTypes.Atom: remainingTokens = tokens.Tail; parseTree = new ParseTreeAtom(tokens[0].StartPosition, tokens[0].EndPosition, tokens[0].Content, SexpParser.GetInstance(ParseType.Sexp), null, text); return; default: throw new ParseException(String.Format("Unknown token '{0}'.", tokens[0].ToString())); } }
private static string CharListToString(CowList<CharWithPosition> chars) { StringBuilder sb = new StringBuilder(); foreach (CharWithPosition ch in chars) { sb.Append(ch.Char); } return sb.ToString(); }
public static CowList<Token> Tokenize(CowList<CharWithPosition> text) { CowList<Token> result = new CowList<Token>(); for (int pos = 0; pos < text.Count;) { CharWithPosition ch = text[pos]; if (ch.Char =='(') { result.Add(new Token((int)TokenTypes.OpenParen, "(", ch.Position, ch.Position + 1)); pos ++; } else if (ch.Char == ')') { result.Add(new Token((int)TokenTypes.CloseParen, ")", ch.Position, ch.Position + 1)); pos++; } else if (Char.IsWhiteSpace(ch.Char)) { while (pos < text.Count && Char.IsWhiteSpace(text[pos].Char)) { pos ++; } } else if (ch.Char == '\'') { result.Add(new Token((int)TokenTypes.Quote, "'", ch.Position, ch.Position + 1)); pos ++; } else if (ch.Char == ';') { while (pos < text.Count && text[pos].Char != '\n') { pos++; } } else { StringBuilder sb = new StringBuilder(); int startPos = ch.Position; int endPos = startPos; while (pos < text.Count && !Char.IsWhiteSpace(text[pos].Char) && text[pos].Char != '(' && text[pos].Char != ')' && text[pos].Char != '\'') { sb.Append(text[pos].Char); endPos = text[pos].Position + 1; pos ++; } result.Add(new Token((int)TokenTypes.Atom, sb.ToString(), startPos, endPos)); } } return result; }
private ParseTree TryReparse(CowList<CharWithPosition> code) { ParseTree result = null; try { result = Reparse(code); } catch (ParseException) { return null; } return result; }
public void TestGetCurrentSlice() { SetupText(); CowList<CharWithPosition> slice0 = _textWc.GetCurrentSlice(0, 20); CowList<CharWithPosition> expected = new CowList<CharWithPosition>() { new CharWithPosition(0, 'A'), new CharWithPosition(1, 'n'), new CharWithPosition(2, 'a'), new CharWithPosition(3, ' '), new CharWithPosition(4, 'b'), new CharWithPosition(5, 'c'), new CharWithPosition(6, 'e'), new CharWithPosition(7, ' '), new CharWithPosition(8, 'm'), new CharWithPosition(9, 'e'), new CharWithPosition(10, 'r'), new CharWithPosition(11, 'e'), new CharWithPosition(12, '.') }; Assert.AreEqual(expected, slice0); }