Skip to content

Commit 860d7e8

Browse files
nixel2007claude
andcommitted
SDBL: virtual table colouring is structural, not lexical
Virtual-table names like 'Остатки' / 'СрезПоследних' / 'Обороты' double as legitimate query aliases — code like `КАК Остатки … ВЫБРАТЬ Остатки.Количество` is normal SDBL. The previous global VtKw specializer painted every such reference in the className/Namespace yellow even when the user clearly meant an alias, which is exactly what bsl-parser sidesteps with its DOT_MODE lexer state. Replaced the lexer-level recognition with a structural MdoRef rule: MdoRef { MdoKw (!mdoTail Dot Identifier)* } The dotted tail is greedy (the !mdoTail precedence biases shift over reduce) so 'РегистрНакопления.ТоварыНаСкладах.Остатки' parses as a single MdoRef with two tail components. The styleTags now colours 'MdoRef/Identifier' as className — that's the only place where 'Остатки' lights up yellow now. Aliases and field-access references stay plain variableName. Side cleanup: - Removed the VtKw term from the SDBL specializer table, terms file and Parameter/sdblName alternative. - Removed the corresponding 'VtKw → t.className' styleTag entry. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent f1423fe commit 860d7e8

4 files changed

Lines changed: 44 additions & 33 deletions

File tree

src/index.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,16 @@ export const sdblLanguage = sdblParser.configure({
103103
FuncKw: t.function(t.keyword),
104104
// Built-in type names (Булево/Число/Строка used in CAST etc.).
105105
TypeKw: t.typeName,
106-
// Metadata-object roots (Справочник/Документ/РегистрСведений/…). The
107-
// bsl-language-server tags these as Namespace at the LSP level.
106+
// Metadata-object roots (Справочник/Документ/РегистрСведений/…).
107+
// bsl-language-server tags them as Namespace at the LSP level.
108108
MdoKw: t.namespace,
109-
// Virtual table suffixes (.Остатки, .СрезПоследних, .Обороты). Tagged
110-
// as className so themes can distinguish them from base metadata.
111-
VtKw: t.className,
109+
// Identifier components inside an MdoRef path become Class — the
110+
// table name (`Контрагенты` in `Справочник.Контрагенты`) and the
111+
// optional virtual-table suffix (`Остатки` in
112+
// `РегистрНакопления.ТоварыНаСкладах.Остатки`) both qualify. Outside
113+
// of MdoRef the same words stay as plain variableName so query
114+
// aliases like `КАК Остатки` don't get the metadata-class colour.
115+
"MdoRef/Identifier": t.className,
112116
// Field accessors (ТочкаМаршрута, ROUTEPOINT) — propertyName tier.
113117
FieldKw: t.propertyName,
114118
// Literals.
@@ -126,7 +130,7 @@ export const sdblLanguage = sdblParser.configure({
126130
// tag so the parameter renders as one visual block. We enumerate the
127131
// keyword categories because @lezer/highlight resolves at the leaf
128132
// level and the global FuncKw / StmtKw / etc. tags would otherwise win.
129-
"Parameter/Ampersand Parameter/Identifier Parameter/StmtKw Parameter/OpKw Parameter/FuncKw Parameter/TypeKw Parameter/MdoKw Parameter/VtKw Parameter/FieldKw Parameter/BoolLit Parameter/NullLit Parameter/UndefinedLit": t.special(t.variableName),
133+
"Parameter/Ampersand Parameter/Identifier Parameter/StmtKw Parameter/OpKw Parameter/FuncKw Parameter/TypeKw Parameter/MdoKw Parameter/FieldKw Parameter/BoolLit Parameter/NullLit Parameter/UndefinedLit": t.special(t.variableName),
130134
// Punctuation
131135
"LParen RParen": t.paren,
132136
// `{...}` configuration blocks — tag the whole group as t.meta so a

src/sdbl-tokens.ts

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// SDBLLexer.g4`.
99

1010
import {
11-
StmtKw, OpKw, FuncKw, TypeKw, MdoKw, VtKw, FieldKw,
11+
StmtKw, OpKw, FuncKw, TypeKw, MdoKw, FieldKw,
1212
BoolLit, NullLit, UndefinedLit
1313
} from "./sdbl.grammar.terms"
1414

@@ -166,27 +166,20 @@ const MDO_WORDS = [
166166
"externaldatasource", "внешнийисточникданных"
167167
]
168168

169-
// Virtual table suffixes that appear after the metadata-object name:
170-
// e.g. `РегистрНакопления.Товары.Остатки`, `РегистрСведений.Курсы.СрезПоследних`.
171-
const VT_WORDS = [
172-
"balance", "остатки",
173-
"balanceandturnovers", "остаткииобороты",
174-
"boundaries", "границы",
175-
"drcrturnovers", "оборотыдткт",
176-
"extdimensions", "субконто",
177-
"recordswithextdimensions", "движенияссубконто",
178-
"scheduledata", "данныеграфика",
179-
"slicefirst", "срезпервых",
180-
"slicelast", "срезпоследних",
181-
"taskbyperformer", "задачипоисполнителю",
182-
"turnovers", "обороты",
183-
"actualactionperiod", "фактическийпериоддействия",
184-
"table", "таблица",
185-
"cube", "куб",
186-
"dimensiontable", "таблицаизмерения"
187-
]
169+
// Virtual-table suffixes are NOT globally specialized. Words like "Остатки",
170+
// "Обороты", "СрезПоследних" double as legitimate query aliases (e.g.
171+
// `ВЫБРАТЬ Остатки.Количество ИЗ ... КАК Остатки`), and globally tagging
172+
// them as VtKw paints those alias references yellow even when the user
173+
// never intended a metadata-object reference. ANTLR's BSL parser side-steps
174+
// this with a lexer DOT_MODE that only recognises BALANCE_VT etc. right
175+
// after a dot inside a metadata path; we cannot replicate that mode purely
176+
// at the specializer level, so we let the structural MdoRef rule in the
177+
// grammar collect them as ordinary Identifiers and rely on contextual
178+
// styleTags (MdoRef/Identifier → className) to colour them when they sit
179+
// at the tail of a metadata path.
188180

189-
// Special field accessors (route points etc.).
181+
// Special field accessors (route points etc.). These are unambiguous —
182+
// `ТочкаМаршрута` doesn't double as an alias name in real queries.
190183
const FIELD_WORDS = [
191184
"routepoint", "точкамаршрута", "точки"
192185
]
@@ -197,7 +190,6 @@ for (const w of OP_WORDS) MAP[w] = OpKw
197190
for (const w of FUNC_WORDS) MAP[w] = FuncKw
198191
for (const w of TYPE_WORDS) MAP[w] = TypeKw
199192
for (const w of MDO_WORDS) MAP[w] = MdoKw
200-
for (const w of VT_WORDS) MAP[w] = VtKw
201193
for (const w of FIELD_WORDS) MAP[w] = FieldKw
202194

203195
// Literals

src/sdbl.grammar

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ fragment {
2222
OpKw |
2323
FuncKw |
2424
TypeKw |
25-
MdoKw |
26-
VtKw |
25+
MdoRef |
2726
FieldKw |
2827
BoolLit |
2928
NullLit |
@@ -40,6 +39,18 @@ fragment {
4039
Punct
4140
}
4241

42+
// Metadata-object reference path: `Справочник.Контрагенты`,
43+
// `РегистрНакопления.ТоварыНаСкладах.Остатки`, etc. Only inside this
44+
// structure do the trailing identifier components mean "table name" and
45+
// "virtual table" — at the lexer level we keep them as plain Identifier
46+
// so they don't get the namespace/class colour in other positions
47+
// (e.g. an alias `Остатки` defined via `КАК Остатки`).
48+
//
49+
// `!mdoTail` biases the parser to shift each `Dot Identifier` into the
50+
// current MdoRef rather than reduce early (which would leak the dot into
51+
// a sibling Punct(Dot) and split the path).
52+
MdoRef { MdoKw (!mdoTail Dot Identifier)* }
53+
4354
ParenGroup { LParen fragment* RParen }
4455

4556
// `{...}` blocks in SDBL carry data-composition-system parameters that the
@@ -57,7 +68,7 @@ BraceGroup { LBrace fragment* RBrace }
5768
// stops being recognised.
5869
Parameter { Ampersand sdblName }
5970
sdblName {
60-
Identifier | StmtKw | OpKw | FuncKw | TypeKw | MdoKw | VtKw | FieldKw |
71+
Identifier | StmtKw | OpKw | FuncKw | TypeKw | MdoKw | FieldKw |
6172
BoolLit | NullLit | UndefinedLit
6273
}
6374

@@ -68,6 +79,12 @@ Punct { Comma | Semicolon | Colon | Dot | Hash }
6879

6980
// ---- Skipping ----
7081

82+
@precedence {
83+
// Used by MdoRef to prefer extending the path with another `Dot
84+
// Identifier` over reducing the MdoRef early.
85+
mdoTail @left
86+
}
87+
7188
@skip { space | LineComment }
7289

7390
// ---- Tokens ----
@@ -138,7 +155,6 @@ Punct { Comma | Semicolon | Colon | Dot | Hash }
138155
FuncKw,
139156
TypeKw,
140157
MdoKw,
141-
VtKw,
142158
FieldKw,
143159
BoolLit,
144160
NullLit,

src/sdbl.grammar.terms.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ export const OpKw: number
66
export const FuncKw: number
77
export const TypeKw: number
88
export const MdoKw: number
9-
export const VtKw: number
109
export const FieldKw: number
1110
export const BoolLit: number
1211
export const NullLit: number

0 commit comments

Comments
 (0)