|
|
|
@ -15,6 +15,8 @@ namespace ICSharpCode.NRefactory.Parser.CSharp |
|
|
|
{ |
|
|
|
{ |
|
|
|
internal sealed class Lexer : AbstractLexer |
|
|
|
internal sealed class Lexer : AbstractLexer |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
bool isAtLineBegin = true; |
|
|
|
|
|
|
|
|
|
|
|
public Lexer(TextReader reader) : base(reader) |
|
|
|
public Lexer(TextReader reader) : base(reader) |
|
|
|
{ |
|
|
|
{ |
|
|
|
} |
|
|
|
} |
|
|
|
@ -24,7 +26,10 @@ namespace ICSharpCode.NRefactory.Parser.CSharp |
|
|
|
int nextChar; |
|
|
|
int nextChar; |
|
|
|
char ch; |
|
|
|
char ch; |
|
|
|
bool hadLineEnd = false; |
|
|
|
bool hadLineEnd = false; |
|
|
|
if (Line == 1 && Col == 1) hadLineEnd = true; // beginning of document
|
|
|
|
if (Line == 1 && Col == 1) { |
|
|
|
|
|
|
|
isAtLineBegin = true; |
|
|
|
|
|
|
|
hadLineEnd = true; // beginning of document
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
while ((nextChar = ReaderRead()) != -1) { |
|
|
|
while ((nextChar = ReaderRead()) != -1) { |
|
|
|
Token token; |
|
|
|
Token token; |
|
|
|
@ -42,6 +47,7 @@ namespace ICSharpCode.NRefactory.Parser.CSharp |
|
|
|
} |
|
|
|
} |
|
|
|
HandleLineEnd((char)nextChar); |
|
|
|
HandleLineEnd((char)nextChar); |
|
|
|
hadLineEnd = true; |
|
|
|
hadLineEnd = true; |
|
|
|
|
|
|
|
isAtLineBegin = true; |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
case '/': |
|
|
|
case '/': |
|
|
|
int peek = ReaderPeek(); |
|
|
|
int peek = ReaderPeek(); |
|
|
|
@ -49,19 +55,24 @@ namespace ICSharpCode.NRefactory.Parser.CSharp |
|
|
|
ReadComment(); |
|
|
|
ReadComment(); |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
|
|
|
|
isAtLineBegin = false; |
|
|
|
token = ReadOperator('/'); |
|
|
|
token = ReadOperator('/'); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
case '#': |
|
|
|
case '#': |
|
|
|
ReadPreProcessingDirective(); |
|
|
|
ReadPreProcessingDirective(); |
|
|
|
|
|
|
|
isAtLineBegin = false; |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
case '"': |
|
|
|
case '"': |
|
|
|
token = ReadString(); |
|
|
|
token = ReadString(); |
|
|
|
|
|
|
|
isAtLineBegin = false; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case '\'': |
|
|
|
case '\'': |
|
|
|
token = ReadChar(); |
|
|
|
token = ReadChar(); |
|
|
|
|
|
|
|
isAtLineBegin = false; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case '@': |
|
|
|
case '@': |
|
|
|
|
|
|
|
isAtLineBegin = false; |
|
|
|
int next = ReaderRead(); |
|
|
|
int next = ReaderRead(); |
|
|
|
if (next == -1) { |
|
|
|
if (next == -1) { |
|
|
|
errors.Error(Line, Col, String.Format("EOF after @")); |
|
|
|
errors.Error(Line, Col, String.Format("EOF after @")); |
|
|
|
@ -83,6 +94,7 @@ namespace ICSharpCode.NRefactory.Parser.CSharp |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
|
|
|
|
|
isAtLineBegin = false; // non-ws chars are handled here
|
|
|
|
ch = (char)nextChar; |
|
|
|
ch = (char)nextChar; |
|
|
|
if (Char.IsLetter(ch) || ch == '_' || ch == '\\') { |
|
|
|
if (Char.IsLetter(ch) || ch == '_' || ch == '\\') { |
|
|
|
int x = Col - 1; // Col was incremented above, but we want the start of the identifier
|
|
|
|
int x = Col - 1; // Col was incremented above, but we want the start of the identifier
|
|
|
|
@ -780,6 +792,7 @@ namespace ICSharpCode.NRefactory.Parser.CSharp |
|
|
|
switch (ReaderRead()) { |
|
|
|
switch (ReaderRead()) { |
|
|
|
case '*': |
|
|
|
case '*': |
|
|
|
ReadMultiLineComment(); |
|
|
|
ReadMultiLineComment(); |
|
|
|
|
|
|
|
isAtLineBegin = false; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case '/': |
|
|
|
case '/': |
|
|
|
if (ReaderPeek() == '/') { |
|
|
|
if (ReaderPeek() == '/') { |
|
|
|
@ -788,6 +801,7 @@ namespace ICSharpCode.NRefactory.Parser.CSharp |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
ReadSingleLineComment(CommentType.SingleLine); |
|
|
|
ReadSingleLineComment(CommentType.SingleLine); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
isAtLineBegin = true; |
|
|
|
break; |
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
|
errors.Error(Line, Col, String.Format("Error while reading comment")); |
|
|
|
errors.Error(Line, Col, String.Format("Error while reading comment")); |
|
|
|
@ -820,7 +834,7 @@ namespace ICSharpCode.NRefactory.Parser.CSharp |
|
|
|
if (specialCommentHash.ContainsKey(tag)) { |
|
|
|
if (specialCommentHash.ContainsKey(tag)) { |
|
|
|
Location p = new Location(Col, Line); |
|
|
|
Location p = new Location(Col, Line); |
|
|
|
string comment = ch + ReadToEndOfLine(); |
|
|
|
string comment = ch + ReadToEndOfLine(); |
|
|
|
this.TagComments.Add(new TagComment(tag, comment, p, new Location(Col, Line))); |
|
|
|
this.TagComments.Add(new TagComment(tag, comment, isAtLineBegin, p, new Location(Col, Line))); |
|
|
|
sb.Append(comment); |
|
|
|
sb.Append(comment); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -834,7 +848,7 @@ namespace ICSharpCode.NRefactory.Parser.CSharp |
|
|
|
if (this.SkipAllComments) { |
|
|
|
if (this.SkipAllComments) { |
|
|
|
SkipToEndOfLine(); |
|
|
|
SkipToEndOfLine(); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
specialTracker.StartComment(commentType, new Location(Col, Line)); |
|
|
|
specialTracker.StartComment(commentType, isAtLineBegin, new Location(Col, Line)); |
|
|
|
specialTracker.AddString(ReadCommentToEOL()); |
|
|
|
specialTracker.AddString(ReadCommentToEOL()); |
|
|
|
specialTracker.FinishComment(new Location(Col, Line)); |
|
|
|
specialTracker.FinishComment(new Location(Col, Line)); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -854,7 +868,7 @@ namespace ICSharpCode.NRefactory.Parser.CSharp |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
specialTracker.StartComment(CommentType.Block, new Location(Col, Line)); |
|
|
|
specialTracker.StartComment(CommentType.Block, isAtLineBegin, new Location(Col, Line)); |
|
|
|
|
|
|
|
|
|
|
|
// sc* = special comment handling (TO DO markers)
|
|
|
|
// sc* = special comment handling (TO DO markers)
|
|
|
|
string scTag = null; // is set to non-null value when we are inside a comment marker
|
|
|
|
string scTag = null; // is set to non-null value when we are inside a comment marker
|
|
|
|
@ -866,7 +880,7 @@ namespace ICSharpCode.NRefactory.Parser.CSharp |
|
|
|
|
|
|
|
|
|
|
|
if (HandleLineEnd(ch)) { |
|
|
|
if (HandleLineEnd(ch)) { |
|
|
|
if (scTag != null) { |
|
|
|
if (scTag != null) { |
|
|
|
this.TagComments.Add(new TagComment(scTag, scCurWord.ToString(), scStartLocation, new Location(Col, Line))); |
|
|
|
this.TagComments.Add(new TagComment(scTag, scCurWord.ToString(), isAtLineBegin, scStartLocation, new Location(Col, Line))); |
|
|
|
scTag = null; |
|
|
|
scTag = null; |
|
|
|
} |
|
|
|
} |
|
|
|
scCurWord.Length = 0; |
|
|
|
scCurWord.Length = 0; |
|
|
|
@ -877,7 +891,7 @@ namespace ICSharpCode.NRefactory.Parser.CSharp |
|
|
|
// End of multiline comment reached ?
|
|
|
|
// End of multiline comment reached ?
|
|
|
|
if (ch == '*' && ReaderPeek() == '/') { |
|
|
|
if (ch == '*' && ReaderPeek() == '/') { |
|
|
|
if (scTag != null) { |
|
|
|
if (scTag != null) { |
|
|
|
this.TagComments.Add(new TagComment(scTag, scCurWord.ToString(), scStartLocation, new Location(Col, Line))); |
|
|
|
this.TagComments.Add(new TagComment(scTag, scCurWord.ToString(), isAtLineBegin, scStartLocation, new Location(Col, Line))); |
|
|
|
} |
|
|
|
} |
|
|
|
ReaderRead(); |
|
|
|
ReaderRead(); |
|
|
|
specialTracker.FinishComment(new Location(Col, Line)); |
|
|
|
specialTracker.FinishComment(new Location(Col, Line)); |
|
|
|
@ -919,13 +933,16 @@ namespace ICSharpCode.NRefactory.Parser.CSharp |
|
|
|
lastToken = curToken; |
|
|
|
lastToken = curToken; |
|
|
|
curToken = curToken.next; |
|
|
|
curToken = curToken.next; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
isAtLineBegin = true; |
|
|
|
int nextChar; |
|
|
|
int nextChar; |
|
|
|
while ((nextChar = ReaderRead()) != -1) { |
|
|
|
while ((nextChar = ReaderRead()) != -1) { |
|
|
|
switch (nextChar) { |
|
|
|
switch (nextChar) { |
|
|
|
case '{': |
|
|
|
case '{': |
|
|
|
|
|
|
|
isAtLineBegin = false; |
|
|
|
braceCount++; |
|
|
|
braceCount++; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case '}': |
|
|
|
case '}': |
|
|
|
|
|
|
|
isAtLineBegin = false; |
|
|
|
if (--braceCount < 0) { |
|
|
|
if (--braceCount < 0) { |
|
|
|
curToken = new Token(Tokens.CloseCurlyBrace, Col - 1, Line); |
|
|
|
curToken = new Token(Tokens.CloseCurlyBrace, Col - 1, Line); |
|
|
|
return; |
|
|
|
return; |
|
|
|
@ -936,19 +953,24 @@ namespace ICSharpCode.NRefactory.Parser.CSharp |
|
|
|
if (peek == '/' || peek == '*') { |
|
|
|
if (peek == '/' || peek == '*') { |
|
|
|
ReadComment(); |
|
|
|
ReadComment(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
isAtLineBegin = false; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case '#': |
|
|
|
case '#': |
|
|
|
ReadPreProcessingDirective(); |
|
|
|
ReadPreProcessingDirective(); |
|
|
|
|
|
|
|
isAtLineBegin = false; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case '"': |
|
|
|
case '"': |
|
|
|
ReadString(); |
|
|
|
ReadString(); |
|
|
|
|
|
|
|
isAtLineBegin = false; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case '\'': |
|
|
|
case '\'': |
|
|
|
ReadChar(); |
|
|
|
ReadChar(); |
|
|
|
|
|
|
|
isAtLineBegin = false; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case '\r': |
|
|
|
case '\r': |
|
|
|
case '\n': |
|
|
|
case '\n': |
|
|
|
HandleLineEnd((char)nextChar); |
|
|
|
HandleLineEnd((char)nextChar); |
|
|
|
|
|
|
|
isAtLineBegin = true; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case '@': |
|
|
|
case '@': |
|
|
|
int next = ReaderRead(); |
|
|
|
int next = ReaderRead(); |
|
|
|
@ -957,6 +979,7 @@ namespace ICSharpCode.NRefactory.Parser.CSharp |
|
|
|
} else if (next == '"') { |
|
|
|
} else if (next == '"') { |
|
|
|
ReadVerbatimString(); |
|
|
|
ReadVerbatimString(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
isAtLineBegin = false; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -1072,7 +1095,7 @@ namespace ICSharpCode.NRefactory.Parser.CSharp |
|
|
|
} |
|
|
|
} |
|
|
|
SkipToEndOfLine(); // skip comment
|
|
|
|
SkipToEndOfLine(); // skip comment
|
|
|
|
} |
|
|
|
} |
|
|
|
return new PreprocessingDirective(directive, null, start, endLocation) { Expression = expr }; |
|
|
|
return new PreprocessingDirective(directive, null, start, endLocation) { Expression = expr, LastLineEnd = lastLineEnd }; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
Location endLocation = new Location(Col, Line); |
|
|
|
Location endLocation = new Location(Col, Line); |
|
|
|
string arg = ReadToEndOfLine(); |
|
|
|
string arg = ReadToEndOfLine(); |
|
|
|
@ -1081,7 +1104,7 @@ namespace ICSharpCode.NRefactory.Parser.CSharp |
|
|
|
if (pos >= 0) |
|
|
|
if (pos >= 0) |
|
|
|
arg = arg.Substring(0, pos); |
|
|
|
arg = arg.Substring(0, pos); |
|
|
|
arg = arg.Trim(); |
|
|
|
arg = arg.Trim(); |
|
|
|
return new PreprocessingDirective(directive, arg, start, endLocation); |
|
|
|
return new PreprocessingDirective(directive, arg, start, endLocation) { LastLineEnd = lastLineEnd }; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|