-
-
Notifications
You must be signed in to change notification settings - Fork 41
Expand file tree
/
Copy pathbase.ts
More file actions
79 lines (60 loc) · 1.89 KB
/
base.ts
File metadata and controls
79 lines (60 loc) · 1.89 KB
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
import * as assert from 'assert';
import * as frontend from 'llparse-frontend';
import { Compilation } from '../compilation';
import {
STATE_PREFIX, LABEL_PREFIX,
} from '../constants';
export interface INodeEdge {
readonly node: frontend.IWrap<frontend.node.Node>;
readonly noAdvance: boolean;
readonly value?: number;
}
export abstract class Node<T extends frontend.node.Node> {
protected cachedDecl: string | undefined;
protected privCompilation: Compilation | undefined;
public readonly ref: T;
constructor(ref: T) {
this.ref = ref;
}
public build(compilation: Compilation): string {
if (this.cachedDecl !== undefined) {
return this.cachedDecl;
}
const res = STATE_PREFIX + this.ref.id.name;
this.cachedDecl = res;
this.privCompilation = compilation;
const out: string[] = [];
compilation.debug(out,
`Entering node "${this.ref.id.originalName}" ("${this.ref.id.name}")`);
this.doBuild(out);
compilation.addState(res, out);
return res;
}
protected get compilation(): Compilation {
assert(this.privCompilation !== undefined);
return this.privCompilation!;
}
protected prologue(out: string[]): void {
const ctx = this.compilation;
out.push(`if (${ctx.posArg()} == ${ctx.endPosArg()}) {`);
const tmp: string[] = [];
this.pause(tmp);
this.compilation.indent(out, tmp, ' ');
out.push('}');
}
protected pause(out: string[]): void {
out.push(`return ${this.cachedDecl};`);
}
protected tailTo(out: string[], edge: INodeEdge): void {
const ctx = this.compilation;
const target = ctx.unwrapNode(edge.node).build(ctx);
if (!edge.noAdvance) {
out.push(`${ctx.posArg()}++;`);
}
if (edge.value !== undefined) {
out.push(`${ctx.matchVar()} = ${edge.value};`);
}
out.push(`goto ${LABEL_PREFIX}${target};`);
}
protected abstract doBuild(out: string[]): void;
}