Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2586 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
23 changed files with 487 additions and 658 deletions
@ -0,0 +1,154 @@ |
|||||||
|
/* |
||||||
|
* Created by SharpDevelop. |
||||||
|
* User: Daniel |
||||||
|
* Date: 24.06.2007 |
||||||
|
* Time: 15:29 |
||||||
|
* |
||||||
|
* To change this template use Tools | Options | Coding | Edit Standard Headers. |
||||||
|
*/ |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Drawing; |
||||||
|
using System.Diagnostics; |
||||||
|
using ICSharpCode.SharpDevelop.Dom.CSharp; |
||||||
|
using ICSharpCode.Core; |
||||||
|
using ICSharpCode.SharpDevelop; |
||||||
|
using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; |
||||||
|
using ICSharpCode.SharpDevelop.Dom; |
||||||
|
using ICSharpCode.SharpDevelop.Gui; |
||||||
|
using ICSharpCode.TextEditor; |
||||||
|
using ICSharpCode.TextEditor.Document; |
||||||
|
|
||||||
|
namespace CSharpBinding |
||||||
|
{ |
||||||
|
public class CSharpAdvancedHighlighter : AsynchronousAdvancedHighlighter |
||||||
|
{ |
||||||
|
public override void Initialize(TextEditorControl textEditor) |
||||||
|
{ |
||||||
|
base.Initialize(textEditor); |
||||||
|
ParserService.ParserUpdateStepFinished += OnUpdateStep; |
||||||
|
} |
||||||
|
|
||||||
|
public override void Dispose() |
||||||
|
{ |
||||||
|
ParserService.ParserUpdateStepFinished -= OnUpdateStep; |
||||||
|
base.Dispose(); |
||||||
|
} |
||||||
|
|
||||||
|
void OnUpdateStep(object sender, ParserUpdateStepEventArgs e) |
||||||
|
{ |
||||||
|
if (FileUtility.IsEqualFileName(e.FileName, this.TextEditor.FileName)) { |
||||||
|
ParseInformation parseInfo = e.ParseInformation; |
||||||
|
// if (parseInfo == null && this.storedParseInformation)
|
||||||
|
// parseInfo = ParserService.GetParseInformation(this.TextEditor.FileName);
|
||||||
|
// if (parseInfo != null) {
|
||||||
|
// ICompilationUnit cu = parseInfo.MostRecentCompilationUnit;
|
||||||
|
// }
|
||||||
|
WorkbenchSingleton.SafeThreadAsyncCall(MarkOutstanding); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static bool IsInMultilineCommentOrStringLiteral(LineSegment line) |
||||||
|
{ |
||||||
|
if (line.HighlightSpanStack == null || line.HighlightSpanStack.IsEmpty) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
return !line.HighlightSpanStack.Peek().StopEOL; |
||||||
|
} |
||||||
|
|
||||||
|
protected override void MarkWords(int lineNumber, LineSegment currentLine, List<TextWord> words) |
||||||
|
{ |
||||||
|
if (IsInMultilineCommentOrStringLiteral(currentLine)) { |
||||||
|
return; |
||||||
|
} |
||||||
|
ParseInformation parseInfo = ParserService.GetParseInformation(this.TextEditor.FileName); |
||||||
|
if (parseInfo == null) return; |
||||||
|
|
||||||
|
CSharpExpressionFinder finder = new CSharpExpressionFinder(parseInfo); |
||||||
|
Func<string, int, ExpressionResult> findExpressionMethod; |
||||||
|
IClass callingClass = parseInfo.MostRecentCompilationUnit.GetInnermostClass(lineNumber, 0); |
||||||
|
if (callingClass != null) { |
||||||
|
if (GetCurrentMember(callingClass, lineNumber, 0) != null) { |
||||||
|
findExpressionMethod = finder.FindFullExpressionInMethod; |
||||||
|
} else { |
||||||
|
findExpressionMethod = finder.FindFullExpressionInTypeDeclaration; |
||||||
|
} |
||||||
|
} else { |
||||||
|
findExpressionMethod = finder.FindFullExpression; |
||||||
|
} |
||||||
|
|
||||||
|
string lineText = this.Document.GetText(currentLine.Offset, currentLine.Length); |
||||||
|
bool changedLine = false; |
||||||
|
// now go through the word list:
|
||||||
|
foreach (TextWord word in words) { |
||||||
|
if (word.IsWhiteSpace) continue; |
||||||
|
if (char.IsLetter(lineText[word.Offset]) || lineText[word.Offset] == '_') { |
||||||
|
ExpressionResult result = findExpressionMethod(lineText, word.Offset); |
||||||
|
if (result.Expression != null) { |
||||||
|
// result.Expression
|
||||||
|
if (ICSharpCode.NRefactory.Parser.CSharp.Keywords.GetToken(result.Expression) >= 0) |
||||||
|
continue; |
||||||
|
// convert text editor to DOM coordinates:
|
||||||
|
resolveCount++; |
||||||
|
ResolveResult rr = ParserService.Resolve(result, lineNumber + 1, word.Offset + 1, this.TextEditor.FileName, this.TextEditor.Text); |
||||||
|
if (rr is MixedResolveResult || rr is TypeResolveResult) { |
||||||
|
changedLine = true; |
||||||
|
word.SyntaxColor = this.Document.HighlightingStrategy.GetColorFor("TypeReference"); |
||||||
|
} else if (rr == null) { |
||||||
|
changedLine = true; |
||||||
|
word.SyntaxColor = this.Document.HighlightingStrategy.GetColorFor("UnknownEntity"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (markingOutstanding && changedLine) { |
||||||
|
this.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, lineNumber)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static IMember GetCurrentMember(IClass callingClass, int caretLine, int caretColumn) |
||||||
|
{ |
||||||
|
if (callingClass == null) |
||||||
|
return null; |
||||||
|
foreach (IMethod method in callingClass.Methods) { |
||||||
|
if (method.Region.IsInside(caretLine, caretColumn) || method.BodyRegion.IsInside(caretLine, caretColumn)) { |
||||||
|
return method; |
||||||
|
} |
||||||
|
} |
||||||
|
foreach (IProperty property in callingClass.Properties) { |
||||||
|
if (property.Region.IsInside(caretLine, caretColumn) || property.BodyRegion.IsInside(caretLine, caretColumn)) { |
||||||
|
return property; |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
bool markingOutstanding; |
||||||
|
int resolveCount; |
||||||
|
|
||||||
|
protected override void MarkOutstanding() |
||||||
|
{ |
||||||
|
#if DEBUG
|
||||||
|
int time = Environment.TickCount; |
||||||
|
#endif
|
||||||
|
markingOutstanding = true; |
||||||
|
resolveCount = 0; |
||||||
|
base.MarkOutstanding(); |
||||||
|
markingOutstanding = false; |
||||||
|
#if DEBUG
|
||||||
|
time = Environment.TickCount - time; |
||||||
|
if (time > 0) { |
||||||
|
LoggingService.Info("CSharpHighlighter took " + time + "ms for " + resolveCount + " resolves"); |
||||||
|
} |
||||||
|
#endif
|
||||||
|
this.Document.CommitUpdate(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,525 +0,0 @@ |
|||||||
// <file>
|
|
||||||
// <copyright see="prj:///doc/copyright.txt"/>
|
|
||||||
// <license see="prj:///doc/license.txt"/>
|
|
||||||
// <owner name="Markus Palme" email="MarkusPalme@gmx.de"/>
|
|
||||||
// <version>$Revision$</version>
|
|
||||||
// </file>
|
|
||||||
|
|
||||||
using System; |
|
||||||
using System.Text; |
|
||||||
using ICSharpCode.SharpDevelop.Dom; |
|
||||||
|
|
||||||
namespace VBNetBinding.Parser |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Description of ExpressionFinder.
|
|
||||||
/// </summary>
|
|
||||||
public class ExpressionFinder : IExpressionFinder |
|
||||||
{ |
|
||||||
ExpressionResult CreateResult(string expression) |
|
||||||
{ |
|
||||||
if (expression == null) |
|
||||||
return ExpressionResult.Empty; |
|
||||||
if (expression.Length > 8 && expression.Substring(0, 8).Equals("Imports ", StringComparison.InvariantCultureIgnoreCase)) |
|
||||||
return new ExpressionResult(expression.Substring(8).TrimStart(), ExpressionContext.Type, null); |
|
||||||
if (expression.Length > 4 && expression.Substring(0, 4).Equals("New ", StringComparison.InvariantCultureIgnoreCase)) |
|
||||||
return new ExpressionResult(expression.Substring(4).TrimStart(), ExpressionContext.ObjectCreation, null); |
|
||||||
if (curTokenType == Ident && lastIdentifier.Equals("as", StringComparison.InvariantCultureIgnoreCase)) |
|
||||||
return new ExpressionResult(expression, ExpressionContext.Type); |
|
||||||
return new ExpressionResult(expression); |
|
||||||
} |
|
||||||
|
|
||||||
public ExpressionResult FindExpression(string inText, int offset) |
|
||||||
{ |
|
||||||
return CreateResult(FindExpressionInternal(inText, offset)); |
|
||||||
} |
|
||||||
|
|
||||||
public string FindExpressionInternal(string inText, int offset) |
|
||||||
{ |
|
||||||
this.text = FilterComments(inText, ref offset); |
|
||||||
this.offset = this.lastAccept = offset; |
|
||||||
this.state = START; |
|
||||||
if (this.text == null) |
|
||||||
{ |
|
||||||
return null; |
|
||||||
} |
|
||||||
//Console.WriteLine("---------------");
|
|
||||||
while (state != ERROR) |
|
||||||
{ |
|
||||||
ReadNextToken(); |
|
||||||
//Console.WriteLine("cur state {0} got token {1}/{3} going to {2}", GetStateName(state), GetTokenName(curTokenType), GetStateName(stateTable[state, curTokenType]), curTokenType);
|
|
||||||
state = stateTable[state, curTokenType]; |
|
||||||
|
|
||||||
if (state == ACCEPT || state == ACCEPT2 || state == DOT) |
|
||||||
{ |
|
||||||
lastAccept = this.offset; |
|
||||||
} |
|
||||||
if (state == ACCEPTNOMORE) |
|
||||||
{ |
|
||||||
return this.text.Substring(this.offset + 1, offset - this.offset); |
|
||||||
} |
|
||||||
} |
|
||||||
return this.text.Substring(this.lastAccept + 1, offset - this.lastAccept); |
|
||||||
} |
|
||||||
|
|
||||||
internal int LastExpressionStartPosition { |
|
||||||
get { |
|
||||||
return ((state == ACCEPTNOMORE) ? offset : lastAccept) + 1; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public ExpressionResult FindFullExpression(string inText, int offset) |
|
||||||
{ |
|
||||||
string expressionBeforeOffset = FindExpressionInternal(inText, offset); |
|
||||||
if (expressionBeforeOffset == null || expressionBeforeOffset.Length == 0) |
|
||||||
return CreateResult(null); |
|
||||||
StringBuilder b = new StringBuilder(expressionBeforeOffset); |
|
||||||
// append characters after expression
|
|
||||||
for (int i = offset + 1; i < inText.Length; ++i) { |
|
||||||
char c = inText[i]; |
|
||||||
if (Char.IsLetterOrDigit(c)) { |
|
||||||
if (Char.IsWhiteSpace(inText, i - 1)) |
|
||||||
break; |
|
||||||
b.Append(c); |
|
||||||
} else if (c == ' ') { |
|
||||||
b.Append(c); |
|
||||||
} else if (c == '(') { |
|
||||||
int otherBracket = SearchBracketForward(inText, i + 1, '(', ')'); |
|
||||||
if (otherBracket < 0) |
|
||||||
break; |
|
||||||
b.Append(inText, i, otherBracket - i + 1); |
|
||||||
break; |
|
||||||
} else { |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
return CreateResult(b.ToString()); |
|
||||||
} |
|
||||||
|
|
||||||
// Like VBNetFormattingStrategy.SearchBracketForward, but operates on a string.
|
|
||||||
private int SearchBracketForward(string text, int offset, char openBracket, char closingBracket) |
|
||||||
{ |
|
||||||
bool inString = false; |
|
||||||
bool inComment = false; |
|
||||||
int brackets = 1; |
|
||||||
for (int i = offset; i < text.Length; ++i) { |
|
||||||
char ch = text[i]; |
|
||||||
if (ch == '\n') { |
|
||||||
inString = false; |
|
||||||
inComment = false; |
|
||||||
} |
|
||||||
if (inComment) continue; |
|
||||||
if (ch == '"') inString = !inString; |
|
||||||
if (inString) continue; |
|
||||||
if (ch == '\'') { |
|
||||||
inComment = true; |
|
||||||
} else if (ch == openBracket) { |
|
||||||
++brackets; |
|
||||||
} else if (ch == closingBracket) { |
|
||||||
--brackets; |
|
||||||
if (brackets == 0) return i; |
|
||||||
} |
|
||||||
} |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removed the last part of the expression.
|
|
||||||
/// </summary>
|
|
||||||
/// <example>
|
|
||||||
/// "obj.Field" => "obj"
|
|
||||||
/// "obj.Method(args,...)" => "obj.Method"
|
|
||||||
/// </example>
|
|
||||||
public string RemoveLastPart(string expression) |
|
||||||
{ |
|
||||||
text = expression; |
|
||||||
offset = text.Length - 1; |
|
||||||
ReadNextToken(); |
|
||||||
if (curTokenType == Ident && Peek() == '.') |
|
||||||
GetNext(); |
|
||||||
return text.Substring(0, offset + 1); |
|
||||||
} |
|
||||||
|
|
||||||
#region Comment Filter and 'inside string watcher'
|
|
||||||
int initialOffset; |
|
||||||
public string FilterComments(string text, ref int offset) |
|
||||||
{ |
|
||||||
if (text.Length <= offset) |
|
||||||
return null; |
|
||||||
this.initialOffset = offset; |
|
||||||
StringBuilder outText = new StringBuilder(); |
|
||||||
int curOffset = 0; |
|
||||||
while (curOffset <= initialOffset) |
|
||||||
{ |
|
||||||
char ch = text[curOffset]; |
|
||||||
|
|
||||||
switch (ch) |
|
||||||
{ |
|
||||||
case '@': |
|
||||||
if (curOffset + 1 < text.Length && text[curOffset + 1] == '"') |
|
||||||
{ |
|
||||||
outText.Append(text[curOffset++]); // @
|
|
||||||
outText.Append(text[curOffset++]); // "
|
|
||||||
if (!ReadVerbatimString(outText, text, ref curOffset)) |
|
||||||
{ |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
outText.Append(ch); |
|
||||||
++curOffset; |
|
||||||
} |
|
||||||
break; |
|
||||||
case '"': |
|
||||||
outText.Append(ch); |
|
||||||
curOffset++; |
|
||||||
if (!ReadString(outText, text, ref curOffset)) |
|
||||||
{ |
|
||||||
return null; |
|
||||||
} |
|
||||||
break; |
|
||||||
case '\'': |
|
||||||
offset -= 1; |
|
||||||
curOffset += 1; |
|
||||||
if (!ReadToEOL(text, ref curOffset, ref offset)) |
|
||||||
{ |
|
||||||
return null; |
|
||||||
} |
|
||||||
break; |
|
||||||
default: |
|
||||||
outText.Append(ch); |
|
||||||
++curOffset; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return outText.ToString(); |
|
||||||
} |
|
||||||
|
|
||||||
bool ReadToEOL(string text, ref int curOffset, ref int offset) |
|
||||||
{ |
|
||||||
while (curOffset <= initialOffset) |
|
||||||
{ |
|
||||||
char ch = text[curOffset++]; |
|
||||||
--offset; |
|
||||||
if (ch == '\n') |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
bool ReadString(StringBuilder outText, string text, ref int curOffset) |
|
||||||
{ |
|
||||||
while (curOffset <= initialOffset) |
|
||||||
{ |
|
||||||
char ch = text[curOffset++]; |
|
||||||
outText.Append(ch); |
|
||||||
if (ch == '"') |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
bool ReadVerbatimString(StringBuilder outText, string text, ref int curOffset) |
|
||||||
{ |
|
||||||
while (curOffset <= initialOffset) |
|
||||||
{ |
|
||||||
char ch = text[curOffset++]; |
|
||||||
outText.Append(ch); |
|
||||||
if (ch == '"') |
|
||||||
{ |
|
||||||
if (curOffset < text.Length && text[curOffset] == '"') |
|
||||||
{ |
|
||||||
outText.Append(text[curOffset++]); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
bool ReadMultiLineComment(string text, ref int curOffset, ref int offset) |
|
||||||
{ |
|
||||||
while (curOffset <= initialOffset) |
|
||||||
{ |
|
||||||
char ch = text[curOffset++]; |
|
||||||
--offset; |
|
||||||
if (ch == '*') |
|
||||||
{ |
|
||||||
if (curOffset < text.Length && text[curOffset] == '/') |
|
||||||
{ |
|
||||||
++curOffset; |
|
||||||
--offset; |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region mini backward lexer
|
|
||||||
string text; |
|
||||||
int offset; |
|
||||||
|
|
||||||
char GetNext() |
|
||||||
{ |
|
||||||
if (offset >= 0) |
|
||||||
{ |
|
||||||
return text[offset--]; |
|
||||||
} |
|
||||||
return '\0'; |
|
||||||
} |
|
||||||
|
|
||||||
char Peek() |
|
||||||
{ |
|
||||||
if (offset >= 0) |
|
||||||
{ |
|
||||||
return text[offset]; |
|
||||||
} |
|
||||||
return '\0'; |
|
||||||
} |
|
||||||
|
|
||||||
void UnGet() |
|
||||||
{ |
|
||||||
++offset; |
|
||||||
} |
|
||||||
|
|
||||||
// tokens for our lexer
|
|
||||||
static int Err = 0; |
|
||||||
static int Dot = 1; |
|
||||||
static int StrLit = 2; |
|
||||||
static int Ident = 3; |
|
||||||
static int New = 4; |
|
||||||
// static int Bracket = 5;
|
|
||||||
static int Parent = 6; |
|
||||||
static int Curly = 7; |
|
||||||
static int Using = 8; |
|
||||||
int curTokenType; |
|
||||||
|
|
||||||
readonly static string[] tokenStateName = new string[] { |
|
||||||
"Err", "Dot", "StrLit", "Ident", "New", "Bracket", "Paren", "Curly", "Using" |
|
||||||
}; |
|
||||||
string GetTokenName(int state) |
|
||||||
{ |
|
||||||
return tokenStateName[state]; |
|
||||||
} |
|
||||||
|
|
||||||
string lastIdentifier; |
|
||||||
|
|
||||||
void ReadNextToken() |
|
||||||
{ |
|
||||||
char ch = GetNext(); |
|
||||||
|
|
||||||
curTokenType = Err; |
|
||||||
if (ch == '\0' || ch == '\n' || ch == '\r') |
|
||||||
{ |
|
||||||
return; |
|
||||||
} |
|
||||||
while (Char.IsWhiteSpace(ch)) |
|
||||||
{ |
|
||||||
ch = GetNext(); |
|
||||||
if (ch == '\n' || ch == '\r') |
|
||||||
{ |
|
||||||
return; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
switch (ch) |
|
||||||
{ |
|
||||||
case '}': |
|
||||||
if (ReadBracket('{', '}')) |
|
||||||
{ |
|
||||||
curTokenType = Curly; |
|
||||||
} |
|
||||||
break; |
|
||||||
case ')': |
|
||||||
if (ReadBracket('(', ')')) |
|
||||||
{ |
|
||||||
curTokenType = Parent; |
|
||||||
} |
|
||||||
break; |
|
||||||
case ']': |
|
||||||
if (ReadBracket('[', ']')) |
|
||||||
{ |
|
||||||
curTokenType = Ident; |
|
||||||
} |
|
||||||
break; |
|
||||||
case '.': |
|
||||||
curTokenType = Dot; |
|
||||||
break; |
|
||||||
case '\'': |
|
||||||
case '"': |
|
||||||
if (ReadStringLiteral(ch)) |
|
||||||
{ |
|
||||||
curTokenType = StrLit; |
|
||||||
} |
|
||||||
break; |
|
||||||
default: |
|
||||||
if (IsIdentifierPart(ch)) |
|
||||||
{ |
|
||||||
string ident = ReadIdentifier(ch); |
|
||||||
if (ident != null) |
|
||||||
{ |
|
||||||
switch (ident.ToLowerInvariant()) |
|
||||||
{ |
|
||||||
case "new": |
|
||||||
curTokenType = New; |
|
||||||
break; |
|
||||||
case "imports": |
|
||||||
curTokenType = Using; |
|
||||||
break; |
|
||||||
default: |
|
||||||
lastIdentifier = ident; |
|
||||||
curTokenType = Ident; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
bool ReadStringLiteral(char litStart) |
|
||||||
{ |
|
||||||
while (true) |
|
||||||
{ |
|
||||||
char ch = GetNext(); |
|
||||||
if (ch == '\0') |
|
||||||
{ |
|
||||||
return false; |
|
||||||
} |
|
||||||
if (ch == litStart) |
|
||||||
{ |
|
||||||
if (Peek() == '@' && litStart == '"') |
|
||||||
{ |
|
||||||
GetNext(); |
|
||||||
} |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
bool ReadBracket(char openBracket, char closingBracket) |
|
||||||
{ |
|
||||||
int curlyBraceLevel = 0; |
|
||||||
int squareBracketLevel = 0; |
|
||||||
int parenthesisLevel = 0; |
|
||||||
switch (openBracket) |
|
||||||
{ |
|
||||||
case '(': |
|
||||||
parenthesisLevel++; |
|
||||||
break; |
|
||||||
case '[': |
|
||||||
squareBracketLevel++; |
|
||||||
break; |
|
||||||
case '{': |
|
||||||
curlyBraceLevel++; |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
while (parenthesisLevel != 0 || squareBracketLevel != 0 || curlyBraceLevel != 0) |
|
||||||
{ |
|
||||||
char ch = GetNext(); |
|
||||||
if (ch == '\0') |
|
||||||
{ |
|
||||||
return false; |
|
||||||
} |
|
||||||
switch (ch) |
|
||||||
{ |
|
||||||
case '(': |
|
||||||
parenthesisLevel--; |
|
||||||
break; |
|
||||||
case '[': |
|
||||||
squareBracketLevel--; |
|
||||||
break; |
|
||||||
case '{': |
|
||||||
curlyBraceLevel--; |
|
||||||
break; |
|
||||||
case ')': |
|
||||||
parenthesisLevel++; |
|
||||||
break; |
|
||||||
case ']': |
|
||||||
squareBracketLevel++; |
|
||||||
break; |
|
||||||
case '}': |
|
||||||
curlyBraceLevel++; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
string ReadIdentifier(char ch) |
|
||||||
{ |
|
||||||
string identifier = ch.ToString(); |
|
||||||
while (IsIdentifierPart(Peek())) |
|
||||||
{ |
|
||||||
identifier = GetNext() + identifier; |
|
||||||
} |
|
||||||
return identifier; |
|
||||||
} |
|
||||||
|
|
||||||
bool IsIdentifierPart(char ch) |
|
||||||
{ |
|
||||||
return Char.IsLetterOrDigit(ch) || ch == '_'; |
|
||||||
} |
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region finite state machine
|
|
||||||
readonly static int ERROR = 0; |
|
||||||
readonly static int START = 1; |
|
||||||
readonly static int DOT = 2; |
|
||||||
readonly static int MORE = 3; |
|
||||||
readonly static int CURLY = 4; |
|
||||||
readonly static int CURLY2 = 5; |
|
||||||
readonly static int CURLY3 = 6; |
|
||||||
|
|
||||||
readonly static int ACCEPT = 7; |
|
||||||
readonly static int ACCEPTNOMORE = 8; |
|
||||||
readonly static int ACCEPT2 = 9; |
|
||||||
|
|
||||||
readonly static string[] stateName = new string[] { |
|
||||||
"ERROR", |
|
||||||
"START", |
|
||||||
"DOT", |
|
||||||
"MORE", |
|
||||||
"CURLY", |
|
||||||
"CURLY2", |
|
||||||
"CURLY3", |
|
||||||
"ACCEPT", |
|
||||||
"ACCEPTNOMORE", |
|
||||||
"ACCEPT2" |
|
||||||
}; |
|
||||||
|
|
||||||
string GetStateName(int state) |
|
||||||
{ |
|
||||||
return stateName[state]; |
|
||||||
} |
|
||||||
|
|
||||||
int state = 0; |
|
||||||
int lastAccept = 0; |
|
||||||
static int[,] stateTable = new int[,] { |
|
||||||
// Err, Dot, Str, ID, New, Brk, Par, Cur, Using
|
|
||||||
/*ERROR*/ { ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR}, |
|
||||||
/*START*/ { ERROR, ERROR, ACCEPT, ACCEPT, ERROR, MORE, ACCEPT2, CURLY, ACCEPTNOMORE}, |
|
||||||
/*DOT*/ { ERROR, ERROR, ACCEPT, ACCEPT, ERROR, MORE, ACCEPT2, CURLY, ERROR}, |
|
||||||
/*MORE*/ { ERROR, ERROR, ACCEPT, ACCEPT, ERROR, MORE, ACCEPT2, CURLY, ERROR}, |
|
||||||
/*CURLY*/ { ERROR, ERROR, ERROR, ERROR, ERROR, CURLY2, ERROR, ERROR, ERROR}, |
|
||||||
/*CURLY2*/ { ERROR, ERROR, ERROR, CURLY3, ERROR, ERROR, ERROR, ERROR, ERROR}, |
|
||||||
/*CURLY3*/ { ERROR, ERROR, ERROR, ERROR, ACCEPTNOMORE, ERROR, ERROR, ERROR, ERROR}, |
|
||||||
/*ACCEPT*/ { ERROR, DOT, ERROR, ERROR, ACCEPT, ERROR, ERROR, ERROR, ACCEPTNOMORE}, |
|
||||||
/*ACCEPTNOMORE*/ { ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR}, |
|
||||||
/*ACCEPT2*/ { ERROR, DOT, ERROR, ACCEPT, ACCEPT, ERROR, ERROR, ERROR, ERROR}, |
|
||||||
}; |
|
||||||
#endregion
|
|
||||||
} |
|
||||||
} |
|
||||||
Loading…
Reference in new issue