5 changed files with 2 additions and 12484 deletions
@ -1,386 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
using System.Collections; |
|
||||||
using System.Collections.Generic; |
|
||||||
using System.IO; |
|
||||||
using System.Text; |
|
||||||
|
|
||||||
namespace ICSharpCode.NRefactory.Parser |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// This is the base class for the C# and VB.NET lexer
|
|
||||||
/// </summary>
|
|
||||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1708:IdentifiersShouldDifferByMoreThanCase")] |
|
||||||
internal abstract class AbstractLexer : ILexer |
|
||||||
{ |
|
||||||
LATextReader reader; |
|
||||||
int col = 1; |
|
||||||
int line = 1; |
|
||||||
|
|
||||||
protected Errors errors = new Errors(); |
|
||||||
|
|
||||||
protected Token lastToken = null; |
|
||||||
protected Token curToken = null; |
|
||||||
protected Token peekToken = null; |
|
||||||
|
|
||||||
string[] specialCommentTags = null; |
|
||||||
protected Hashtable specialCommentHash = null; |
|
||||||
List<TagComment> tagComments = new List<TagComment>(); |
|
||||||
protected StringBuilder sb = new StringBuilder(); |
|
||||||
protected SpecialTracker specialTracker = new SpecialTracker(); |
|
||||||
|
|
||||||
// used for the original value of strings (with escape sequences).
|
|
||||||
protected StringBuilder originalValue = new StringBuilder(); |
|
||||||
|
|
||||||
public bool SkipAllComments { get; set; } |
|
||||||
public bool EvaluateConditionalCompilation { get; set; } |
|
||||||
public virtual IDictionary<string, object> ConditionalCompilationSymbols { |
|
||||||
get { throw new NotSupportedException(); } |
|
||||||
} |
|
||||||
|
|
||||||
protected static IEnumerable<string> GetSymbols (string symbols) |
|
||||||
{ |
|
||||||
if (!string.IsNullOrEmpty(symbols)) { |
|
||||||
foreach (string symbol in symbols.Split (';', ' ', '\t')) { |
|
||||||
string s = symbol.Trim (); |
|
||||||
if (s.Length == 0) |
|
||||||
continue; |
|
||||||
yield return s; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public virtual void SetConditionalCompilationSymbols (string symbols) |
|
||||||
{ |
|
||||||
throw new NotSupportedException (); |
|
||||||
} |
|
||||||
|
|
||||||
protected int Line { |
|
||||||
get { |
|
||||||
return line; |
|
||||||
} |
|
||||||
} |
|
||||||
protected int Col { |
|
||||||
get { |
|
||||||
return col; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected bool recordRead = false; |
|
||||||
protected StringBuilder recordedText = new StringBuilder (); |
|
||||||
|
|
||||||
protected int ReaderRead() |
|
||||||
{ |
|
||||||
int val = reader.Read(); |
|
||||||
if (recordRead && val >= 0) |
|
||||||
recordedText.Append ((char)val); |
|
||||||
if ((val == '\r' && reader.Peek() != '\n') || val == '\n') { |
|
||||||
++line; |
|
||||||
col = 1; |
|
||||||
LineBreak(); |
|
||||||
} else if (val >= 0) { |
|
||||||
col++; |
|
||||||
} |
|
||||||
return val; |
|
||||||
} |
|
||||||
|
|
||||||
protected int ReaderPeek() |
|
||||||
{ |
|
||||||
return reader.Peek(); |
|
||||||
} |
|
||||||
|
|
||||||
protected int ReaderPeek(int step) |
|
||||||
{ |
|
||||||
return reader.Peek(step); |
|
||||||
} |
|
||||||
|
|
||||||
protected void ReaderSkip(int steps) |
|
||||||
{ |
|
||||||
for (int i = 0; i < steps; i++) { |
|
||||||
ReaderRead(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected string ReaderPeekString(int length) |
|
||||||
{ |
|
||||||
StringBuilder builder = new StringBuilder(); |
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) { |
|
||||||
int peek = ReaderPeek(i); |
|
||||||
if (peek != -1) |
|
||||||
builder.Append((char)peek); |
|
||||||
} |
|
||||||
|
|
||||||
return builder.ToString(); |
|
||||||
} |
|
||||||
|
|
||||||
public void SetInitialLocation(Location location) |
|
||||||
{ |
|
||||||
if (lastToken != null || curToken != null || peekToken != null) |
|
||||||
throw new InvalidOperationException(); |
|
||||||
this.line = location.Line; |
|
||||||
this.col = location.Column; |
|
||||||
} |
|
||||||
|
|
||||||
public Errors Errors { |
|
||||||
get { |
|
||||||
return errors; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the comments that had been read and containing tag key words.
|
|
||||||
/// </summary>
|
|
||||||
public List<TagComment> TagComments { |
|
||||||
get { |
|
||||||
return tagComments; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public SpecialTracker SpecialTracker { |
|
||||||
get { |
|
||||||
return specialTracker; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Special comment tags are tags like TODO, HACK or UNDONE which are read by the lexer and stored in <see cref="TagComments"/>.
|
|
||||||
/// </summary>
|
|
||||||
public string[] SpecialCommentTags { |
|
||||||
get { |
|
||||||
return specialCommentTags; |
|
||||||
} |
|
||||||
set { |
|
||||||
specialCommentTags = value; |
|
||||||
specialCommentHash = null; |
|
||||||
if (specialCommentTags != null && specialCommentTags.Length > 0) { |
|
||||||
specialCommentHash = new Hashtable(); |
|
||||||
foreach (string str in specialCommentTags) { |
|
||||||
specialCommentHash.Add(str, null); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The current Token. <seealso cref="ICSharpCode.NRefactory.Parser.Token"/>
|
|
||||||
/// </summary>
|
|
||||||
public Token Token { |
|
||||||
get { |
|
||||||
// Console.WriteLine("Call to Token");
|
|
||||||
return lastToken; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The next Token (The <see cref="Token"/> after <see cref="NextToken"/> call) . <seealso cref="ICSharpCode.NRefactory.Parser.Token"/>
|
|
||||||
/// </summary>
|
|
||||||
public Token LookAhead { |
|
||||||
get { |
|
||||||
// Console.WriteLine("Call to LookAhead");
|
|
||||||
return curToken; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor for the abstract lexer class.
|
|
||||||
/// </summary>
|
|
||||||
protected AbstractLexer(TextReader reader) |
|
||||||
{ |
|
||||||
this.reader = new LATextReader(reader); |
|
||||||
} |
|
||||||
|
|
||||||
protected AbstractLexer(TextReader reader, LexerMemento state) |
|
||||||
: this(reader) |
|
||||||
{ |
|
||||||
SetInitialLocation(new Location(state.Column, state.Line)); |
|
||||||
lastToken = new Token(state.PrevTokenKind, 0, 0); |
|
||||||
} |
|
||||||
|
|
||||||
#region System.IDisposable interface implementation
|
|
||||||
public virtual void Dispose() |
|
||||||
{ |
|
||||||
reader.Close(); |
|
||||||
reader = null; |
|
||||||
errors = null; |
|
||||||
lastToken = curToken = peekToken = null; |
|
||||||
specialCommentHash = null; |
|
||||||
tagComments = null; |
|
||||||
sb = originalValue = null; |
|
||||||
} |
|
||||||
#endregion
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Must be called before a peek operation.
|
|
||||||
/// </summary>
|
|
||||||
public void StartPeek() |
|
||||||
{ |
|
||||||
peekToken = curToken; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gives back the next token. A second call to Peek() gives the next token after the last call for Peek() and so on.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>An <see cref="Token"/> object.</returns>
|
|
||||||
public Token Peek() |
|
||||||
{ |
|
||||||
// Console.WriteLine("Call to Peek");
|
|
||||||
if (peekToken.next == null) { |
|
||||||
peekToken.next = Next(); |
|
||||||
} |
|
||||||
peekToken = peekToken.next; |
|
||||||
return peekToken; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reads the next token and gives it back.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>An <see cref="Token"/> object.</returns>
|
|
||||||
public virtual Token NextToken() |
|
||||||
{ |
|
||||||
if (curToken == null) { |
|
||||||
curToken = Next(); |
|
||||||
//Console.WriteLine(ICSharpCode.NRefactory.Parser.CSharp.Tokens.GetTokenString(curToken.kind) + " -- " + curToken.val + "(" + curToken.kind + ")");
|
|
||||||
return curToken; |
|
||||||
} |
|
||||||
|
|
||||||
lastToken = curToken; |
|
||||||
|
|
||||||
if (curToken.next == null) { |
|
||||||
curToken.next = Next(); |
|
||||||
} |
|
||||||
|
|
||||||
curToken = curToken.next; |
|
||||||
//Console.WriteLine(ICSharpCode.NRefactory.Parser.CSharp.Tokens.GetTokenString(curToken.kind) + " -- " + curToken.val + "(" + curToken.kind + ")");
|
|
||||||
return curToken; |
|
||||||
} |
|
||||||
|
|
||||||
protected abstract Token Next(); |
|
||||||
|
|
||||||
protected static bool IsIdentifierPart(int ch) |
|
||||||
{ |
|
||||||
if (ch == 95) return true; // 95 = '_'
|
|
||||||
if (ch == -1) return false; |
|
||||||
return char.IsLetterOrDigit((char)ch); // accept unicode letters
|
|
||||||
} |
|
||||||
|
|
||||||
protected static bool IsHex(char digit) |
|
||||||
{ |
|
||||||
return Char.IsDigit(digit) || ('A' <= digit && digit <= 'F') || ('a' <= digit && digit <= 'f'); |
|
||||||
} |
|
||||||
|
|
||||||
protected int GetHexNumber(char digit) |
|
||||||
{ |
|
||||||
if (Char.IsDigit(digit)) { |
|
||||||
return digit - '0'; |
|
||||||
} |
|
||||||
if ('A' <= digit && digit <= 'F') { |
|
||||||
return digit - 'A' + 0xA; |
|
||||||
} |
|
||||||
if ('a' <= digit && digit <= 'f') { |
|
||||||
return digit - 'a' + 0xA; |
|
||||||
} |
|
||||||
errors.Error(line, col, "Invalid hex number '" + digit + "'"); |
|
||||||
return 0; |
|
||||||
} |
|
||||||
protected Location lastLineEnd = new Location (1, 1); |
|
||||||
protected Location curLineEnd = new Location (1, 1); |
|
||||||
protected void LineBreak () |
|
||||||
{ |
|
||||||
lastLineEnd = curLineEnd; |
|
||||||
curLineEnd = new Location (col - 1, line); |
|
||||||
} |
|
||||||
protected bool HandleLineEnd(char ch) |
|
||||||
{ |
|
||||||
// Handle MS-DOS or MacOS line ends.
|
|
||||||
if (ch == '\r') { |
|
||||||
if (reader.Peek() == '\n') { // MS-DOS line end '\r\n'
|
|
||||||
ReaderRead(); // LineBreak (); called by ReaderRead ();
|
|
||||||
return true; |
|
||||||
} else { // assume MacOS line end which is '\r'
|
|
||||||
LineBreak (); |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
if (ch == '\n') { |
|
||||||
LineBreak (); |
|
||||||
return true; |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
protected void SkipToEndOfLine() |
|
||||||
{ |
|
||||||
int nextChar; |
|
||||||
while ((nextChar = reader.Read()) != -1) { |
|
||||||
if (nextChar == '\r') { |
|
||||||
if (reader.Peek() == '\n') |
|
||||||
reader.Read(); |
|
||||||
nextChar = '\n'; |
|
||||||
} |
|
||||||
if (nextChar == '\n') { |
|
||||||
++line; |
|
||||||
col = 1; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected string ReadToEndOfLine() |
|
||||||
{ |
|
||||||
sb.Length = 0; |
|
||||||
int nextChar; |
|
||||||
while ((nextChar = reader.Read()) != -1) { |
|
||||||
char ch = (char)nextChar; |
|
||||||
|
|
||||||
if (nextChar == '\r') { |
|
||||||
if (reader.Peek() == '\n') |
|
||||||
reader.Read(); |
|
||||||
nextChar = '\n'; |
|
||||||
} |
|
||||||
// Return read string, if EOL is reached
|
|
||||||
if (nextChar == '\n') { |
|
||||||
++line; |
|
||||||
col = 1; |
|
||||||
return sb.ToString(); |
|
||||||
} |
|
||||||
|
|
||||||
sb.Append(ch); |
|
||||||
} |
|
||||||
|
|
||||||
// Got EOF before EOL
|
|
||||||
string retStr = sb.ToString(); |
|
||||||
col += retStr.Length; |
|
||||||
return retStr; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Skips to the end of the current code block.
|
|
||||||
/// For this, the lexer must have read the next token AFTER the token opening the
|
|
||||||
/// block (so that Lexer.Token is the block-opening token, not Lexer.LookAhead).
|
|
||||||
/// After the call, Lexer.LookAhead will be the block-closing token.
|
|
||||||
/// </summary>
|
|
||||||
public abstract void SkipCurrentBlock(int targetToken); |
|
||||||
|
|
||||||
public event EventHandler<SavepointEventArgs> SavepointReached; |
|
||||||
|
|
||||||
protected virtual void OnSavepointReached(SavepointEventArgs e) |
|
||||||
{ |
|
||||||
if (SavepointReached != null) { |
|
||||||
SavepointReached(this, e); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public virtual LexerMemento Export() |
|
||||||
{ |
|
||||||
throw new NotSupportedException(); |
|
||||||
} |
|
||||||
|
|
||||||
public virtual void SetInitialContext(SnippetType context) |
|
||||||
{ |
|
||||||
throw new NotSupportedException(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,188 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
using System.IO; |
|
||||||
using NUnit.Framework; |
|
||||||
using ICSharpCode.NRefactory.Parser; |
|
||||||
using ICSharpCode.NRefactory.Parser.CSharp; |
|
||||||
using ICSharpCode.NRefactory.PrettyPrinter; |
|
||||||
|
|
||||||
namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp |
|
||||||
{ |
|
||||||
[TestFixture] |
|
||||||
public sealed class NumberLexerTests |
|
||||||
{ |
|
||||||
ILexer GenerateLexer(StringReader sr) |
|
||||||
{ |
|
||||||
return ParserFactory.CreateLexer(SupportedLanguage.CSharp, sr); |
|
||||||
} |
|
||||||
|
|
||||||
Token GetSingleToken(string text) |
|
||||||
{ |
|
||||||
ILexer lexer = GenerateLexer(new StringReader(text)); |
|
||||||
Token t = lexer.NextToken(); |
|
||||||
Assert.AreEqual(Tokens.EOF, lexer.NextToken().Kind, "Tokens.EOF"); |
|
||||||
Assert.AreEqual("", lexer.Errors.ErrorOutput); |
|
||||||
return t; |
|
||||||
} |
|
||||||
|
|
||||||
void CheckToken(string text, object val) |
|
||||||
{ |
|
||||||
Token t = GetSingleToken(text); |
|
||||||
Assert.AreEqual(Tokens.Literal, t.Kind, "Tokens.Literal"); |
|
||||||
Assert.AreEqual(text, t.Value, "value"); |
|
||||||
Assert.IsNotNull(t.LiteralValue, "literalValue is null"); |
|
||||||
Assert.AreEqual(val.GetType(), t.LiteralValue.GetType(), "literalValue.GetType()"); |
|
||||||
Assert.AreEqual(val, t.LiteralValue, "literalValue"); |
|
||||||
} |
|
||||||
|
|
||||||
[Test] |
|
||||||
public void TestSingleDigit() |
|
||||||
{ |
|
||||||
CheckToken("5", 5); |
|
||||||
} |
|
||||||
|
|
||||||
[Test] |
|
||||||
public void TestZero() |
|
||||||
{ |
|
||||||
CheckToken("0", 0); |
|
||||||
} |
|
||||||
|
|
||||||
[Test] |
|
||||||
public void TestInteger() |
|
||||||
{ |
|
||||||
CheckToken("66", 66); |
|
||||||
} |
|
||||||
|
|
||||||
[Test] |
|
||||||
public void TestNonOctalInteger() |
|
||||||
{ |
|
||||||
// C# does not have octal integers, so 077 should parse to 77
|
|
||||||
Assert.IsTrue(077 == 77); |
|
||||||
|
|
||||||
CheckToken("077", 077); |
|
||||||
CheckToken("056", 056); |
|
||||||
} |
|
||||||
|
|
||||||
[Test] |
|
||||||
public void TestHexadecimalInteger() |
|
||||||
{ |
|
||||||
CheckToken("0x99F", 0x99F); |
|
||||||
CheckToken("0xAB1f", 0xAB1f); |
|
||||||
CheckToken("0xffffffff", 0xffffffff); |
|
||||||
CheckToken("0xffffffffL", 0xffffffffL); |
|
||||||
CheckToken("0xffffffffuL", 0xffffffffuL); |
|
||||||
} |
|
||||||
|
|
||||||
[Test] |
|
||||||
public void InvalidHexadecimalInteger() |
|
||||||
{ |
|
||||||
// don't check result, just make sure there is no exception
|
|
||||||
GenerateLexer(new StringReader("0x2GF")).NextToken(); |
|
||||||
GenerateLexer(new StringReader("0xG2F")).NextToken(); |
|
||||||
// SD2-457
|
|
||||||
GenerateLexer(new StringReader("0x")).NextToken(); |
|
||||||
// hexadecimal integer >ulong.MaxValue
|
|
||||||
GenerateLexer(new StringReader("0xfedcba98765432100")).NextToken(); |
|
||||||
} |
|
||||||
|
|
||||||
[Test] |
|
||||||
public void TestLongHexadecimalInteger() |
|
||||||
{ |
|
||||||
CheckToken("0x4244636f446c6d58", 0x4244636f446c6d58); |
|
||||||
CheckToken("0xf244636f446c6d58", 0xf244636f446c6d58); |
|
||||||
} |
|
||||||
|
|
||||||
[Test] |
|
||||||
public void TestLongInteger() |
|
||||||
{ |
|
||||||
CheckToken("9223372036854775807", 9223372036854775807); // long.MaxValue
|
|
||||||
CheckToken("9223372036854775808", 9223372036854775808); // long.MaxValue+1
|
|
||||||
CheckToken("18446744073709551615", 18446744073709551615); // ulong.MaxValue
|
|
||||||
CheckToken("18446744073709551616f", 18446744073709551616f); // ulong.MaxValue+1 as float
|
|
||||||
CheckToken("18446744073709551616d", 18446744073709551616d); // ulong.MaxValue+1 as double
|
|
||||||
CheckToken("18446744073709551616m", 18446744073709551616m); // ulong.MaxValue+1 as decimal
|
|
||||||
} |
|
||||||
|
|
||||||
[Test] |
|
||||||
public void TestDouble() |
|
||||||
{ |
|
||||||
CheckToken("1.0", 1.0); |
|
||||||
CheckToken("1.1", 1.1); |
|
||||||
CheckToken("1.1e-2", 1.1e-2); |
|
||||||
} |
|
||||||
|
|
||||||
[Test] |
|
||||||
public void TestFloat() |
|
||||||
{ |
|
||||||
CheckToken("1f", 1f); |
|
||||||
CheckToken("1.0f", 1.0f); |
|
||||||
CheckToken("1.1f", 1.1f); |
|
||||||
CheckToken("1.1e-2f", 1.1e-2f); |
|
||||||
} |
|
||||||
|
|
||||||
[Test] |
|
||||||
public void TestDecimal() |
|
||||||
{ |
|
||||||
CheckToken("1m", 1m); |
|
||||||
CheckToken("1.0m", 1.0m); |
|
||||||
CheckToken("1.1m", 1.1m); |
|
||||||
CheckToken("1.1e-2m", 1.1e-2m); |
|
||||||
CheckToken("2.0e-5m", 2.0e-5m); |
|
||||||
} |
|
||||||
|
|
||||||
[Test] |
|
||||||
public void TestString() |
|
||||||
{ |
|
||||||
CheckToken(@"@""-->""""<--""", @"-->""<--"); |
|
||||||
CheckToken(@"""-->\""<--""", "-->\"<--"); |
|
||||||
|
|
||||||
CheckToken(@"""\U00000041""", "\U00000041"); |
|
||||||
CheckToken(@"""\U00010041""", "\U00010041"); |
|
||||||
} |
|
||||||
|
|
||||||
[Test] |
|
||||||
public void TestInvalidString() |
|
||||||
{ |
|
||||||
// ensure that line numbers are correct after newline in string
|
|
||||||
ILexer l = GenerateLexer(new StringReader("\"\n\"\n;")); |
|
||||||
Token t = l.NextToken(); |
|
||||||
Assert.AreEqual(Tokens.Literal, t.Kind); |
|
||||||
Assert.AreEqual(new Location(1, 1), t.Location); |
|
||||||
|
|
||||||
t = l.NextToken(); |
|
||||||
Assert.AreEqual(Tokens.Literal, t.Kind); |
|
||||||
Assert.AreEqual(new Location(1, 2), t.Location); |
|
||||||
|
|
||||||
t = l.NextToken(); |
|
||||||
Assert.AreEqual(Tokens.Semicolon, t.Kind); |
|
||||||
Assert.AreEqual(new Location(1, 3), t.Location); |
|
||||||
|
|
||||||
t = l.NextToken(); |
|
||||||
Assert.AreEqual(Tokens.EOF, t.Kind); |
|
||||||
} |
|
||||||
|
|
||||||
[Test] |
|
||||||
public void TestCharLiteral() |
|
||||||
{ |
|
||||||
CheckToken(@"'a'", 'a'); |
|
||||||
CheckToken(@"'\u0041'", '\u0041'); |
|
||||||
CheckToken(@"'\x41'", '\x41'); |
|
||||||
CheckToken(@"'\x041'", '\x041'); |
|
||||||
CheckToken(@"'\x0041'", '\x0041'); |
|
||||||
CheckToken(@"'\U00000041'", '\U00000041'); |
|
||||||
} |
|
||||||
|
|
||||||
[Test] |
|
||||||
public void TestInvalidStringLiteral2() |
|
||||||
{ |
|
||||||
ILexer l = GenerateLexer(new StringReader(@"""\u{0}""")); |
|
||||||
Token t = l.NextToken(); |
|
||||||
Assert.AreEqual(Tokens.Literal, t.Kind); |
|
||||||
Assert.AreEqual(new Location(1, 1), t.Location); |
|
||||||
Assert.AreEqual(new Location(8, 1), t.EndLocation); |
|
||||||
Assert.AreEqual(1, l.Errors.Count); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
Loading…
Reference in new issue