-
Notifications
You must be signed in to change notification settings - Fork 1
/
autoresponders.ts
114 lines (114 loc) · 3.25 KB
/
autoresponders.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
class ParserStream<T> {
characters: T[];
constructor(input: T[]) {
this.characters = input;
}
get atEnd(): boolean {
return !this.characters.length;
}
peek(n?: number): T | undefined {
if (this.characters.length <= (n || 0)) return undefined;
return this.characters[n || 0];
}
consume(n?: number): T | undefined {
if (this.characters.length <= (n || 0)) return undefined;
const tmp = this.peek(n);
this.characters.splice(n || 0, 1);
return tmp;
}
nextn(n: number): T[] {
return this.characters.slice(0, n);
}
consumen(n: number): T[] {
const tmp = this.nextn(n);
for (let i = 0; i < n; i++) this.consume();
return tmp;
}
}
interface Variable {
name: string;
type: 'variable';
}
export function parsePrompt(inputStr: string): Array<string | Variable> {
const input: ParserStream<string> = new ParserStream(inputStr.split(''));
const output: Array<string | Variable> = [];
let stringBuffer = '';
let inTag = false;
while (!input.atEnd) {
if (input.peek() === '{' && input.peek(1) === '{') {
output.push(stringBuffer);
stringBuffer = '';
inTag = true;
input.consume();
input.consume();
} else if (inTag && input.peek() === '}' && input.peek(1) === '}') {
inTag = false;
output.push({ name: stringBuffer, type: 'variable' });
stringBuffer = '';
input.consume();
input.consume();
} else {
stringBuffer += input.consume();
}
}
if (inTag) output.push('{{');
output.push(stringBuffer);
const cleanedOutput: Array<string | Variable> = [];
let i = 0;
for (const item of output) {
if (i === 0) {
cleanedOutput.push(output[i]);
i++;
} else {
if (
typeof cleanedOutput[i - 1] === 'string' &&
typeof item === 'string'
) {
cleanedOutput[i - 1] += item;
} else {
cleanedOutput.push(item);
i++;
}
}
}
return cleanedOutput.filter(Boolean);
}
export function parseText(
text: string,
promptTree: Array<string | Variable>
): [boolean, Map<string, string | null>] {
const parserSyntax: ParserStream<string | Variable> = new ParserStream(
promptTree
);
const parserInput: ParserStream<string> = new ParserStream(text.split(''));
const parserVars: Map<string, string | null> = new Map();
let matched = true;
while (!parserSyntax.atEnd && matched === true) {
const next = parserSyntax.peek();
const next1 = parserSyntax.peek(1);
if (typeof next === 'string') {
const consumed = parserInput.consumen(next.length);
if (consumed.join('').toLowerCase() !== next.toLowerCase())
matched = false;
} else if (next?.type === 'variable') {
let buffer = '';
// eslint-disable-next-line no-constant-condition
while (true) {
buffer += parserInput.consume() || '';
if (
typeof next1 === 'string' &&
parserInput.nextn(next1.length).join('').toLowerCase() ===
next1.toLowerCase()
) {
break;
} else {
if (parserInput.peek() === undefined) break;
}
}
parserVars.set(next.name, buffer || null);
}
parserSyntax.consume();
}
if (matched && !parserInput.atEnd) matched = false;
return [matched, parserVars];
}