summaryrefslogtreecommitdiffstats
path: root/llparse-frontend/test
diff options
context:
space:
mode:
Diffstat (limited to 'llparse-frontend/test')
-rw-r--r--llparse-frontend/test/container-test.ts46
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/code/and.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/code/base.ts6
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/code/index.ts15
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/code/is-equal.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/code/load.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/code/match.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/code/mul-add.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/code/or.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/code/span.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/code/store.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/code/test.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/code/update.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/code/value.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/index.ts5
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/node/base.ts38
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/node/consume.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/node/empty.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/node/error.ts10
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/node/index.ts15
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/node/invoke.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/node/pause.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/node/sequence.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/node/single.ts18
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/node/span-end.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/node/span-start.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/node/table-lookup.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/transform/base.ts6
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/transform/id.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/transform/index.ts5
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/transform/to-lower-unsafe.ts8
-rw-r--r--llparse-frontend/test/fixtures/a-implementation/transform/to-lower.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/code/and.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/code/base.ts6
-rw-r--r--llparse-frontend/test/fixtures/implementation/code/index.ts15
-rw-r--r--llparse-frontend/test/fixtures/implementation/code/is-equal.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/code/load.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/code/match.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/code/mul-add.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/code/or.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/code/span.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/code/store.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/code/test.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/code/update.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/code/value.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/index.ts5
-rw-r--r--llparse-frontend/test/fixtures/implementation/node/base.ts39
-rw-r--r--llparse-frontend/test/fixtures/implementation/node/consume.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/node/empty.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/node/error.ts10
-rw-r--r--llparse-frontend/test/fixtures/implementation/node/index.ts15
-rw-r--r--llparse-frontend/test/fixtures/implementation/node/invoke.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/node/pause.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/node/sequence.ts15
-rw-r--r--llparse-frontend/test/fixtures/implementation/node/single.ts22
-rw-r--r--llparse-frontend/test/fixtures/implementation/node/span-end.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/node/span-start.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/node/table-lookup.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/transform/base.ts6
-rw-r--r--llparse-frontend/test/fixtures/implementation/transform/id.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/transform/index.ts5
-rw-r--r--llparse-frontend/test/fixtures/implementation/transform/to-lower-unsafe.ts8
-rw-r--r--llparse-frontend/test/fixtures/implementation/transform/to-lower.ts8
-rw-r--r--llparse-frontend/test/frontend-test.ts187
64 files changed, 833 insertions, 0 deletions
diff --git a/llparse-frontend/test/container-test.ts b/llparse-frontend/test/container-test.ts
new file mode 100644
index 0000000..28b7f1b
--- /dev/null
+++ b/llparse-frontend/test/container-test.ts
@@ -0,0 +1,46 @@
+import * as assert from 'assert';
+
+import { Builder } from 'llparse-builder';
+
+import { Container, ContainerWrap, Frontend, node } from '../src/frontend';
+import implementation from './fixtures/a-implementation';
+import { Node } from './fixtures/implementation/node/base';
+
+describe('llparse-frontend/Container', () => {
+ let b: Builder;
+ beforeEach(() => {
+ b = new Builder();
+ });
+
+ it('should translate nodes to implementation', () => {
+ const comb = new Container();
+ comb.add('a', implementation);
+ comb.add('b', implementation);
+
+ const f = new Frontend('llparse', comb.build());
+
+ const root = b.node('root');
+
+ root.match('ab', root);
+ root.match('acd', root);
+ root.match('efg', root);
+ root.otherwise(b.error(123, 'hello'));
+
+ const fRoot = f.compile(root, []).root as ContainerWrap<node.Node>;
+
+ const out: string[] = [];
+ (fRoot.get('a') as Node<node.Node>).build(out);
+
+ assert.deepStrictEqual(out, [
+ '<Single name=llparse__n_root k97=llparse__n_root_1 ' +
+ 'k101=llparse__n_root_3 otherwise-no_adv=llparse__n_error/>',
+ '<Single name=llparse__n_root_1 k98=llparse__n_root ' +
+ 'k99=llparse__n_root_2 otherwise-no_adv=llparse__n_error/>',
+ '<Single name=llparse__n_root_2 k100=llparse__n_root ' +
+ 'otherwise-no_adv=llparse__n_error/>',
+ '<ErrorNode name=llparse__n_error code=123 reason="hello"/>',
+ '<Sequence name=llparse__n_root_3 select="6667" ' +
+ 'otherwise-no_adv=llparse__n_error/>',
+ ]);
+ });
+});
diff --git a/llparse-frontend/test/fixtures/a-implementation/code/and.ts b/llparse-frontend/test/fixtures/a-implementation/code/and.ts
new file mode 100644
index 0000000..c1df821
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/code/and.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class And extends Code<code.And> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/code/base.ts b/llparse-frontend/test/fixtures/a-implementation/code/base.ts
new file mode 100644
index 0000000..d9a7ace
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/code/base.ts
@@ -0,0 +1,6 @@
+export abstract class Code<T> {
+ constructor(public readonly ref: T) {
+ }
+
+ public abstract build(): string;
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/code/index.ts b/llparse-frontend/test/fixtures/a-implementation/code/index.ts
new file mode 100644
index 0000000..855a5cf
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/code/index.ts
@@ -0,0 +1,15 @@
+import { And } from './and';
+import { IsEqual } from './is-equal';
+import { Load } from './load';
+import { Match } from './match';
+import { MulAdd } from './mul-add';
+import { Or } from './or';
+import { Span } from './span';
+import { Store } from './store';
+import { Test } from './test';
+import { Update } from './update';
+import { Value } from './value';
+
+export default {
+ And, IsEqual, Load, Match, MulAdd, Or, Span, Store, Test, Update, Value,
+};
diff --git a/llparse-frontend/test/fixtures/a-implementation/code/is-equal.ts b/llparse-frontend/test/fixtures/a-implementation/code/is-equal.ts
new file mode 100644
index 0000000..13a1737
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/code/is-equal.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class IsEqual extends Code<code.IsEqual> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/code/load.ts b/llparse-frontend/test/fixtures/a-implementation/code/load.ts
new file mode 100644
index 0000000..bc97f27
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/code/load.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class Load extends Code<code.Load> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/code/match.ts b/llparse-frontend/test/fixtures/a-implementation/code/match.ts
new file mode 100644
index 0000000..e933a71
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/code/match.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class Match extends Code<code.Match> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/code/mul-add.ts b/llparse-frontend/test/fixtures/a-implementation/code/mul-add.ts
new file mode 100644
index 0000000..e06a217
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/code/mul-add.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class MulAdd extends Code<code.MulAdd> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/code/or.ts b/llparse-frontend/test/fixtures/a-implementation/code/or.ts
new file mode 100644
index 0000000..a569db4
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/code/or.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class Or extends Code<code.Or> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/code/span.ts b/llparse-frontend/test/fixtures/a-implementation/code/span.ts
new file mode 100644
index 0000000..46fc410
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/code/span.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class Span extends Code<code.Span> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/code/store.ts b/llparse-frontend/test/fixtures/a-implementation/code/store.ts
new file mode 100644
index 0000000..7a1ca9f
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/code/store.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class Store extends Code<code.Store> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/code/test.ts b/llparse-frontend/test/fixtures/a-implementation/code/test.ts
new file mode 100644
index 0000000..4fc8ddb
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/code/test.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class Test extends Code<code.Test> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/code/update.ts b/llparse-frontend/test/fixtures/a-implementation/code/update.ts
new file mode 100644
index 0000000..16b20e2
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/code/update.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class Update extends Code<code.Update> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/code/value.ts b/llparse-frontend/test/fixtures/a-implementation/code/value.ts
new file mode 100644
index 0000000..8e76e2a
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/code/value.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class Value extends Code<code.Value> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/index.ts b/llparse-frontend/test/fixtures/a-implementation/index.ts
new file mode 100644
index 0000000..1d8d29a
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/index.ts
@@ -0,0 +1,5 @@
+import code from './code';
+import node from './node';
+import transform from './transform';
+
+export default { code, node, transform };
diff --git a/llparse-frontend/test/fixtures/a-implementation/node/base.ts b/llparse-frontend/test/fixtures/a-implementation/node/base.ts
new file mode 100644
index 0000000..04c8285
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/node/base.ts
@@ -0,0 +1,38 @@
+import { ContainerWrap, node } from '../../../../src/frontend';
+
+export abstract class Node<T extends node.Node> {
+ private built: boolean = false;
+
+ constructor(public readonly ref: T) {
+ }
+
+ public build(out: string[]): void {
+ if (this.built) {
+ return;
+ }
+
+ this.built = true;
+ this.doBuild(out);
+
+ if (this.ref.otherwise !== undefined) {
+ const cwrap = this.ref.otherwise.node as ContainerWrap<T>;
+ const otherwise = cwrap.get<Node<T>>('a');
+ otherwise.build(out);
+ }
+ }
+
+ protected format(value: string): string {
+ let otherwise: string = '';
+ if (this.ref.otherwise !== undefined) {
+ const otherwiseRef = this.ref.otherwise.node.ref;
+ otherwise = ' otherwise' +
+ `${this.ref.otherwise.noAdvance ? '-no_adv' : ''}=` +
+ `${otherwiseRef.id.name}`;
+ }
+
+ return `<${this.constructor.name} name=${this.ref.id.name} ` +
+ `${value}${otherwise}/>`;
+ }
+
+ protected abstract doBuild(out: string[]): void;
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/node/consume.ts b/llparse-frontend/test/fixtures/a-implementation/node/consume.ts
new file mode 100644
index 0000000..cdc6cef
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/node/consume.ts
@@ -0,0 +1,8 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class Consume extends Node<node.Consume> {
+ protected doBuild(out: string[]): void {
+ out.push(this.format(`field=${this.ref.field}`));
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/node/empty.ts b/llparse-frontend/test/fixtures/a-implementation/node/empty.ts
new file mode 100644
index 0000000..ef1499b
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/node/empty.ts
@@ -0,0 +1,8 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class Empty extends Node<node.Empty> {
+ protected doBuild(out: string[]): void {
+ out.push(this.format(''));
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/node/error.ts b/llparse-frontend/test/fixtures/a-implementation/node/error.ts
new file mode 100644
index 0000000..1a4f31d
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/node/error.ts
@@ -0,0 +1,10 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+class ErrorNode extends Node<node.Error> {
+ protected doBuild(out: string[]): void {
+ out.push(this.format(`code=${this.ref.code} reason="${this.ref.reason}"`));
+ }
+}
+
+export { ErrorNode as Error };
diff --git a/llparse-frontend/test/fixtures/a-implementation/node/index.ts b/llparse-frontend/test/fixtures/a-implementation/node/index.ts
new file mode 100644
index 0000000..31dbc5e
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/node/index.ts
@@ -0,0 +1,15 @@
+import { Consume } from './consume';
+import { Empty } from './empty';
+import { Error } from './error';
+import { Invoke } from './invoke';
+import { Pause } from './pause';
+import { Sequence } from './sequence';
+import { Single } from './single';
+import { SpanEnd } from './span-end';
+import { SpanStart } from './span-start';
+import { TableLookup } from './table-lookup';
+
+export default {
+ Consume, Empty, Error, Invoke, Pause, Sequence, Single, SpanEnd,
+ SpanStart, TableLookup,
+};
diff --git a/llparse-frontend/test/fixtures/a-implementation/node/invoke.ts b/llparse-frontend/test/fixtures/a-implementation/node/invoke.ts
new file mode 100644
index 0000000..674be5f
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/node/invoke.ts
@@ -0,0 +1,8 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class Invoke extends Node<node.Invoke> {
+ protected doBuild(out: string[]): void {
+ out.push(this.format(''));
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/node/pause.ts b/llparse-frontend/test/fixtures/a-implementation/node/pause.ts
new file mode 100644
index 0000000..94da63c
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/node/pause.ts
@@ -0,0 +1,8 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class Pause extends Node<node.Pause> {
+ protected doBuild(out: string[]): void {
+ out.push(this.format(''));
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/node/sequence.ts b/llparse-frontend/test/fixtures/a-implementation/node/sequence.ts
new file mode 100644
index 0000000..13fd336
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/node/sequence.ts
@@ -0,0 +1,8 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class Sequence extends Node<node.Sequence> {
+ protected doBuild(out: string[]): void {
+ out.push(this.format(`select="${this.ref.select.toString('hex')}"`));
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/node/single.ts b/llparse-frontend/test/fixtures/a-implementation/node/single.ts
new file mode 100644
index 0000000..d7bcc72
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/node/single.ts
@@ -0,0 +1,18 @@
+import { ContainerWrap, node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class Single extends Node<node.Single> {
+ protected doBuild(out: string[]): void {
+ const edges: string[] = [];
+ for (const edge of this.ref.edges) {
+ edges.push(`k${edge.key}${edge.noAdvance ? '-no_adv-' : ''}=` +
+ `${edge.node.ref.id.name}`);
+ }
+ out.push(this.format(edges.join(' ')));
+
+ for (const edge of this.ref.edges) {
+ const edgeNode = edge.node as ContainerWrap<node.Node>;
+ edgeNode.get<Node<node.Node>>('a').build(out);
+ }
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/node/span-end.ts b/llparse-frontend/test/fixtures/a-implementation/node/span-end.ts
new file mode 100644
index 0000000..dc79b81
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/node/span-end.ts
@@ -0,0 +1,8 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class SpanEnd extends Node<node.SpanEnd> {
+ protected doBuild(out: string[]): void {
+ out.push(this.format(''));
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/node/span-start.ts b/llparse-frontend/test/fixtures/a-implementation/node/span-start.ts
new file mode 100644
index 0000000..32e373c
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/node/span-start.ts
@@ -0,0 +1,8 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class SpanStart extends Node<node.SpanStart> {
+ protected doBuild(out: string[]): void {
+ out.push(this.format(''));
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/node/table-lookup.ts b/llparse-frontend/test/fixtures/a-implementation/node/table-lookup.ts
new file mode 100644
index 0000000..e6166d0
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/node/table-lookup.ts
@@ -0,0 +1,8 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class TableLookup extends Node<node.TableLookup> {
+ protected doBuild(out: string[]): void {
+ out.push(this.format(''));
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/transform/base.ts b/llparse-frontend/test/fixtures/a-implementation/transform/base.ts
new file mode 100644
index 0000000..96dc27d
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/transform/base.ts
@@ -0,0 +1,6 @@
+export abstract class Transform<T> {
+ constructor(public readonly ref: T) {
+ }
+
+ public abstract build(): string;
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/transform/id.ts b/llparse-frontend/test/fixtures/a-implementation/transform/id.ts
new file mode 100644
index 0000000..e6c1adc
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/transform/id.ts
@@ -0,0 +1,8 @@
+import { transform } from '../../../../src/frontend';
+import { Transform } from './base';
+
+export class ID extends Transform<transform.ID> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/transform/index.ts b/llparse-frontend/test/fixtures/a-implementation/transform/index.ts
new file mode 100644
index 0000000..bed8bc9
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/transform/index.ts
@@ -0,0 +1,5 @@
+import { ID } from './id';
+import { ToLower } from './to-lower';
+import { ToLowerUnsafe } from './to-lower-unsafe';
+
+export default { ID, ToLower, ToLowerUnsafe };
diff --git a/llparse-frontend/test/fixtures/a-implementation/transform/to-lower-unsafe.ts b/llparse-frontend/test/fixtures/a-implementation/transform/to-lower-unsafe.ts
new file mode 100644
index 0000000..9d175a9
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/transform/to-lower-unsafe.ts
@@ -0,0 +1,8 @@
+import { transform } from '../../../../src/frontend';
+import { Transform } from './base';
+
+export class ToLowerUnsafe extends Transform<transform.ToLowerUnsafe> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/a-implementation/transform/to-lower.ts b/llparse-frontend/test/fixtures/a-implementation/transform/to-lower.ts
new file mode 100644
index 0000000..cbe6456
--- /dev/null
+++ b/llparse-frontend/test/fixtures/a-implementation/transform/to-lower.ts
@@ -0,0 +1,8 @@
+import { transform } from '../../../../src/frontend';
+import { Transform } from './base';
+
+export class ToLower extends Transform<transform.ToLower> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/code/and.ts b/llparse-frontend/test/fixtures/implementation/code/and.ts
new file mode 100644
index 0000000..c1df821
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/code/and.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class And extends Code<code.And> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/code/base.ts b/llparse-frontend/test/fixtures/implementation/code/base.ts
new file mode 100644
index 0000000..d9a7ace
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/code/base.ts
@@ -0,0 +1,6 @@
+export abstract class Code<T> {
+ constructor(public readonly ref: T) {
+ }
+
+ public abstract build(): string;
+}
diff --git a/llparse-frontend/test/fixtures/implementation/code/index.ts b/llparse-frontend/test/fixtures/implementation/code/index.ts
new file mode 100644
index 0000000..855a5cf
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/code/index.ts
@@ -0,0 +1,15 @@
+import { And } from './and';
+import { IsEqual } from './is-equal';
+import { Load } from './load';
+import { Match } from './match';
+import { MulAdd } from './mul-add';
+import { Or } from './or';
+import { Span } from './span';
+import { Store } from './store';
+import { Test } from './test';
+import { Update } from './update';
+import { Value } from './value';
+
+export default {
+ And, IsEqual, Load, Match, MulAdd, Or, Span, Store, Test, Update, Value,
+};
diff --git a/llparse-frontend/test/fixtures/implementation/code/is-equal.ts b/llparse-frontend/test/fixtures/implementation/code/is-equal.ts
new file mode 100644
index 0000000..13a1737
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/code/is-equal.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class IsEqual extends Code<code.IsEqual> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/code/load.ts b/llparse-frontend/test/fixtures/implementation/code/load.ts
new file mode 100644
index 0000000..bc97f27
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/code/load.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class Load extends Code<code.Load> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/code/match.ts b/llparse-frontend/test/fixtures/implementation/code/match.ts
new file mode 100644
index 0000000..e933a71
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/code/match.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class Match extends Code<code.Match> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/code/mul-add.ts b/llparse-frontend/test/fixtures/implementation/code/mul-add.ts
new file mode 100644
index 0000000..e06a217
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/code/mul-add.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class MulAdd extends Code<code.MulAdd> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/code/or.ts b/llparse-frontend/test/fixtures/implementation/code/or.ts
new file mode 100644
index 0000000..a569db4
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/code/or.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class Or extends Code<code.Or> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/code/span.ts b/llparse-frontend/test/fixtures/implementation/code/span.ts
new file mode 100644
index 0000000..46fc410
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/code/span.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class Span extends Code<code.Span> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/code/store.ts b/llparse-frontend/test/fixtures/implementation/code/store.ts
new file mode 100644
index 0000000..7a1ca9f
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/code/store.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class Store extends Code<code.Store> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/code/test.ts b/llparse-frontend/test/fixtures/implementation/code/test.ts
new file mode 100644
index 0000000..4fc8ddb
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/code/test.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class Test extends Code<code.Test> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/code/update.ts b/llparse-frontend/test/fixtures/implementation/code/update.ts
new file mode 100644
index 0000000..16b20e2
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/code/update.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class Update extends Code<code.Update> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/code/value.ts b/llparse-frontend/test/fixtures/implementation/code/value.ts
new file mode 100644
index 0000000..8e76e2a
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/code/value.ts
@@ -0,0 +1,8 @@
+import { code } from '../../../../src/frontend';
+import { Code } from './base';
+
+export class Value extends Code<code.Value> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/index.ts b/llparse-frontend/test/fixtures/implementation/index.ts
new file mode 100644
index 0000000..1d8d29a
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/index.ts
@@ -0,0 +1,5 @@
+import code from './code';
+import node from './node';
+import transform from './transform';
+
+export default { code, node, transform };
diff --git a/llparse-frontend/test/fixtures/implementation/node/base.ts b/llparse-frontend/test/fixtures/implementation/node/base.ts
new file mode 100644
index 0000000..c9fd589
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/node/base.ts
@@ -0,0 +1,39 @@
+import { node } from '../../../../src/frontend';
+
+export abstract class Node<T extends node.Node> {
+ private built: boolean = false;
+
+ constructor(public readonly ref: T) {
+ }
+
+ public build(out: string[]): void {
+ if (this.built) {
+ return;
+ }
+
+ this.built = true;
+ this.doBuild(out);
+
+ if (this.ref.otherwise !== undefined) {
+ (this.ref.otherwise.node as Node<T>).build(out);
+ }
+ }
+
+ protected format(value: string): string {
+ let otherwise: string = '';
+ if (this.ref.otherwise !== undefined) {
+ const otherwiseRef = this.ref.otherwise.node.ref;
+ otherwise = ' otherwise' +
+ `${this.ref.otherwise.noAdvance ? '-no_adv' : ''}=` +
+ `${otherwiseRef.id.name}`;
+ if (this.ref.otherwise.value !== undefined) {
+ otherwise += `:${this.ref.otherwise.value}`;
+ }
+ }
+
+ return `<${this.constructor.name} name=${this.ref.id.name} ` +
+ `${value}${otherwise}/>`;
+ }
+
+ protected abstract doBuild(out: string[]): void;
+}
diff --git a/llparse-frontend/test/fixtures/implementation/node/consume.ts b/llparse-frontend/test/fixtures/implementation/node/consume.ts
new file mode 100644
index 0000000..cdc6cef
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/node/consume.ts
@@ -0,0 +1,8 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class Consume extends Node<node.Consume> {
+ protected doBuild(out: string[]): void {
+ out.push(this.format(`field=${this.ref.field}`));
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/node/empty.ts b/llparse-frontend/test/fixtures/implementation/node/empty.ts
new file mode 100644
index 0000000..ef1499b
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/node/empty.ts
@@ -0,0 +1,8 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class Empty extends Node<node.Empty> {
+ protected doBuild(out: string[]): void {
+ out.push(this.format(''));
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/node/error.ts b/llparse-frontend/test/fixtures/implementation/node/error.ts
new file mode 100644
index 0000000..1a4f31d
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/node/error.ts
@@ -0,0 +1,10 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+class ErrorNode extends Node<node.Error> {
+ protected doBuild(out: string[]): void {
+ out.push(this.format(`code=${this.ref.code} reason="${this.ref.reason}"`));
+ }
+}
+
+export { ErrorNode as Error };
diff --git a/llparse-frontend/test/fixtures/implementation/node/index.ts b/llparse-frontend/test/fixtures/implementation/node/index.ts
new file mode 100644
index 0000000..31dbc5e
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/node/index.ts
@@ -0,0 +1,15 @@
+import { Consume } from './consume';
+import { Empty } from './empty';
+import { Error } from './error';
+import { Invoke } from './invoke';
+import { Pause } from './pause';
+import { Sequence } from './sequence';
+import { Single } from './single';
+import { SpanEnd } from './span-end';
+import { SpanStart } from './span-start';
+import { TableLookup } from './table-lookup';
+
+export default {
+ Consume, Empty, Error, Invoke, Pause, Sequence, Single, SpanEnd,
+ SpanStart, TableLookup,
+};
diff --git a/llparse-frontend/test/fixtures/implementation/node/invoke.ts b/llparse-frontend/test/fixtures/implementation/node/invoke.ts
new file mode 100644
index 0000000..674be5f
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/node/invoke.ts
@@ -0,0 +1,8 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class Invoke extends Node<node.Invoke> {
+ protected doBuild(out: string[]): void {
+ out.push(this.format(''));
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/node/pause.ts b/llparse-frontend/test/fixtures/implementation/node/pause.ts
new file mode 100644
index 0000000..94da63c
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/node/pause.ts
@@ -0,0 +1,8 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class Pause extends Node<node.Pause> {
+ protected doBuild(out: string[]): void {
+ out.push(this.format(''));
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/node/sequence.ts b/llparse-frontend/test/fixtures/implementation/node/sequence.ts
new file mode 100644
index 0000000..bb745f5
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/node/sequence.ts
@@ -0,0 +1,15 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class Sequence extends Node<node.Sequence> {
+ protected doBuild(out: string[]): void {
+ let str = `select="${this.ref.select.toString('hex')}" ` +
+ `edge="${this.ref.edge!.node.ref.id.name}"`;
+ if (this.ref.edge!.value !== undefined) {
+ str += `:${this.ref.edge!.value}`;
+ }
+ out.push(this.format(str));
+ const edgeNode = this.ref.edge!.node as Node<node.Node>;
+ edgeNode.build(out);
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/node/single.ts b/llparse-frontend/test/fixtures/implementation/node/single.ts
new file mode 100644
index 0000000..b24ef93
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/node/single.ts
@@ -0,0 +1,22 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class Single extends Node<node.Single> {
+ protected doBuild(out: string[]): void {
+ const edges: string[] = [];
+ for (const edge of this.ref.edges) {
+ let str = `k${edge.key}${edge.noAdvance ? '-no_adv-' : ''}=` +
+ `${edge.node.ref.id.name}`;
+ if (edge.value !== undefined) {
+ str += `:${edge.value}`;
+ }
+ edges.push(str);
+ }
+ out.push(this.format(edges.join(' ')));
+
+ for (const edge of this.ref.edges) {
+ const edgeNode = edge.node as Node<node.Node>;
+ edgeNode.build(out);
+ }
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/node/span-end.ts b/llparse-frontend/test/fixtures/implementation/node/span-end.ts
new file mode 100644
index 0000000..dc79b81
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/node/span-end.ts
@@ -0,0 +1,8 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class SpanEnd extends Node<node.SpanEnd> {
+ protected doBuild(out: string[]): void {
+ out.push(this.format(''));
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/node/span-start.ts b/llparse-frontend/test/fixtures/implementation/node/span-start.ts
new file mode 100644
index 0000000..32e373c
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/node/span-start.ts
@@ -0,0 +1,8 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class SpanStart extends Node<node.SpanStart> {
+ protected doBuild(out: string[]): void {
+ out.push(this.format(''));
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/node/table-lookup.ts b/llparse-frontend/test/fixtures/implementation/node/table-lookup.ts
new file mode 100644
index 0000000..e6166d0
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/node/table-lookup.ts
@@ -0,0 +1,8 @@
+import { node } from '../../../../src/frontend';
+import { Node } from './base';
+
+export class TableLookup extends Node<node.TableLookup> {
+ protected doBuild(out: string[]): void {
+ out.push(this.format(''));
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/transform/base.ts b/llparse-frontend/test/fixtures/implementation/transform/base.ts
new file mode 100644
index 0000000..96dc27d
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/transform/base.ts
@@ -0,0 +1,6 @@
+export abstract class Transform<T> {
+ constructor(public readonly ref: T) {
+ }
+
+ public abstract build(): string;
+}
diff --git a/llparse-frontend/test/fixtures/implementation/transform/id.ts b/llparse-frontend/test/fixtures/implementation/transform/id.ts
new file mode 100644
index 0000000..e6c1adc
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/transform/id.ts
@@ -0,0 +1,8 @@
+import { transform } from '../../../../src/frontend';
+import { Transform } from './base';
+
+export class ID extends Transform<transform.ID> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/transform/index.ts b/llparse-frontend/test/fixtures/implementation/transform/index.ts
new file mode 100644
index 0000000..bed8bc9
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/transform/index.ts
@@ -0,0 +1,5 @@
+import { ID } from './id';
+import { ToLower } from './to-lower';
+import { ToLowerUnsafe } from './to-lower-unsafe';
+
+export default { ID, ToLower, ToLowerUnsafe };
diff --git a/llparse-frontend/test/fixtures/implementation/transform/to-lower-unsafe.ts b/llparse-frontend/test/fixtures/implementation/transform/to-lower-unsafe.ts
new file mode 100644
index 0000000..9d175a9
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/transform/to-lower-unsafe.ts
@@ -0,0 +1,8 @@
+import { transform } from '../../../../src/frontend';
+import { Transform } from './base';
+
+export class ToLowerUnsafe extends Transform<transform.ToLowerUnsafe> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/fixtures/implementation/transform/to-lower.ts b/llparse-frontend/test/fixtures/implementation/transform/to-lower.ts
new file mode 100644
index 0000000..cbe6456
--- /dev/null
+++ b/llparse-frontend/test/fixtures/implementation/transform/to-lower.ts
@@ -0,0 +1,8 @@
+import { transform } from '../../../../src/frontend';
+import { Transform } from './base';
+
+export class ToLower extends Transform<transform.ToLower> {
+ public build(): string {
+ return '';
+ }
+}
diff --git a/llparse-frontend/test/frontend-test.ts b/llparse-frontend/test/frontend-test.ts
new file mode 100644
index 0000000..69e075c
--- /dev/null
+++ b/llparse-frontend/test/frontend-test.ts
@@ -0,0 +1,187 @@
+import * as assert from 'assert';
+
+import * as source from 'llparse-builder';
+
+import { Frontend, node } from '../src/frontend';
+import implementation from './fixtures/implementation';
+import { Node } from './fixtures/implementation/node/base';
+
+function checkNodes(f: Frontend, root: source.node.Node,
+ expected: ReadonlyArray<string>) {
+ const fRoot = f.compile(root, []).root as Node<node.Node>;
+
+ const out: string[] = [];
+ fRoot.build(out);
+
+ assert.deepStrictEqual(out, expected);
+
+ return fRoot;
+}
+
+function checkResumptionTargets(f: Frontend, expected: ReadonlyArray<string>) {
+ const targets = Array.from(f.getResumptionTargets()).map((t) => {
+ return t.ref.id.name;
+ });
+
+ assert.deepStrictEqual(targets, expected);
+}
+
+describe('llparse-frontend', () => {
+ let b: source.Builder;
+ let f: Frontend;
+ beforeEach(() => {
+ b = new source.Builder();
+ f = new Frontend('llparse', implementation);
+ });
+
+ it('should translate nodes to implementation', () => {
+ const root = b.node('root');
+
+ root.match('ab', root);
+ root.match('acd', root);
+ root.match('efg', root);
+ root.otherwise(b.error(123, 'hello'));
+
+ checkNodes(f, root, [
+ '<Single name=llparse__n_root k97=llparse__n_root_1 ' +
+ 'k101=llparse__n_root_3 otherwise-no_adv=llparse__n_error/>',
+ '<Single name=llparse__n_root_1 k98=llparse__n_root ' +
+ 'k99=llparse__n_root_2 otherwise-no_adv=llparse__n_error/>',
+ '<Single name=llparse__n_root_2 k100=llparse__n_root ' +
+ 'otherwise-no_adv=llparse__n_error/>',
+ '<ErrorNode name=llparse__n_error code=123 reason="hello"/>',
+ '<Sequence name=llparse__n_root_3 select="6667" ' +
+ 'edge=\"llparse__n_root\" ' +
+ 'otherwise-no_adv=llparse__n_error/>',
+ ]);
+
+ checkResumptionTargets(f, [
+ 'llparse__n_root',
+ 'llparse__n_root_1',
+ 'llparse__n_root_3',
+ 'llparse__n_root_2',
+ ]);
+ });
+
+ it('should do peephole optimization', () => {
+ const root = b.node('root');
+ const root1 = b.node('a');
+ const root2 = b.node('b');
+ const node1 = b.node('c');
+ const node2 = b.node('d');
+
+ root.otherwise(root1);
+ root1.otherwise(root2);
+ root2.skipTo(node1);
+ node1.otherwise(node2);
+ node2.otherwise(root);
+
+ checkNodes(f, root, [
+ '<Empty name=llparse__n_b otherwise=llparse__n_b/>',
+ ]);
+
+ checkResumptionTargets(f, [
+ 'llparse__n_b',
+ ]);
+ });
+
+ it('should generate proper resumption targets', () => {
+ b.property('i64', 'counter');
+
+ const root = b.node('root');
+ const end = b.node('end');
+ const store = b.invoke(b.code.store('counter'));
+
+ root.select({ a: 1, b: 2 }, store);
+ root.otherwise(b.error(1, 'okay'));
+
+ store.otherwise(end);
+
+ end.match('ohai', root);
+ end.match('paus', b.pause(1, 'paused').otherwise(
+ b.pause(2, 'paused').otherwise(root)));
+ end.otherwise(b.error(2, 'ohai'));
+
+ checkNodes(f, root, [
+ '<Single name=llparse__n_root k97=llparse__n_invoke_store_counter:1 ' +
+ 'k98=llparse__n_invoke_store_counter:2 ' +
+ 'otherwise-no_adv=llparse__n_error_1/>',
+ '<Invoke name=llparse__n_invoke_store_counter ' +
+ 'otherwise-no_adv=llparse__n_end/>',
+ '<Single name=llparse__n_end k111=llparse__n_end_1 ' +
+ 'k112=llparse__n_end_2 otherwise-no_adv=llparse__n_error/>',
+ '<Sequence name=llparse__n_end_1 select="686169" ' +
+ 'edge="llparse__n_root" otherwise-no_adv=llparse__n_error/>',
+ '<ErrorNode name=llparse__n_error code=2 reason="ohai"/>',
+ '<Sequence name=llparse__n_end_2 select="617573" ' +
+ 'edge="llparse__n_pause" otherwise-no_adv=llparse__n_error/>',
+ '<Pause name=llparse__n_pause otherwise-no_adv=llparse__n_pause_1/>',
+ '<Pause name=llparse__n_pause_1 otherwise-no_adv=llparse__n_root/>',
+ '<ErrorNode name=llparse__n_error_1 code=1 reason="okay"/>',
+ ]);
+
+ checkResumptionTargets(f, [
+ 'llparse__n_root',
+ 'llparse__n_end',
+ 'llparse__n_end_1',
+ 'llparse__n_end_2',
+ 'llparse__n_pause_1',
+ ]);
+ });
+
+ it('should translate Span code into Span', () => {
+ const root = b.invoke(b.code.span('my_span'));
+ root.otherwise(b.error(1, 'okay'));
+
+ const fRoot = checkNodes(f, root, [
+ '<Invoke name=llparse__n_invoke_my_span ' +
+ 'otherwise-no_adv=llparse__n_error/>',
+ '<ErrorNode name=llparse__n_error code=1 reason="okay"/>',
+ ]);
+
+ assert((fRoot.ref as any).code instanceof implementation.code.Span);
+ });
+
+ it('should translate overlapping matches', () => {
+ const root = b.node('root');
+
+ root.match('ab', root);
+ root.match('abc', root);
+ root.otherwise(b.error(123, 'hello'));
+
+ checkNodes(f, root, [
+ '<Sequence name=llparse__n_root select="6162" edge="llparse__n_root_1" otherwise-no_adv=llparse__n_error/>',
+ '<Single name=llparse__n_root_1 k99=llparse__n_root otherwise-no_adv=llparse__n_root/>',
+ '<ErrorNode name=llparse__n_error code=123 reason="hello"/>',
+ ]);
+
+ checkResumptionTargets(f, [
+ 'llparse__n_root',
+ 'llparse__n_root_1',
+ ]);
+ });
+
+ it('should translate overlapping matches with values', () => {
+ const root = b.node('root');
+ const store = b.invoke(b.code.store('counter'));
+
+ root.select({
+ ab: 1,
+ abc: 2,
+ }, store);
+ store.otherwise(root);
+ root.otherwise(b.error(123, 'hello'));
+
+ checkNodes(f, root, [
+ '<Sequence name=llparse__n_root select="6162" edge="llparse__n_root_1" otherwise-no_adv=llparse__n_error/>',
+ '<Single name=llparse__n_root_1 k99=llparse__n_invoke_store_counter:2 otherwise-no_adv=llparse__n_invoke_store_counter:1/>',
+ '<Invoke name=llparse__n_invoke_store_counter otherwise-no_adv=llparse__n_root/>',
+ '<ErrorNode name=llparse__n_error code=123 reason="hello"/>',
+ ]);
+
+ checkResumptionTargets(f, [
+ 'llparse__n_root',
+ 'llparse__n_root_1',
+ ]);
+ });
+});