Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"homepage": "https://github.com/indutny/llparse-frontend#readme",
"dependencies": {
"debug": "^3.2.6",
"llparse-builder": "^1.3.2"
"llparse-builder": "git+https://github.com/arthurschreiber/llparse-builder.git#arthur/binary-parsing"
},
"devDependencies": {
"@types/debug": "0.0.30",
Expand Down
1 change: 1 addition & 0 deletions src/container/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export class Container {
Consume: this.combine((impl) => impl.node.Consume),
Empty: this.combine((impl) => impl.node.Empty),
Error: this.combine((impl) => impl.node.Error),
Int: this.combine((impl) => impl.node.Int),
Invoke: this.combine((impl) => impl.node.Invoke),
Pause: this.combine((impl) => impl.node.Pause),
Sequence: this.combine((impl) => impl.node.Sequence),
Expand Down
67 changes: 52 additions & 15 deletions src/frontend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ export class Frontend {
} else if (node instanceof source.node.Consume) {
result = new nodeImpl.Consume(
new frontend.node.Consume(id(), node.field));
} else if (node instanceof source.node.Int) {
result = this.translateInt(node);
} else if (node instanceof source.node.SpanStart) {
result = new nodeImpl.SpanStart(
new frontend.node.SpanStart(id(), this.spanMap.get(node.span)!,
Expand All @@ -184,27 +186,37 @@ export class Frontend {

// Initialize result
const otherwise = node.getOtherwiseEdge();

if (Array.isArray(result)) {
assert(node instanceof source.node.Match);
const match = node as source.node.Match;
assert(node instanceof source.node.Match || node instanceof source.node.Int);

// TODO(indutny): move this to llparse-builder?
assert.notStrictEqual(otherwise, undefined,
`Node "${node.name}" has no \`.otherwise()\``);
if (node instanceof source.node.Match) {
// TODO(indutny): move this to llparse-builder?
assert.notStrictEqual(otherwise, undefined,
`Node "${node.name}" has no \`.otherwise()\``);

// Assign otherwise to every node of Trie
if (otherwise !== undefined) {
// Assign otherwise to every node of Trie
if (otherwise !== undefined) {
for (const child of result) {
child.ref.setOtherwise(this.translate(otherwise.node),
otherwise.noAdvance);
}
}

// Assign transform to every node of Trie
const transform = this.translateTransform(node.getTransform());
for (const child of result) {
child.ref.setOtherwise(this.translate(otherwise.node),
otherwise.noAdvance);
child.ref.setTransform(transform);
}
}
} else if (node instanceof source.node.Int) {
// TODO(indutny): move this to llparse-builder?
assert.notStrictEqual(otherwise, undefined,
`Node "${node.name}" has no \`.otherwise()\``);

// Assign transform to every node of Trie
const transform = this.translateTransform(match.getTransform());
for (const child of result) {
child.ref.setTransform(transform);
// Assign otherwise to last node of int expansion
if (otherwise !== undefined) {
result[result.length - 1].ref.setOtherwise(this.translate(otherwise.node),
otherwise.noAdvance)
}
}

assert(result.length >= 1);
Expand Down Expand Up @@ -256,6 +268,31 @@ export class Frontend {
}
}

private translateInt(node: source.node.Int) : ReadonlyArray<IWrap<frontend.node.Node>> {
const { name, field, bytes, signed, littleEndian } = node;

let result = [
new this.implementation.node.Int(
new frontend.node.Int(this.id.id(name), field, bytes, signed, littleEndian, 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Let's split it into multiple statements. Something like: const tmp = new frontend.node.Int(...).

)
];

// Break loops
this.map.set(node, result[0]);

let next = result[0];
for (let offset = 1; offset < node.bytes; offset++) {
result[offset] = new this.implementation.node.Int(
new frontend.node.Int(this.id.id(name + '_byte' + (offset + 1)), field, bytes, signed, littleEndian, offset)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: similar recommendation here. Perhaps even move this.id.id() to a separate statement too. Also, would be great opportunity to use template syntax here: ${name}_byte${offset + 1}.

);

next.ref.setOtherwise(result[offset], false);
next = result[offset];
}

return result;
}

private translateMatch(node: source.node.Match): MatchResult {
const trie = new Trie(node.name);

Expand Down
1 change: 1 addition & 0 deletions src/implementation/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface INodeImplementation {
readonly Consume: new(n: node.Consume) => IWrap<node.Consume>;
readonly Empty: new(n: node.Empty) => IWrap<node.Empty>;
readonly Error: new(n: node.Error) => IWrap<node.Error>;
readonly Int: new(n: node.Int) => IWrap<node.Int>;
readonly Invoke: new(n: node.Invoke) => IWrap<node.Invoke>;
readonly Pause: new(n: node.Pause) => IWrap<node.Pause>;
readonly Sequence: new(n: node.Sequence) => IWrap<node.Sequence>;
Expand Down
1 change: 1 addition & 0 deletions src/node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './base';
export * from './consume';
export * from './empty';
export * from './error';
export * from './int';
export * from './invoke';
export * from './match';
export * from './pause';
Expand Down
8 changes: 8 additions & 0 deletions src/node/int.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { IUniqueName } from '../utils';
import { Node } from './base';

export class Int extends Node {
constructor(id: IUniqueName, readonly field: string, public readonly bytes: number, public readonly signed: boolean, public readonly littleEndian: boolean, public readonly byteOffset: number) {
super(id);
}
}