protected override void onDraw(Context gr) { base.onDraw(gr); gr.SelectFontFace(Font.Name, Font.Slant, Font.Wheight); gr.SetFontSize(Font.Size); gr.FontOptions = Interface.FontRenderingOptions; gr.Antialias = Interface.Antialias; Rectangle cb = ClientRectangle; Foreground.SetAsSource(gr); buffer.editMutex.EnterReadLock(); editorMutex.EnterReadLock(); #region draw text cursor if (buffer.SelectionInProgress) { selStartCol = getTabulatedColumn(buffer.SelectionStart); selEndCol = getTabulatedColumn(buffer.SelectionEnd); } else if (HasFocus && printedCurrentLine >= 0) { gr.LineWidth = 1.0; double cursorX = cb.X + (getTabulatedColumn(buffer.CurrentPosition) - ScrollX) * fe.MaxXAdvance + leftMargin; gr.MoveTo(0.5 + cursorX, cb.Y + (printedCurrentLine) * (fe.Ascent + fe.Descent)); gr.LineTo(0.5 + cursorX, cb.Y + (printedCurrentLine + 1) * (fe.Ascent + fe.Descent)); gr.Stroke(); } #endregion if (PrintedLines?.Count > 0) { int unfoldedLines = buffer.UnfoldedLines; currentNode = null; CodeLine cl = PrintedLines[0]; int idx0 = buffer.IndexOf(cl); int li = idx0 - 1; while (li >= 0) { if (buffer [li].IsFoldable && !buffer [li].IsFolded) { if (buffer.IndexOf(buffer [li].SyntacticNode.EndLine) > idx0) { currentNode = buffer [li].SyntacticNode; break; } } li--; } for (int i = 0; i < visibleLines; i++) { if (i + ScrollY >= unfoldedLines) //TODO:need optimize { break; } drawLine(gr, cb, i); } } editorMutex.ExitReadLock(); buffer.editMutex.ExitReadLock(); }
void drawLine(Context gr, Rectangle cb, int i) { CodeLine cl = PrintedLines[i]; int lineIndex = buffer.IndexOf(cl); double y = cb.Y + (fe.Ascent + fe.Descent) * i, x = cb.X; //Draw line numbering Color mgFg = Colors.Jet; Color mgBg = Colors.Grey; if (PrintLineNumbers) { Rectangle mgR = new Rectangle((int)x, (int)y, leftMargin - leftMarginGap, (int)Math.Ceiling((fe.Ascent + fe.Descent))); if (cl.exception != null) { mgBg = Colors.Red; if (buffer.CurrentLine == lineIndex) { mgFg = Colors.White; } else { mgFg = Colors.LightGrey; } } else if (buffer.CurrentLine == lineIndex && HasFocus) { mgFg = Colors.Black; mgBg = Colors.DarkGrey; } string strLN = (lineIndex + 1).ToString(); gr.SetSourceColor(mgBg); gr.Rectangle(mgR); gr.Fill(); gr.SetSourceColor(mgFg); gr.MoveTo(cb.X + (int)(gr.TextExtents(buffer.LineCount.ToString()).Width - gr.TextExtents(strLN).Width), y + fe.Ascent); gr.ShowText(strLN); gr.Fill(); } //draw folding if (foldingEnabled) { Rectangle rFld = new Rectangle(cb.X + leftMargin - leftMarginGap - foldMargin, (int)(y + (fe.Ascent + fe.Descent) / 2.0 - foldSize / 2.0), foldSize, foldSize); gr.SetSourceColor(Colors.Black); gr.LineWidth = 1.0; int level = 0; bool closingNode = false; if (currentNode != null) { if (cl == currentNode.EndLine) { currentNode = currentNode.Parent; closingNode = true; } if (currentNode != null) { level = currentNode.Level - 1; } } /*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 (level > 0) { gr.MoveTo(rFld.Center.X + 0.5, y); gr.LineTo(rFld.Center.X + 0.5, y + fe.Ascent + fe.Descent); } 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(Colors.Grey); gr.Stroke(); gr.SetDash(new double[] {}, 0.0); if (cl.IsFoldable) { gr.Rectangle(rFld); gr.SetSourceColor(Colors.White); gr.Fill(); gr.SetSourceColor(Colors.Black); gr.Rectangle(rFld, 1.0); if (cl.IsFolded) { gr.MoveTo(rFld.Center.X + 0.5, rFld.Y + 2); gr.LineTo(rFld.Center.X + 0.5, rFld.Bottom - 2); } else { currentNode = cl.SyntacticNode; } gr.MoveTo(rFld.Left + 2, rFld.Center.Y + 0.5); gr.LineTo(rFld.Right - 2, rFld.Center.Y + 0.5); gr.Stroke(); } } gr.SetSourceColor(Foreground); x += leftMargin; if (cl.Tokens == null) { drawRawCodeLine(gr, x, y, i, lineIndex); } else { drawParsedCodeLine(gr, x, y, i, lineIndex); } }
void drawParsedCodeLine(Context gr, double x, double y, int i, int lineIndex) { int lPtr = 0; CodeLine cl = PrintedLines[i]; for (int t = 0; t < cl.Tokens.Count; t++) { string lstr = cl.Tokens [t].PrintableContent; if (lPtr < ScrollX) { if (lPtr - ScrollX + lstr.Length <= 0) { lPtr += lstr.Length; continue; } lstr = lstr.Substring(ScrollX - lPtr); lPtr += ScrollX - lPtr; } Color bg = this.Background; Color fg = this.Foreground; Color selbg = this.SelectionBackground; Color selfg = this.SelectionForeground; FontSlant fts = FontSlant.Normal; FontWeight ftw = FontWeight.Normal; if (formatting.ContainsKey((int)cl.Tokens [t].Type)) { TextFormatting tf = formatting [(int)cl.Tokens [t].Type]; bg = tf.Background; fg = tf.Foreground; if (tf.Bold) { ftw = FontWeight.Bold; } if (tf.Italic) { fts = FontSlant.Italic; } } gr.SelectFontFace(Font.Name, fts, ftw); gr.SetSourceColor(fg); gr.MoveTo(x, y + fe.Ascent); gr.ShowText(lstr); gr.Fill(); if (buffer.SelectionInProgress && lineIndex >= buffer.SelectionStart.Y && lineIndex <= buffer.SelectionEnd.Y && !(lineIndex == buffer.SelectionStart.Y && lPtr + lstr.Length <= selStartCol) && !(lineIndex == buffer.SelectionEnd.Y && selEndCol <= lPtr)) { double rLineX = x, rLineY = y, rLineW = lstr.Length * fe.MaxXAdvance; double startAdjust = 0.0; if ((lineIndex == buffer.SelectionStart.Y) && (selStartCol < lPtr + lstr.Length) && (selStartCol > lPtr)) { startAdjust = (selStartCol - lPtr) * fe.MaxXAdvance; } rLineX += startAdjust; if ((lineIndex == buffer.SelectionEnd.Y) && (selEndCol < lPtr + lstr.Length)) { rLineW = (selEndCol - lPtr) * fe.MaxXAdvance; } rLineW -= startAdjust; gr.Save(); gr.Operator = Operator.Source; gr.Rectangle(rLineX, rLineY, rLineW, (fe.Ascent + fe.Descent)); gr.SetSourceColor(selbg); gr.FillPreserve(); gr.Clip(); gr.Operator = Operator.Over; gr.SetSourceColor(selfg); gr.MoveTo(x, y + fe.Ascent); gr.ShowText(lstr); gr.Fill(); gr.Restore(); } x += (int)lstr.Length * fe.MaxXAdvance; lPtr += lstr.Length; } }
protected void closeNodeAndGoUp(ref Node n, CodeLine cl) { SyntacticTreeDepth--; n.EndLine = cl; n = n.Parent; }
public int IndexOf(CodeLine cl) { return(lines.IndexOf(cl)); }
public override void ParseCurrentLine() { //Debug.WriteLine (string.Format("parsing line:{0}", currentLine)); CodeLine cl = buffer [currentLine]; cl.Tokens = new List <Token> (); //retrieve current parser state from previous line if (currentLine > 0) { curState = (States)buffer[currentLine - 1].EndingState; } else { curState = States.init; } 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; } switch (Peek()) { case '/': readToCurrTok(true); switch (Peek()) { case '/': currentTok += ReadLine(); saveAndResetCurrentTok(TokenType.LineComment); break; default: currentTok += ReadLine(); saveAndResetCurrentTok(TokenType.Unknown); break; } break; case ',': if (curState != States.init && curState != States.classNames) { throw new ParserException(currentLine, currentColumn, "Unexpected char ','"); } readAndResetCurrentTok(TokenType.OperatorOrPunctuation, true); curState = States.classNames; break; case '{': if (!(curState == States.init || curState == States.classNames)) { throw new ParserException(currentLine, currentColumn, "Unexpected char '{'"); } readAndResetCurrentTok(TokenType.OpenBlock, true); curState = States.members; break; case '}': if (curState != States.members) { throw new ParserException(currentLine, currentColumn, "Unexpected char '}'"); } readAndResetCurrentTok(TokenType.CloseBlock, true); curState = States.classNames; break; case '=': if (curState == States.classNames) { throw new ParserException(currentLine, currentColumn, "Unexpected char '='"); } setPreviousTokOfTypeTo(TokenType.Type, TokenType.Identifier); readAndResetCurrentTok(TokenType.OperatorOrPunctuation, true); curState = States.value; break; case '"': if (curState != States.value) { throw new ParserException(currentLine, currentColumn, "Unexpected char '\"'"); } readAndResetCurrentTok(TokenType.StringLitteralOpening, true); while (!eol) { currentTok += ReadLineUntil("\""); if (currentTok.Content [currentTok.Content.Length - 1] == '\\') { readToCurrTok(); } else { break; } } if (eol) { throw new ParserException(currentLine, currentColumn, "Unexpected end of line"); } saveAndResetCurrentTok(TokenType.StringLitteral); readAndResetCurrentTok(TokenType.StringLitteralClosing, true); curState = States.endOfStatement; break; case ';': if (curState != States.endOfStatement) { throw new ParserException(currentLine, currentColumn, "Unexpected end of statement"); } readAndResetCurrentTok(TokenType.StatementEnding, true); curState = States.members; break; default: if (currentTok.Type != TokenType.Unknown) { throw new ParserException(currentLine, currentColumn, "error curtok not null"); } if (curState == States.value) { throw new ParserException(currentLine, currentColumn, "expecting value enclosed in '\"'"); } if (curState == States.endOfStatement) { throw new ParserException(currentLine, currentColumn, "expecting end of statement"); } if (nextCharIsValidCharStartName) { readToCurrTok(true); while (nextCharIsValidCharName) { readToCurrTok(); } } saveAndResetCurrentTok(TokenType.Type); break; } } if (cl.EndingState != (int)curState && currentLine < buffer.LineCount - 1) { buffer [currentLine + 1].Tokens = null; } cl.EndingState = (int)curState; }
public override void SyntaxAnalysis() { initSyntaxAnalysis(); Node currentNode = RootNode; int ptrLine = 0; while (ptrLine < buffer.LineCount) { CodeLine cl = buffer [ptrLine]; if (cl.Tokens == null) { ptrLine++; continue; } cl.SyntacticNode = null; int tokPtr = 0; bool onlyWhiteSpace = true; while (tokPtr < cl.Tokens.Count) { if (cl.Tokens [tokPtr].Type == TokenType.WhiteSpace) { tokPtr++; continue; } if (cl.Tokens [tokPtr].Type == TokenType.LineComment && onlyWhiteSpace) { int startLine = ptrLine; ptrLine++; while (ptrLine < buffer.LineCount) { int idx = buffer [ptrLine].FirstNonBlankTokIndex; if (idx < 0) { break; } if (buffer [ptrLine].Tokens [idx].Type != TokenType.LineComment) { break; } ptrLine++; } ptrLine--; if (ptrLine - startLine > 0) { currentNode = addChildNode(currentNode, cl, tokPtr, "comment"); closeNodeAndGoUp(ref currentNode, buffer [ptrLine], "comment"); } break; } switch (cl.Tokens [tokPtr].Type) { case TokenType.OpenBlock: currentNode = addChildNode(currentNode, cl, tokPtr); break; case TokenType.CloseBlock: closeNodeAndGoUp(ref currentNode, cl); break; case TokenType.Preprocessor: if (cl.Tokens [tokPtr].Content.StartsWith("#region")) { currentNode = addChildNode(currentNode, cl, tokPtr, "region"); } else if (cl.Tokens [tokPtr].Content.StartsWith("#endregion")) { closeNodeAndGoUp(ref currentNode, cl, "region"); } break; } onlyWhiteSpace = false; tokPtr++; } 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++; } }
public override void ParseCurrentLine() { //Debug.WriteLine (string.Format("parsing line:{0}", currentLine)); CodeLine cl = buffer [currentLine]; cl.Tokens = new List <Token> (); //retrieve current parser state from previous line if (currentLine > 0) { curState = (States)buffer[currentLine - 1].EndingState; } else { curState = States.init; } States previousEndingState = (States)cl.EndingState; while (!eol) { if (currentTok.IsNull) { SkipWhiteSpaces(); } if (curState == States.BlockComment) { currentTok.Start = CurrentPosition; currentTok.Type = (BufferParser.TokenType)TokenType.BlockComment; currentTok += ReadLineUntil("*/"); if (Peek(2) == "*/") { readToCurrTok(2); curState = savedState; } saveAndResetCurrentTok(); continue; } switch (Peek()) { case '\n': eol = true; if (!currentTok.IsNull) { saveAndResetCurrentTok(); } break; case '#': readToCurrTok(true); currentTok += ReadLine(); saveAndResetCurrentTok(TokenType.Preprocessor); break; case '/': readToCurrTok(true); switch (Peek()) { case '*': readToCurrTok(); currentTok += ReadLine(); //currentTok.Type = (Parser.TokenType)TokenType.BlockComment; savedState = curState; curState = States.BlockComment; saveAndResetCurrentTok(TokenType.BlockComment); break; case '/': //readToCurrTok (); currentTok += ReadLine(); saveAndResetCurrentTok(TokenType.LineComment); //currentTok.Type = (Parser.TokenType)TokenType.LineComment; break; default: currentTok += ReadLine(); saveAndResetCurrentTok(TokenType.Unknown); break; } break; 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 (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; } 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; } } if (cl.EndingState != (int)curState && currentLine < buffer.LineCount - 1) { buffer [currentLine + 1].Tokens = null; } cl.EndingState = (int)curState; }