1 | // @flow
|
2 | import SourceLocation from "./SourceLocation";
|
3 |
|
4 | /**
|
5 | * Interface required to break circular dependency between Token, Lexer, and
|
6 | * ParseError.
|
7 | */
|
8 | export interface LexerInterface {input: string, tokenRegex: RegExp}
|
9 |
|
10 | /**
|
11 | * The resulting token returned from `lex`.
|
12 | *
|
13 | * It consists of the token text plus some position information.
|
14 | * The position information is essentially a range in an input string,
|
15 | * but instead of referencing the bare input string, we refer to the lexer.
|
16 | * That way it is possible to attach extra metadata to the input string,
|
17 | * like for example a file name or similar.
|
18 | *
|
19 | * The position information is optional, so it is OK to construct synthetic
|
20 | * tokens if appropriate. Not providing available position information may
|
21 | * lead to degraded error reporting, though.
|
22 | */
|
23 | export class Token {
|
24 | text: string;
|
25 | loc: ?SourceLocation;
|
26 |
|
27 | constructor(
|
28 | text: string, // the text of this token
|
29 | loc: ?SourceLocation,
|
30 | ) {
|
31 | this.text = text;
|
32 | this.loc = loc;
|
33 | }
|
34 |
|
35 | /**
|
36 | * Given a pair of tokens (this and endToken), compute a `Token` encompassing
|
37 | * the whole input range enclosed by these two.
|
38 | */
|
39 | range(
|
40 | endToken: Token, // last token of the range, inclusive
|
41 | text: string, // the text of the newly constructed token
|
42 | ) {
|
43 | return new Token(text, SourceLocation.range(this, endToken));
|
44 | }
|
45 | }
|