Browse Source

#d builds again; work on the parser layer

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@38 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Markus Palme 21 years ago
parent
commit
604df08af5
  1. 367
      src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/ExpressionFinder.cs
  2. 102
      src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/Parser.cs
  3. 4
      src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.csproj

367
src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/ExpressionFinder.cs

@ -12,80 +12,74 @@ namespace VBNetBinding.Parser @@ -12,80 +12,74 @@ namespace VBNetBinding.Parser
public string FindExpression(string inText, int offset)
{
this.text = FilterComments(inText, ref offset);
this.text = text;
this.offset = this.lastAccept = offset;
this.state = START;
if (this.text == null) {
this.state = START;
if (this.text == null)
{
return null;
}
while (state != ERROR) {
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) {
if (state == ACCEPT || state == ACCEPT2)
{
lastAccept = this.offset;
}
if (state == ACCEPTNOMORE) {
if (state == ACCEPTNOMORE)
{
return this.text.Substring(this.offset + 1, offset - this.offset);
}
}
return this.text.Substring(this.lastAccept + 1, offset - this.lastAccept);
}
#region Comment Filter and 'inside string watcher'
#region Comment Filter and 'inside string watcher'
int initialOffset;
public string FilterComments(string text, ref int offset)
{
this.initialOffset = offset;
StringBuilder outText = new StringBuilder();
int curOffset = 0;
while (curOffset <= initialOffset) {
while (curOffset <= initialOffset)
{
char ch = text[curOffset];
switch (ch) {
switch (ch)
{
case '@':
if (curOffset + 1 < text.Length && text[curOffset + 1] == '"') {
if (curOffset + 1 < text.Length && text[curOffset + 1] == '"')
{
outText.Append(text[curOffset++]); // @
outText.Append(text[curOffset++]); // "
if (!ReadVerbatimString(outText, text, ref curOffset)) {
if (!ReadVerbatimString(outText, text, ref curOffset))
{
return null;
}
}else{
}
else
{
outText.Append(ch);
++curOffset;
}
break;
case '\'':
outText.Append(ch);
curOffset++;
if(! ReadChar(outText, text, ref curOffset)) {
return null;
}
break;
case '"':
outText.Append(ch);
curOffset++;
if (!ReadString(outText, text, ref curOffset)) {
if (!ReadString(outText, text, ref curOffset))
{
return null;
}
break;
case '/':
if (curOffset + 1 < text.Length && text[curOffset + 1] == '/') {
offset -= 2;
curOffset += 2;
if (!ReadToEOL(text, ref curOffset, ref offset)) {
return null;
}
} else if (curOffset + 1 < text.Length && text[curOffset + 1] == '*') {
offset -= 2;
curOffset += 2;
if (!ReadMultiLineComment(text, ref curOffset, ref offset)) {
return null;
}
} else {
goto default;
case '\'':
offset -= 1;
curOffset += 1;
if (!ReadToEOL(text, ref curOffset, ref offset))
{
return null;
}
break;
default:
@ -94,77 +88,69 @@ namespace VBNetBinding.Parser @@ -94,77 +88,69 @@ namespace VBNetBinding.Parser
break;
}
}
return outText.ToString();
}
bool ReadToEOL(string text, ref int curOffset, ref int offset)
{
while (curOffset <= initialOffset) {
while (curOffset <= initialOffset)
{
char ch = text[curOffset++];
--offset;
if (ch == '\n') {
if (ch == '\n')
{
return true;
}
}
return false;
}
bool ReadChar(StringBuilder outText, string text, ref int curOffset)
{
char first = text[curOffset];
if (curOffset <= initialOffset) {
outText.Append(text[curOffset++]);
}
if (curOffset <= initialOffset) {
outText.Append(text[curOffset++]);
}
// special case: '\''
if(first == '\\' && curOffset <= initialOffset) {
outText.Append(text[curOffset++]);
}
return text[curOffset - 1] == '\'';
}
bool ReadString(StringBuilder outText, string text, ref int curOffset)
{
while (curOffset <= initialOffset) {
while (curOffset <= initialOffset)
{
char ch = text[curOffset++];
outText.Append(ch);
if (ch == '"') {
if (ch == '"')
{
return true;
} else if (ch == '\\') {
outText.Append(text[curOffset++]);
}
}
return false;
}
bool ReadVerbatimString(StringBuilder outText, string text, ref int curOffset)
{
while (curOffset <= initialOffset) {
while (curOffset <= initialOffset)
{
char ch = text[curOffset++];
outText.Append(ch);
if (ch == '"') {
if (curOffset < text.Length && text[curOffset] == '"') {
if (ch == '"')
{
if (curOffset < text.Length && text[curOffset] == '"')
{
outText.Append(text[curOffset++]);
} else {
}
else
{
return true;
}
}
}
return false;
}
bool ReadMultiLineComment(string text, ref int curOffset, ref int offset)
{
while (curOffset <= initialOffset) {
while (curOffset <= initialOffset)
{
char ch = text[curOffset++];
--offset;
if (ch == '*') {
if (curOffset < text.Length && text[curOffset] == '/') {
if (ch == '*')
{
if (curOffset < text.Length && text[curOffset] == '/')
{
++curOffset;
--offset;
return true;
@ -173,89 +159,91 @@ namespace VBNetBinding.Parser @@ -173,89 +159,91 @@ namespace VBNetBinding.Parser
}
return false;
}
#endregion
#region mini backward lexer
#endregion
#region mini backward lexer
string text;
int offset;
int offset;
char GetNext()
{
if (offset >= 0) {
if (offset >= 0)
{
return text[offset--];
}
return '\0';
}
char Peek(int n)
{
if (offset - n >= 0) {
return text[offset - n];
}
return '\0';
}
char Peek()
{
if (offset >= 0) {
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;
static int Digit = 9;
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", "Digit"
"Err", "Dot", "StrLit", "Ident", "New", "Bracket", "Paren", "Curly", "Using"
};
string GetTokenName(int state)
{
return tokenStateName[state];
}
void ReadNextToken()
{
char ch = GetNext();
curTokenType = Err;
if (ch == '\0') {
if (ch == '\0' || ch == '\n' || ch == '\r')
{
return;
}
while (Char.IsWhiteSpace(ch)) {
while (Char.IsWhiteSpace(ch))
{
ch = GetNext();
if (ch == '\n' || ch == '\r')
{
return;
}
}
switch (ch) {
switch (ch)
{
case '}':
if (ReadBracket('{', '}')) {
if (ReadBracket('{', '}'))
{
curTokenType = Curly;
}
break;
case ')':
if (ReadBracket('(', ')')) {
if (ReadBracket('(', ')'))
{
curTokenType = Parent;
}
break;
case ']':
if (ReadBracket('[', ']')) {
curTokenType = Bracket;
if (ReadBracket('[', ']'))
{
curTokenType = Ident;
}
break;
case '.':
@ -263,22 +251,23 @@ namespace VBNetBinding.Parser @@ -263,22 +251,23 @@ namespace VBNetBinding.Parser
break;
case '\'':
case '"':
if (ReadStringLiteral(ch)) {
if (ReadStringLiteral(ch))
{
curTokenType = StrLit;
}
break;
default:
if (IsDigit()) {
string digit = ReadDigit(ch);
curTokenType = Digit;
} else if (IsIdentifierPart(ch)) {
if (IsIdentifierPart(ch))
{
string ident = ReadIdentifier(ch);
if (ident != null) {
switch (ident) {
if (ident != null)
{
switch (ident.ToLower())
{
case "new":
curTokenType = New;
break;
case "using":
case "imports":
curTokenType = Using;
break;
default:
@ -287,44 +276,37 @@ namespace VBNetBinding.Parser @@ -287,44 +276,37 @@ namespace VBNetBinding.Parser
}
}
}
break;
}
}
bool IsDigit()
{
int n = 0;
while (true) {
char ch = Peek(n);
if (Char.IsDigit(ch)) {
n++;
continue;
}
return n > 0 && !Char.IsLetter(ch);
}
}
bool ReadStringLiteral(char litStart)
{
while (true) {
while (true)
{
char ch = GetNext();
if (ch == '\0') {
if (ch == '\0')
{
return false;
}
if (ch == litStart) {
if (Peek() == '@' && litStart == '"') {
if (ch == litStart)
{
if (Peek() == '@' && litStart == '"')
{
GetNext();
}
return true;
}
}
}
bool ReadBracket(char openBracket, char closingBracket)
{
int curlyBraceLevel = 0;
int curlyBraceLevel = 0;
int squareBracketLevel = 0;
int parenthesisLevel = 0;
switch (openBracket) {
int parenthesisLevel = 0;
switch (openBracket)
{
case '(':
parenthesisLevel++;
break;
@ -335,13 +317,16 @@ namespace VBNetBinding.Parser @@ -335,13 +317,16 @@ namespace VBNetBinding.Parser
curlyBraceLevel++;
break;
}
while (parenthesisLevel != 0 || squareBracketLevel != 0 || curlyBraceLevel != 0) {
while (parenthesisLevel != 0 || squareBracketLevel != 0 || curlyBraceLevel != 0)
{
char ch = GetNext();
if (ch == '\0') {
if (ch == '\0')
{
return false;
}
switch (ch) {
switch (ch)
{
case '(':
parenthesisLevel--;
break;
@ -364,77 +349,69 @@ namespace VBNetBinding.Parser @@ -364,77 +349,69 @@ namespace VBNetBinding.Parser
}
return true;
}
string ReadIdentifier(char ch)
{
string identifier = ch.ToString();
while (IsIdentifierPart(Peek())) {
while (IsIdentifierPart(Peek()))
{
identifier = GetNext() + identifier;
}
return identifier;
}
string ReadDigit(char ch)
{
string digit = ch.ToString();
while (Char.IsDigit(Peek()) || Peek() == '.') {
digit = GetNext() + digit;
}
return digit;
}
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;
#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",
"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, digit
/*ERROR*/ { ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR},
/*START*/ { ERROR, DOT, ACCEPT, ACCEPT, ERROR, MORE, ACCEPT2, CURLY, ACCEPTNOMORE, ERROR},
/*DOT*/ { ERROR, ERROR, ACCEPT, ACCEPT, ERROR, MORE, ACCEPT, CURLY, ERROR, ACCEPT},
/*MORE*/ { ERROR, ERROR, ACCEPT, ACCEPT, ERROR, MORE, ACCEPT2, CURLY, ERROR, ACCEPT},
/*CURLY*/ { ERROR, ERROR, ERROR, ERROR, ERROR, CURLY2, ERROR, ERROR, ERROR, ERROR},
/*CURLY2*/ { ERROR, ERROR, ERROR, CURLY3, ERROR, ERROR, ERROR, ERROR, ERROR, CURLY3},
/*CURLY3*/ { ERROR, ERROR, ERROR, ERROR, ACCEPTNOMORE, ERROR, ERROR, ERROR, ERROR, ERROR},
/*ACCEPT*/ { ERROR, MORE, ERROR, ERROR, ACCEPT, ERROR, ERROR, ERROR, ACCEPTNOMORE, ERROR},
/*ACCEPTNOMORE*/ { ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR},
/*ACCEPT2*/ { ERROR, MORE, ERROR, ACCEPT, ACCEPT, ERROR, ERROR, ERROR, ERROR, ACCEPT},
// Err, Dot, Str, ID, New, Brk, Par, Cur, Using
/*ERROR*/ { ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR},
/*START*/ { ERROR, DOT, ACCEPT, ACCEPT, ERROR, MORE, ACCEPT2, CURLY, ACCEPTNOMORE},
/*DOT*/ { ERROR, ERROR, ACCEPT, ACCEPT, ERROR, MORE, ACCEPT, 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, MORE, ERROR, ERROR, ACCEPT, ERROR, ERROR, ERROR, ACCEPTNOMORE},
/*ACCEPTNOMORE*/ { ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR},
/*ACCEPT2*/ { ERROR, MORE, ERROR, ACCEPT, ACCEPT, ERROR, ERROR, ERROR, ERROR},
};
#endregion
#endregion
}
}

102
src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/Parser.cs

@ -21,76 +21,83 @@ namespace VBNetBinding.Parser @@ -21,76 +21,83 @@ namespace VBNetBinding.Parser
{
///<summary>IParser Interface</summary>
string[] lexerTags;
public string[] LexerTags {
get {
public string[] LexerTags
{
get
{
return lexerTags;
}
set {
set
{
lexerTags = value;
}
}
public IExpressionFinder ExpressionFinder {
get {
public IExpressionFinder ExpressionFinder
{
get
{
return new ExpressionFinder();
}
}
public bool CanParse(string fileName)
{
return Path.GetExtension(fileName).ToUpper() == ".CS";
return Path.GetExtension(fileName).ToUpper() == ".VB";
}
public bool CanParse(IProject project)
{
return project.Language == "C#";
return project.Language == "VBNet";
}
void RetrieveRegions(ICompilationUnit cu, ICSharpCode.NRefactory.Parser.SpecialTracker tracker)
{
for (int i = 0; i < tracker.CurrentSpecials.Count; ++i) {
for (int i = 0; i < tracker.CurrentSpecials.Count; ++i)
{
ICSharpCode.NRefactory.Parser.PreProcessingDirective directive = tracker.CurrentSpecials[i] as ICSharpCode.NRefactory.Parser.PreProcessingDirective;
if (directive != null) {
if (directive.Cmd == "#region") {
int deep = 1;
for (int j = i + 1; j < tracker.CurrentSpecials.Count; ++j) {
if (directive != null)
{
if (directive.Cmd == "#region")
{
int deep = 1;
for (int j = i + 1; j < tracker.CurrentSpecials.Count; ++j)
{
ICSharpCode.NRefactory.Parser.PreProcessingDirective nextDirective = tracker.CurrentSpecials[j] as ICSharpCode.NRefactory.Parser.PreProcessingDirective;
if (nextDirective != null) {
switch (nextDirective.Cmd) {
if (nextDirective != null)
{
switch (nextDirective.Cmd)
{
case "#region":
++deep;
break;
case "#endregion":
--deep;
if (deep == 0) {
cu.FoldingRegions.Add(new FoldingRegion(directive.Arg.Trim(), new DefaultRegion(directive.Start, new Point(nextDirective.End.X, nextDirective.End.Y))));
goto end;
case "#end":
if (nextDirective.Arg.ToLower() == "region") {
--deep;
if (deep == 0) {
cu.FoldingRegions.Add(new FoldingRegion(directive.Arg.Trim('"'), new DefaultRegion(directive.Start, nextDirective.End)));
goto end;
}
}
break;
}
}
}
end: ;
end: ;
}
}
}
}
public ICompilationUnitBase Parse(string fileName)
public ICompilationUnit Parse(IProjectContent projectContent, string fileName)
{
// ICSharpCode.NRefactory.Parser.Parser p = new ICSharpCode.NRefactory.Parser.Parser();
//
// Lexer lexer = new Lexer(new FileReader(fileName));
// lexer.SpecialCommentTags = lexerTags;
// p.Parse(lexer);
Properties textEditorProperties = ((Properties)PropertyService.Get("ICSharpCode.TextEditor.Document.Document.DefaultDocumentAggregatorProperties", new Properties()));
ICSharpCode.NRefactory.Parser.IParser p = ICSharpCode.NRefactory.Parser.ParserFactory.CreateParser(fileName, Encoding.GetEncoding(textEditorProperties.Get("Encoding", 1252)));
p.Lexer.SpecialCommentTags = lexerTags;
p.Parse();
NRefactoryASTConvertVisitor visitor = new NRefactoryASTConvertVisitor();
NRefactoryASTConvertVisitor visitor = new NRefactoryASTConvertVisitor(projectContent);
visitor.Visit(p.CompilationUnit, null);
visitor.Cu.FileName = fileName;
visitor.Cu.ErrorsDuringCompile = p.Errors.count > 0;
@ -98,43 +105,38 @@ namespace VBNetBinding.Parser @@ -98,43 +105,38 @@ namespace VBNetBinding.Parser
AddCommentTags(visitor.Cu, p.Lexer.TagComments);
return visitor.Cu;
}
public ICompilationUnitBase Parse(string fileName, string fileContent)
public ICompilationUnit Parse(IProjectContent projectContent, string fileName, string fileContent)
{
// ICSharpCode.NRefactory.Parser.Parser p = new ICSharpCode.NRefactory.Parser.Parser();
//
// Lexer lexer = new Lexer(new StringReader(fileContent));
// lexer.SpecialCommentTags = lexerTags;
// p.Parse(lexer);
ICSharpCode.NRefactory.Parser.IParser p = ICSharpCode.NRefactory.Parser.ParserFactory.CreateParser(ICSharpCode.NRefactory.Parser.SupportedLanguages.CSharp, new StringReader(fileContent));
p.Lexer.SpecialCommentTags = lexerTags;
p.Parse();
NRefactoryASTConvertVisitor visitor = new NRefactoryASTConvertVisitor();
NRefactoryASTConvertVisitor visitor = new NRefactoryASTConvertVisitor(projectContent);
visitor.Visit(p.CompilationUnit, null);
visitor.Cu.FileName = fileName;
visitor.Cu.ErrorsDuringCompile = p.Errors.count > 0;
visitor.Cu.Tag = p.CompilationUnit;
RetrieveRegions(visitor.Cu, p.Lexer.SpecialTracker);
AddCommentTags(visitor.Cu, p.Lexer.TagComments);
return visitor.Cu;
}
void AddCommentTags(ICompilationUnit cu, ArrayList tagComments)
{
foreach (ICSharpCode.NRefactory.Parser.TagComment tagComment in tagComments) {
foreach (ICSharpCode.NRefactory.Parser.TagComment tagComment in tagComments)
{
DefaultRegion tagRegion = new DefaultRegion(tagComment.StartPosition.Y, tagComment.StartPosition.X);
ICSharpCode.SharpDevelop.Dom.Tag tag = new ICSharpCode.SharpDevelop.Dom.Tag(tagComment.Tag, tagRegion);
tag.CommentString = tagComment.CommentText;
cu.TagComments.Add(tag);
}
}
public IResolver CreateResolver()
{
return new ICSharpCode.SharpDevelop.Dom.NRefactoryResolver.NRefactoryResolver(ICSharpCode.NRefactory.Parser.SupportedLanguages.CSharp);
return new ICSharpCode.SharpDevelop.Dom.NRefactoryResolver.NRefactoryResolver(ICSharpCode.NRefactory.Parser.SupportedLanguages.CSharp);
}
///////// IParser Interface END
}

4
src/AddIns/BackendBindings/VBNetBinding/Project/VBNetBinding.csproj

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.41115</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BF38FB72-B380-4196-AF8C-95749D726C61}</ProjectGuid>
<ProjectGuid>{1F1AC7CD-D154-45BB-8EAF-804CA8055F5A}</ProjectGuid>
<AssemblyName>VBNetBinding</AssemblyName>
<OutputTarget>Library</OutputTarget>
<WarningLevel>4</WarningLevel>
@ -61,7 +61,7 @@ @@ -61,7 +61,7 @@
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Src\OptionPanels\BuildOptions.cs">
<SubType>UserControl</SubType>
<SubType>Form</SubType>
</Compile>
<Compile Include="Src\OptionPanels\DebugOptions.cs">
<SubType>UserControl</SubType>

Loading…
Cancel
Save