diff --git a/package-lock.json b/package-lock.json index a581084..f88fe21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -404,9 +404,8 @@ } }, "llparse-builder": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/llparse-builder/-/llparse-builder-1.3.2.tgz", - "integrity": "sha512-0l2slf0O7TpzR+uWsENSCbMv+kdAgLC9eBuaLZYpXKYGg5bD4o4xX9MRKw8a51Prce+HvkpEWpR+8d/VYGpQpg==", + "version": "git+https://github.com/arthurschreiber/llparse-builder.git#591065e9eb043a068547f35c951b533e91a58b99", + "from": "git+https://github.com/arthurschreiber/llparse-builder.git#arthur/binary-parsing", "requires": { "@types/debug": "0.0.30", "binary-search": "^1.3.3", @@ -414,12 +413,11 @@ } }, "llparse-frontend": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/llparse-frontend/-/llparse-frontend-1.2.1.tgz", - "integrity": "sha512-7n7NHAU2ZVNP/7S3llhvScY5FoDzMbPo5Le1lYr3JMAH91EPOxEbCxristRtMVcGKgij8qb2Ar7SBeu4mnb++g==", + "version": "git+https://github.com/arthurschreiber/llparse-frontend.git#14aa483f7ffd6048db768d77e07c7e8231844f5f", + "from": "git+https://github.com/arthurschreiber/llparse-frontend.git#arthur/binary-parsing", "requires": { "debug": "^3.2.6", - "llparse-builder": "^1.3.2" + "llparse-builder": "git+https://github.com/arthurschreiber/llparse-builder.git#arthur/binary-parsing" } }, "llparse-test-fixture": { diff --git a/package.json b/package.json index d17c866..6c11745 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,6 @@ "dependencies": { "bitcode": "^1.2.0", "debug": "^3.2.6", - "llparse-frontend": "^1.2.1" + "llparse-frontend": "git+https://github.com/arthurschreiber/llparse-frontend.git#arthur/binary-parsing" } } diff --git a/src/implementation/bitcode/node/index.ts b/src/implementation/bitcode/node/index.ts index 3ee9305..aa2ec03 100644 --- a/src/implementation/bitcode/node/index.ts +++ b/src/implementation/bitcode/node/index.ts @@ -4,6 +4,7 @@ import { Consume } from './consume'; import { Empty } from './empty'; import { Error as ErrorNode } from './error'; import { Invoke } from './invoke'; +import { Int } from './int'; import { Pause } from './pause'; import { Sequence } from './sequence'; import { Single } from './single'; @@ -17,6 +18,7 @@ export default { Consume, Empty, Error: class Error extends ErrorNode {}, + Int, Invoke, Pause, Sequence, diff --git a/src/implementation/bitcode/node/int.ts b/src/implementation/bitcode/node/int.ts new file mode 100644 index 0000000..b450913 --- /dev/null +++ b/src/implementation/bitcode/node/int.ts @@ -0,0 +1,19 @@ +import * as assert from 'assert'; +import * as frontend from 'llparse-frontend'; + +import { Code } from '../code'; +import { IRBasicBlock, IRValue } from '../compilation'; +import { CONTAINER_KEY } from '../constants'; +import { INodePosition, Node } from './base'; + +export class Int extends Node { + protected doBuild(bb: IRBasicBlock, pos: INodePosition): void { + const otherwise = this.ref.otherwise!; + + if (!otherwise.noAdvance) { + bb = this.prologue(bb, pos); + } + + this.tailTo(bb, otherwise, pos); + } +} diff --git a/src/implementation/c/node/index.ts b/src/implementation/c/node/index.ts index ba751d9..f50ea9f 100644 --- a/src/implementation/c/node/index.ts +++ b/src/implementation/c/node/index.ts @@ -3,6 +3,7 @@ import * as frontend from 'llparse-frontend'; import { Consume } from './consume'; import { Empty } from './empty'; import { Error as ErrorNode } from './error'; +import { Int } from './int'; import { Invoke } from './invoke'; import { Pause } from './pause'; import { Sequence } from './sequence'; @@ -17,6 +18,7 @@ export default { Consume, Empty, Error: class Error extends ErrorNode {}, + Int, Invoke, Pause, Sequence, diff --git a/src/implementation/c/node/int.ts b/src/implementation/c/node/int.ts new file mode 100644 index 0000000..1c3c7e6 --- /dev/null +++ b/src/implementation/c/node/int.ts @@ -0,0 +1,10 @@ +import * as frontend from 'llparse-frontend'; + +import { Compilation } from '../compilation'; +import { Node } from './base'; + +export class Int extends Node { + public doBuild(out: string[]): void { + + } +} diff --git a/src/implementation/js/node/index.ts b/src/implementation/js/node/index.ts index ba751d9..f50ea9f 100644 --- a/src/implementation/js/node/index.ts +++ b/src/implementation/js/node/index.ts @@ -3,6 +3,7 @@ import * as frontend from 'llparse-frontend'; import { Consume } from './consume'; import { Empty } from './empty'; import { Error as ErrorNode } from './error'; +import { Int } from './int'; import { Invoke } from './invoke'; import { Pause } from './pause'; import { Sequence } from './sequence'; @@ -17,6 +18,7 @@ export default { Consume, Empty, Error: class Error extends ErrorNode {}, + Int, Invoke, Pause, Sequence, diff --git a/src/implementation/js/node/int.ts b/src/implementation/js/node/int.ts new file mode 100644 index 0000000..11f8ee8 --- /dev/null +++ b/src/implementation/js/node/int.ts @@ -0,0 +1,355 @@ +import * as frontend from 'llparse-frontend'; + +import { Node } from './base'; + +export class Int extends Node { + public doBuild(out: string[]): void { + this.prologue(out); + + switch (this.ref.bytes) { + case 1: { + if (this.ref.signed) { + this.readInt8(out); + } else { + this.readUInt8(out); + } + break; + } + + case 2: { + if (this.ref.littleEndian) { + if (this.ref.signed) { + this.readInt16LE(out); + } else { + this.readUInt16LE(out); + } + } else { + if (this.ref.signed) { + this.readInt16BE(out); + } else { + this.readUInt16BE(out); + } + } + break; + } + + case 3: { + if (this.ref.littleEndian) { + if (this.ref.signed) { + this.readInt24LE(out); + } else { + this.readUInt24LE(out); + } + } else { + if (this.ref.signed) { + this.readInt24BE(out); + } else { + this.readUInt24BE(out); + } + } + break; + } + + case 4: { + if (this.ref.littleEndian) { + if (this.ref.signed) { + this.readInt32LE(out); + } else { + this.readUInt32LE(out); + } + } else { + if (this.ref.signed) { + this.readInt32BE(out); + } else { + this.readUInt32BE(out); + } + } + break; + } + } + + this.tailTo(out, this.ref.otherwise!); + } + + private readInt8(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + out.push(`${index} = (${ctx.bufArg()}[${ctx.offArg()}] & 2 ** 7) * 0x1fffffe;`); + } + + private readUInt8(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`); + } + + private readInt16LE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + out.push(`${index} |= (${index} & 2 ** 15) * 0x1fffe;`); + break; + } + } + } + + private readUInt16LE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + } + } + + private readInt24LE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 2: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`); + out.push(`${index} |= (${index} & 2 ** 23) * 0x1fe`); + break; + } + } + } + + private readUInt24LE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 2: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`); + break; + } + } + } + + private readInt32LE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 2: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`); + break; + } + + case 3: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] << 24;`); // Overflow + break; + } + } + } + + private readUInt32LE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 2: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`); + break; + } + + case 3: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 24;`); + break; + } + } + } + + private readInt16BE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`); + out.push(`${index} |= (${index} & 2 ** 15) * 0x1fffe;`); + break; + } + } + } + + private readUInt16BE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`); + break; + } + } + } + + private readInt24BE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 2: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`); + out.push(`${index} |= (${index} & 2 ** 23) * 0x1fe;`); + break; + } + } + } + + private readUInt24BE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 2: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`); + break; + } + } + } + + private readInt32BE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}] << 24;`); // Overflow + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`); + break; + } + + case 2: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 3: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`); + break; + } + } + } + + private readUInt32BE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 24;`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`); + break; + } + + case 2: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 3: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`); + break; + } + } + } +}