deukpack 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/NOTICE +6 -0
- package/README.ko.md +138 -0
- package/README.md +182 -0
- package/RELEASING.md +71 -0
- package/bin/deukpack.js +9 -0
- package/dist/ast/DeukPackASTBuilder.d.ts +153 -0
- package/dist/ast/DeukPackASTBuilder.d.ts.map +1 -0
- package/dist/ast/DeukPackASTBuilder.js +931 -0
- package/dist/ast/DeukPackASTBuilder.js.map +1 -0
- package/dist/codegen/CSharpGenerator.d.ts +136 -0
- package/dist/codegen/CSharpGenerator.d.ts.map +1 -0
- package/dist/codegen/CSharpGenerator.js +2303 -0
- package/dist/codegen/CSharpGenerator.js.map +1 -0
- package/dist/codegen/CodeGenerator.d.ts +11 -0
- package/dist/codegen/CodeGenerator.d.ts.map +1 -0
- package/dist/codegen/CodeGenerator.js +11 -0
- package/dist/codegen/CodeGenerator.js.map +1 -0
- package/dist/codegen/CppGenerator.d.ts +23 -0
- package/dist/codegen/CppGenerator.d.ts.map +1 -0
- package/dist/codegen/CppGenerator.js +215 -0
- package/dist/codegen/CppGenerator.js.map +1 -0
- package/dist/codegen/HighPerformanceCSharpGenerator.d.ts +29 -0
- package/dist/codegen/HighPerformanceCSharpGenerator.d.ts.map +1 -0
- package/dist/codegen/HighPerformanceCSharpGenerator.js +486 -0
- package/dist/codegen/HighPerformanceCSharpGenerator.js.map +1 -0
- package/dist/core/DeukPackEngine.d.ts +69 -0
- package/dist/core/DeukPackEngine.d.ts.map +1 -0
- package/dist/core/DeukPackEngine.js +379 -0
- package/dist/core/DeukPackEngine.js.map +1 -0
- package/dist/core/DeukPackGenerator.d.ts +9 -0
- package/dist/core/DeukPackGenerator.d.ts.map +1 -0
- package/dist/core/DeukPackGenerator.js +15 -0
- package/dist/core/DeukPackGenerator.js.map +1 -0
- package/dist/core/DeukParser.d.ts +12 -0
- package/dist/core/DeukParser.d.ts.map +1 -0
- package/dist/core/DeukParser.js +27 -0
- package/dist/core/DeukParser.js.map +1 -0
- package/dist/core/IdlParser.d.ts +27 -0
- package/dist/core/IdlParser.d.ts.map +1 -0
- package/dist/core/IdlParser.js +157 -0
- package/dist/core/IdlParser.js.map +1 -0
- package/dist/core/ProtoParser.d.ts +12 -0
- package/dist/core/ProtoParser.d.ts.map +1 -0
- package/dist/core/ProtoParser.js +27 -0
- package/dist/core/ProtoParser.js.map +1 -0
- package/dist/csharp/DpExcelProtocol.cs +3005 -0
- package/dist/csharp/DpProtocolLibrary.cs +13 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/lexer/DeukLexer.d.ts +31 -0
- package/dist/lexer/DeukLexer.d.ts.map +1 -0
- package/dist/lexer/DeukLexer.js +292 -0
- package/dist/lexer/DeukLexer.js.map +1 -0
- package/dist/lexer/IdlLexer.d.ts +33 -0
- package/dist/lexer/IdlLexer.d.ts.map +1 -0
- package/dist/lexer/IdlLexer.js +286 -0
- package/dist/lexer/IdlLexer.js.map +1 -0
- package/dist/native/NativeDeukPackEngine.d.ts +30 -0
- package/dist/native/NativeDeukPackEngine.d.ts.map +1 -0
- package/dist/native/NativeDeukPackEngine.js +99 -0
- package/dist/native/NativeDeukPackEngine.js.map +1 -0
- package/dist/proto/ProtoASTBuilder.d.ts +29 -0
- package/dist/proto/ProtoASTBuilder.d.ts.map +1 -0
- package/dist/proto/ProtoASTBuilder.js +239 -0
- package/dist/proto/ProtoASTBuilder.js.map +1 -0
- package/dist/proto/ProtoLexer.d.ts +29 -0
- package/dist/proto/ProtoLexer.d.ts.map +1 -0
- package/dist/proto/ProtoLexer.js +264 -0
- package/dist/proto/ProtoLexer.js.map +1 -0
- package/dist/proto/ProtoTypes.d.ts +40 -0
- package/dist/proto/ProtoTypes.d.ts.map +1 -0
- package/dist/proto/ProtoTypes.js +37 -0
- package/dist/proto/ProtoTypes.js.map +1 -0
- package/dist/protocols/BinaryProtocol.d.ts +7 -0
- package/dist/protocols/BinaryProtocol.d.ts.map +1 -0
- package/dist/protocols/BinaryProtocol.js +11 -0
- package/dist/protocols/BinaryProtocol.js.map +1 -0
- package/dist/protocols/BinaryWriter.d.ts +22 -0
- package/dist/protocols/BinaryWriter.d.ts.map +1 -0
- package/dist/protocols/BinaryWriter.js +104 -0
- package/dist/protocols/BinaryWriter.js.map +1 -0
- package/dist/protocols/CompactProtocol.d.ts +7 -0
- package/dist/protocols/CompactProtocol.d.ts.map +1 -0
- package/dist/protocols/CompactProtocol.js +11 -0
- package/dist/protocols/CompactProtocol.js.map +1 -0
- package/dist/protocols/ExcelProtocol.d.ts +98 -0
- package/dist/protocols/ExcelProtocol.d.ts.map +1 -0
- package/dist/protocols/ExcelProtocol.js +639 -0
- package/dist/protocols/ExcelProtocol.js.map +1 -0
- package/dist/protocols/JsonProtocol.d.ts +68 -0
- package/dist/protocols/JsonProtocol.d.ts.map +1 -0
- package/dist/protocols/JsonProtocol.js +422 -0
- package/dist/protocols/JsonProtocol.js.map +1 -0
- package/dist/protocols/WireProtocol.d.ts +348 -0
- package/dist/protocols/WireProtocol.d.ts.map +1 -0
- package/dist/protocols/WireProtocol.js +912 -0
- package/dist/protocols/WireProtocol.js.map +1 -0
- package/dist/serialization/WireDeserializer.d.ts +8 -0
- package/dist/serialization/WireDeserializer.d.ts.map +1 -0
- package/dist/serialization/WireDeserializer.js +13 -0
- package/dist/serialization/WireDeserializer.js.map +1 -0
- package/dist/serialization/WireSerializer.d.ts +20 -0
- package/dist/serialization/WireSerializer.d.ts.map +1 -0
- package/dist/serialization/WireSerializer.js +100 -0
- package/dist/serialization/WireSerializer.js.map +1 -0
- package/dist/types/DeukPackTypes.d.ts +291 -0
- package/dist/types/DeukPackTypes.d.ts.map +1 -0
- package/dist/types/DeukPackTypes.js +76 -0
- package/dist/types/DeukPackTypes.js.map +1 -0
- package/dist/utils/EndianUtils.d.ts +11 -0
- package/dist/utils/EndianUtils.d.ts.map +1 -0
- package/dist/utils/EndianUtils.js +32 -0
- package/dist/utils/EndianUtils.js.map +1 -0
- package/dist/utils/PerformanceMonitor.d.ts +26 -0
- package/dist/utils/PerformanceMonitor.d.ts.map +1 -0
- package/dist/utils/PerformanceMonitor.js +57 -0
- package/dist/utils/PerformanceMonitor.js.map +1 -0
- package/package.json +77 -0
- package/scripts/build_deukpack.js +669 -0
|
@@ -0,0 +1,931 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* DeukPack AST Builder
|
|
4
|
+
* Builds Abstract Syntax Tree from tokens
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.DeukPackASTBuilder = void 0;
|
|
8
|
+
const DeukPackTypes_1 = require("../types/DeukPackTypes");
|
|
9
|
+
class DeukPackASTBuilder {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.tokens = [];
|
|
12
|
+
this.position = 0;
|
|
13
|
+
this.currentFile = '';
|
|
14
|
+
/** Collected doc comments for the next declaration (struct/enum/field etc.) */
|
|
15
|
+
this.leadingCommentBuffer = '';
|
|
16
|
+
this.deukMode = false;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Collect consecutive LINE_COMMENT/BLOCK_COMMENT tokens and return combined text (trimmed). Consumes tokens.
|
|
20
|
+
*/
|
|
21
|
+
collectLeadingComments() {
|
|
22
|
+
const parts = [];
|
|
23
|
+
while (this.check(DeukPackTypes_1.TokenType.LINE_COMMENT) || this.check(DeukPackTypes_1.TokenType.BLOCK_COMMENT)) {
|
|
24
|
+
const t = this.advance();
|
|
25
|
+
const text = (t.value || '').trim();
|
|
26
|
+
if (text)
|
|
27
|
+
parts.push(text);
|
|
28
|
+
}
|
|
29
|
+
return parts.join('\n').trim();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Split leading comment into docComment and C# attribute lines.
|
|
33
|
+
* Lines that look like [AttrName] or [AttrName("arg")] are treated as csharpAttributes (DeukPack extension).
|
|
34
|
+
*/
|
|
35
|
+
parseDocCommentAndCSharpAttributes(comment) {
|
|
36
|
+
if (!comment || !comment.trim())
|
|
37
|
+
return {};
|
|
38
|
+
const attrLineRe = /^\[.+\]$/;
|
|
39
|
+
const docLines = [];
|
|
40
|
+
const attrLines = [];
|
|
41
|
+
for (const line of comment.split(/\r?\n/)) {
|
|
42
|
+
const trimmed = line.trim();
|
|
43
|
+
if (!trimmed)
|
|
44
|
+
continue;
|
|
45
|
+
if (attrLineRe.test(trimmed)) {
|
|
46
|
+
attrLines.push(trimmed);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
docLines.push(line);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const out = {};
|
|
53
|
+
if (docLines.length)
|
|
54
|
+
out.docComment = docLines.join('\n').trim();
|
|
55
|
+
if (attrLines.length)
|
|
56
|
+
out.csharpAttributes = attrLines;
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Parse IDL annotations: ( key = "value", key2 = "value2" ) or ( key ). Consumes tokens.
|
|
61
|
+
*/
|
|
62
|
+
tryParseAnnotations() {
|
|
63
|
+
if (!this.check(DeukPackTypes_1.TokenType.LEFT_PAREN))
|
|
64
|
+
return undefined;
|
|
65
|
+
this.advance();
|
|
66
|
+
const ann = {};
|
|
67
|
+
while (!this.check(DeukPackTypes_1.TokenType.RIGHT_PAREN) && !this.isAtEnd()) {
|
|
68
|
+
const key = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
69
|
+
let val = 'true';
|
|
70
|
+
if (this.check(DeukPackTypes_1.TokenType.EQUALS)) {
|
|
71
|
+
this.advance();
|
|
72
|
+
if (this.check(DeukPackTypes_1.TokenType.STRING_LITERAL)) {
|
|
73
|
+
val = this.advance().value;
|
|
74
|
+
}
|
|
75
|
+
else if (this.check(DeukPackTypes_1.TokenType.IDENTIFIER)) {
|
|
76
|
+
val = this.advance().value;
|
|
77
|
+
}
|
|
78
|
+
else if (this.check(DeukPackTypes_1.TokenType.NUMBER)) {
|
|
79
|
+
val = this.advance().value;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
ann[key] = val;
|
|
83
|
+
if (this.check(DeukPackTypes_1.TokenType.COMMA))
|
|
84
|
+
this.advance();
|
|
85
|
+
}
|
|
86
|
+
if (this.check(DeukPackTypes_1.TokenType.RIGHT_PAREN))
|
|
87
|
+
this.advance();
|
|
88
|
+
return Object.keys(ann).length ? ann : undefined;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Build AST from tokens
|
|
92
|
+
*/
|
|
93
|
+
build(tokens, fileName, options) {
|
|
94
|
+
this.tokens = tokens;
|
|
95
|
+
this.position = 0;
|
|
96
|
+
this.currentFile = fileName;
|
|
97
|
+
this.leadingCommentBuffer = '';
|
|
98
|
+
this.deukMode = options?.deuk ?? false;
|
|
99
|
+
const ast = {
|
|
100
|
+
namespaces: [],
|
|
101
|
+
structs: [],
|
|
102
|
+
enums: [],
|
|
103
|
+
services: [],
|
|
104
|
+
typedefs: [],
|
|
105
|
+
constants: [],
|
|
106
|
+
includes: [],
|
|
107
|
+
annotations: {}
|
|
108
|
+
};
|
|
109
|
+
while (!this.isAtEnd()) {
|
|
110
|
+
const token = this.peek();
|
|
111
|
+
switch (token.type) {
|
|
112
|
+
case DeukPackTypes_1.TokenType.NAMESPACE:
|
|
113
|
+
this.leadingCommentBuffer = '';
|
|
114
|
+
const namespace = this.parseNamespace();
|
|
115
|
+
namespace.sourceFile = this.currentFile;
|
|
116
|
+
ast.namespaces.push(namespace);
|
|
117
|
+
break;
|
|
118
|
+
case DeukPackTypes_1.TokenType.RECORD: {
|
|
119
|
+
const doc = this.leadingCommentBuffer;
|
|
120
|
+
this.leadingCommentBuffer = '';
|
|
121
|
+
const struct = this.parseStruct(doc);
|
|
122
|
+
struct.sourceFile = this.currentFile;
|
|
123
|
+
ast.structs.push(struct);
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
case DeukPackTypes_1.TokenType.IDENTIFIER:
|
|
127
|
+
if (token.value === 'message' && this.tokens[this.position + 1]?.type === DeukPackTypes_1.TokenType.LEFT_BRACKET) {
|
|
128
|
+
const doc = this.leadingCommentBuffer;
|
|
129
|
+
this.leadingCommentBuffer = '';
|
|
130
|
+
const struct = this.parseMessage(doc);
|
|
131
|
+
struct.sourceFile = this.currentFile;
|
|
132
|
+
ast.structs.push(struct);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
this.leadingCommentBuffer = '';
|
|
136
|
+
this.advance();
|
|
137
|
+
}
|
|
138
|
+
break;
|
|
139
|
+
case DeukPackTypes_1.TokenType.ENUM: {
|
|
140
|
+
const doc = this.leadingCommentBuffer;
|
|
141
|
+
this.leadingCommentBuffer = '';
|
|
142
|
+
const enumDef = this.parseEnum(doc);
|
|
143
|
+
enumDef.sourceFile = this.currentFile;
|
|
144
|
+
ast.enums.push(enumDef);
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
case DeukPackTypes_1.TokenType.SERVICE: {
|
|
148
|
+
const doc = this.leadingCommentBuffer;
|
|
149
|
+
this.leadingCommentBuffer = '';
|
|
150
|
+
const service = this.parseService(doc);
|
|
151
|
+
service.sourceFile = this.currentFile;
|
|
152
|
+
ast.services.push(service);
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
case DeukPackTypes_1.TokenType.INCLUDE:
|
|
156
|
+
this.leadingCommentBuffer = '';
|
|
157
|
+
ast.includes.push(this.parseInclude());
|
|
158
|
+
break;
|
|
159
|
+
case DeukPackTypes_1.TokenType.TYPEDEF: {
|
|
160
|
+
const doc = this.leadingCommentBuffer;
|
|
161
|
+
this.leadingCommentBuffer = '';
|
|
162
|
+
const typedef = this.parseTypedef(doc);
|
|
163
|
+
typedef.sourceFile = this.currentFile;
|
|
164
|
+
ast.typedefs.push(typedef);
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
case DeukPackTypes_1.TokenType.CONST: {
|
|
168
|
+
const doc = this.leadingCommentBuffer;
|
|
169
|
+
this.leadingCommentBuffer = '';
|
|
170
|
+
const constant = this.parseConst(doc);
|
|
171
|
+
constant.sourceFile = this.currentFile;
|
|
172
|
+
ast.constants.push(constant);
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
case DeukPackTypes_1.TokenType.TABLE: {
|
|
176
|
+
this.leadingCommentBuffer = '';
|
|
177
|
+
const tableStruct = this.parseTableDefinition();
|
|
178
|
+
tableStruct.sourceFile = this.currentFile;
|
|
179
|
+
ast.structs.push(tableStruct);
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
case DeukPackTypes_1.TokenType.LINE_COMMENT:
|
|
183
|
+
case DeukPackTypes_1.TokenType.BLOCK_COMMENT:
|
|
184
|
+
this.leadingCommentBuffer = this.collectLeadingComments();
|
|
185
|
+
break;
|
|
186
|
+
default:
|
|
187
|
+
this.leadingCommentBuffer = '';
|
|
188
|
+
this.advance();
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return ast;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Parse namespace declaration
|
|
196
|
+
*/
|
|
197
|
+
parseNamespace() {
|
|
198
|
+
this.advance(); // consume 'namespace'
|
|
199
|
+
if (this.deukMode) {
|
|
200
|
+
const name = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
201
|
+
return { language: '*', name };
|
|
202
|
+
}
|
|
203
|
+
// Handle namespace * syntax
|
|
204
|
+
let language = '*';
|
|
205
|
+
if (this.check(DeukPackTypes_1.TokenType.ASTERISK)) {
|
|
206
|
+
this.advance(); // consume '*'
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
language = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
210
|
+
}
|
|
211
|
+
const name = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
212
|
+
return { language, name };
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Parse struct declaration
|
|
216
|
+
*/
|
|
217
|
+
parseStruct(docComment) {
|
|
218
|
+
this.advance(); // consume 'struct' or 'record'
|
|
219
|
+
const name = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
220
|
+
const annotations = this.tryParseAnnotations();
|
|
221
|
+
while (this.check(DeukPackTypes_1.TokenType.LINE_COMMENT) || this.check(DeukPackTypes_1.TokenType.BLOCK_COMMENT)) {
|
|
222
|
+
this.advance();
|
|
223
|
+
}
|
|
224
|
+
this.expect(DeukPackTypes_1.TokenType.LEFT_BRACE);
|
|
225
|
+
const fields = [];
|
|
226
|
+
while (!this.check(DeukPackTypes_1.TokenType.RIGHT_BRACE)) {
|
|
227
|
+
if (this.check(DeukPackTypes_1.TokenType.LINE_COMMENT) || this.check(DeukPackTypes_1.TokenType.BLOCK_COMMENT)) {
|
|
228
|
+
this.advance();
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
const field = this.parseField();
|
|
232
|
+
if (field) {
|
|
233
|
+
fields.push(field);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
this.expect(DeukPackTypes_1.TokenType.RIGHT_BRACE);
|
|
237
|
+
const result = { name, fields };
|
|
238
|
+
if (docComment) {
|
|
239
|
+
const parsed = this.parseDocCommentAndCSharpAttributes(docComment);
|
|
240
|
+
if (parsed.docComment)
|
|
241
|
+
result.docComment = parsed.docComment;
|
|
242
|
+
if (parsed.csharpAttributes?.length)
|
|
243
|
+
result.csharpAttributes = parsed.csharpAttributes;
|
|
244
|
+
}
|
|
245
|
+
if (annotations)
|
|
246
|
+
result.annotations = annotations;
|
|
247
|
+
if (annotations && annotations['key']) {
|
|
248
|
+
const raw = String(annotations['key']).replace(/^["']|["']$/g, '').trim();
|
|
249
|
+
if (raw) {
|
|
250
|
+
result.keyFieldNames = raw.split(',').map((s) => s.trim()).filter(Boolean);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return result;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Parse message<id> name { fields } — 득팩 프로토콜 메시지.
|
|
257
|
+
* IDL에는 사용자 필드만 적고, 파서가 예약 ID(31000)로 msgInfo 필드를 자동 주입.
|
|
258
|
+
*/
|
|
259
|
+
parseMessage(docComment) {
|
|
260
|
+
this.advance(); // consume 'message'
|
|
261
|
+
this.expect(DeukPackTypes_1.TokenType.LEFT_BRACKET);
|
|
262
|
+
const msgIdStr = this.expect(DeukPackTypes_1.TokenType.NUMBER).value;
|
|
263
|
+
this.expect(DeukPackTypes_1.TokenType.RIGHT_BRACKET);
|
|
264
|
+
const name = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
265
|
+
const annotations = this.tryParseAnnotations();
|
|
266
|
+
while (this.check(DeukPackTypes_1.TokenType.LINE_COMMENT) || this.check(DeukPackTypes_1.TokenType.BLOCK_COMMENT)) {
|
|
267
|
+
this.advance();
|
|
268
|
+
}
|
|
269
|
+
this.expect(DeukPackTypes_1.TokenType.LEFT_BRACE);
|
|
270
|
+
const userFields = [];
|
|
271
|
+
while (!this.check(DeukPackTypes_1.TokenType.RIGHT_BRACE)) {
|
|
272
|
+
if (this.check(DeukPackTypes_1.TokenType.LINE_COMMENT) || this.check(DeukPackTypes_1.TokenType.BLOCK_COMMENT)) {
|
|
273
|
+
this.advance();
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
const field = this.parseField();
|
|
277
|
+
if (field)
|
|
278
|
+
userFields.push(field);
|
|
279
|
+
}
|
|
280
|
+
this.expect(DeukPackTypes_1.TokenType.RIGHT_BRACE);
|
|
281
|
+
const syntheticMsgInfo = {
|
|
282
|
+
id: DeukPackASTBuilder.MSGINFO_FIELD_ID,
|
|
283
|
+
name: 'msgInfo',
|
|
284
|
+
type: 'MsgInfo',
|
|
285
|
+
required: false,
|
|
286
|
+
annotations: { msgId: msgIdStr }
|
|
287
|
+
};
|
|
288
|
+
const fields = [syntheticMsgInfo, ...userFields];
|
|
289
|
+
const result = { name, fields };
|
|
290
|
+
if (docComment) {
|
|
291
|
+
const parsed = this.parseDocCommentAndCSharpAttributes(docComment);
|
|
292
|
+
if (parsed.docComment)
|
|
293
|
+
result.docComment = parsed.docComment;
|
|
294
|
+
if (parsed.csharpAttributes?.length)
|
|
295
|
+
result.csharpAttributes = parsed.csharpAttributes;
|
|
296
|
+
}
|
|
297
|
+
if (annotations)
|
|
298
|
+
result.annotations = annotations;
|
|
299
|
+
result.annotations = result.annotations ?? {};
|
|
300
|
+
result.annotations['msgId'] = msgIdStr;
|
|
301
|
+
return result;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Parse table<rowType> = { version: "...", key?: "..." } — 득팩 테이블 정의.
|
|
305
|
+
* Produces a synthetic struct named "table" with header + infos for existing codegen (IDeukMetaContainer).
|
|
306
|
+
*/
|
|
307
|
+
parseTableDefinition() {
|
|
308
|
+
this.advance(); // consume 'table'
|
|
309
|
+
this.expect(DeukPackTypes_1.TokenType.LEFT_BRACKET);
|
|
310
|
+
const rowTypeName = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
311
|
+
this.expect(DeukPackTypes_1.TokenType.RIGHT_BRACKET);
|
|
312
|
+
this.expect(DeukPackTypes_1.TokenType.EQUALS);
|
|
313
|
+
this.expect(DeukPackTypes_1.TokenType.LEFT_BRACE);
|
|
314
|
+
const annotations = {};
|
|
315
|
+
let keyFieldNames;
|
|
316
|
+
while (!this.check(DeukPackTypes_1.TokenType.RIGHT_BRACE)) {
|
|
317
|
+
const key = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
318
|
+
this.expect(DeukPackTypes_1.TokenType.COLON);
|
|
319
|
+
if (this.check(DeukPackTypes_1.TokenType.STRING_LITERAL)) {
|
|
320
|
+
const val = this.advance().value;
|
|
321
|
+
const unquoted = val.replace(/^["']|["']$/g, '').trim();
|
|
322
|
+
if (key === 'version')
|
|
323
|
+
annotations['version'] = unquoted;
|
|
324
|
+
else if (key === 'key')
|
|
325
|
+
keyFieldNames = [unquoted];
|
|
326
|
+
}
|
|
327
|
+
else if (this.check(DeukPackTypes_1.TokenType.LEFT_BRACKET)) {
|
|
328
|
+
this.advance();
|
|
329
|
+
const list = [];
|
|
330
|
+
while (!this.check(DeukPackTypes_1.TokenType.RIGHT_BRACKET)) {
|
|
331
|
+
const t = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER);
|
|
332
|
+
list.push(t.value);
|
|
333
|
+
if (this.check(DeukPackTypes_1.TokenType.COMMA))
|
|
334
|
+
this.advance();
|
|
335
|
+
}
|
|
336
|
+
this.expect(DeukPackTypes_1.TokenType.RIGHT_BRACKET);
|
|
337
|
+
if (key === 'key')
|
|
338
|
+
keyFieldNames = list;
|
|
339
|
+
}
|
|
340
|
+
if (this.check(DeukPackTypes_1.TokenType.COMMA))
|
|
341
|
+
this.advance();
|
|
342
|
+
}
|
|
343
|
+
this.expect(DeukPackTypes_1.TokenType.RIGHT_BRACE);
|
|
344
|
+
// 테이블 헤더 타입명: 프로젝트 IDL에 해당 이름의 record/typedef 필요. 레거시 호환용 기본명.
|
|
345
|
+
const headerType = 'MetaHeader';
|
|
346
|
+
const infosType = {
|
|
347
|
+
type: 'map',
|
|
348
|
+
keyType: 'int64',
|
|
349
|
+
valueType: rowTypeName
|
|
350
|
+
};
|
|
351
|
+
const tableStruct = {
|
|
352
|
+
name: 'container',
|
|
353
|
+
fields: [
|
|
354
|
+
{ id: 1, name: 'header', type: headerType, required: false, defaultValue: {} },
|
|
355
|
+
{ id: 2, name: 'infos', type: infosType, required: false, defaultValue: {} }
|
|
356
|
+
]
|
|
357
|
+
};
|
|
358
|
+
if (Object.keys(annotations).length)
|
|
359
|
+
tableStruct.annotations = annotations;
|
|
360
|
+
if (keyFieldNames?.length)
|
|
361
|
+
tableStruct.keyFieldNames = keyFieldNames;
|
|
362
|
+
return tableStruct;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Parse field declaration. Deuk: id> [Attr]… type name [= default]. Legacy .thrift: id: [required|optional] type name [= default]
|
|
366
|
+
*/
|
|
367
|
+
parseField() {
|
|
368
|
+
const rawComment = this.collectLeadingComments();
|
|
369
|
+
if (this.check(DeukPackTypes_1.TokenType.RIGHT_BRACE)) {
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
372
|
+
const id = parseInt(this.expect(DeukPackTypes_1.TokenType.NUMBER).value);
|
|
373
|
+
if (this.deukMode) {
|
|
374
|
+
this.expect(DeukPackTypes_1.TokenType.RIGHT_BRACKET); // '>'
|
|
375
|
+
const inlineAttrs = [];
|
|
376
|
+
while (this.check(DeukPackTypes_1.TokenType.LEFT_BRACKET)) {
|
|
377
|
+
inlineAttrs.push(this.parseOneDeukInlineAttribute());
|
|
378
|
+
}
|
|
379
|
+
const type = this.parseType();
|
|
380
|
+
const name = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
381
|
+
let defaultValue = undefined;
|
|
382
|
+
if (this.check(DeukPackTypes_1.TokenType.EQUALS)) {
|
|
383
|
+
this.advance();
|
|
384
|
+
defaultValue = this.parseDefaultValue();
|
|
385
|
+
}
|
|
386
|
+
if (this.check(DeukPackTypes_1.TokenType.COMMA))
|
|
387
|
+
this.advance();
|
|
388
|
+
if (this.check(DeukPackTypes_1.TokenType.SEMICOLON))
|
|
389
|
+
this.advance();
|
|
390
|
+
const result = { id, name, type, required: false };
|
|
391
|
+
if (defaultValue !== undefined)
|
|
392
|
+
result.defaultValue = defaultValue;
|
|
393
|
+
if (rawComment) {
|
|
394
|
+
const parsed = this.parseDocCommentAndCSharpAttributes(rawComment);
|
|
395
|
+
if (parsed.docComment)
|
|
396
|
+
result.docComment = parsed.docComment;
|
|
397
|
+
if (parsed.csharpAttributes?.length)
|
|
398
|
+
result.csharpAttributes = parsed.csharpAttributes;
|
|
399
|
+
}
|
|
400
|
+
if (inlineAttrs.length) {
|
|
401
|
+
result.csharpAttributes = result.csharpAttributes || [];
|
|
402
|
+
result.csharpAttributes.push(...inlineAttrs);
|
|
403
|
+
}
|
|
404
|
+
return result;
|
|
405
|
+
}
|
|
406
|
+
this.expect(DeukPackTypes_1.TokenType.COLON);
|
|
407
|
+
let required = false;
|
|
408
|
+
if (this.check(DeukPackTypes_1.TokenType.REQUIRED)) {
|
|
409
|
+
required = true;
|
|
410
|
+
this.advance();
|
|
411
|
+
}
|
|
412
|
+
else if (this.check(DeukPackTypes_1.TokenType.OPTIONAL)) {
|
|
413
|
+
this.advance();
|
|
414
|
+
}
|
|
415
|
+
const type = this.parseType();
|
|
416
|
+
const name = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
417
|
+
const annotations = this.tryParseAnnotations();
|
|
418
|
+
let defaultValue = undefined;
|
|
419
|
+
if (this.check(DeukPackTypes_1.TokenType.EQUALS)) {
|
|
420
|
+
this.advance();
|
|
421
|
+
defaultValue = this.parseDefaultValue();
|
|
422
|
+
}
|
|
423
|
+
if (this.check(DeukPackTypes_1.TokenType.COMMA))
|
|
424
|
+
this.advance();
|
|
425
|
+
if (this.check(DeukPackTypes_1.TokenType.SEMICOLON))
|
|
426
|
+
this.advance();
|
|
427
|
+
const result = { id, name, type, required };
|
|
428
|
+
if (defaultValue !== undefined)
|
|
429
|
+
result.defaultValue = defaultValue;
|
|
430
|
+
if (rawComment) {
|
|
431
|
+
const parsed = this.parseDocCommentAndCSharpAttributes(rawComment);
|
|
432
|
+
if (parsed.docComment)
|
|
433
|
+
result.docComment = parsed.docComment;
|
|
434
|
+
if (parsed.csharpAttributes?.length)
|
|
435
|
+
result.csharpAttributes = parsed.csharpAttributes;
|
|
436
|
+
}
|
|
437
|
+
if (annotations)
|
|
438
|
+
result.annotations = annotations;
|
|
439
|
+
return result;
|
|
440
|
+
}
|
|
441
|
+
/** Parse one [Attr] or [Attr("v")] or [Attr(K=V)] in .deuk; return string for csharpAttributes */
|
|
442
|
+
parseOneDeukInlineAttribute() {
|
|
443
|
+
this.expect(DeukPackTypes_1.TokenType.LEFT_BRACKET);
|
|
444
|
+
let piece = '[';
|
|
445
|
+
piece += this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
446
|
+
if (this.check(DeukPackTypes_1.TokenType.LEFT_PAREN)) {
|
|
447
|
+
this.advance();
|
|
448
|
+
piece += '(';
|
|
449
|
+
while (!this.check(DeukPackTypes_1.TokenType.RIGHT_PAREN) && !this.isAtEnd()) {
|
|
450
|
+
piece += this.peek().value;
|
|
451
|
+
this.advance();
|
|
452
|
+
}
|
|
453
|
+
if (this.check(DeukPackTypes_1.TokenType.RIGHT_PAREN)) {
|
|
454
|
+
this.advance();
|
|
455
|
+
piece += ')';
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
this.expect(DeukPackTypes_1.TokenType.RIGHT_BRACKET);
|
|
459
|
+
return piece + ']';
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Parse type declaration
|
|
463
|
+
*/
|
|
464
|
+
parseType() {
|
|
465
|
+
const token = this.peek();
|
|
466
|
+
switch (token.type) {
|
|
467
|
+
case DeukPackTypes_1.TokenType.BOOL:
|
|
468
|
+
this.advance();
|
|
469
|
+
return 'bool';
|
|
470
|
+
case DeukPackTypes_1.TokenType.BYTE: {
|
|
471
|
+
const v = token.value;
|
|
472
|
+
this.advance();
|
|
473
|
+
return v === 'byte' ? 'byte' : 'int8';
|
|
474
|
+
}
|
|
475
|
+
case DeukPackTypes_1.TokenType.I16:
|
|
476
|
+
this.advance();
|
|
477
|
+
return 'int16';
|
|
478
|
+
case DeukPackTypes_1.TokenType.I32:
|
|
479
|
+
this.advance();
|
|
480
|
+
return 'int32';
|
|
481
|
+
case DeukPackTypes_1.TokenType.I64:
|
|
482
|
+
this.advance();
|
|
483
|
+
return 'int64';
|
|
484
|
+
case DeukPackTypes_1.TokenType.DOUBLE: {
|
|
485
|
+
const v = token.value;
|
|
486
|
+
this.advance();
|
|
487
|
+
return v === 'float' ? 'float' : 'double';
|
|
488
|
+
}
|
|
489
|
+
case DeukPackTypes_1.TokenType.STRING:
|
|
490
|
+
this.advance();
|
|
491
|
+
return 'string';
|
|
492
|
+
case DeukPackTypes_1.TokenType.BINARY:
|
|
493
|
+
this.advance();
|
|
494
|
+
return 'binary';
|
|
495
|
+
case DeukPackTypes_1.TokenType.IDENTIFIER:
|
|
496
|
+
return this.parseIdentifierType();
|
|
497
|
+
case DeukPackTypes_1.TokenType.LIST:
|
|
498
|
+
return this.parseListType();
|
|
499
|
+
case DeukPackTypes_1.TokenType.SET:
|
|
500
|
+
return this.parseSetType();
|
|
501
|
+
case DeukPackTypes_1.TokenType.MAP:
|
|
502
|
+
return this.parseMapType();
|
|
503
|
+
case DeukPackTypes_1.TokenType.TABLELINK:
|
|
504
|
+
return this.parseTableLinkType();
|
|
505
|
+
default:
|
|
506
|
+
throw new Error(`Unexpected token: ${token.type}`);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Parse identifier type (handles namespaced types like mo_define.projectile_type_e)
|
|
511
|
+
*/
|
|
512
|
+
parseIdentifierType() {
|
|
513
|
+
let typeName = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
514
|
+
// Handle namespaced types: . or :: (DeukPack uses :: in .deuk; store as . in AST)
|
|
515
|
+
while (this.check(DeukPackTypes_1.TokenType.DOT) || this.check(DeukPackTypes_1.TokenType.COLON)) {
|
|
516
|
+
if (this.check(DeukPackTypes_1.TokenType.DOT))
|
|
517
|
+
this.advance();
|
|
518
|
+
else {
|
|
519
|
+
this.advance();
|
|
520
|
+
this.expect(DeukPackTypes_1.TokenType.COLON);
|
|
521
|
+
}
|
|
522
|
+
const nextPart = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
523
|
+
typeName += '.' + nextPart;
|
|
524
|
+
}
|
|
525
|
+
// 득팩 테이블 프리미티브(id, tid, mname, mnote) — 단일 식별자일 때만
|
|
526
|
+
const primitive = DeukPackASTBuilder.META_PRIMITIVES[typeName];
|
|
527
|
+
if (primitive !== undefined)
|
|
528
|
+
return primitive;
|
|
529
|
+
// 레거시 식별자(i32 등) → 득팩 타입으로 정규화 (단일 식별자일 때만)
|
|
530
|
+
const normalized = DeukPackASTBuilder.THRIFT_TYPE_TO_DEUKPACK[typeName];
|
|
531
|
+
if (normalized !== undefined)
|
|
532
|
+
return normalized;
|
|
533
|
+
return typeName;
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Parse list type
|
|
537
|
+
*/
|
|
538
|
+
parseListType() {
|
|
539
|
+
this.advance(); // consume 'list'
|
|
540
|
+
this.expect(DeukPackTypes_1.TokenType.LEFT_BRACKET);
|
|
541
|
+
const elementType = this.parseType();
|
|
542
|
+
this.expect(DeukPackTypes_1.TokenType.RIGHT_BRACKET);
|
|
543
|
+
return {
|
|
544
|
+
type: 'list',
|
|
545
|
+
elementType
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Parse set type
|
|
550
|
+
*/
|
|
551
|
+
parseSetType() {
|
|
552
|
+
this.advance(); // consume 'set'
|
|
553
|
+
this.expect(DeukPackTypes_1.TokenType.LEFT_BRACKET);
|
|
554
|
+
const elementType = this.parseType();
|
|
555
|
+
this.expect(DeukPackTypes_1.TokenType.RIGHT_BRACKET);
|
|
556
|
+
return {
|
|
557
|
+
type: 'set',
|
|
558
|
+
elementType
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Parse tablelink<TableCategory, KeyField> — 득팩 테이블 행 참조.
|
|
563
|
+
*/
|
|
564
|
+
parseTableLinkType() {
|
|
565
|
+
this.advance(); // consume 'tablelink'
|
|
566
|
+
this.expect(DeukPackTypes_1.TokenType.LEFT_BRACKET);
|
|
567
|
+
const tableCategory = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
568
|
+
this.expect(DeukPackTypes_1.TokenType.COMMA);
|
|
569
|
+
const keyField = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
570
|
+
this.expect(DeukPackTypes_1.TokenType.RIGHT_BRACKET);
|
|
571
|
+
return { type: 'tablelink', tableCategory, keyField };
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Parse map type
|
|
575
|
+
*/
|
|
576
|
+
parseMapType() {
|
|
577
|
+
this.advance(); // consume 'map'
|
|
578
|
+
this.expect(DeukPackTypes_1.TokenType.LEFT_BRACKET);
|
|
579
|
+
const keyType = this.parseType();
|
|
580
|
+
this.expect(DeukPackTypes_1.TokenType.COMMA);
|
|
581
|
+
const valueType = this.parseType();
|
|
582
|
+
this.expect(DeukPackTypes_1.TokenType.RIGHT_BRACKET);
|
|
583
|
+
return {
|
|
584
|
+
type: 'map',
|
|
585
|
+
keyType,
|
|
586
|
+
valueType
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Parse default value
|
|
591
|
+
*/
|
|
592
|
+
parseDefaultValue() {
|
|
593
|
+
const token = this.peek();
|
|
594
|
+
switch (token.type) {
|
|
595
|
+
case DeukPackTypes_1.TokenType.NUMBER:
|
|
596
|
+
this.advance();
|
|
597
|
+
return parseFloat(token.value);
|
|
598
|
+
case DeukPackTypes_1.TokenType.STRING_LITERAL:
|
|
599
|
+
this.advance();
|
|
600
|
+
return token.value;
|
|
601
|
+
case DeukPackTypes_1.TokenType.BOOLEAN:
|
|
602
|
+
this.advance();
|
|
603
|
+
return token.value === 'true';
|
|
604
|
+
case DeukPackTypes_1.TokenType.IDENTIFIER:
|
|
605
|
+
return this.parseIdentifierDefaultValue();
|
|
606
|
+
case DeukPackTypes_1.TokenType.LEFT_BRACE:
|
|
607
|
+
return this.parseObjectDefaultValue();
|
|
608
|
+
case DeukPackTypes_1.TokenType.LEFT_BRACKET:
|
|
609
|
+
return this.parseArrayDefaultValue();
|
|
610
|
+
default:
|
|
611
|
+
throw new Error(`Unexpected default value: ${token.type}`);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Parse identifier default value (handles namespaced values; . or :: in .deuk, stored as . in AST)
|
|
616
|
+
*/
|
|
617
|
+
parseIdentifierDefaultValue() {
|
|
618
|
+
let value = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
619
|
+
while (this.check(DeukPackTypes_1.TokenType.DOT) || this.check(DeukPackTypes_1.TokenType.COLON)) {
|
|
620
|
+
if (this.check(DeukPackTypes_1.TokenType.DOT))
|
|
621
|
+
this.advance();
|
|
622
|
+
else {
|
|
623
|
+
this.advance();
|
|
624
|
+
this.expect(DeukPackTypes_1.TokenType.COLON);
|
|
625
|
+
}
|
|
626
|
+
const nextPart = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
627
|
+
value += '.' + nextPart;
|
|
628
|
+
}
|
|
629
|
+
return value;
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Parse array default value (handles values like [{"weight":30}, {"weight":30}] or [])
|
|
633
|
+
*/
|
|
634
|
+
parseArrayDefaultValue() {
|
|
635
|
+
this.expect(DeukPackTypes_1.TokenType.LEFT_BRACKET);
|
|
636
|
+
// Handle empty array []
|
|
637
|
+
if (this.check(DeukPackTypes_1.TokenType.RIGHT_BRACKET)) {
|
|
638
|
+
this.advance();
|
|
639
|
+
return [];
|
|
640
|
+
}
|
|
641
|
+
// Parse array content
|
|
642
|
+
const arr = [];
|
|
643
|
+
while (!this.check(DeukPackTypes_1.TokenType.RIGHT_BRACKET) && !this.isAtEnd()) {
|
|
644
|
+
// Skip whitespace and comments
|
|
645
|
+
if (this.check(DeukPackTypes_1.TokenType.LINE_COMMENT) || this.check(DeukPackTypes_1.TokenType.BLOCK_COMMENT)) {
|
|
646
|
+
this.advance();
|
|
647
|
+
continue;
|
|
648
|
+
}
|
|
649
|
+
// Parse array element
|
|
650
|
+
let element = undefined;
|
|
651
|
+
if (this.check(DeukPackTypes_1.TokenType.STRING_LITERAL)) {
|
|
652
|
+
element = this.expect(DeukPackTypes_1.TokenType.STRING_LITERAL).value;
|
|
653
|
+
}
|
|
654
|
+
else if (this.check(DeukPackTypes_1.TokenType.NUMBER)) {
|
|
655
|
+
element = parseFloat(this.expect(DeukPackTypes_1.TokenType.NUMBER).value);
|
|
656
|
+
}
|
|
657
|
+
else if (this.check(DeukPackTypes_1.TokenType.BOOLEAN)) {
|
|
658
|
+
element = this.expect(DeukPackTypes_1.TokenType.BOOLEAN).value === 'true';
|
|
659
|
+
}
|
|
660
|
+
else if (this.check(DeukPackTypes_1.TokenType.LEFT_BRACE)) {
|
|
661
|
+
element = this.parseObjectDefaultValue();
|
|
662
|
+
}
|
|
663
|
+
else if (this.check(DeukPackTypes_1.TokenType.LEFT_BRACKET)) {
|
|
664
|
+
element = this.parseArrayDefaultValue();
|
|
665
|
+
}
|
|
666
|
+
if (element !== undefined) {
|
|
667
|
+
arr.push(element);
|
|
668
|
+
}
|
|
669
|
+
// Skip comma if present
|
|
670
|
+
if (this.check(DeukPackTypes_1.TokenType.COMMA)) {
|
|
671
|
+
this.advance();
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
this.expect(DeukPackTypes_1.TokenType.RIGHT_BRACKET);
|
|
675
|
+
return arr;
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* Parse object default value (handles values like { "version": 20250802 } or {})
|
|
679
|
+
*/
|
|
680
|
+
parseObjectDefaultValue() {
|
|
681
|
+
this.expect(DeukPackTypes_1.TokenType.LEFT_BRACE);
|
|
682
|
+
// Handle empty object {}
|
|
683
|
+
if (this.check(DeukPackTypes_1.TokenType.RIGHT_BRACE)) {
|
|
684
|
+
this.advance();
|
|
685
|
+
return {};
|
|
686
|
+
}
|
|
687
|
+
// Parse object content
|
|
688
|
+
const obj = {};
|
|
689
|
+
while (!this.check(DeukPackTypes_1.TokenType.RIGHT_BRACE) && !this.isAtEnd()) {
|
|
690
|
+
// Skip whitespace and comments
|
|
691
|
+
if (this.check(DeukPackTypes_1.TokenType.LINE_COMMENT) || this.check(DeukPackTypes_1.TokenType.BLOCK_COMMENT)) {
|
|
692
|
+
this.advance();
|
|
693
|
+
continue;
|
|
694
|
+
}
|
|
695
|
+
// Parse key-value pairs
|
|
696
|
+
if (this.check(DeukPackTypes_1.TokenType.STRING_LITERAL)) {
|
|
697
|
+
const key = this.expect(DeukPackTypes_1.TokenType.STRING_LITERAL).value;
|
|
698
|
+
// Skip colon
|
|
699
|
+
if (this.check(DeukPackTypes_1.TokenType.COLON)) {
|
|
700
|
+
this.advance();
|
|
701
|
+
}
|
|
702
|
+
// Parse value (string, number, boolean, object, or identifier e.g. id_e.req_login)
|
|
703
|
+
let value = undefined;
|
|
704
|
+
if (this.check(DeukPackTypes_1.TokenType.STRING_LITERAL)) {
|
|
705
|
+
value = this.expect(DeukPackTypes_1.TokenType.STRING_LITERAL).value;
|
|
706
|
+
}
|
|
707
|
+
else if (this.check(DeukPackTypes_1.TokenType.NUMBER)) {
|
|
708
|
+
value = parseFloat(this.expect(DeukPackTypes_1.TokenType.NUMBER).value);
|
|
709
|
+
}
|
|
710
|
+
else if (this.check(DeukPackTypes_1.TokenType.BOOLEAN)) {
|
|
711
|
+
value = this.expect(DeukPackTypes_1.TokenType.BOOLEAN).value === 'true';
|
|
712
|
+
}
|
|
713
|
+
else if (this.check(DeukPackTypes_1.TokenType.LEFT_BRACE)) {
|
|
714
|
+
value = this.parseObjectDefaultValue();
|
|
715
|
+
}
|
|
716
|
+
else if (this.check(DeukPackTypes_1.TokenType.IDENTIFIER)) {
|
|
717
|
+
value = this.parseIdentifierDefaultValue();
|
|
718
|
+
}
|
|
719
|
+
obj[key] = value;
|
|
720
|
+
// Skip comma if present
|
|
721
|
+
if (this.check(DeukPackTypes_1.TokenType.COMMA)) {
|
|
722
|
+
this.advance();
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
else {
|
|
726
|
+
this.advance(); // Skip unknown tokens
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
if (this.check(DeukPackTypes_1.TokenType.RIGHT_BRACE)) {
|
|
730
|
+
this.advance();
|
|
731
|
+
}
|
|
732
|
+
return obj;
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Parse enum declaration
|
|
736
|
+
*/
|
|
737
|
+
parseEnum(docComment) {
|
|
738
|
+
this.advance(); // consume 'enum'
|
|
739
|
+
const name = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
740
|
+
const annotations = this.tryParseAnnotations();
|
|
741
|
+
this.expect(DeukPackTypes_1.TokenType.LEFT_BRACE);
|
|
742
|
+
const values = {};
|
|
743
|
+
const valueComments = {};
|
|
744
|
+
let currentValue = 0;
|
|
745
|
+
while (!this.check(DeukPackTypes_1.TokenType.RIGHT_BRACE)) {
|
|
746
|
+
const memberComment = this.collectLeadingComments();
|
|
747
|
+
if (this.check(DeukPackTypes_1.TokenType.RIGHT_BRACE))
|
|
748
|
+
break;
|
|
749
|
+
const enumName = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
750
|
+
if (this.check(DeukPackTypes_1.TokenType.EQUALS)) {
|
|
751
|
+
this.advance();
|
|
752
|
+
currentValue = parseInt(this.expect(DeukPackTypes_1.TokenType.NUMBER).value);
|
|
753
|
+
}
|
|
754
|
+
values[enumName] = currentValue;
|
|
755
|
+
if (memberComment)
|
|
756
|
+
valueComments[enumName] = memberComment;
|
|
757
|
+
currentValue++;
|
|
758
|
+
if (this.check(DeukPackTypes_1.TokenType.COMMA))
|
|
759
|
+
this.advance();
|
|
760
|
+
while (this.check(DeukPackTypes_1.TokenType.WHITESPACE) || this.check(DeukPackTypes_1.TokenType.NEWLINE)) {
|
|
761
|
+
this.advance();
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
this.expect(DeukPackTypes_1.TokenType.RIGHT_BRACE);
|
|
765
|
+
const result = { name, values };
|
|
766
|
+
if (docComment) {
|
|
767
|
+
const parsed = this.parseDocCommentAndCSharpAttributes(docComment);
|
|
768
|
+
if (parsed.docComment)
|
|
769
|
+
result.docComment = parsed.docComment;
|
|
770
|
+
if (parsed.csharpAttributes?.length)
|
|
771
|
+
result.csharpAttributes = parsed.csharpAttributes;
|
|
772
|
+
}
|
|
773
|
+
if (Object.keys(valueComments).length)
|
|
774
|
+
result.valueComments = valueComments;
|
|
775
|
+
if (annotations)
|
|
776
|
+
result.annotations = annotations;
|
|
777
|
+
return result;
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Parse service declaration
|
|
781
|
+
*/
|
|
782
|
+
parseService(docComment) {
|
|
783
|
+
this.advance(); // consume 'service'
|
|
784
|
+
const name = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
785
|
+
const annotations = this.tryParseAnnotations();
|
|
786
|
+
this.expect(DeukPackTypes_1.TokenType.LEFT_BRACE);
|
|
787
|
+
const methods = [];
|
|
788
|
+
while (!this.check(DeukPackTypes_1.TokenType.RIGHT_BRACE)) {
|
|
789
|
+
if (this.check(DeukPackTypes_1.TokenType.LINE_COMMENT) || this.check(DeukPackTypes_1.TokenType.BLOCK_COMMENT)) {
|
|
790
|
+
this.advance(); // skip comments
|
|
791
|
+
continue;
|
|
792
|
+
}
|
|
793
|
+
methods.push(this.parseServiceMethod());
|
|
794
|
+
if (this.check(DeukPackTypes_1.TokenType.COMMA) || this.check(DeukPackTypes_1.TokenType.SEMICOLON)) {
|
|
795
|
+
this.advance();
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
this.expect(DeukPackTypes_1.TokenType.RIGHT_BRACE);
|
|
799
|
+
const result = { name, methods };
|
|
800
|
+
if (docComment)
|
|
801
|
+
result.docComment = docComment;
|
|
802
|
+
if (annotations)
|
|
803
|
+
result.annotations = annotations;
|
|
804
|
+
return result;
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Parse a single service method: returnType methodName( [ params ] )
|
|
808
|
+
*/
|
|
809
|
+
parseServiceMethod() {
|
|
810
|
+
const returnType = this.parseType();
|
|
811
|
+
const methodName = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
812
|
+
this.expect(DeukPackTypes_1.TokenType.LEFT_PAREN);
|
|
813
|
+
const parameters = [];
|
|
814
|
+
while (this.check(DeukPackTypes_1.TokenType.NUMBER) && !this.isAtEnd()) {
|
|
815
|
+
const idToken = this.advance();
|
|
816
|
+
const fieldId = typeof idToken.value === 'number' ? idToken.value : parseInt(String(idToken.value), 10);
|
|
817
|
+
if (this.check(DeukPackTypes_1.TokenType.COLON))
|
|
818
|
+
this.advance();
|
|
819
|
+
const paramType = this.parseType();
|
|
820
|
+
const paramName = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
821
|
+
parameters.push({ id: fieldId, name: paramName, type: paramType, required: true });
|
|
822
|
+
if (this.check(DeukPackTypes_1.TokenType.COMMA))
|
|
823
|
+
this.advance();
|
|
824
|
+
}
|
|
825
|
+
if (this.check(DeukPackTypes_1.TokenType.RIGHT_PAREN))
|
|
826
|
+
this.advance();
|
|
827
|
+
return { name: methodName, returnType, parameters, oneway: false };
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* Parse include statement
|
|
831
|
+
*/
|
|
832
|
+
parseInclude() {
|
|
833
|
+
this.advance(); // consume 'include'
|
|
834
|
+
const fileName = this.expect(DeukPackTypes_1.TokenType.STRING_LITERAL).value;
|
|
835
|
+
// Include statements don't require semicolons
|
|
836
|
+
return fileName;
|
|
837
|
+
}
|
|
838
|
+
/**
|
|
839
|
+
* Parse typedef declaration
|
|
840
|
+
*/
|
|
841
|
+
parseTypedef(docComment) {
|
|
842
|
+
this.advance(); // consume 'typedef'
|
|
843
|
+
const type = this.parseType();
|
|
844
|
+
const name = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
845
|
+
const annotations = this.tryParseAnnotations();
|
|
846
|
+
const result = { name, type };
|
|
847
|
+
if (docComment)
|
|
848
|
+
result.docComment = docComment;
|
|
849
|
+
if (annotations)
|
|
850
|
+
result.annotations = annotations;
|
|
851
|
+
return result;
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Parse const declaration
|
|
855
|
+
*/
|
|
856
|
+
parseConst(docComment) {
|
|
857
|
+
this.advance(); // consume 'const'
|
|
858
|
+
const type = this.parseType();
|
|
859
|
+
const name = this.expect(DeukPackTypes_1.TokenType.IDENTIFIER).value;
|
|
860
|
+
const annotations = this.tryParseAnnotations();
|
|
861
|
+
this.expect(DeukPackTypes_1.TokenType.EQUALS);
|
|
862
|
+
const value = this.parseDefaultValue();
|
|
863
|
+
const result = { name, type, value };
|
|
864
|
+
if (docComment)
|
|
865
|
+
result.docComment = docComment;
|
|
866
|
+
if (annotations)
|
|
867
|
+
result.annotations = annotations;
|
|
868
|
+
return result;
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* Check if current token matches expected type
|
|
872
|
+
*/
|
|
873
|
+
check(type) {
|
|
874
|
+
if (this.isAtEnd())
|
|
875
|
+
return false;
|
|
876
|
+
return this.peek().type === type;
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* Expect token of specific type and advance
|
|
880
|
+
*/
|
|
881
|
+
expect(type) {
|
|
882
|
+
if (this.check(type)) {
|
|
883
|
+
return this.advance();
|
|
884
|
+
}
|
|
885
|
+
const current = this.peek();
|
|
886
|
+
throw new Error(`Expected ${type}, got ${current.type} (value: "${current.value}") at line ${current.line}, column ${current.column}`);
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Advance and return current token
|
|
890
|
+
*/
|
|
891
|
+
advance() {
|
|
892
|
+
if (!this.isAtEnd()) {
|
|
893
|
+
this.position++;
|
|
894
|
+
}
|
|
895
|
+
return this.previous();
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Get current token without advancing
|
|
899
|
+
*/
|
|
900
|
+
peek() {
|
|
901
|
+
return this.tokens[this.position] || { type: DeukPackTypes_1.TokenType.EOF, value: '', position: 0, line: 0, column: 0 };
|
|
902
|
+
}
|
|
903
|
+
/**
|
|
904
|
+
* Get previous token
|
|
905
|
+
*/
|
|
906
|
+
previous() {
|
|
907
|
+
return this.tokens[this.position - 1] || { type: DeukPackTypes_1.TokenType.EOF, value: '', position: 0, line: 0, column: 0 };
|
|
908
|
+
}
|
|
909
|
+
/**
|
|
910
|
+
* Check if at end of tokens
|
|
911
|
+
*/
|
|
912
|
+
isAtEnd() {
|
|
913
|
+
return this.peek().type === DeukPackTypes_1.TokenType.EOF;
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
exports.DeukPackASTBuilder = DeukPackASTBuilder;
|
|
917
|
+
/** 예약 필드 ID: message<> 자동 주입 msgInfo (IDL에는 적지 않음, 코드젠에서만 사용). DEUKPACK_MESSAGE_INFO_KEYWORD §5. */
|
|
918
|
+
DeukPackASTBuilder.MSGINFO_FIELD_ID = 31000;
|
|
919
|
+
/** 레거시 식별자 타입(i32 등) → 득팩 이름 정규화 (Protobuf와 동일하게 AST에는 득팩 타입만 저장) */
|
|
920
|
+
DeukPackASTBuilder.THRIFT_TYPE_TO_DEUKPACK = {
|
|
921
|
+
i8: 'int8',
|
|
922
|
+
i16: 'int16',
|
|
923
|
+
i32: 'int32',
|
|
924
|
+
i64: 'int64'
|
|
925
|
+
};
|
|
926
|
+
/** 득팩 테이블 프리미티브(DEUKPACK_IDL_DESIGN §5.1): name/note는 string 별칭. id/tid는 int64와 동일해 타입 구분 불필요. */
|
|
927
|
+
DeukPackASTBuilder.META_PRIMITIVES = {
|
|
928
|
+
mname: 'string',
|
|
929
|
+
mnote: 'string'
|
|
930
|
+
};
|
|
931
|
+
//# sourceMappingURL=DeukPackASTBuilder.js.map
|