From: Jean-Philippe Bruyère Date: Thu, 8 Mar 2018 07:46:43 +0000 (+0100) Subject: csharp parser wip X-Git-Tag: 0.7.3~4^2~18 X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=50c1a39395af0123771c1572e004cd77fef10af8;p=jp%2Fcrow.git csharp parser wip --- diff --git a/CrowIDE/src/CrowIDE.cs b/CrowIDE/src/CrowIDE.cs index 752f6a70..f2b4d9c2 100644 --- a/CrowIDE/src/CrowIDE.cs +++ b/CrowIDE/src/CrowIDE.cs @@ -131,6 +131,9 @@ namespace Crow.Coding DockWindow dw = loadDockWindow ("#Crow.Coding.ui.DockWindows.winEditor.crow"); dw.DockingPosition = Alignment.Center; dw.Dock (mainDock.Children [0] as DockStack); + dw = loadDockWindow ("#Crow.Coding.ui.DockWindows.winSolution.crow"); + dw.DockingPosition = Alignment.Right; + dw.Dock (mainDock.Children [0] as DockStack); } void loadProjProps () { diff --git a/CrowIDE/src/SourceEditor/BufferParser.cs b/CrowIDE/src/SourceEditor/BufferParser.cs index 0d1d0667..6bef920d 100644 --- a/CrowIDE/src/SourceEditor/BufferParser.cs +++ b/CrowIDE/src/SourceEditor/BufferParser.cs @@ -81,6 +81,17 @@ namespace Crow.Coding internal int currentLine = 0; internal int currentColumn = 0; + int syntTreeDepth = 0; + public int SyntacticTreeDepth { + get { return syntTreeDepth;} + set { + syntTreeDepth = value; + if (syntTreeDepth > SyntacticTreeMaxDepth) + SyntacticTreeMaxDepth = syntTreeDepth; + } + } + public int SyntacticTreeMaxDepth = 0; + protected CodeBuffer buffer; protected Token currentTok; protected bool eol = true; @@ -177,6 +188,10 @@ namespace Crow.Coding } #region low level parsing + protected void addCharToCurTok(char c, Point position){ + currentTok.Start = position; + currentTok += c; + } /// /// Read one char from current position in buffer and store it into the current token /// @@ -268,6 +283,15 @@ namespace Crow.Coding currentColumn++; return c; } + protected virtual string Read(int charCount){ + string tmp = ""; + for (int i = 0; i < charCount; i++) { + if (eol) + break; + tmp += Read (); + } + return tmp; + } /// /// read until end of line is reached /// @@ -316,5 +340,9 @@ namespace Crow.Coding saveAndResetCurrentTok (); } #endregion + + protected void throwParserException(string msg){ + throw new ParserException (currentLine, currentColumn, msg); + } } } \ No newline at end of file diff --git a/CrowIDE/src/SourceEditor/CSharpParser.cs b/CrowIDE/src/SourceEditor/CSharpParser.cs index 2878ce19..f612dacc 100644 --- a/CrowIDE/src/SourceEditor/CSharpParser.cs +++ b/CrowIDE/src/SourceEditor/CSharpParser.cs @@ -135,13 +135,20 @@ namespace Crow.Coding static Regex rxDecimal = new Regex(@"[0-9]+"); static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+"); + public static bool CharIsValidCharStartName (char c) { + return rxNameStartChar.IsMatch(new string(new char[]{c})); + } + public static bool CharIsValidCharName (char c) { + return rxNameChar.IsMatch(new string(new char[]{c})); + } + public bool nextCharIsValidCharStartName { - get { return rxNameStartChar.IsMatch(new string(new char[]{Peek()})); } + get { return CharIsValidCharStartName(Peek()); } } public bool nextCharIsValidCharName { - get { return rxNameChar.IsMatch(new string(new char[]{Peek()})); } + get { return CharIsValidCharName(Peek()); } } #endregion @@ -164,23 +171,10 @@ namespace Crow.Coding States previousEndingState = (States)cl.EndingState; while (! eol) { - SkipWhiteSpaces (); - - if (eol) - break; - - if (Peek () == '\n') { - if (currentTok != TokenType.Unknown) - throw new ParserException (currentLine, currentColumn, "Unexpected end of line"); - Read (); - eol = true; - continue; - } + if (currentTok.IsNull) + SkipWhiteSpaces (); if (curState == States.BlockComment) { - if (currentTok != TokenType.Unknown) - Debugger.Break (); - currentTok.Start = CurrentPosition; currentTok.Type = (BufferParser.TokenType)TokenType.BlockComment; currentTok += ReadLineUntil ("*/"); @@ -193,6 +187,11 @@ namespace Crow.Coding } switch (Peek()) { + case '\n': + eol = true; + if (!currentTok.IsNull) + saveAndResetCurrentTok (); + break; case '#': readToCurrTok (true); currentTok += ReadLine (); @@ -221,21 +220,83 @@ namespace Crow.Coding break; } break; - default: - if (nextCharIsValidCharStartName) { - readToCurrTok (true); - while (nextCharIsValidCharName) - readToCurrTok (); + case '{': + if (currentTok.IsNull) + readAndResetCurrentTok (TokenType.OpenBlock, true); + else + readToCurrTok (); + break; + case '}': + if (currentTok.IsNull) + readAndResetCurrentTok (TokenType.CloseBlock, true); + else + readToCurrTok (); + break; + case '\\'://unicode escape sequence + if (!(currentTok.Type == TokenType.Identifier || + currentTok.IsEmpty || currentTok.Type == TokenType.StringLitteral || currentTok.Type == TokenType.CharLitteral)) { + saveAndResetCurrentTok (); + } + Point pos = CurrentPosition; + Read (); + char escChar = Read (); - if (keywords.Contains (currentTok.Content)) - saveAndResetCurrentTok (TokenType.Keyword); - else - saveAndResetCurrentTok (TokenType.Identifier); - continue; + if (escChar == 'u') { + char c = char.ConvertFromUtf32 (int.Parse (Read (4), System.Globalization.NumberStyles.HexNumber))[0]; + if (currentTok.IsEmpty) { + if (!CharIsValidCharStartName (c)) + throwParserException ("expecting identifier start"); + currentTok.Start = pos; + currentTok.Type = TokenType.Identifier; + } else if (currentTok.Type == TokenType.Identifier) { + if (!CharIsValidCharName (c)) + throwParserException ("expecting identifier valid char"); + } + currentTok += c; + break; } - readToCurrTok (true); - currentTok+=ReadLine (); - saveAndResetCurrentTok (TokenType.Unknown); + currentTok += new String (new char[] { '\\', escChar }); + break; + case '\'': + if (currentTok.IsNull) { + readAndResetCurrentTok (TokenType.CharLitteralOpening, true); + currentTok.Type = TokenType.CharLitteral; + } else if (currentTok.Type == TokenType.CharLitteral) { + saveAndResetCurrentTok (); + readAndResetCurrentTok (TokenType.CharLitteralClosing, true); + } else if (currentTok.Type == TokenType.StringLitteral){ + readToCurrTok (); + } else + throwParserException ("unexpected character: (\')"); + break; + case '"': + if (currentTok.IsNull) { + readAndResetCurrentTok (TokenType.StringLitteralOpening, true); + currentTok.Type = TokenType.StringLitteral; + } else if (currentTok.Type == TokenType.StringLitteral) { + saveAndResetCurrentTok (); + readAndResetCurrentTok (TokenType.StringLitteralClosing, true); + } else + throwParserException ("unexpected character: (\")"); + break; + default: + if (currentTok.Type == TokenType.StringLitteral || currentTok.Type == TokenType.CharLitteral) { + readToCurrTok (currentTok.IsEmpty); + } else if (currentTok.IsNull) { + if (nextCharIsValidCharStartName) { + readToCurrTok (true); + while (nextCharIsValidCharName) + readToCurrTok (); + + if (keywords.Contains (currentTok.Content)) + saveAndResetCurrentTok (TokenType.Keyword); + else + saveAndResetCurrentTok (TokenType.Identifier); + continue; + } else + readAndResetCurrentTok(TokenType.Unknown, true); + } else + readAndResetCurrentTok(TokenType.Unknown, true); break; } } @@ -245,21 +306,41 @@ namespace Crow.Coding cl.EndingState = (int)curState; } - - Node addChildNode (Node curNode, CodeLine cl, int tokPtr) { - Node n = new Node () { Name = cl.Tokens [tokPtr].Content, StartLine = cl }; + + Node addChildNode (Node curNode, CodeLine cl, int tokPtr, string type = "") { + Node n = new Node () { Name = cl.Tokens [tokPtr].Content, StartLine = cl, Type = type }; curNode.AddChild (n); if (cl.SyntacticNode == null) cl.SyntacticNode = n; + SyntacticTreeDepth++; return n; } + void closeNodeAndGoUp (ref Node n, CodeLine cl, string type = ""){ + while (n != null) { + if (n.Type == type) { + n.EndLine = cl; + n = n.Parent; + SyntacticTreeDepth--; + break; + } + n = n.Parent; + SyntacticTreeDepth--; + } +// if (n.StartLine == cl){//prevent single line node +// n.Parent.Children.Remove (n); +// if (cl.SyntacticNode == n) +// cl.SyntacticNode = null; +// }else + + } void closeNodeAndGoUp (ref Node n, CodeLine cl){ - if (n.StartLine == cl){//prevent single line node - n.Parent.Children.Remove (n); - if (cl.SyntacticNode == n) - cl.SyntacticNode = null; - }else - n.EndLine = cl; + // if (n.StartLine == cl){//prevent single line node + // n.Parent.Children.Remove (n); + // if (cl.SyntacticNode == n) + // cl.SyntacticNode = null; + // }else + SyntacticTreeDepth--; + n.EndLine = cl; n = n.Parent; } @@ -268,6 +349,7 @@ namespace Crow.Coding RootNode = new Node () { Name = "RootNode", Type="Root" }; Node currentNode = RootNode; + SyntacticTreeDepth = SyntacticTreeMaxDepth = 0; int ptrLine = 0; while (ptrLine < buffer.LineCount) { @@ -299,8 +381,8 @@ namespace Crow.Coding } ptrLine--; if (ptrLine - startLine > 0) { - currentNode = addChildNode (currentNode, cl, tokPtr); - closeNodeAndGoUp (ref currentNode, buffer [ptrLine]); + currentNode = addChildNode (currentNode, cl, tokPtr, "comment"); + closeNodeAndGoUp (ref currentNode, buffer [ptrLine], "comment"); } break; } @@ -314,9 +396,11 @@ namespace Crow.Coding break; case TokenType.Preprocessor: if (cl.Tokens [tokPtr].Content.StartsWith ("#region")) { - currentNode = addChildNode (currentNode, cl, tokPtr); - }else if (cl.Tokens [tokPtr].Content.StartsWith("#endregion")) - closeNodeAndGoUp (ref currentNode, cl); + currentNode = addChildNode (currentNode, cl, tokPtr, "region"); + } else if (cl.Tokens [tokPtr].Content.StartsWith ("#endregion")) { + + closeNodeAndGoUp (ref currentNode, cl,"region"); + } break; } onlyWhiteSpace = false; @@ -324,6 +408,15 @@ namespace Crow.Coding } ptrLine++; } + ptrLine = 0; + while (ptrLine < buffer.LineCount) { + CodeLine cl = buffer [ptrLine]; + if (cl.IsFoldable) { + if (cl.SyntacticNode.Type == "comment" || cl.SyntacticNode.Type == "region") + cl.IsFolded = true; + } + ptrLine++; + } } } } diff --git a/CrowIDE/src/SourceEditor/SourceEditor.cs b/CrowIDE/src/SourceEditor/SourceEditor.cs index 5e012c19..760bd2c8 100644 --- a/CrowIDE/src/SourceEditor/SourceEditor.cs +++ b/CrowIDE/src/SourceEditor/SourceEditor.cs @@ -63,7 +63,7 @@ namespace Crow.Coding formatting.Add ((int)BufferParser.TokenType.BlockComment, new TextFormatting (Color.Gray, Color.Transparent, false, true)); formatting.Add ((int)BufferParser.TokenType.LineComment, new TextFormatting (Color.Gray, Color.Transparent, false, true)); formatting.Add ((int)BufferParser.TokenType.OperatorOrPunctuation, new TextFormatting (Color.Black, Color.Transparent)); - formatting.Add ((int)BufferParser.TokenType.Keyword, new TextFormatting (Color.DarkCyan, Color.Transparent)); + //formatting.Add ((int)BufferParser.TokenType.Keyword, new TextFormatting (Color.DarkCyan, Color.Transparent)); parsing.Add (".crow", "Crow.Coding.XMLParser"); parsing.Add (".template", "Crow.Coding.XMLParser"); @@ -115,8 +115,8 @@ namespace Crow.Coding } const int leftMarginGap = 3;//gap between items in margin and text const int foldSize = 9;//folding rectangles size - const int foldMargin = 50;//folding margin size - const int foldHSpace = 7;//folding level tabulation x + const int foldHSpace = 4;//folding level tabulation x + int foldMargin { get { return parser == null ? 0 : parser.SyntacticTreeMaxDepth * foldHSpace; }}//folding margin size #region private and protected fields bool foldingEnabled = true; @@ -154,7 +154,7 @@ namespace Crow.Coding if (foldingEnabled) leftMargin += foldMargin; if (leftMargin > 0) - leftMargin += leftMarginGap; + leftMargin += leftMarginGap; updateVisibleColumns (); } void findLongestLineAndUpdateMaxScrollX() { @@ -265,11 +265,12 @@ namespace Crow.Coding continue; parser.TryParseBufferLine (e.LineStart + i); } - measureLeftMargin (); if (parser != null) parser.reparseSource (); + measureLeftMargin (); + updatePrintedLines (); updateMaxScrollY (); RegisterForGraphicUpdate (); @@ -607,6 +608,7 @@ namespace Crow.Coding (int)(y + (fe.Ascent + fe.Descent) / 2.0 - foldSize / 2.0), foldSize, foldSize); gr.SetSourceColor (Color.Black); + gr.LineWidth = 1.0; int level = 0; bool closingNode = false; @@ -620,9 +622,27 @@ namespace Crow.Coding level = currentNode.Level - 1; } - rFld.Left += level * foldHSpace; + for (int l = 0; l < level; l++) { + gr.MoveTo (rFld.Center.X + 0.5, y); + gr.LineTo (rFld.Center.X + 0.5, y + fe.Ascent + fe.Descent); + rFld.Left += foldHSpace; + } + if (closingNode) { + gr.MoveTo (rFld.Center.X + 0.5, y); + gr.LineTo (rFld.Center.X + 0.5, y + fe.Ascent / 2 + 0.5); + gr.LineTo (rFld.Center.X + 0.5 + foldSize / 2, y + fe.Ascent / 2 + 0.5); + closingNode = false; + } + gr.SetDash (new double[]{ 1.5 },0.0); + gr.SetSourceColor (Color.Gray); + gr.Stroke (); + gr.SetDash (new double[]{}, 0.0); if (cl.IsFoldable) { + gr.Rectangle (rFld); + gr.SetSourceColor (Color.White); + gr.Fill(); + gr.SetSourceColor (Color.Black); gr.Rectangle (rFld, 1.0); if (cl.IsFolded) { gr.MoveTo (rFld.Center.X + 0.5, rFld.Y + 2); @@ -633,27 +653,7 @@ namespace Crow.Coding gr.MoveTo (rFld.Left + 2, rFld.Center.Y + 0.5); gr.LineTo (rFld.Right - 2, rFld.Center.Y + 0.5); gr.Stroke (); - } - - if (closingNode) { - gr.MoveTo (rFld.Center.X + 0.5, y); - gr.LineTo (rFld.Center.X + 0.5, y + fe.Ascent / 2 + 0.5); - gr.LineTo (rFld.Center.X + 0.5 + foldSize / 2, y + fe.Ascent / 2 + 0.5); - closingNode = false; - } - - - while (level > 0) { - level--; - rFld.Left -= foldHSpace; - gr.MoveTo (rFld.Center.X + 0.5, y); - gr.LineTo (rFld.Center.X + 0.5, y + fe.Ascent + fe.Descent); - } - gr.SetDash (new double[]{ 1.5 },0.0); - gr.Stroke (); - gr.SetDash (new double[]{}, 0.0); - } gr.SetSourceColor (Foreground); @@ -880,11 +880,14 @@ namespace Crow.Coding int unfoldedLines = buffer.UnfoldedLines; currentNode = null; CodeLine cl = PrintedLines[0]; - int li = buffer.IndexOf(cl); + int idx0 = buffer.IndexOf(cl); + int li = idx0-1; while (li >= 0) { - if (buffer [li].IsFoldable) { - currentNode = buffer [li].SyntacticNode; - break; + if (buffer [li].IsFoldable && !buffer [li].IsFolded) { + if (buffer.IndexOf(buffer [li].SyntacticNode.EndLine) > idx0){ + currentNode = buffer [li].SyntacticNode; + break; + } } li--; } diff --git a/CrowIDE/src/SourceEditor/Token.cs b/CrowIDE/src/SourceEditor/Token.cs index c6b8a3bb..8b4df5e5 100644 --- a/CrowIDE/src/SourceEditor/Token.cs +++ b/CrowIDE/src/SourceEditor/Token.cs @@ -38,6 +38,7 @@ namespace Crow.Coding // Content = content; // } + public bool IsNull { get { return IsEmpty && Type == BufferParser.TokenType.Unknown; }} public bool IsEmpty { get { return string.IsNullOrEmpty(Content); }} public static bool operator == (Token t, System.Enum tt){ diff --git a/CrowIDE/src/SourceEditor/XMLParser.cs b/CrowIDE/src/SourceEditor/XMLParser.cs index 6f001587..ad7aaa62 100644 --- a/CrowIDE/src/SourceEditor/XMLParser.cs +++ b/CrowIDE/src/SourceEditor/XMLParser.cs @@ -17,8 +17,8 @@ namespace Crow.Coding BlockCommentStart = BufferParser.TokenType.BlockCommentStart, BlockComment = BufferParser.TokenType.BlockComment, BlockCommentEnd = BufferParser.TokenType.BlockCommentEnd, - ElementName = BufferParser.TokenType.Type, - AttributeName = BufferParser.TokenType.Identifier, + ElementName = BufferParser.TokenType.Identifier, + AttributeName = BufferParser.TokenType.Keyword, ElementClosing = BufferParser.TokenType.StatementEnding, Affectation = BufferParser.TokenType.OperatorOrPunctuation, AttributeValueOpening = BufferParser.TokenType.StringLitteralOpening, @@ -260,6 +260,7 @@ namespace Crow.Coding RootNode = new Node () { Name = "RootNode", Type="Root" }; Node currentNode = RootNode; + SyntacticTreeDepth = SyntacticTreeMaxDepth = 0; for (int i = 0; i < buffer.LineCount; i++) { CodeLine cl = buffer[i]; @@ -277,6 +278,7 @@ namespace Crow.Coding currentNode = newElt; if (cl.SyntacticNode == null) cl.SyntacticNode = newElt; + SyntacticTreeDepth++; break; case TokenType.ElementEnd: tokPtr++; @@ -287,6 +289,7 @@ namespace Crow.Coding } currentNode.EndLine = cl; currentNode = currentNode.Parent; + SyntacticTreeDepth--; break; case TokenType.ElementClosing: //currentNode = currentNode.Parent; diff --git a/src/GraphicObjects/DockStack.cs b/src/GraphicObjects/DockStack.cs index bfd3ac9a..e9a53486 100644 --- a/src/GraphicObjects/DockStack.cs +++ b/src/GraphicObjects/DockStack.cs @@ -204,6 +204,8 @@ namespace Crow } DockWindow dw = IFace.DragAndDropOperation.DragSource as DockWindow; + if (dw == null) + return; if (!dw.IsDocked) { Rectangle cb = ClientRectangle; double minDim = Math.Min (cb.Width, cb.Height);