cariboujs 2.0.4 → 2.0.5
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/README.md +8 -2
- package/ada/ada2012/AdaLexer.js +486 -316
- package/ada/ada2012/AdaLexerBase.js +25 -0
- package/ada/ada2012/AdaParser.js +4547 -3823
- package/ada/ada2012/AdaParserBase.js +682 -0
- package/ada/ada2012/AdaParserListener.js +36 -0
- package/ada/ada2012/AdaParserVisitor.js +24 -0
- package/ada/ada2012/Symbol.js +20 -0
- package/ada/ada2012/SymbolTable.js +144 -0
- package/ada/ada2012/TypeClassification.js +15 -0
- package/ada/ada2022/AdaLexer.js +699 -0
- package/ada/ada2022/AdaLexerBase.js +25 -0
- package/ada/ada2022/AdaParser.js +37818 -0
- package/ada/ada2022/AdaParserBase.js +686 -0
- package/ada/ada2022/AdaParserListener.js +3024 -0
- package/ada/ada2022/AdaParserVisitor.js +2020 -0
- package/ada/ada2022/Symbol.js +20 -0
- package/ada/ada2022/SymbolTable.js +144 -0
- package/ada/ada2022/TypeClassification.js +15 -0
- package/c/CLexer.js +919 -0
- package/c/CLexerBase.js +96 -0
- package/c/CParser.js +14878 -0
- package/c/CParserBase.js +591 -0
- package/c/CParserListener.js +1062 -0
- package/c/CParserVisitor.js +712 -0
- package/c/ErrorListener.js +50 -0
- package/c/Symbol.js +28 -0
- package/c/SymbolTable.js +215 -0
- package/c/TypeClassification.js +21 -0
- package/cpp/CPP14Parser.js +215 -215
- package/cpp/CPP14ParserListener.js +56 -56
- package/cpp/CPP14ParserVisitor.js +28 -28
- package/csharp/v7/CSharpLexer.js +1339 -0
- package/csharp/v7/CSharpLexerBase.js +332 -0
- package/csharp/v7/CSharpParser.js +29239 -0
- package/csharp/v7/CSharpParserBase.js +48 -0
- package/csharp/v7/CSharpParserListener.js +2304 -0
- package/csharp/v7/CSharpParserVisitor.js +1540 -0
- package/csharp/v8-spec/CSharpLexer.js +1549 -0
- package/csharp/v8-spec/CSharpLexerBase.js +296 -0
- package/csharp/v8-spec/CSharpParser.js +45044 -0
- package/csharp/v8-spec/CSharpParserBase.js +569 -0
- package/csharp/v8-spec/CSharpParserListener.js +3582 -0
- package/csharp/v8-spec/CSharpParserVisitor.js +2392 -0
- package/geekcode/geekcodeLexer.js +232 -0
- package/geekcode/geekcodeListener.js +81 -0
- package/geekcode/geekcodeParser.js +1516 -0
- package/geekcode/geekcodeVisitor.js +58 -0
- package/kotlin/kotlin/KotlinLexer.js +1257 -1247
- package/kotlin/kotlin/KotlinParser.js +3991 -3425
- package/kotlin/kotlin/KotlinParserListener.js +36 -0
- package/kotlin/kotlin/KotlinParserVisitor.js +24 -0
- package/package.json +1 -1
- package/plantUML/PlantUMLLexer.js +215 -316
- package/plantUML/PlantUMLParser.js +1045 -2393
- package/plantUML/PlantUMLParserListener.js +171 -0
- package/plantUML/PlantUMLParserVisitor.js +118 -0
- package/sql/plsql/PlSqlParser.js +27973 -43771
- package/sql/plsql/PlSqlParserBase.js +30 -0
- package/sql/plsql/PlSqlParserListener.js +0 -9
- package/sql/plsql/PlSqlParserVisitor.js +0 -6
- package/sql/snowflake/SnowflakeLexer.js +5675 -5497
- package/sql/snowflake/SnowflakeParser.js +27230 -22653
- package/sql/snowflake/SnowflakeParserListener.js +278 -8
- package/sql/snowflake/SnowflakeParserVisitor.js +184 -4
- package/sql/sqlite/SQLiteParser.js +1115 -1115
- package/sql/sqlite/SQLiteParserListener.js +9 -9
- package/sql/sqlite/SQLiteParserVisitor.js +6 -6
- package/sysml-v2/SysMLv2Lexer.js +1047 -0
- package/sysml-v2/SysMLv2Parser.js +51339 -0
- package/sysml-v2/SysMLv2ParserListener.js +4464 -0
- package/sysml-v2/SysMLv2ParserVisitor.js +2980 -0
- package/plantUML/PlantUMLListener.js +0 -279
- package/plantUML/PlantUMLVisitor.js +0 -190
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
import antlr4 from 'antlr4';
|
|
2
|
+
import CSharpLexer from './CSharpLexer.js';
|
|
3
|
+
import CSharpParser from './CSharpParser.js';
|
|
4
|
+
|
|
5
|
+
export default class CSharpParserBase extends antlr4.Parser {
|
|
6
|
+
constructor(input) {
|
|
7
|
+
super(input);
|
|
8
|
+
this._symTable = null;
|
|
9
|
+
this._pendingVarType = '?';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// -------------------------------------------------------------------------
|
|
13
|
+
// Symbol table — lazily initialised
|
|
14
|
+
// -------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
get symTable() {
|
|
17
|
+
if (!this._symTable) {
|
|
18
|
+
this._symTable = new CSharpSymbolTable();
|
|
19
|
+
}
|
|
20
|
+
return this._symTable;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// -------------------------------------------------------------------------
|
|
24
|
+
// Look-ahead helpers
|
|
25
|
+
// -------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
LookAheadIs(pos, value) {
|
|
28
|
+
return this._input.LA(pos) === value;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
LookAheadIsNot(pos, value) {
|
|
32
|
+
return this._input.LA(pos) !== value;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// -------------------------------------------------------------------------
|
|
36
|
+
// Error reporting
|
|
37
|
+
// -------------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
_notifySemanticError(line, charPositionInLine, msg) {
|
|
40
|
+
this.notifyErrorListeners(msg);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// -------------------------------------------------------------------------
|
|
44
|
+
// ReduceTree — post-parse cleanup (for external tooling)
|
|
45
|
+
// -------------------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
ReduceTree(currentctx) {
|
|
48
|
+
const ruleNames = this.ruleNames;
|
|
49
|
+
const ruleTypeArgumentList = ruleNames.indexOf("type_argument_list");
|
|
50
|
+
|
|
51
|
+
const takeOutEmpties = (node) => {
|
|
52
|
+
if (!node || !node.children) return;
|
|
53
|
+
for (let ix = node.children.length - 1; ix >= 0; ix--) {
|
|
54
|
+
const child = node.children[ix];
|
|
55
|
+
if (child && child.ruleIndex !== undefined) {
|
|
56
|
+
if (child.ruleIndex === ruleTypeArgumentList && child.getChildCount() === 0)
|
|
57
|
+
node.children.splice(ix, 1);
|
|
58
|
+
else
|
|
59
|
+
takeOutEmpties(child);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
takeOutEmpties(currentctx);
|
|
64
|
+
|
|
65
|
+
const reduceTree = process.env.ANTLR_REDUCE_TREE === "yes";
|
|
66
|
+
if (!reduceTree) return;
|
|
67
|
+
|
|
68
|
+
const reduceAllChildren = process.env.ANTLR_REDUCE_ALL_CHILDREN === "yes";
|
|
69
|
+
|
|
70
|
+
const reducer = (node) => {
|
|
71
|
+
if (!node || !node.children) return;
|
|
72
|
+
for (const child of node.children) reducer(child);
|
|
73
|
+
if (reduceAllChildren || node.getChildCount() === 1) {
|
|
74
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
75
|
+
const child = node.children[i];
|
|
76
|
+
if (child && child.ruleIndex !== undefined && child.getChildCount() === 1) {
|
|
77
|
+
const grandchild = child.getChild(0);
|
|
78
|
+
if (grandchild && grandchild.ruleIndex !== undefined)
|
|
79
|
+
node.children[i] = grandchild;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
if (currentctx.children) reducer(currentctx);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// -------------------------------------------------------------------------
|
|
88
|
+
// _insertNode — rewire parse tree (MLR un-inlining)
|
|
89
|
+
// -------------------------------------------------------------------------
|
|
90
|
+
|
|
91
|
+
_insertNode(currentctx, contextTypeName) {
|
|
92
|
+
return;
|
|
93
|
+
const CtxCls = this.constructor[contextTypeName];
|
|
94
|
+
if (!CtxCls) return;
|
|
95
|
+
const inserted = new CtxCls(currentctx, currentctx.invokingState);
|
|
96
|
+
inserted.children = currentctx.children ? [...currentctx.children] : [];
|
|
97
|
+
currentctx.children = [inserted];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
AsInvocationExpression(currentctx) { this._insertNode(currentctx, "Invocation_expressionContext"); }
|
|
101
|
+
AsElementAccess(currentctx) { this._insertNode(currentctx, "Element_accessContext"); }
|
|
102
|
+
AsMemberAccess(currentctx) { this._insertNode(currentctx, "Member_accessContext"); }
|
|
103
|
+
AsNullConditionalMemberAccess(currentctx) { this._insertNode(currentctx, "Null_conditional_member_accessContext"); }
|
|
104
|
+
AsNullConditionalElementAccess(currentctx) { this._insertNode(currentctx, "Null_conditional_element_accessContext"); }
|
|
105
|
+
AsPostIncrementExpression(currentctx) { this._insertNode(currentctx, "Post_increment_expressionContext"); }
|
|
106
|
+
AsPostDecrementExpression(currentctx) { this._insertNode(currentctx, "Post_decrement_expressionContext"); }
|
|
107
|
+
AsNullForgivingExpression(currentctx) { this._insertNode(currentctx, "Null_forgiving_expressionContext"); }
|
|
108
|
+
AsPointerMemberAccess(currentctx) { this._insertNode(currentctx, "Pointer_member_accessContext"); }
|
|
109
|
+
|
|
110
|
+
// -------------------------------------------------------------------------
|
|
111
|
+
// ElementAccessSemanticCheck
|
|
112
|
+
// -------------------------------------------------------------------------
|
|
113
|
+
|
|
114
|
+
ElementAccessSemanticCheck(currentctx) {
|
|
115
|
+
const ruleNames = this.ruleNames;
|
|
116
|
+
const rIdx = (name) => ruleNames.indexOf(name);
|
|
117
|
+
|
|
118
|
+
const rulePrimaryExpression = rIdx("primary_expression");
|
|
119
|
+
const ruleElementAccess = rIdx("element_access");
|
|
120
|
+
const rulePointerElementAccess = rIdx("pointer_element_access");
|
|
121
|
+
const ruleNullConditionalElementAccess = rIdx("null_conditional_element_access");
|
|
122
|
+
const ruleArrayCreationExpression = rIdx("array_creation_expression");
|
|
123
|
+
const ruleStackallocExpression = rIdx("stackalloc_expression");
|
|
124
|
+
|
|
125
|
+
if (!currentctx || currentctx.ruleIndex !== rulePrimaryExpression
|
|
126
|
+
|| currentctx.getChildCount() !== 1) return;
|
|
127
|
+
|
|
128
|
+
const childRule = currentctx.getChild(0);
|
|
129
|
+
if (!childRule || childRule.ruleIndex === undefined) return;
|
|
130
|
+
|
|
131
|
+
const childRuleIndex = childRule.ruleIndex;
|
|
132
|
+
const childChildCount = childRule.getChildCount();
|
|
133
|
+
|
|
134
|
+
if (childRuleIndex === ruleElementAccess || childRuleIndex === rulePointerElementAccess) {
|
|
135
|
+
if (childChildCount !== 4) return;
|
|
136
|
+
} else if (childRuleIndex === ruleNullConditionalElementAccess) {
|
|
137
|
+
if (childChildCount !== 5) return;
|
|
138
|
+
} else return;
|
|
139
|
+
|
|
140
|
+
const accessTarget = childRule.getChild(0);
|
|
141
|
+
if (!accessTarget || accessTarget.ruleIndex === undefined) return;
|
|
142
|
+
if (accessTarget.ruleIndex !== rulePrimaryExpression || accessTarget.getChildCount() === 0) return;
|
|
143
|
+
|
|
144
|
+
const lhsTarget = accessTarget.getChild(0);
|
|
145
|
+
if (!lhsTarget || lhsTarget.ruleIndex === undefined) return;
|
|
146
|
+
|
|
147
|
+
if (lhsTarget.ruleIndex !== ruleArrayCreationExpression
|
|
148
|
+
&& lhsTarget.ruleIndex !== ruleStackallocExpression) return;
|
|
149
|
+
|
|
150
|
+
const lhsLast = lhsTarget.stop;
|
|
151
|
+
const lhsLastType = lhsLast ? lhsLast.type : -1;
|
|
152
|
+
|
|
153
|
+
if (lhsLastType === CSharpLexer.TK_RBRACE) return;
|
|
154
|
+
|
|
155
|
+
if (lhsLastType !== CSharpLexer.TK_RBRACK) {
|
|
156
|
+
process.stderr.write(
|
|
157
|
+
`${lhsLast.line}:${lhsLast.column} Error: Unexpected LHS last token ${lhsLast.text} (${lhsLastType}).\n`);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const childRuleName = ruleNames[childRuleIndex];
|
|
162
|
+
const lhsRuleName = ruleNames[lhsTarget.ruleIndex];
|
|
163
|
+
const childPrefix = "AEIOUaeiou".includes(childRuleName[0]) ? "an" : "a";
|
|
164
|
+
const lhsPrefix = "AEIOUaeiou".includes(lhsRuleName[0]) ? "an" : "a";
|
|
165
|
+
|
|
166
|
+
this._notifySemanticError(lhsLast.line, lhsLast.column,
|
|
167
|
+
`LHS of ${childPrefix} ${childRuleName} cannot be ${lhsPrefix} ${lhsRuleName} unless it has an initializer`);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// =========================================================================
|
|
171
|
+
// Scope management
|
|
172
|
+
// =========================================================================
|
|
173
|
+
|
|
174
|
+
EnterNamespaceScope() { this.symTable.enterScope(CSharpScopeKind.Namespace); }
|
|
175
|
+
EnterTypeScope() { this.symTable.enterScope(CSharpScopeKind.Type); }
|
|
176
|
+
EnterBlockScope() { this.symTable.enterScope(CSharpScopeKind.Block); }
|
|
177
|
+
ExitCurrentScope() { this.symTable.exitScope(); }
|
|
178
|
+
|
|
179
|
+
// =========================================================================
|
|
180
|
+
// Grammar actions — using directive, type parameter, variable declarator
|
|
181
|
+
// =========================================================================
|
|
182
|
+
|
|
183
|
+
OnTypeParameter() {
|
|
184
|
+
const ctx = this._ctx;
|
|
185
|
+
if (!ctx) return;
|
|
186
|
+
const name = ctx.getChild(ctx.getChildCount() - 1).getText();
|
|
187
|
+
this.symTable.declareTypeParam(name);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
OnUsingAliasDirective() {
|
|
191
|
+
const ctx = this._ctx;
|
|
192
|
+
if (!ctx) return;
|
|
193
|
+
this.symTable.declareAlias(ctx.getChild(1).getText(), ctx.getChild(3).getText());
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
OnUsingNamespaceDirective() {
|
|
197
|
+
const ctx = this._ctx;
|
|
198
|
+
if (!ctx) return;
|
|
199
|
+
this.symTable.importNamespace(ctx.getChild(1).getText());
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
BeginVariableDeclaration() {
|
|
203
|
+
const ctx = this._ctx;
|
|
204
|
+
if (!ctx) return;
|
|
205
|
+
this._pendingVarType = ctx.getChild(ctx.getChildCount() - 1).getText() || '?';
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
OnVariableDeclarator() {
|
|
209
|
+
const ctx = this._ctx;
|
|
210
|
+
if (!ctx) return;
|
|
211
|
+
const id = ctx.getChild(ctx.getChildCount() - 1).getText();
|
|
212
|
+
this.symTable.declareVariable(id, this._pendingVarType);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// =========================================================================
|
|
216
|
+
// Semantic predicates
|
|
217
|
+
// =========================================================================
|
|
218
|
+
|
|
219
|
+
IsCastExpressionAhead() {
|
|
220
|
+
const tok = this._input.LT(2);
|
|
221
|
+
if (!tok) return true;
|
|
222
|
+
const sym = this.symTable.currentScope.lookupChain(tok.text);
|
|
223
|
+
return sym === null || sym.kind !== CSharpSymbolKind.Variable;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
IsTypeParameterName() {
|
|
227
|
+
const tok = this._input.LT(1);
|
|
228
|
+
if (!tok) return false;
|
|
229
|
+
const sym = this.symTable.currentScope.lookupChain(tok.text);
|
|
230
|
+
return sym !== null && sym.kind === CSharpSymbolKind.TypeParameter;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
IsValueTypeName() {
|
|
234
|
+
const tok = this._input.LT(1);
|
|
235
|
+
if (!tok) return false;
|
|
236
|
+
const vt = new Set([
|
|
237
|
+
CSharpLexer.KW_BOOL, CSharpLexer.KW_BYTE, CSharpLexer.KW_CHAR,
|
|
238
|
+
CSharpLexer.KW_DECIMAL, CSharpLexer.KW_DOUBLE, CSharpLexer.KW_FLOAT,
|
|
239
|
+
CSharpLexer.KW_INT, CSharpLexer.KW_LONG, CSharpLexer.KW_SBYTE,
|
|
240
|
+
CSharpLexer.KW_SHORT, CSharpLexer.KW_UINT, CSharpLexer.KW_ULONG,
|
|
241
|
+
CSharpLexer.KW_USHORT, CSharpLexer.TK_LPAREN,
|
|
242
|
+
]);
|
|
243
|
+
if (vt.has(tok.type)) return true;
|
|
244
|
+
const sym = this.symTable.currentScope.lookupChain(tok.text);
|
|
245
|
+
if (!sym || sym.kind !== CSharpSymbolKind.Type) return false;
|
|
246
|
+
return sym.typeKind === CSharpTypeKind.Struct || sym.typeKind === CSharpTypeKind.Enum;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
IsReferenceTypeName() {
|
|
250
|
+
const tok = this._input.LT(1);
|
|
251
|
+
if (!tok) return true;
|
|
252
|
+
if (tok.type === CSharpLexer.KW_DYNAMIC || tok.type === CSharpLexer.KW_OBJECT ||
|
|
253
|
+
tok.type === CSharpLexer.KW_STRING || tok.type === CSharpLexer.TK_LBRACK) return true;
|
|
254
|
+
const sym = this.symTable.currentScope.lookupChain(tok.text);
|
|
255
|
+
if (!sym) return true;
|
|
256
|
+
if (sym.kind === CSharpSymbolKind.TypeParameter) return false;
|
|
257
|
+
if (sym.kind === CSharpSymbolKind.Type &&
|
|
258
|
+
(sym.typeKind === CSharpTypeKind.Struct || sym.typeKind === CSharpTypeKind.Enum)) return false;
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
IsDelegateTypeName() {
|
|
263
|
+
const tok = this._input.LT(1);
|
|
264
|
+
if (!tok) return false;
|
|
265
|
+
const sym = this.symTable.currentScope.lookupChain(tok.text);
|
|
266
|
+
return sym !== null && sym.kind === CSharpSymbolKind.Type && sym.typeKind === CSharpTypeKind.Delegate;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
IsInterfaceTypeName() {
|
|
270
|
+
const tok = this._input.LT(1);
|
|
271
|
+
if (!tok) return false;
|
|
272
|
+
const sym = this.symTable.currentScope.lookupChain(tok.text);
|
|
273
|
+
return sym !== null && sym.kind === CSharpSymbolKind.Type && sym.typeKind === CSharpTypeKind.Interface;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
IsClassTypeName() {
|
|
277
|
+
const tok = this._input.LT(1);
|
|
278
|
+
if (!tok) return true;
|
|
279
|
+
if (tok.type === CSharpLexer.KW_OBJECT || tok.type === CSharpLexer.KW_STRING) return true;
|
|
280
|
+
const sym = this.symTable.currentScope.lookupChain(tok.text);
|
|
281
|
+
if (!sym) return true;
|
|
282
|
+
if (sym.kind !== CSharpSymbolKind.Type) return true;
|
|
283
|
+
return sym.typeKind !== CSharpTypeKind.Interface && sym.typeKind !== CSharpTypeKind.Delegate;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
_classBaseTypeCheck(wantInterface) {
|
|
287
|
+
const tok = this._input.LT(2);
|
|
288
|
+
if (!tok) return !wantInterface;
|
|
289
|
+
if (tok.type === CSharpLexer.KW_OBJECT || tok.type === CSharpLexer.KW_STRING) return !wantInterface;
|
|
290
|
+
const sym = this.symTable.currentScope.lookupChain(tok.text);
|
|
291
|
+
if (!sym || sym.kind !== CSharpSymbolKind.Type) return !wantInterface;
|
|
292
|
+
const isIface = sym.typeKind === CSharpTypeKind.Interface;
|
|
293
|
+
return wantInterface ? isIface : !isIface;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
IsClassBaseInterfaceList() { return this._classBaseTypeCheck(true); }
|
|
297
|
+
IsClassBaseClassType() { return this._classBaseTypeCheck(false); }
|
|
298
|
+
|
|
299
|
+
IsDeclarationPatternAhead() {
|
|
300
|
+
// Heuristic lookahead (avoids stream corruption from Parser constructor
|
|
301
|
+
// reset() and BailErrorStrategy.sync() silently consuming mismatched tokens):
|
|
302
|
+
// A declaration_pattern is "type simple_designation".
|
|
303
|
+
// If LT(1) is a value-type keyword, check LT(2) is a designator.
|
|
304
|
+
// If LT(1) is an identifier known to be a type, check LT(2) likewise.
|
|
305
|
+
// Otherwise (string/number literals, unknown names) it is a constant_pattern.
|
|
306
|
+
const tok1 = this._input.LT(1);
|
|
307
|
+
if (!tok1) return false;
|
|
308
|
+
const vt = new Set([CSharpLexer.KW_BOOL, CSharpLexer.KW_BYTE, CSharpLexer.KW_CHAR,
|
|
309
|
+
CSharpLexer.KW_DECIMAL, CSharpLexer.KW_DOUBLE, CSharpLexer.KW_FLOAT,
|
|
310
|
+
CSharpLexer.KW_INT, CSharpLexer.KW_LONG, CSharpLexer.KW_SBYTE,
|
|
311
|
+
CSharpLexer.KW_SHORT, CSharpLexer.KW_UINT, CSharpLexer.KW_ULONG,
|
|
312
|
+
CSharpLexer.KW_USHORT]);
|
|
313
|
+
if (vt.has(tok1.type)) {
|
|
314
|
+
const tok2 = this._input.LT(2);
|
|
315
|
+
return tok2 !== null && (tok2.type === CSharpLexer.Simple_Identifier || tok2.text === '_');
|
|
316
|
+
}
|
|
317
|
+
if (tok1.type !== CSharpLexer.Simple_Identifier) return false;
|
|
318
|
+
const sym = this.symTable.currentScope.lookupChain(tok1.text);
|
|
319
|
+
const isKnownType = sym !== null && sym.kind === CSharpSymbolKind.Type;
|
|
320
|
+
if (!isKnownType) return false;
|
|
321
|
+
const tok2 = this._input.LT(2);
|
|
322
|
+
return tok2 !== null && (tok2.type === CSharpLexer.Simple_Identifier || tok2.text === '_');
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
IsConstantPatternAhead() { return !this.IsDeclarationPatternAhead(); }
|
|
326
|
+
|
|
327
|
+
IsImplicitlyTypedLocalVariable() {
|
|
328
|
+
const tok = this._input.LT(1);
|
|
329
|
+
if (!tok) return true;
|
|
330
|
+
if (tok.type !== CSharpLexer.KW_VAR) return false;
|
|
331
|
+
const sym = this.symTable.currentScope.lookupChain('var');
|
|
332
|
+
if (sym && sym.kind === CSharpSymbolKind.Type) return false;
|
|
333
|
+
const lt3 = this._input.LT(3);
|
|
334
|
+
if (!lt3 || lt3.text !== '=') return false;
|
|
335
|
+
const lt4 = this._input.LT(4);
|
|
336
|
+
if (lt4 && lt4.text === '{') return false;
|
|
337
|
+
return true;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
IsExplicitlyTypedLocalVariable() {
|
|
341
|
+
const tok = this._input.LT(1);
|
|
342
|
+
if (!tok) return true;
|
|
343
|
+
if (tok.type !== CSharpLexer.KW_VAR) return true;
|
|
344
|
+
const sym = this.symTable.currentScope.lookupChain('var');
|
|
345
|
+
if (sym && sym.kind === CSharpSymbolKind.Type) return true;
|
|
346
|
+
const lt3 = this._input.LT(3);
|
|
347
|
+
if (!lt3 || lt3.text !== '=') return true;
|
|
348
|
+
const lt4 = this._input.LT(4);
|
|
349
|
+
if (lt4 && lt4.text === '{') return true;
|
|
350
|
+
return false;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
IsExplicitlyTypedRefLocalVariable() {
|
|
354
|
+
const tok = this._input.LT(1);
|
|
355
|
+
return tok !== null && tok.type === CSharpLexer.KW_REF;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Gates comma-separated declarators: false when type is 'var' (only one declarator allowed).
|
|
359
|
+
IsLocalVariableDeclaration() {
|
|
360
|
+
const local_var_decl = this._ctx;
|
|
361
|
+
if (!(local_var_decl instanceof CSharpParser.Local_variable_declarationContext)) return true;
|
|
362
|
+
const local_variable_type = local_var_decl.local_variable_type();
|
|
363
|
+
if (local_variable_type == null) return true;
|
|
364
|
+
return local_variable_type.getText() !== "var";
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// =============================================================================
|
|
369
|
+
// Symbol table helpers
|
|
370
|
+
// =============================================================================
|
|
371
|
+
|
|
372
|
+
const CSharpSymbolKind = Object.freeze({
|
|
373
|
+
Type: 'Type', Variable: 'Variable', Namespace: 'Namespace',
|
|
374
|
+
TypeParameter: 'TypeParameter', Alias: 'Alias',
|
|
375
|
+
});
|
|
376
|
+
const CSharpTypeKind = Object.freeze({
|
|
377
|
+
Class: 'Class', Struct: 'Struct', Interface: 'Interface',
|
|
378
|
+
Enum: 'Enum', Delegate: 'Delegate',
|
|
379
|
+
});
|
|
380
|
+
const CSharpScopeKind = Object.freeze({
|
|
381
|
+
Global: 'Global', Namespace: 'Namespace', Type: 'Type',
|
|
382
|
+
Method: 'Method', Block: 'Block',
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
class CSharpScope {
|
|
386
|
+
constructor(kind, parent, name = '') {
|
|
387
|
+
this.kind = kind; this.parent = parent; this.name = name;
|
|
388
|
+
this._symbols = new Map();
|
|
389
|
+
}
|
|
390
|
+
declare(sym) { this._symbols.set(sym.name, sym); }
|
|
391
|
+
lookup(name) { return this._symbols.get(name) ?? null; }
|
|
392
|
+
lookupChain(name) {
|
|
393
|
+
const s = this.lookup(name);
|
|
394
|
+
if (s !== null) return s;
|
|
395
|
+
return this.parent ? this.parent.lookupChain(name) : null;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
const _CS_RESERVED = new Set([
|
|
400
|
+
'abstract','as','base','bool','break','byte','case','catch','char','checked',
|
|
401
|
+
'class','const','continue','decimal','default','delegate','do','double','else',
|
|
402
|
+
'enum','event','explicit','extern','false','finally','fixed','float','for',
|
|
403
|
+
'foreach','goto','if','implicit','in','int','interface','internal','is','lock',
|
|
404
|
+
'long','namespace','new','null','object','operator','out','override','params',
|
|
405
|
+
'private','protected','public','readonly','ref','return','sbyte','sealed','short',
|
|
406
|
+
'sizeof','stackalloc','static','string','struct','switch','this','throw','true',
|
|
407
|
+
'try','typeof','uint','ulong','unchecked','unsafe','ushort','using','virtual',
|
|
408
|
+
'void','volatile','while',
|
|
409
|
+
]);
|
|
410
|
+
|
|
411
|
+
function _csIsIdentLike(t) { return t ? /^[A-Za-z_@]/.test(t) : false; }
|
|
412
|
+
|
|
413
|
+
class CSharpSymbolTable {
|
|
414
|
+
constructor() {
|
|
415
|
+
this._knownTypeNames = new Set();
|
|
416
|
+
this._genericArities = new Map();
|
|
417
|
+
this._scopeStack = [];
|
|
418
|
+
this.globalScope = new CSharpScope(CSharpScopeKind.Global, null, '<global>');
|
|
419
|
+
this._scopeStack.push(this.globalScope);
|
|
420
|
+
this._populateBuiltins();
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
get currentScope() { return this._scopeStack[this._scopeStack.length - 1]; }
|
|
424
|
+
|
|
425
|
+
isTypeName(name) {
|
|
426
|
+
const sym = this.currentScope.lookupChain(name);
|
|
427
|
+
if (sym !== null)
|
|
428
|
+
return sym.kind === CSharpSymbolKind.Type ||
|
|
429
|
+
sym.kind === CSharpSymbolKind.TypeParameter ||
|
|
430
|
+
sym.kind === CSharpSymbolKind.Alias;
|
|
431
|
+
return this._knownTypeNames.has(name);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
enterScope(kind, name = '') {
|
|
435
|
+
this._scopeStack.push(new CSharpScope(kind, this.currentScope, name));
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
exitScope() { if (this._scopeStack.length > 1) this._scopeStack.pop(); }
|
|
439
|
+
|
|
440
|
+
declareType(name, kind, arity = 0) {
|
|
441
|
+
this.currentScope.declare({ name, kind: CSharpSymbolKind.Type, typeKind: kind, arity });
|
|
442
|
+
this._knownTypeNames.add(name);
|
|
443
|
+
if (arity > 0) {
|
|
444
|
+
if (!this._genericArities.has(name)) this._genericArities.set(name, new Set());
|
|
445
|
+
this._genericArities.get(name).add(arity);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
declareTypeParam(name) {
|
|
450
|
+
this.currentScope.declare({ name, kind: CSharpSymbolKind.TypeParameter });
|
|
451
|
+
this._knownTypeNames.add(name);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
declareVariable(name, typeRef) {
|
|
455
|
+
this.currentScope.declare({ name, kind: CSharpSymbolKind.Variable, typeRef });
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
declareAlias(alias, target) {
|
|
459
|
+
this.currentScope.declare({ name: alias, kind: CSharpSymbolKind.Alias, target });
|
|
460
|
+
this._knownTypeNames.add(alias);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
importNamespace(ns) {
|
|
464
|
+
this.currentScope.declare({ name: ns, kind: CSharpSymbolKind.Namespace });
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
preScan(tokens) {
|
|
468
|
+
try { tokens.fill(); } catch (e) {}
|
|
469
|
+
const n = tokens.size;
|
|
470
|
+
for (let i = 0; i < n; i++) {
|
|
471
|
+
const tok = tokens.get(i);
|
|
472
|
+
if (tok.channel !== 0) continue;
|
|
473
|
+
const txt = tok.text;
|
|
474
|
+
if (txt === 'class' || txt === 'struct' || txt === 'interface' || txt === 'enum') {
|
|
475
|
+
let j = this._nextDefault(tokens, i + 1, n);
|
|
476
|
+
while (j < n && (tokens.get(j).text === 'partial' || tokens.get(j).text === 'ref'))
|
|
477
|
+
j = this._nextDefault(tokens, j + 1, n);
|
|
478
|
+
if (j < n && _csIsIdentLike(tokens.get(j).text)) {
|
|
479
|
+
const typeName = tokens.get(j).text;
|
|
480
|
+
const [arity, typeParams] = this._countTypeParams(tokens, j + 1, n);
|
|
481
|
+
this._registerType(typeName, arity, typeParams);
|
|
482
|
+
}
|
|
483
|
+
} else if (txt === 'delegate') {
|
|
484
|
+
let j = this._nextDefault(tokens, i + 1, n);
|
|
485
|
+
while (j < n && (tokens.get(j).text === 'ref' || tokens.get(j).text === 'readonly'))
|
|
486
|
+
j = this._nextDefault(tokens, j + 1, n);
|
|
487
|
+
if (j >= n) continue;
|
|
488
|
+
j = this._nextDefault(tokens, j + 1, n);
|
|
489
|
+
if (j < n && tokens.get(j).text === '<') j = this._skipAngled(tokens, j, n);
|
|
490
|
+
while (j < n && (tokens.get(j).text === '[' || tokens.get(j).text === ']' || tokens.get(j).text === ','))
|
|
491
|
+
j = this._nextDefault(tokens, j + 1, n);
|
|
492
|
+
if (j < n && tokens.get(j).text === '?') j = this._nextDefault(tokens, j + 1, n);
|
|
493
|
+
if (j < n && _csIsIdentLike(tokens.get(j).text)) {
|
|
494
|
+
const typeName = tokens.get(j).text;
|
|
495
|
+
const [arity, typeParams] = this._countTypeParams(tokens, j + 1, n);
|
|
496
|
+
this._registerType(typeName, arity, typeParams);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
_registerType(name, arity, typeParams) {
|
|
503
|
+
if (!_CS_RESERVED.has(name)) this._knownTypeNames.add(name);
|
|
504
|
+
if (arity > 0 && !_CS_RESERVED.has(name)) {
|
|
505
|
+
if (!this._genericArities.has(name)) this._genericArities.set(name, new Set());
|
|
506
|
+
this._genericArities.get(name).add(arity);
|
|
507
|
+
}
|
|
508
|
+
for (const tp of typeParams)
|
|
509
|
+
if (_csIsIdentLike(tp) && !_CS_RESERVED.has(tp)) this._knownTypeNames.add(tp);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
_nextDefault(tokens, pos, n) {
|
|
513
|
+
while (pos < n && tokens.get(pos).channel !== 0) pos++;
|
|
514
|
+
return pos;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
_skipAngled(tokens, pos, n) {
|
|
518
|
+
let depth = 1, i = this._nextDefault(tokens, pos + 1, n);
|
|
519
|
+
while (i < n && depth > 0) {
|
|
520
|
+
const t = tokens.get(i).text;
|
|
521
|
+
if (t === '<') depth++; else if (t === '>') depth--;
|
|
522
|
+
i = this._nextDefault(tokens, i + 1, n);
|
|
523
|
+
}
|
|
524
|
+
return i;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
_countTypeParams(tokens, pos, n) {
|
|
528
|
+
const p = this._nextDefault(tokens, pos, n);
|
|
529
|
+
if (p >= n || tokens.get(p).text !== '<') return [0, []];
|
|
530
|
+
let depth = 1, arity = 1;
|
|
531
|
+
const names = [];
|
|
532
|
+
let i = this._nextDefault(tokens, p + 1, n);
|
|
533
|
+
while (i < n && depth > 0) {
|
|
534
|
+
const t = tokens.get(i).text;
|
|
535
|
+
if (t === '<') depth++;
|
|
536
|
+
else if (t === '>') depth--;
|
|
537
|
+
else if (t === ',' && depth === 1) arity++;
|
|
538
|
+
else if (depth === 1 && _csIsIdentLike(t)) names.push(t);
|
|
539
|
+
i = this._nextDefault(tokens, i + 1, n);
|
|
540
|
+
}
|
|
541
|
+
return depth === 0 ? [arity, names] : [0, []];
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
_populateBuiltins() {
|
|
545
|
+
for (const t of [
|
|
546
|
+
'bool','byte','sbyte','char','decimal','double','float','int','uint',
|
|
547
|
+
'long','ulong','short','ushort','object','string','void','dynamic',
|
|
548
|
+
'Boolean','Byte','SByte','Char','Decimal','Double','Single',
|
|
549
|
+
'Int16','Int32','Int64','UInt16','UInt32','UInt64',
|
|
550
|
+
'IntPtr','UIntPtr','Object','String','Void',
|
|
551
|
+
'Guid','DateTime','DateTimeOffset','TimeSpan','Uri',
|
|
552
|
+
'Exception','Type','Enum','Delegate','MulticastDelegate',
|
|
553
|
+
'Attribute','Math','Convert','Console','Environment',
|
|
554
|
+
'List','IList','IEnumerable','IEnumerator','ICollection',
|
|
555
|
+
'IReadOnlyList','IReadOnlyCollection','IReadOnlyDictionary',
|
|
556
|
+
'Dictionary','IDictionary','SortedDictionary','SortedList',
|
|
557
|
+
'HashSet','SortedSet','Queue','Stack','LinkedList','LinkedListNode',
|
|
558
|
+
'Func','Action','Predicate','Comparison','Converter',
|
|
559
|
+
'Task','ValueTask','Nullable',
|
|
560
|
+
'IAsyncEnumerable','IAsyncEnumerator',
|
|
561
|
+
'Span','ReadOnlySpan','Memory','ReadOnlyMemory',
|
|
562
|
+
'KeyValuePair','Tuple',
|
|
563
|
+
'ImmutableArray','ImmutableList','ImmutableDictionary','ImmutableHashSet',
|
|
564
|
+
'Lazy','WeakReference','EventHandler',
|
|
565
|
+
'IEqualityComparer','IComparer','EqualityComparer','Comparer',
|
|
566
|
+
'ConcurrentDictionary','ConcurrentQueue','ConcurrentStack','ConcurrentBag',
|
|
567
|
+
]) this._knownTypeNames.add(t);
|
|
568
|
+
}
|
|
569
|
+
}
|