public ParseTreeQuote(int startPosition, int endPosition, ParseTree quotedTree, Synpl.Core.Parser parser, ParseTree parent, TextWithChanges text) : base(startPosition, endPosition, MakeList(quotedTree), parser, parent, text, "' (quote)") { }
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 ParseTreeAtom(int startPosition, int endPosition, string content, Synpl.Core.Parser parser, ParseTree parent, TextWithChanges text) : base(startPosition, endPosition, new CowList<ParseTree>(), parser, parent, text, content) { _content = content; }
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; } }
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(); }
private void AdjustCoordinates(ParseTree oldNode) { int offset = _endPosition - oldNode._endPosition; if (offset != 0) { OffsetSuccessorsPositionBy(offset); } }
private void UpdateSelection(ParseTree newRoot, CowList<int> path) { if (newRoot != null) { _selectedTreeStack.Clear(); _parseTree = newRoot; _selectedTreeStack.Add(_parseTree.GetNodeAtPath(path)); SelectInEditor(); } }
private void TryParsing(TextChangedEventArgs e) { if (_parseTree == null || _parseTree.EndPosition <= e.Start || _parseTree.StartPosition >= e.Start) { Console.WriteLine("Complete Reparse."); _text.SetText(""); string text = _editor.GetText(0, _editor.Length); int pos = 0; foreach (char ch in text) { _text.InsertChar(ch, pos); pos ++; } CompleteReparse(); } else { // TODO: Add multiple char deletion and insertion to parse nodes and TWC. // Also add unit tests for them. switch (e.Operation) { case TextChangedEventArgs.OperationType.Insertion: for (int i = 0; i < e.Length; i++) { _parseTree = _parseTree.CharInsertedAt(e.Text[i], e.Start + i); } // Console.WriteLine(">>> After insert:"); break; case TextChangedEventArgs.OperationType.Deletion: // Console.WriteLine(">>> TWC is: {0}", _text.TestRender()); for (int i = 0; i < e.Length; i++) { _parseTree = _parseTree.CharDeletedAt(e.Start); } // Console.WriteLine(">>> After delete:"); break; default: // Console.WriteLine("Unknown text change operation."); break; } // Console.WriteLine(">>> Code tree is:{0}{1}", // Environment.NewLine, // _parseTree.ToStringAsTree()); // Console.WriteLine(">>> TWC is: {1}: {0}", // _text.TestRender(), // _text.GetHashCode()); // Console.WriteLine(">>> Old code is '{0}'.", _parseTree.ToStringAsCode(true)); // Console.WriteLine(">>> New code is '{0}'.", _parseTree.ToStringAsCode(false)); } }
private void CompleteReparse() { _parseTree = ReparseAll(false); if (_parseTree == null) { return; } // HACK: Maybe validate slice should be called by the parser? _text.ValidateSlice(_parseTree.StartPosition, _parseTree.EndPosition); // Console.WriteLine(">>> New parse tree:"); // Console.WriteLine(">>> TWC is: {0}", _text.TestRender()); Console.WriteLine(">>> Code tree is:{0}{1}", Environment.NewLine, _parseTree.ToStringAsTree()); // Console.WriteLine(">>> Old code is '{0}'.", _parseTree.ToStringAsCode(true)); // Console.WriteLine(">>> New code is '{0}'.", _parseTree.ToStringAsCode(false)); }
public void ReplaceText(string newText) { _parseTree = null; _editor.DeleteText(0, _editor.Length, false); _editor.InsertText(0, newText, false); _selectedTreeStack.Clear(); }
public ParseTree PrettyPrint() { if (_selectedTreeStack.Count == 0) { return _parseTree; } CowList<int> path = _selectedTreeStack.Last.GetPath(); Console.WriteLine("path of pped node: {0}", path.ToString()); _parseTree = _selectedTreeStack.Last.PrettyPrint(Shell.MaxColumn, _editor); _selectedTreeStack.Clear(); ParseTree previouslySelected = _parseTree.GetNodeAtPath(path); if (previouslySelected != null) { _selectedTreeStack.Add(previouslySelected); SelectInEditor(); } Console.WriteLine(">>> Code tree is:{0}{1}", Environment.NewLine, _parseTree.ToStringAsTree()); UpdateFormatting(); ConsistencyCheck(); return _parseTree; }
public void Indent() { if (_parseTree == null) { return; } CowList<int> pathToCursor; int cursorOffset; GetEditorPositionAsPath(out pathToCursor, out cursorOffset); ParseTree newParseTree = _parseTree.Indent(_editor.CursorOffset, Shell.MaxColumn, _editor); // If newParseTree is _parseTree, then the indend didn't do anything // and we don't need to cancel the selection and update the stored parse tree. if (newParseTree != _parseTree) { // We need to clear the selected tree stack as the trees on the stack are no longer // valid. // TODO: store trees on the stack as paths to nodes and do not invalidate on indent? _parseTree = newParseTree; _selectedTreeStack.Clear(); } UpdateFormatting(); ConsistencyCheck(); SetEditorPositionFromPath(pathToCursor, cursorOffset); }
public bool HandleKey(Synpl.EditorAbstraction.Key key) { // Console.WriteLine("Shell key handling: {0}", key.ToString()); _chordBuffer.Enqueue(key); while (_chordBuffer.Count > 5) { _chordBuffer.Dequeue(); } DebugDisplayChordBuffer(); if (TypedChord("C-a")) { _editor.MoveToStartOfLine(); return true; } else if (TypedChord("Tab")) { Indent(); return true; } else if (TypedChord("C-e")) { _editor.MoveToEndOfLine(); return true; } else if (TypedChord("C-x C-t") && !InStructureMode()) { EnterStructureMode(); return true; } else if (TypedChord("C-g") && InStructureMode()) { ExitStructureMode(); return true; } else if (TypedChord("C-n")) { _editor.MoveForwardLines(1); return true; } else if (TypedChord("C-p")) { _editor.MoveForwardLines(-1); return true; } else if (TypedChord("C-b")) { _editor.MoveForwardChars(-1); return true; } else if (TypedChord("C-f")) { _editor.MoveForwardChars(1); return true; } if (InStructureMode()) { if (TypedChord("q")) { ExitStructureMode(); return true; } else if (TypedChord("i")) { Indent(); return true; } else if (TypedChord("p")) { ExtendToParent(); return true; } else if (TypedChord("l")) { LastSelection(); return true; } else if (TypedChord("m")) { _structureModeAction = "m"; return true; } else if (TypedChord("r")) { _structureModeAction = "r"; return true; } else if (TypedChord("x")) { _structureModeAction = "x"; return true; } else if (TypedChord("t")) { _structureModeAction = "t"; return true; } else if (TypedChord("u")) { switch (_structureModeAction) { case "m": SelectPreviousSibling(); return true; case "t": MoveUp(); UpdateFormatting(); ConsistencyCheck(); return true; } } else if (TypedChord("d")) { switch (_structureModeAction) { case "m": SelectNextSibling(); return true; case "t": MoveDown(); UpdateFormatting(); ConsistencyCheck(); return true; } } else if (TypedChord("c")) { SelectFirstChild(); return true; } else if (TypedChord("y")) { _parseTree = PrettyPrint(); return true; } } return false; }
private static CowList<ParseTree> MakeList(ParseTree item) { CowList<ParseTree> result = new CowList<ParseTree>(); result.Add(item); return result; }
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 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())); } }