Skip to content

Commit c8dc631

Browse files
committed
columnをUTF-16コード単位に変更
1 parent d89995b commit c8dc631

2 files changed

Lines changed: 34 additions & 7 deletions

File tree

src/parser/streams/char-stream.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ export class CharStream {
1212
private address: number;
1313
/** Unicode character */
1414
private _char?: string;
15-
/** zero-based number, based on Unicode code points */
15+
/** zero-based number */
1616
private line: number;
17-
/** zero-based number, based on Unicode code points */
17+
/** zero-based number, based on UTF-16 code unit */
1818
private column: number;
1919

2020
constructor(source: string, opts?: { line?: number, column?: number }) {
@@ -64,7 +64,7 @@ export class CharStream {
6464
this.line++;
6565
this.column = 0;
6666
} else {
67-
this.column++;
67+
this.column += this._char!.length;
6868
}
6969
this.incAddr();
7070
this.moveNext();
@@ -82,9 +82,9 @@ export class CharStream {
8282
const lastLineBreak = page.lastIndexOf('\n', this.address - 1);
8383
const lineStart = lastLineBreak >= 0 ? lastLineBreak + 1 : 0;
8484
const line = page.slice(lineStart, this.address);
85-
this.column = [...line].length - 1;
85+
this.column = line.length;
8686
} else {
87-
this.column--;
87+
this.column -= this._char!.length;
8888
}
8989
}
9090

test/parser.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ describe('CharStream', () => {
4545
assert.strictEqual('b', stream.char);
4646
stream.prev();
4747
assert.strictEqual('\n', stream.char);
48-
assert.deepStrictEqual(stream.getPos(), { line: 1, column: 1 });
48+
assert.deepStrictEqual(stream.getPos(), { line: 1, column: 2 });
4949
});
5050

5151
test.concurrent('line breaks', async () => {
@@ -56,7 +56,7 @@ describe('CharStream', () => {
5656
assert.strictEqual('c', stream.char);
5757
stream.prev();
5858
assert.strictEqual('\n', stream.char);
59-
assert.deepStrictEqual(stream.getPos(), { line: 2, column: 0 });
59+
assert.deepStrictEqual(stream.getPos(), { line: 2, column: 1 });
6060
});
6161

6262
test.concurrent('CRは読み飛ばされる', async () => {
@@ -77,6 +77,26 @@ describe('CharStream', () => {
7777
stream.prev();
7878
assert.strictEqual('\ud83e\udd2f', stream.char);
7979
});
80+
81+
test.concurrent('column is based on UTF-16 code unit', async () => {
82+
const source = '\ud83e\udd2f!';
83+
const stream = new CharStream(source);
84+
stream.next();
85+
stream.next();
86+
stream.prev();
87+
assert.strictEqual(stream.char, '!');
88+
assert.deepStrictEqual(stream.getPos(), { line: 1, column: 3 });
89+
});
90+
91+
test.concurrent('column is based on UTF-16 code unit, line break', async () => {
92+
const source = '\ud83e\udd2f\n';
93+
const stream = new CharStream(source);
94+
stream.next();
95+
stream.next();
96+
stream.prev();
97+
assert.strictEqual(stream.char, '\n');
98+
assert.deepStrictEqual(stream.getPos(), { line: 1, column: 3 });
99+
});
80100
});
81101

82102
test.concurrent('eof', async () => {
@@ -122,6 +142,13 @@ describe('CharStream', () => {
122142
stream.next();
123143
assert.strictEqual(true, stream.eof);
124144
});
145+
146+
test.concurrent('column is based on UTF-16 code unit', async () => {
147+
const source = '\ud83e\udd2f';
148+
const stream = new CharStream(source);
149+
stream.next();
150+
assert.deepStrictEqual(stream.getPos(), { line: 1, column: 3 });
151+
});
125152
});
126153

127154
describe('Scanner', () => {

0 commit comments

Comments
 (0)