Skip to content

Commit 92caac2

Browse files
committed
new parser better error messages
1 parent 20fc8df commit 92caac2

File tree

6 files changed

+153
-97
lines changed

6 files changed

+153
-97
lines changed

exampleVault/examples.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Domestic_tasks:
66
- Lunch 🍲
77
Meditate: 100
88
Slept: 00:00
9-
select: option a
9+
select: option c
1010
nested:
1111
---
1212

src/parsers/newInputFieldParser/InputFieldParser.ts

Lines changed: 105 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import { AbstractInputFieldArgument } from '../../inputFieldArguments/AbstractIn
88
import { InputFieldArgumentFactory } from '../../inputFieldArguments/InputFieldArgumentFactory';
99
import { isTruthy } from '../../utils/Utils';
1010
import { getEntryFromContext, getSubContextArrayFromContext, hasContextEntry, ValidationContext, ValidationGraph } from './validationGraph/ValidationGraph';
11-
import { TL_C_Enumeration, TL_C_Literal, TL_C_Loop, TL_C_Optional, TL_C_Or } from './validationGraph/treeLayout/ComplexTreeLayout';
11+
import { ComplexTreeLayout, TL_C_Enumeration, TL_C_Literal, TL_C_Loop, TL_C_Optional, TL_C_Or } from './validationGraph/treeLayout/ComplexTreeLayout';
1212
import { ParsingError } from './ParsingError';
1313
import { InputFieldParsingTreeParser } from './InputFieldParsingTreeParser';
1414
import { Abstract_PT_Node, ParsingTree, PT_Closure, PT_Element_Type, PT_Literal } from './ParsingTree';
1515
import { InputFieldToken, InputFieldTokenizer, InputFieldTokenType } from './InputFieldTokenizer';
1616

1717
export class DeclarationParser {
18-
plugin: IPlugin;
18+
inputFieldParser: NewInputFieldDeclarationParser;
1919
filePath: string;
2020

2121
fullDeclaration: string;
@@ -28,15 +28,20 @@ export class DeclarationParser {
2828
argumentContainer: InputFieldArgumentContainer;
2929
errorCollection: ErrorCollection;
3030

31+
fullDeclarationValidationGraph: ValidationGraph;
32+
declarationValidationGraph: ValidationGraph;
33+
partialDeclarationValidationGraph: ValidationGraph;
34+
templateValidationGraph: ValidationGraph;
35+
3136
constructor(
32-
plugin: IPlugin,
37+
inputFieldParser: NewInputFieldDeclarationParser,
3338
filePath: string,
3439
fullDeclaration: string,
3540
tokens: InputFieldToken[],
3641
parsingTree: ParsingTree,
3742
errorCollection: ErrorCollection
3843
) {
39-
this.plugin = plugin;
44+
this.inputFieldParser = inputFieldParser;
4045
this.filePath = filePath;
4146
this.fullDeclaration = fullDeclaration;
4247
this.tokens = tokens;
@@ -45,34 +50,55 @@ export class DeclarationParser {
4550

4651
this.type = InputFieldType.INVALID;
4752
this.argumentContainer = new InputFieldArgumentContainer();
48-
}
4953

50-
public parse(): InputFieldDeclaration {
51-
try {
52-
return this.parseDeclaration();
53-
} catch (e) {
54-
this.errorCollection.add(e);
55-
return this.buildDeclaration();
56-
}
57-
}
54+
// Validation Graphs
5855

59-
private parseDeclaration(): InputFieldDeclaration {
6056
// literal.closure or literal.closure.closure
61-
const layoutValidationGraph = new ValidationGraph([
57+
this.fullDeclarationValidationGraph = new ValidationGraph([
6258
new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD, 'INPUT'),
6359
new TL_C_Optional([new TL_C_Literal(PT_Element_Type.CLOSURE, InputFieldTokenType.L_SQUARE, undefined, 'template')]),
6460
new TL_C_Literal(PT_Element_Type.CLOSURE, InputFieldTokenType.L_SQUARE, undefined, 'declaration'),
6561
]);
66-
const validationContext = this.validateNodeAndThrow(this.parsingTree, layoutValidationGraph);
62+
this.fullDeclarationValidationGraph.optimize();
6763

68-
console.log(validationContext);
64+
const inputFieldType_TL_C_Element: TL_C_Literal = new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD, undefined, 'type');
65+
const arguments_TL_C_Element: TL_C_Literal = new TL_C_Literal(PT_Element_Type.CLOSURE, InputFieldTokenType.L_PAREN, undefined, 'arguments');
66+
const bindTarget_TL_C_Elements: ComplexTreeLayout = [
67+
new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.COLON, undefined, 'bindTargetSeparator'), // bind target separator
68+
new TL_C_Optional([
69+
new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD, undefined, 'bindTargetFile'), // file
70+
new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.HASHTAG), // hashtag
71+
]), // optional file and hashtag
72+
new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD, undefined, 'bindTarget'), // first bind target metadata path part
73+
new TL_C_Loop(
74+
[
75+
new TL_C_Or([
76+
[new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD)],
77+
[new TL_C_Literal(PT_Element_Type.CLOSURE, InputFieldTokenType.L_SQUARE)],
78+
]), // either literal or closure or none, in a loop
79+
],
80+
0,
81+
-1
82+
), // the other bind target metadata path part
83+
];
84+
85+
this.declarationValidationGraph = new ValidationGraph([
86+
inputFieldType_TL_C_Element,
87+
new TL_C_Optional([arguments_TL_C_Element]), // optional arguments
88+
new TL_C_Optional(bindTarget_TL_C_Elements),
89+
]);
90+
this.declarationValidationGraph.optimize();
6991

70-
if (hasContextEntry(validationContext, 'template')) {
71-
this.parseTemplate(getEntryFromContext<PT_Closure>(validationContext, 'template').element);
72-
}
73-
this.parsePureDeclaration(getEntryFromContext<PT_Closure>(validationContext, 'declaration').element);
92+
this.partialDeclarationValidationGraph = new ValidationGraph([
93+
new TL_C_Optional([inputFieldType_TL_C_Element]), // input field type
94+
new TL_C_Optional([arguments_TL_C_Element]), // optional arguments
95+
new TL_C_Optional(bindTarget_TL_C_Elements),
96+
]);
97+
this.partialDeclarationValidationGraph.optimize();
7498

75-
return this.buildDeclaration();
99+
this.templateValidationGraph = new ValidationGraph([
100+
new TL_C_Optional([new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD, undefined, 'templateName')]),
101+
]);
76102
}
77103

78104
private buildDeclaration(): InputFieldDeclaration {
@@ -86,39 +112,50 @@ export class DeclarationParser {
86112
};
87113
}
88114

115+
public parse(): InputFieldDeclaration {
116+
try {
117+
return this.parseFullDeclaration();
118+
} catch (e) {
119+
this.errorCollection.add(e);
120+
return this.buildDeclaration();
121+
}
122+
}
123+
124+
private parseFullDeclaration(): InputFieldDeclaration {
125+
const validationContext = this.validateNodeAndThrow(this.parsingTree, this.fullDeclarationValidationGraph);
126+
127+
if (hasContextEntry(validationContext, 'template')) {
128+
this.parseTemplate(getEntryFromContext<PT_Closure>(validationContext, 'template').element);
129+
this.parsePartialDeclaration(getEntryFromContext<PT_Closure>(validationContext, 'declaration').element);
130+
} else {
131+
this.parseDeclaration(getEntryFromContext<PT_Closure>(validationContext, 'declaration').element);
132+
}
133+
134+
return this.buildDeclaration();
135+
}
136+
89137
private parseTemplate(closure: PT_Closure): void {
90-
// TODO
138+
const validationContext = this.validateNodeAndThrow(closure, this.templateValidationGraph);
91139
}
92140

93-
private parsePureDeclaration(closure: PT_Closure): void {
94-
const layoutValidationGraph = new ValidationGraph([
95-
new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD, undefined, 'type'), // input field type
96-
new TL_C_Optional([new TL_C_Literal(PT_Element_Type.CLOSURE, InputFieldTokenType.L_PAREN, undefined, 'arguments')]), // optional arguments
97-
new TL_C_Optional([
98-
new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.COLON, undefined, 'bindTargetSeparator'), // bind target separator
99-
new TL_C_Optional([
100-
new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD, undefined, 'bindTargetFile'), // file
101-
new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.HASHTAG), // hashtag
102-
]), // optional file and hashtag
103-
new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD, undefined, 'bindTarget'), // first bind target metadata path part
104-
new TL_C_Loop(
105-
[
106-
new TL_C_Or([
107-
[new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD)],
108-
[new TL_C_Literal(PT_Element_Type.CLOSURE, InputFieldTokenType.L_SQUARE)],
109-
]), // either literal or closure or none, in a loop
110-
],
111-
0,
112-
-1
113-
), // the other bind target metadata path part
114-
]),
115-
]);
141+
private parsePartialDeclaration(closure: PT_Closure): void {
142+
const validationContext = this.validateNodeAndThrow(closure, this.partialDeclarationValidationGraph);
116143

117-
layoutValidationGraph.optimizeParsingGraph();
144+
if (hasContextEntry(validationContext, 'type')) {
145+
this.type = this.parseInputFieldType(getEntryFromContext<PT_Literal>(validationContext, 'type').element);
146+
}
118147

119-
const validationContext = this.validateNodeAndThrow(closure, layoutValidationGraph);
148+
if (hasContextEntry(validationContext, 'arguments')) {
149+
this.parseArguments(getEntryFromContext<PT_Closure>(validationContext, 'arguments').element);
150+
}
120151

121-
console.log(validationContext);
152+
if (hasContextEntry(validationContext, 'bindTargetSeparator')) {
153+
this.parseBindTarget(closure, getEntryFromContext<PT_Literal>(validationContext, 'bindTargetSeparator').inputIndex);
154+
}
155+
}
156+
157+
private parseDeclaration(closure: PT_Closure): void {
158+
const validationContext = this.validateNodeAndThrow(closure, this.declarationValidationGraph);
122159

123160
this.type = this.parseInputFieldType(getEntryFromContext<PT_Literal>(validationContext, 'type').element);
124161

@@ -173,16 +210,24 @@ export class DeclarationParser {
173210
),
174211
]);
175212

176-
layoutValidationGraph.optimizeParsingGraph();
213+
layoutValidationGraph.optimize();
177214

178215
const validationContext = this.validateNodeAndThrow(closure, layoutValidationGraph);
179216

180-
const inputFieldArguments: { type: InputFieldArgumentType; value: string }[] = getSubContextArrayFromContext(validationContext, 'arguments').map(x => {
217+
const subContextArray = getSubContextArrayFromContext(validationContext, 'arguments');
218+
219+
const inputFieldArguments: { type: InputFieldArgumentType; value: string }[] = [];
220+
221+
for (const x of subContextArray) {
181222
const typeLiteral: PT_Literal = getEntryFromContext<PT_Literal>(x, 'name').element;
182223
const valueClosure: PT_Closure | undefined = getEntryFromContext<PT_Closure>(x, 'value')?.element;
183224

184-
return this.parseArgument(typeLiteral, valueClosure);
185-
});
225+
try {
226+
inputFieldArguments.push(this.parseArgument(typeLiteral, valueClosure));
227+
} catch (e) {
228+
this.errorCollection.add(e);
229+
}
230+
}
186231

187232
this.parseArgumentsIntoContainer(inputFieldArguments);
188233
}
@@ -251,18 +296,7 @@ export class DeclarationParser {
251296
const valRes = validationGraph.validateParsingTreeAndExtractContext(astNode);
252297

253298
if (valRes.acceptedState === undefined) {
254-
const layout = validationGraph.layout;
255-
console.log(astNode, validationGraph, valRes);
256-
257-
throw new ParsingError(
258-
ErrorLevel.ERROR,
259-
'failed to parse',
260-
`Encountered invalid token. Expected token types to be of order ${layout} but received ${astNode.children.map(x => x.type)}.`,
261-
{},
262-
astNode.str,
263-
astNode.getToken(),
264-
'AST Parser'
265-
);
299+
throw valRes.validationError;
266300
}
267301

268302
return valRes.acceptedState.context;
@@ -294,7 +328,7 @@ export class DeclarationParser {
294328
}
295329

296330
throw new ParsingError(
297-
ErrorLevel.ERROR,
331+
ErrorLevel.WARNING,
298332
'failed to parse',
299333
`Encountered invalid token. Expected token to be an input field argument type but received '${astLiteral.toLiteral()}'.`,
300334
{},
@@ -320,7 +354,7 @@ export class NewInputFieldDeclarationParser {
320354
const tokens = tokenizer.getTokens();
321355
const parsingTreeParser = new InputFieldParsingTreeParser(fullDeclaration, tokens);
322356
const parsingTree = parsingTreeParser.parse();
323-
const declarationParser = new DeclarationParser(this.plugin, filePath, fullDeclaration, tokens, parsingTree, errorCollection);
357+
const declarationParser = new DeclarationParser(this, filePath, fullDeclaration, tokens, parsingTree, errorCollection);
324358

325359
return declarationParser.parse();
326360
} catch (e) {
@@ -337,4 +371,8 @@ export class NewInputFieldDeclarationParser {
337371
errorCollection: errorCollection,
338372
};
339373
}
374+
375+
public parseTemplates(templates: string): void {
376+
// TODO: rewrite the templates to be multiple input fields (like a table)
377+
}
340378
}

src/parsers/newInputFieldParser/ParsingTree.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ export abstract class Abstract_PT_Node extends Abstract_PT_El {
5959
public toLiteral(): string {
6060
return this.children.map(x => x.toLiteral()).join('');
6161
}
62+
63+
abstract getRange(): Range;
6264
}
6365

6466
export class PT_Literal extends Abstract_PT_El {
@@ -161,6 +163,13 @@ export class ParsingTree extends Abstract_PT_Node {
161163
.map(x => ' ' + x)
162164
.join('\n')}`;
163165
}
166+
167+
public getRange(): Range {
168+
return {
169+
from: this.tokens[0]?.range.from ?? 0,
170+
to: this.tokens[this.tokens.length - 1]?.range.to ?? 0,
171+
};
172+
}
164173
}
165174

166175
export function split_PT_Elements(list: PT_Element[], tokenType: InputFieldTokenType): PT_Element[][] {

0 commit comments

Comments
 (0)