-
Notifications
You must be signed in to change notification settings - Fork 3
/
mapfield.ts
102 lines (96 loc) · 2.77 KB
/
mapfield.ts
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
import { nextTokenIs, Scanner, Token, TokenError } from "./deps.ts";
import { ParseNode } from "./parsenode.ts";
import { Visitor } from "./visitor.ts";
import { Type } from "./type.ts";
import { expectSimpleIdent } from "./util.ts";
enum KeyType {
int32 = "int32",
int64 = "int64",
uint32 = "uint32",
uint64 = "uint64",
sint32 = "sint32",
sint64 = "sint64",
fixed32 = "fixed32",
fixed64 = "fixed64",
sfixed32 = "sfixed32",
sfixed64 = "sfixed64",
bool = "bool",
string = "string",
}
/**
* Represents an Import statement.
*
* Fields are the basic elements of a protocol buffer message. Fields can be
* normal fields, oneof fields, or map fields. A field has a type and field
* number.
*
* A map field has a key type, value type, name, and field number. The key type
* can be any integral or string type.
*
* https://developers.google.com/protocol-buffers/docs/reference/proto3-spec#map_field
*/
export class MapField extends ParseNode {
keyType: KeyType;
constructor(
keyType: KeyType | keyof typeof KeyType,
public valueType: Type,
public name: string,
public id: number,
/**
* The starting [line, column]
*/
public start: [number, number] = [0, 0],
/**
* The ending [line, column]
*/
public end: [number, number] = [0, 0],
) {
super();
this.keyType = KeyType[keyType];
}
toProto() {
return `map<${this.keyType}, ${this.valueType.toProto()}> ${this.name} = ${this.id};`;
}
toJSON() {
return {
type: "MapField",
start: this.start,
end: this.end,
keyType: KeyType[this.keyType],
valueType: this.valueType.toJSON(),
name: this.name,
id: this.id,
};
}
accept(visitor: Visitor) {
visitor.visit?.(this);
visitor.visitMapField?.(this);
this.valueType.accept(visitor);
}
static async parse(scanner: Scanner): Promise<MapField> {
if (scanner.contents !== "map") {
await nextTokenIs(scanner, Token.keyword, "map");
}
const start = scanner.startPos;
await nextTokenIs(scanner, Token.token, "<");
const keyType = KeyType[
await nextTokenIs(scanner, Token.identifier) as keyof typeof KeyType
];
if (!keyType) {
throw new TokenError(
scanner,
Token.identifier,
Token.identifier,
`(one of ${Object.keys(KeyType).join(", ")})`,
);
}
await nextTokenIs(scanner, Token.token, ",");
const valueType = await Type.parse(scanner);
await nextTokenIs(scanner, Token.token, ">");
const name = await expectSimpleIdent(scanner);
await nextTokenIs(scanner, Token.token, "=");
const id = Number(await nextTokenIs(scanner, Token.int));
await nextTokenIs(scanner, Token.token, ";");
return new MapField(keyType, valueType, name, id, start, scanner.endPos);
}
}