Skip to content

Commit 12957fc

Browse files
Switch Lexer to be a proper class, remove 'createLexer' (#2210)
1 parent 48ea2d3 commit 12957fc

File tree

10 files changed

+53
-72
lines changed

10 files changed

+53
-72
lines changed

src/index.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ export {
178178
printLocation,
179179
printSourceLocation,
180180
// Lex
181-
createLexer,
181+
Lexer,
182182
TokenKind,
183183
// Parse
184184
parse,
@@ -207,7 +207,6 @@ export {
207207
} from './language';
208208

209209
export type {
210-
Lexer,
211210
ParseOptions,
212211
SourceLocation,
213212
Location,

src/language/__tests__/lexer-test.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ import { GraphQLError } from '../../error/GraphQLError';
1212

1313
import { Source } from '../source';
1414
import { TokenKind } from '../tokenKind';
15-
import { createLexer, isPunctuatorTokenKind } from '../lexer';
15+
import { Lexer, isPunctuatorTokenKind } from '../lexer';
1616

1717
function lexOne(str) {
18-
const lexer = createLexer(new Source(str));
18+
const lexer = new Lexer(new Source(str));
1919
return lexer.advance();
2020
}
2121

2222
function lexSecond(str) {
23-
const lexer = createLexer(new Source(str));
23+
const lexer = new Lexer(new Source(str));
2424
lexer.advance();
2525
return lexer.advance();
2626
}
@@ -187,7 +187,7 @@ describe('Lexer', () => {
187187
try {
188188
const str = ['', '', ' ?', ''].join('\n');
189189
const source = new Source(str, 'foo.js', { line: 11, column: 12 });
190-
createLexer(source).advance();
190+
new Lexer(source).advance();
191191
} catch (error) {
192192
caughtError = error;
193193
}
@@ -206,7 +206,7 @@ describe('Lexer', () => {
206206
let caughtError;
207207
try {
208208
const source = new Source('?', 'foo.js', { line: 1, column: 5 });
209-
createLexer(source).advance();
209+
new Lexer(source).advance();
210210
} catch (error) {
211211
caughtError = error;
212212
}
@@ -847,7 +847,7 @@ describe('Lexer', () => {
847847

848848
it('lex reports useful information for dashes in names', () => {
849849
const source = new Source('a-b');
850-
const lexer = createLexer(source);
850+
const lexer = new Lexer(source);
851851
const firstToken = lexer.advance();
852852
expect(firstToken).to.contain({
853853
kind: TokenKind.NAME,
@@ -872,7 +872,7 @@ describe('Lexer', () => {
872872
}
873873
`);
874874

875-
const lexer = createLexer(source);
875+
const lexer = new Lexer(source);
876876
const startToken = lexer.token;
877877
let endToken;
878878
do {

src/language/index.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ export type { KindEnum } from './kinds';
1313
export { TokenKind } from './tokenKind';
1414
export type { TokenKindEnum } from './tokenKind';
1515

16-
export { createLexer } from './lexer';
17-
export type { Lexer } from './lexer';
16+
export { Lexer } from './lexer';
1817

1918
export { parse, parseValue, parseType } from './parser';
2019
export type { ParseOptions } from './parser';

src/language/lexer.js

Lines changed: 33 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,83 +10,70 @@ import { dedentBlockStringValue } from './blockString';
1010
import { type TokenKindEnum, TokenKind } from './tokenKind';
1111

1212
/**
13-
* Given a Source object, this returns a Lexer for that source.
13+
* Given a Source object, creates a Lexer for that source.
1414
* A Lexer is a stateful stream generator in that every time
1515
* it is advanced, it returns the next token in the Source. Assuming the
1616
* source lexes, the final Token emitted by the lexer will be of kind
1717
* EOF, after which the lexer will repeatedly return the same EOF token
1818
* whenever called.
1919
*/
20-
export function createLexer(source: Source): Lexer {
21-
const startOfFileToken = new Tok(TokenKind.SOF, 0, 0, 0, 0, null);
22-
const lexer: Lexer = {
23-
source,
24-
lastToken: startOfFileToken,
25-
token: startOfFileToken,
26-
line: 1,
27-
lineStart: 0,
28-
advance: advanceLexer,
29-
lookahead,
30-
};
31-
return lexer;
32-
}
33-
34-
function advanceLexer() {
35-
this.lastToken = this.token;
36-
const token = (this.token = this.lookahead());
37-
return token;
38-
}
39-
40-
function lookahead() {
41-
let token = this.token;
42-
if (token.kind !== TokenKind.EOF) {
43-
do {
44-
// Note: next is only mutable during parsing, so we cast to allow this.
45-
token = token.next || ((token: any).next = readToken(this, token));
46-
} while (token.kind === TokenKind.COMMENT);
47-
}
48-
return token;
49-
}
50-
51-
/**
52-
* The return type of createLexer.
53-
*/
54-
export type Lexer = {
55-
source: Source,
20+
export class Lexer {
21+
source: Source;
5622

5723
/**
5824
* The previously focused non-ignored token.
5925
*/
60-
lastToken: Token,
26+
lastToken: Token;
6127

6228
/**
6329
* The currently focused non-ignored token.
6430
*/
65-
token: Token,
31+
token: Token;
6632

6733
/**
6834
* The (1-indexed) line containing the current token.
6935
*/
70-
line: number,
36+
line: number;
7137

7238
/**
7339
* The character offset at which the current line begins.
7440
*/
75-
lineStart: number,
41+
lineStart: number;
42+
43+
constructor(source: Source) {
44+
const startOfFileToken = new Tok(TokenKind.SOF, 0, 0, 0, 0, null);
45+
46+
this.source = source;
47+
this.lastToken = startOfFileToken;
48+
this.token = startOfFileToken;
49+
this.line = 1;
50+
this.lineStart = 0;
51+
}
7652

7753
/**
7854
* Advances the token stream to the next non-ignored token.
7955
*/
80-
advance(): Token,
56+
advance(): Token {
57+
this.lastToken = this.token;
58+
const token = (this.token = this.lookahead());
59+
return token;
60+
}
8161

8262
/**
8363
* Looks ahead and returns the next non-ignored token, but does not change
8464
* the Lexer's state.
8565
*/
86-
lookahead(): Token,
87-
88-
...
89-
};
66+
lookahead(): Token {
67+
let token = this.token;
68+
if (token.kind !== TokenKind.EOF) {
69+
do {
70+
// Note: next is only mutable during parsing, so we cast to allow this.
71+
token = token.next || ((token: any).next = readToken(this, token));
72+
} while (token.kind === TokenKind.COMMENT);
73+
}
74+
return token;
75+
}
76+
}
9077

9178
/**
9279
* @internal

src/language/parser.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { Kind } from './kinds';
1111
import { Source } from './source';
1212
import { DirectiveLocation } from './directiveLocation';
1313
import { type TokenKindEnum, TokenKind } from './tokenKind';
14-
import { type Lexer, createLexer, isPunctuatorTokenKind } from './lexer';
14+
import { Lexer, isPunctuatorTokenKind } from './lexer';
1515
import {
1616
type Location,
1717
type Token,
@@ -177,7 +177,7 @@ class Parser {
177177
`Must provide Source. Received: ${inspect(sourceObj)}`,
178178
);
179179

180-
this._lexer = createLexer(sourceObj);
180+
this._lexer = new Lexer(sourceObj);
181181
this._options = options || {};
182182
}
183183

src/utilities/__tests__/stripIgnoredCharacters-test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import invariant from '../../jsutils/invariant';
88

99
import { parse } from '../../language/parser';
1010
import { Source } from '../../language/source';
11-
import { createLexer } from '../../language/lexer';
11+
import { Lexer } from '../../language/lexer';
1212

1313
import { stripIgnoredCharacters } from '../stripIgnoredCharacters';
1414

@@ -59,7 +59,7 @@ const nonPunctuatorTokens = [
5959
];
6060

6161
function lexValue(str) {
62-
const lexer = createLexer(new Source(str));
62+
const lexer = new Lexer(new Source(str));
6363
const value = lexer.advance().value;
6464

6565
invariant(lexer.advance().kind === '<EOF>', 'Expected EOF');

src/utilities/stripIgnoredCharacters.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import inspect from '../jsutils/inspect';
44

55
import { Source } from '../language/source';
66
import { TokenKind } from '../language/tokenKind';
7-
import { createLexer, isPunctuatorTokenKind } from '../language/lexer';
7+
import { Lexer, isPunctuatorTokenKind } from '../language/lexer';
88
import {
99
dedentBlockStringValue,
1010
getBlockStringIndentation,
@@ -71,7 +71,7 @@ export function stripIgnoredCharacters(source: string | Source): string {
7171
}
7272

7373
const body = sourceObj.body;
74-
const lexer = createLexer(sourceObj);
74+
const lexer = new Lexer(sourceObj);
7575
let strippedBody = '';
7676

7777
let wasLastAddedTokenNonPunctuator = false;

tstypes/index.d.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ export {
177177
printLocation,
178178
printSourceLocation,
179179
// Lex
180-
createLexer,
180+
Lexer,
181181
TokenKind,
182182
// Parse
183183
parse,
@@ -206,7 +206,6 @@ export {
206206
} from './language';
207207

208208
export {
209-
Lexer,
210209
ParseOptions,
211210
SourceLocation,
212211
Location,

tstypes/language/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export { printLocation, printSourceLocation } from './printLocation';
55

66
export { Kind, KindEnum } from './kinds';
77
export { TokenKind, TokenKindEnum } from './tokenKind';
8-
export { createLexer, Lexer } from './lexer';
8+
export { Lexer } from './lexer';
99
export { parse, parseValue, parseType, ParseOptions } from './parser';
1010
export { print } from './printer';
1111
export {

tstypes/language/lexer.d.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,7 @@ import { Source } from './source';
1010
* EOF, after which the lexer will repeatedly return the same EOF token
1111
* whenever called.
1212
*/
13-
export function createLexer(source: Source): Lexer;
14-
15-
/**
16-
* The return type of createLexer.
17-
*/
18-
export interface Lexer {
13+
export class Lexer {
1914
source: Source;
2015

2116
/**
@@ -38,6 +33,8 @@ export interface Lexer {
3833
*/
3934
lineStart: number;
4035

36+
constructor(source: Source);
37+
4138
/**
4239
* Advances the token stream to the next non-ignored token.
4340
*/

0 commit comments

Comments
 (0)