Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 15147x 15147x 15147x 15147x 1x 1x 4587648x 167179x 167179x 167179x 4587648x 4587648x 15147x 15147x 15147x 4572501x 4572501x 4572501x 4572501x 4572501x 4572501x 1x 1x 895460x 895460x 1x 1x 895460x 895460x 1x 1x 1x 1x 1x 1x 2321x 2321x 2321x 2321x 1x 1x 1x 1x 1x 851x 851x 26x 26x 851x 851x 1x 1x 9175296x 30294x 9175296x 30294x 30294x 9114708x 9114708x 1x 1x 5483454x 5483454x 44992x 44992x 5438462x 5438462x 1x 1x 4587648x 4587648x 45403x 45403x 4542245x 4542245x 1x 1x 884117x 884117x 884117x 1x 1x 15147x 15147x 1x 1x 5483454x 5483454x 1x | const NL = 10; // "\n"
const EOF = -1; // no character (start/end of file)
export class LexerStream {
private readonly raw: string;
private offset = -1;
private row: number;
private col: number;
public constructor(raw: string) {
this.raw = raw;
this.row = 0;
this.col = 0;
}
public advance(): boolean {
if (this.currentChar() === NL) {
this.col = 1;
this.row = this.row + 1;
}
if (this.offset === this.raw.length) {
this.col = this.col - 1;
return false;
}
this.col = this.col + 1;
this.offset = this.offset + 1;
return true;
}
public getCol(): number {
return this.col;
}
public getRow(): number {
return this.row;
}
// the *Char() accessors return character codes (charCodeAt) rather than
// single character strings, to avoid allocating a string per input character
// in the lexer hot loop. EOF (-1) is returned when the offset is out of range.
public prevChar(): number {
const o = this.offset - 1;
if (o < 0) {
return EOF;
}
return this.raw.charCodeAt(o);
}
public prevPrevChar(): number {
const o = this.offset - 2;
if (o < 0) {
return EOF;
}
return this.raw.charCodeAt(o);
}
/** number of consecutive occurrences of the character directly before the current one */
public countPrevious(code: number): number {
let count = 0;
for (let o = this.offset - 1; o >= 0 && this.raw.charCodeAt(o) === code; o--) {
count++;
}
return count;
}
public currentChar(): number {
if (this.offset < 0) {
return NL; // simulate newline at start of file to handle star(*) comments
} else if (this.offset >= this.raw.length) {
return EOF;
}
return this.raw.charCodeAt(this.offset);
}
public nextChar(): number {
const o = this.offset + 1;
if (o >= this.raw.length) {
return EOF;
}
return this.raw.charCodeAt(o);
}
public nextNextChar(): number {
const o = this.offset + 2;
if (o >= this.raw.length) {
return EOF;
}
return this.raw.charCodeAt(o);
}
public charCodeAt(o: number): number {
if (o < 0 || o >= this.raw.length) {
return EOF;
}
return this.raw.charCodeAt(o);
}
public getRaw(): string {
return this.raw;
}
public getOffset() {
return this.offset;
}
}
|