Skip to content

Commit 49fdaa4

Browse files
committed
Chg: NewLine handling, ReadLine, SkipWhiteSpaes
1 parent 053b302 commit 49fdaa4

File tree

2 files changed

+136
-75
lines changed

2 files changed

+136
-75
lines changed

NeoLua.Test/Parser.cs

+35-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ private void TokenTest(ILuaLexer lex, params KeyValuePair<LuaToken, string>[] ex
4040
lex.Next();
4141
}
4242
if (lex.Current.Typ != LuaToken.Eof)
43-
Assert.Fail();
43+
Assert.Fail("Eof expected.");
4444
}
4545
} // func TokenTest
4646

@@ -247,6 +247,8 @@ public void TestConstants()
247247

248248
#endregion
249249

250+
#region -- Test Parser --------------------------------------------------------
251+
250252
[TestMethod]
251253
public void TestParser01()
252254
{
@@ -288,6 +290,8 @@ public void TestParserIssue92()
288290
);
289291
}
290292

293+
#endregion
294+
291295
#region -- Test Position ------------------------------------------------------
292296

293297
[TestMethod]
@@ -361,6 +365,36 @@ public void TestPosition02()
361365
}
362366
}
363367

368+
[TestMethod]
369+
public void TestPosition03()
370+
{
371+
var t = "\r\nNull(";
372+
using (var lex = CreateLuaLexer(t))
373+
{
374+
lex.Next();
375+
376+
Assert.AreEqual(2, lex.Current.Start.Line);
377+
Assert.AreEqual(1, lex.Current.Start.Col);
378+
Assert.AreEqual(2, lex.Current.Start.Index);
379+
380+
Assert.AreEqual(2, lex.Current.End.Line);
381+
Assert.AreEqual(5, lex.Current.End.Col);
382+
Assert.AreEqual(6, lex.Current.End.Index);
383+
Assert.AreEqual("Null", t.Substring((int)lex.Current.Start.Index, (int)lex.Current.End.Index - (int)lex.Current.Start.Index));
384+
385+
lex.Next();
386+
387+
Assert.AreEqual(2, lex.Current.Start.Line);
388+
Assert.AreEqual(5, lex.Current.Start.Col);
389+
Assert.AreEqual(6, lex.Current.Start.Index);
390+
391+
Assert.AreEqual(2, lex.Current.End.Line);
392+
Assert.AreEqual(6, lex.Current.End.Col);
393+
Assert.AreEqual(7, lex.Current.End.Index);
394+
Assert.AreEqual("(", t.Substring((int)lex.Current.Start.Index, (int)lex.Current.End.Index - (int)lex.Current.Start.Index));
395+
}
396+
}
397+
364398
#endregion
365399

366400
#region -- Html Lexer ---------------------------------------------------------
@@ -446,6 +480,5 @@ public void ParseVarTest()
446480

447481

448482
#endregion
449-
450483
} // class Lexer
451484
}

NeoLua/LuaLexer.cs

+101-73
Original file line numberDiff line numberDiff line change
@@ -368,17 +368,15 @@ public sealed class LuaCharLexer : IDisposable
368368
private readonly bool leaveOpen; // do not dispose the text reader at the end
369369

370370
private readonly char[] lookAheadBuffer;
371+
private readonly byte[] moveIndex;
371372
private int lookAheadOffset;
372373
private int lookAheadEof;
373374

374375
private int currentLine; // Line in the source file
375376
private int currentColumn; // Column in the source file
376377
private readonly int firstColumnIndex; // Index of the first char in line
377378
private long currentIndex; // Index in the source file
378-
379-
private bool incrementLine = false;
380-
private bool moveIndex = false;
381-
379+
382380
private Position startPosition; // Start of the current token
383381
private StringBuilder currentStringBuilder = new StringBuilder(); // Char buffer, for collected chars
384382

@@ -404,31 +402,40 @@ public LuaCharLexer(string fileName, TextReader tr, int lookAheadLength, bool le
404402
this.leaveOpen = leaveOpen;
405403

406404
this.lookAheadBuffer = new char[lookAheadLength];
405+
this.moveIndex = new byte[lookAheadLength];
407406
this.lookAheadOffset = lookAheadLength - 1;
408407
this.lookAheadEof = -1;
409408

410409
this.currentLine = currentLine;
411410
this.currentColumn = currentColumn - 1;
412411
this.firstColumnIndex = firstColumnIndex;
413-
this.currentIndex = -1;
412+
this.currentIndex = 0;
414413

415414
// inital fill buffer
416415
for (var i = 0; i < lookAheadLength - 1; i++)
417416
{
418417
if (lookAheadEof >= 0)
418+
{
419419
lookAheadBuffer[i] = '\0';
420+
moveIndex[i] = 0;
421+
}
420422
else
421423
{
422-
var c = ReadCore();
423-
if (c == -1)
424+
var c = ReadCore(out var len);
425+
if (len == 0)
424426
{
425427
lookAheadEof = i;
426428
lookAheadBuffer[i] = '\0';
429+
moveIndex[i] = 0;
427430
}
428431
else
432+
{
429433
lookAheadBuffer[i] = (char)c;
434+
moveIndex[i] = len;
435+
}
430436
}
431437
}
438+
moveIndex[lookAheadOffset] = 0;
432439

433440
// read first char from the buffer
434441
Next();
@@ -460,10 +467,13 @@ public void AppendValue(char value)
460467
public void AppendValue(string value)
461468
=> currentStringBuilder.Append(Cur);
462469

463-
private int ReadCore()
470+
private char ReadCore(out byte len)
464471
{
465472
if (tr == null) // Source file is readed
466-
return -1;
473+
{
474+
len = 0;
475+
return '\0';
476+
}
467477
else
468478
{
469479
var i = tr.Read();
@@ -472,105 +482,93 @@ private int ReadCore()
472482
if (!leaveOpen)
473483
tr.Dispose();
474484
tr = null;
485+
486+
len = 0;
487+
return '\0';
488+
}
489+
else if (i == 10)
490+
{
491+
if (tr.Peek() == 13)
492+
{
493+
tr.Read();
494+
len = 2;
495+
return (char)i;
496+
}
497+
else
498+
{
499+
len = 1;
500+
return (char)i;
501+
}
502+
}
503+
else if (i == 13)
504+
{
505+
if (tr.Peek() == 10)
506+
{
507+
tr.Read();
508+
len = 2;
509+
return '\n';
510+
}
511+
else
512+
{
513+
len = 1;
514+
return '\n';
515+
}
475516
}
476-
return i;
517+
518+
len = 1;
519+
return (char)i;
477520
}
478521
} // func ReadCore
479522

480523
private bool ReadCharToBuffer()
481524
{
482525
if (lookAheadEof < 0)
483526
{
484-
var c = ReadCore();
485-
if (c == -1)
527+
var c = ReadCore(out var len);
528+
if (len == 0)
486529
{
487530
lookAheadEof = lookAheadOffset;
488531
lookAheadBuffer[lookAheadOffset] = '\0';
532+
moveIndex[lookAheadOffset] = 0;
489533
}
490534
else
535+
{
491536
lookAheadBuffer[lookAheadOffset] = (char)c;
537+
moveIndex[lookAheadOffset] = len;
538+
}
492539

493540
return true;
494541
}
495542
else if (lookAheadEof != lookAheadOffset)
496543
{
497544
lookAheadBuffer[lookAheadOffset] = '\0';
545+
moveIndex[lookAheadOffset] = 0;
498546
return true;
499547
}
500548
else
501549
return false;
502550
} // func ReadCharToBuffer
503-
504-
private bool MoveNextCore()
505-
{
506-
if (ReadCharToBuffer())
507-
{
508-
if (lookAheadBuffer.Length > 1)
509-
{
510-
lookAheadOffset++;
511-
if (lookAheadOffset >= lookAheadBuffer.Length)
512-
lookAheadOffset = 0;
513-
}
514-
515-
return true;
516-
}
517-
else
518-
return false;
519-
} // func MoveNextCore
520551

521552
/// <summary>Move the char stream and discard the buffer.</summary>
522553
public void Next()
523554
{
524-
if (moveIndex)
555+
currentIndex += moveIndex[lookAheadOffset];
556+
if (lookAheadBuffer[lookAheadOffset] == '\n')
525557
{
526-
moveIndex = false;
527-
currentIndex++;
558+
currentColumn = firstColumnIndex;
559+
currentLine++;
528560
}
561+
else
562+
currentColumn++;
529563

530-
if (MoveNextCore())
564+
if (ReadCharToBuffer())
531565
{
532-
currentIndex++;
533-
534-
var c = lookAheadBuffer[lookAheadOffset];
535-
536-
// Normalize new line
537-
if (c == '\n')
538-
{
539-
if (lookAheadBuffer.Length > 1 && IsLookAHead('\r', 1))
540-
{
541-
moveIndex = MoveNextCore();
542-
lookAheadBuffer[lookAheadOffset] = '\n'; // replace with unique new line
543-
}
544-
else if (tr != null && tr.Peek() == 13)
545-
{
546-
moveIndex = MoveNextCore();
547-
lookAheadBuffer[lookAheadOffset] = '\n'; // replace with unique new line
548-
}
549-
550-
currentColumn++;
551-
incrementLine = true;
552-
}
553-
else if (c == '\r')
554-
{
555-
if (lookAheadBuffer.Length > 1 && IsLookAHead('\n', 1))
556-
moveIndex = MoveNextCore();
557-
else if (tr != null && tr.Peek() == 10)
558-
moveIndex = MoveNextCore();
559-
else
560-
lookAheadBuffer[lookAheadOffset] = '\n'; // replace with unique new line
561-
562-
currentColumn++;
563-
incrementLine = true;
564-
}
565-
else if (incrementLine)
566+
if (lookAheadBuffer.Length > 1)
566567
{
567-
currentColumn = firstColumnIndex;
568-
currentLine++;
569-
570-
incrementLine = false;
568+
lookAheadOffset++;
569+
if (lookAheadOffset >= lookAheadBuffer.Length)
570+
lookAheadOffset = 0;
571571
}
572-
else
573-
currentColumn++;
574572
}
575573
} // proc Next
576574

@@ -589,6 +587,25 @@ public void Eat()
589587
Next();
590588
} // proc Eat
591589

590+
/// <summary>Read a whole line</summary>
591+
/// <returns></returns>
592+
public string ReadLine()
593+
{
594+
while (!IsEof && Cur != '\n')
595+
Eat();
596+
597+
var curValue = CurValue;
598+
ResetCurValue();
599+
return curValue;
600+
} // func ReadLine
601+
602+
/// <summary>Skip white spaces</summary>
603+
public void SkipWhiteSpaces()
604+
{
605+
while (!IsEof && Cur != '\n' && Char.IsWhiteSpace(Cur))
606+
Next();
607+
} // proc SkipWhiteSpaces
608+
592609
/// <summary>Create a new token with the current buffer.</summary>
593610
/// <param name="kind">Token type</param>
594611
/// <returns>Token</returns>
@@ -661,6 +678,17 @@ public bool IsLookAHead(string value, int offset = 0)
661678
return true;
662679
} // func LookAHead
663680

681+
/// <summary>Get look a head.</summary>
682+
/// <param name="offset"></param>
683+
/// <returns></returns>
684+
public char GetLookAHead(int offset = 0)
685+
{
686+
if (offset > lookAheadBuffer.Length)
687+
throw new ArgumentOutOfRangeException(nameof(offset), lookAheadBuffer.Length, "Look a head buffer is to small.");
688+
689+
return lookAheadBuffer[offset];
690+
}// func GetLookAHead
691+
664692
/// <summary></summary>
665693
public void ResetCurValue()
666694
{

0 commit comments

Comments
 (0)