Skip to content

Commit 20fc8df

Browse files
committed
fixed some bugs and start of error generation
1 parent ee6446b commit 20fc8df

File tree

8 files changed

+215
-115
lines changed

8 files changed

+215
-115
lines changed

exampleVault/examples.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
slider1: 8
2+
slider1: 7
33
suggest: test
44
toggle1: false
55
Domestic_tasks:
@@ -23,7 +23,7 @@ nested:
2323
> ```
2424
2525
## Nested data
26-
`INPUT[text:nested["object"]]`
26+
` INPUT[text:nested["object"]]`
2727
2828
---
2929
@@ -70,6 +70,7 @@ Lorem ipsum dolor sit amet, `INPUT[date():other note#date]` consectetur adipisci
7070
## Error Messages
7171
- `INPUT[text():meta bind/nonExistantFile#title]`
7272
- `INPUT[slider(nonExistantArgument)]`
73+
- `INPUT[slider]`
7374

7475
- `INPUT[inlineSelect(option(option a),option(option b),option(option c),option(option d)):select]`
7576

src/parsers/newInputFieldParser/InputFieldTokenizer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export const InputFieldClosures: Closure<InputFieldTokenType>[] = [
2828

2929
export interface InputFieldToken extends AbstractToken<InputFieldTokenType> {}
3030

31-
function createToken<TokenType extends string>(type: TokenType, literal: string, from: number, to: number): AbstractToken<TokenType> {
31+
export function createToken<TokenType extends string>(type: TokenType, literal: string, from: number, to: number): AbstractToken<TokenType> {
3232
return {
3333
type: type,
3434
literal: literal,

src/parsers/newInputFieldParser/ParsingTree.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ export enum PT_Element_Type {
77
LITERAL = 'LITERAL',
88
CLOSURE = 'CLOSURE',
99
ROOT = 'ROOT',
10+
11+
SPECIAL_END = 'SPECIAL_END',
1012
}
1113

1214
export abstract class Abstract_PT_El {
@@ -68,6 +70,10 @@ export class PT_Literal extends Abstract_PT_El {
6870
this.token = token;
6971
}
7072

73+
public getRange(): Range {
74+
return this.token.range;
75+
}
76+
7177
public getToken(): InputFieldToken {
7278
return this.token;
7379
}

src/parsers/newInputFieldParser/validationGraph/VG_Node.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,15 @@ export class VG_Node {
99
final: boolean;
1010
loopBound: TL_LoopBound;
1111
transitions: VG_Transition[];
12-
13-
// readonly contextKey: string | undefined;
12+
// distanceToFinalNode: number;
1413

1514
constructor(index: number, transitionConstraint: VG_Transition_Constraint | undefined, final: boolean = false, loopBound?: TL_LoopBound | undefined) {
1615
this.index = index;
1716
this.transitionConstraint = transitionConstraint;
1817
this.final = final;
1918
this.loopBound = loopBound ?? new TL_LoopBound(-1, -1);
2019
this.transitions = [];
21-
// this.contextKey = contextKey;
20+
// this.distanceToFinalNode = Number.MAX_VALUE;
2221
}
2322

2423
public createTransition(

src/parsers/newInputFieldParser/validationGraph/ValidationGraph.ts

Lines changed: 88 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import { VG_Transition_Constraint } from './VG_Transition_Constraint';
33
import { VG_Transition } from './VG_Transition';
44
import { VG_Node } from './VG_Node';
55
import { ContextActionType } from './ContextActions';
6-
import { Abstract_PT_Node, PT_Element } from '../ParsingTree';
6+
import { Abstract_PT_Node, PT_Element, PT_Element_Type, PT_Literal } from '../ParsingTree';
77
import { ComplexTreeLayout } from './treeLayout/ComplexTreeLayout';
88
import { TL_Literal, TL_Loop, TL_LoopBound, TL_Or, TreeLayout } from './treeLayout/TreeLayout';
9+
import { createToken, InputFieldTokenType } from '../InputFieldTokenizer';
910

1011
export interface ValidationState {
1112
active: boolean;
@@ -86,12 +87,13 @@ export class ValidationGraph {
8687

8788
this.parseTreeLayout(this.layout, this.nodes[0]);
8889

89-
// const endNode = new VG_Node(this.nodeIndexCounter, AST_El_Type.SPECIAL_END);
90-
// this.nodeIndexCounter += 1;
91-
// this.nodes[this.nodes.length - 1].createTransition(endNode.index, AST_El_Type.SPECIAL_END);
92-
// this.nodes.push(endNode);
90+
const endNodeTransitionConstraint = new VG_Transition_Constraint(PT_Element_Type.LITERAL, InputFieldTokenType.EOF);
91+
const endNode = new VG_Node(this.nodeIndexCounter, endNodeTransitionConstraint, true);
92+
this.nodeIndexCounter += 1;
93+
this.nodes[this.nodes.length - 1].createTransition(endNode.index, endNodeTransitionConstraint, undefined, undefined, undefined);
94+
this.nodes.push(endNode);
9395

94-
this.nodes[this.nodes.length - 1].final = true;
96+
// this.nodes[this.nodes.length - 1].final = true;
9597
}
9698

9799
private parseTreeLayout(treeLayout: TreeLayout, previousNode: VG_Node): { first: VG_Node; last: VG_Node } {
@@ -203,7 +205,7 @@ export class ValidationGraph {
203205
this.nodeIndexCounter += 1;
204206
this.nodes.push(currentNode);
205207

206-
console.log('current layout key', currentLayout.key);
208+
// console.log('current layout key', currentLayout.key);
207209

208210
previousNode.createTransition(currentNode.index, currentLayout.constraint, previousNode.loopBound, currentLayout.key, undefined);
209211

@@ -276,7 +278,8 @@ export class ValidationGraph {
276278

277279
if (hasOnlyEmptyIncomingTransitions) {
278280
for (const incomingTransition of incomingTransitions) {
279-
incomingTransition.node.transitions.remove(incomingTransition.transition);
281+
const transitionIndex = incomingTransition.node.transitions.indexOf(incomingTransition.transition);
282+
incomingTransition.node.transitions.splice(transitionIndex, 1);
280283

281284
if (node.index === incomingTransition.node.index) {
282285
continue;
@@ -354,7 +357,15 @@ export class ValidationGraph {
354357

355358
// TODO: make this +1 better
356359
for (let ptIndex = 0; ptIndex < ptNode.children.length + 1; ptIndex++) {
357-
const ptChild = ptNode.children[ptIndex];
360+
let ptChild: PT_Element;
361+
362+
if (ptIndex === ptNode.children.length) {
363+
const prevChild = ptNode.children[ptIndex - 1];
364+
const pos = prevChild !== undefined ? prevChild.getRange().to + 1 : 0;
365+
ptChild = new PT_Literal(createToken(InputFieldTokenType.EOF, 'eof', pos, pos), '');
366+
} else {
367+
ptChild = ptNode.children[ptIndex];
368+
}
358369

359370
while (this.hasUnfinishedStates(this.state, ptIndex)) {
360371
this.validateParsingTreeChild(ptChild, ptIndex);
@@ -376,6 +387,61 @@ export class ValidationGraph {
376387
// console.log(validResults);
377388

378389
if (validResults.length === 0) {
390+
// TODO: calculate the closest path and generate an error based on it
391+
392+
// case 1: the path has reached the final input, but not a final state
393+
394+
const pathsAtEndOfInput = this.state.filter(x => x.currentInputIndex === ptNode.children.length);
395+
396+
let violatedTransitions: VG_Transition[] = [];
397+
let recievedToken: string;
398+
399+
if (pathsAtEndOfInput.length > 0) {
400+
for (const path of pathsAtEndOfInput) {
401+
const node = this.getNode(path.nodeStates[path.nodeStates.length - 1]);
402+
403+
if (node === undefined) {
404+
throw new Error('This parser sucks');
405+
}
406+
407+
violatedTransitions = violatedTransitions.concat(node.transitions);
408+
}
409+
410+
recievedToken = 'EOF';
411+
} else {
412+
// case 2: the path has not reached the end of the input
413+
414+
// find the paths that got the furthest
415+
416+
let furthestInputIndex = 0;
417+
let furthestPaths: ValidationState[] = [];
418+
419+
for (const path of this.state) {
420+
if (path.currentInputIndex === furthestInputIndex) {
421+
furthestPaths.push(path);
422+
} else if (path.currentInputIndex > furthestInputIndex) {
423+
furthestInputIndex = path.currentInputIndex;
424+
furthestPaths = [];
425+
furthestPaths.push(path);
426+
}
427+
}
428+
429+
for (const path of furthestPaths) {
430+
const node = this.getNode(path.nodeStates[path.nodeStates.length - 1]);
431+
432+
if (node === undefined) {
433+
throw new Error('This parser sucks');
434+
}
435+
436+
violatedTransitions = violatedTransitions.concat(node.transitions);
437+
}
438+
439+
recievedToken = ptNode.children[furthestInputIndex].getToken().literal;
440+
}
441+
442+
console.log('violated transitions:', violatedTransitions, ptNode.str);
443+
console.log(`received ${recievedToken} expected token to be:`, violatedTransitions.map(x => `"${x.constraint?.toString()}"`).join(', '));
444+
379445
return {
380446
acceptedState: undefined,
381447
allStates: this.state,
@@ -390,7 +456,7 @@ export class ValidationGraph {
390456
}
391457
}
392458

393-
private validateParsingTreeChild(ptChild: PT_Element | undefined, ptIndex: number): void {
459+
private validateParsingTreeChild(ptChild: PT_Element, ptIndex: number): void {
394460
const newStates: ValidationState[] = [];
395461

396462
for (const validationState of this.state) {
@@ -446,18 +512,18 @@ export class ValidationGraph {
446512
}
447513
}
448514

449-
if (ptChild === undefined && node.transitions.length === 0) {
450-
newStates.push({
451-
active: true,
452-
currentInputIndex: ptIndex,
453-
context: validationState.context,
454-
currentContextStack: validationState.currentContextStack,
455-
failure: undefined,
456-
nodeStates: validationState.nodeStates,
457-
});
458-
459-
allTransitionsFailed = false;
460-
}
515+
// if (ptChild === undefined && node.transitions.length === 0) {
516+
// newStates.push({
517+
// active: true,
518+
// currentInputIndex: ptIndex,
519+
// context: validationState.context,
520+
// currentContextStack: validationState.currentContextStack,
521+
// failure: undefined,
522+
// nodeStates: validationState.nodeStates,
523+
// });
524+
//
525+
// allTransitionsFailed = false;
526+
// }
461527

462528
if (allTransitionsFailed) {
463529
newStates.push({

src/renderChildren/ParserTestMDRC.ts

Lines changed: 47 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -90,54 +90,64 @@ export class ParserTestMDRC extends AbstractMDRC {
9090
// await this.renderGraph(
9191
// 'loop bound 2 0',
9292
// [
93-
// new TL_C_Literal(PT_Element_Type.LITERAL, undefined, undefined, 'pre'),
94-
// new TL_C_Loop([new TL_C_Literal(PT_Element_Type.CLOSURE, undefined, undefined, 'l1')], 1, 2, 'loop'),
95-
// ],
96-
// true,
97-
// 'a()'
98-
// );
99-
100-
// await this.renderGraph(
101-
// 'inputField',
102-
// [
103-
// new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD, undefined, 'type'), // input field type
104-
// new TL_C_Optional([new TL_C_Literal(PT_Element_Type.CLOSURE, InputFieldTokenType.L_PAREN, undefined, 'arguments')]), // optional arguments
105-
// new TL_C_Optional([
106-
// new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.COLON, undefined, 'bindTargetSeparator'), // bind target separator
107-
// new TL_C_Optional([
108-
// new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD, undefined, 'bindTargetFile'), // file
109-
// new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.HASHTAG), // hashtag
110-
// ]), // optional file and hashtag
111-
// new TL_C_Literal(PT_Element_Type.LITERAL, undefined, 'bindTarget'), // first bind target metadata path part
112-
// new TL_C_Loop(
113-
// [
114-
// new TL_C_Or([[new TL_C_Literal(PT_Element_Type.LITERAL)], [new TL_C_Literal(PT_Element_Type.CLOSURE)]]), // either literal or closure or none, in a loop
115-
// ],
116-
// 0,
117-
// -1
118-
// ), // the other bind target metadata path part
93+
// new TL_C_Literal(PT_Element_Type.CLOSURE),
94+
// new TL_C_Or([
95+
// [new TL_C_Or([[], [new TL_C_Literal(PT_Element_Type.LITERAL)]])],
96+
// [new TL_C_Or([[], [new TL_C_Literal(PT_Element_Type.CLOSURE)]])],
11997
// ]),
98+
// new TL_C_Literal(PT_Element_Type.CLOSURE),
12099
// ],
121100
// true,
122-
// 'toggle(a, b, c(d)):e'
101+
// '[]a()'
123102
// );
124103

125104
await this.renderGraph(
126-
'input field arguments',
105+
'inputField',
127106
[
128-
new TL_C_Enumeration(
129-
[
130-
new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD, undefined, 'name'),
131-
new TL_C_Optional([new TL_C_Literal(PT_Element_Type.CLOSURE, InputFieldTokenType.L_PAREN, undefined, 'value')]),
132-
],
133-
[new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.COMMA)],
134-
'arguments'
135-
),
107+
new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD, undefined, 'type'), // input field type
108+
// new TL_C_Optional([new TL_C_Literal(PT_Element_Type.CLOSURE, InputFieldTokenType.L_PAREN, undefined, 'arguments')]), // optional arguments
109+
new TL_C_Literal(PT_Element_Type.CLOSURE, InputFieldTokenType.L_PAREN, undefined, 'arguments'), // optional arguments
110+
new TL_C_Optional([
111+
new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.COLON, undefined, 'bindTargetSeparator'), // bind target separator
112+
new TL_C_Optional([
113+
new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD, undefined, 'bindTargetFile'), // file
114+
new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.HASHTAG), // hashtag
115+
]), // optional file and hashtag
116+
new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD, undefined, 'bindTarget'), // first bind target metadata path part
117+
new TL_C_Loop(
118+
[
119+
new TL_C_Or([
120+
[new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD)],
121+
[new TL_C_Literal(PT_Element_Type.CLOSURE, InputFieldTokenType.L_SQUARE)],
122+
]), // either literal or closure or none, in a loop
123+
],
124+
0,
125+
-1
126+
), // the other bind target metadata path part
127+
]),
136128
],
137129
true,
138-
'a, b(), c, d()'
130+
'toggle()#'
139131
);
140132

133+
// TODO: ADD EOF TOKEN TO FIX ALL THIS SHIT
134+
135+
// await this.renderGraph(
136+
// 'input field arguments',
137+
// [
138+
// new TL_C_Enumeration(
139+
// [
140+
// new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.WORD, undefined, 'name'),
141+
// new TL_C_Optional([new TL_C_Literal(PT_Element_Type.CLOSURE, InputFieldTokenType.L_PAREN, undefined, 'value')]),
142+
// ],
143+
// [new TL_C_Literal(PT_Element_Type.LITERAL, InputFieldTokenType.COMMA)],
144+
// 'arguments'
145+
// ),
146+
// ],
147+
// true,
148+
// 'a, b(), c, d()'
149+
// );
150+
141151
// const fullDeclaration = 'test(a):b';
142152
//
143153
// const tokenizer = new InputFieldTokenizer(fullDeclaration);

tests/InputFieldParser.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ describe('tree validation tests', function () {
124124
new TL_C_Literal(PT_Element_Type.CLOSURE),
125125
]);
126126

127+
graph.optimizeParsingGraph();
128+
127129
expect(graph.validateParsingTree(createParsingTree('()a[]'))).toEqual(true);
128130
expect(graph.validateParsingTree(createParsingTree('()[]'))).toEqual(true);
129131
expect(graph.validateParsingTree(createParsingTree('()()[]'))).toEqual(true);

0 commit comments

Comments
 (0)