diff options
Diffstat (limited to 'llparse-builder/src/code')
-rw-r--r-- | llparse-builder/src/code/and.ts | 7 | ||||
-rw-r--r-- | llparse-builder/src/code/base.ts | 16 | ||||
-rw-r--r-- | llparse-builder/src/code/creator.ts | 184 | ||||
-rw-r--r-- | llparse-builder/src/code/field-value.ts | 9 | ||||
-rw-r--r-- | llparse-builder/src/code/field.ts | 10 | ||||
-rw-r--r-- | llparse-builder/src/code/index.ts | 15 | ||||
-rw-r--r-- | llparse-builder/src/code/is-equal.ts | 7 | ||||
-rw-r--r-- | llparse-builder/src/code/load.ts | 7 | ||||
-rw-r--r-- | llparse-builder/src/code/match.ts | 7 | ||||
-rw-r--r-- | llparse-builder/src/code/mul-add.ts | 28 | ||||
-rw-r--r-- | llparse-builder/src/code/or.ts | 7 | ||||
-rw-r--r-- | llparse-builder/src/code/span.ts | 5 | ||||
-rw-r--r-- | llparse-builder/src/code/store.ts | 7 | ||||
-rw-r--r-- | llparse-builder/src/code/test.ts | 7 | ||||
-rw-r--r-- | llparse-builder/src/code/update.ts | 7 | ||||
-rw-r--r-- | llparse-builder/src/code/value.ts | 7 |
16 files changed, 330 insertions, 0 deletions
diff --git a/llparse-builder/src/code/and.ts b/llparse-builder/src/code/and.ts new file mode 100644 index 0000000..5f78675 --- /dev/null +++ b/llparse-builder/src/code/and.ts @@ -0,0 +1,7 @@ +import { FieldValue } from './field-value'; + +export class And extends FieldValue { + constructor(field: string, value: number) { + super('match', 'and', field, value); + } +} diff --git a/llparse-builder/src/code/base.ts b/llparse-builder/src/code/base.ts new file mode 100644 index 0000000..00b479f --- /dev/null +++ b/llparse-builder/src/code/base.ts @@ -0,0 +1,16 @@ +export type Signature = 'match' | 'value'; + +/** + * Base code class. + */ +export abstract class Code { + /** + * @param signature Code signature to be used. `match` means that code takes + * no input value (from `.select()`), otherwise it must be + * `value` + * @param name External function or intrinsic name. + */ + constructor(public readonly signature: Signature, + public readonly name: string) { + } +} diff --git a/llparse-builder/src/code/creator.ts b/llparse-builder/src/code/creator.ts new file mode 100644 index 0000000..98f9296 --- /dev/null +++ b/llparse-builder/src/code/creator.ts @@ -0,0 +1,184 @@ +import * as code from './'; + +/** + * API for creating external callbacks and intrinsic operations. + */ +export class Creator { + // Callbacks to external C functions + + /** + * Create an external callback that **has no** `value` argument. + * + * This callback can be used in all `Invoke` nodes except those that are + * targets of `.select()` method. + * + * C signature of callback must be: + * + * ```c + * int name(llparse_t* state, const char* p, const char* endp) + * ``` + * + * Where `llparse_t` is parser state's type name. + * + * @param name External function name. + */ + public match(name: string): code.Match { + return new code.Match(name); + } + + /** + * Create an external callback that **has** `value` argument. + * + * This callback can be used only in `Invoke` nodes that are targets of + * `.select()` method. + * + * C signature of callback must be: + * + * ```c + * int name(llparse_t* state, const char* p, const char* endp, int value) + * ``` + * + * Where `llparse_t` is parser state's type name. + * + * @param name External function name. + */ + public value(name: string): code.Value { + return new code.Value(name); + } + + /** + * Create an external span callback. + * + * This callback can be used only in `Span` constructor. + * + * C signature of callback must be: + * + * ```c + * int name(llparse_t* state, const char* p, const char* endp) + * ``` + * + * NOTE: non-zero return value is treated as resumable error. + * + * @param name External function name. + */ + public span(name: string): code.Span { + return new code.Span(name); + } + + // Helpers + + /** + * Intrinsic operation. Stores `value` from `.select()` node into the state's + * property with the name specified by `field`, returns zero. + * + * state[field] = value; + * return 0; + * + * @param field Property name + */ + public store(field: string): code.Store { + return new code.Store(field); + } + + /** + * Intrinsic operation. Loads and returns state's property with the name + * specified by `field`. + * + * The value of the property is either truncated or zero-extended to fit into + * 32-bit unsigned integer. + * + * return state[field]; + * + * @param field Property name. + */ + public load(field: string): code.Load { + return new code.Load(field); + } + + /** + * Intrinsic operation. Takes `value` from `.select()`, state's property + * with the name `field` and does: + * + * field = state[field]; + * field *= options.base; + * field += value; + * state[field] = field; + * return 0; // or 1 on overflow + * + * Return values are: + * + * - 0 - success + * - 1 - overflow + * + * @param field Property name + * @param options See `code.MulAdd` documentation. + */ + public mulAdd(field: string, options: code.IMulAddOptions): code.MulAdd { + return new code.MulAdd(field, options); + } + + /** + * Intrinsic operation. Puts `value` integer into the state's property with + * the name specified by `field`. + * + * state[field] = value; + * return 0; + * + * @param field Property name + * @param value Integer value to be stored into the property. + */ + public update(field: string, value: number): code.Update { + return new code.Update(field, value); + } + + /** + * Intrinsic operation. Returns 1 if the integer `value` is equal to the + * state's property with the name specified by `field`. + * + * return state[field] === value ? 1 : 0; + * + * @param field Property name + * @param value Integer value to be checked against. + */ + public isEqual(field: string, value: number): code.IsEqual { + return new code.IsEqual(field, value); + } + + /** + * Intrinsic operation. + * + * state[field] &= value + * return 0; + * + * @param field Property name + * @param value Integer value + */ + public and(field: string, value: number): code.And { + return new code.And(field, value); + } + + /** + * Intrinsic operation. + * + * state[field] |= value + * return 0; + * + * @param field Property name + * @param value Integer value + */ + public or(field: string, value: number): code.Or { + return new code.Or(field, value); + } + + /** + * Intrinsic operation. + * + * return (state[field] & value) == value ? 1 : 0; + * + * @param field Property name + * @param value Integer value + */ + public test(field: string, value: number): code.Test { + return new code.Test(field, value); + } +} diff --git a/llparse-builder/src/code/field-value.ts b/llparse-builder/src/code/field-value.ts new file mode 100644 index 0000000..2ceea69 --- /dev/null +++ b/llparse-builder/src/code/field-value.ts @@ -0,0 +1,9 @@ +import { Signature } from './base'; +import { Field } from './field'; + +export abstract class FieldValue extends Field { + constructor(signature: Signature, name: string, field: string, + public readonly value: number) { + super(signature, name, field); + } +} diff --git a/llparse-builder/src/code/field.ts b/llparse-builder/src/code/field.ts new file mode 100644 index 0000000..af58c84 --- /dev/null +++ b/llparse-builder/src/code/field.ts @@ -0,0 +1,10 @@ +import * as assert from 'assert'; +import { Code, Signature } from './base'; + +export abstract class Field extends Code { + constructor(signature: Signature, name: string, + public readonly field: string) { + super(signature, name + '_' + field); + assert(!/^_/.test(field), 'Can\'t access internal field from user code'); + } +} diff --git a/llparse-builder/src/code/index.ts b/llparse-builder/src/code/index.ts new file mode 100644 index 0000000..7a651e3 --- /dev/null +++ b/llparse-builder/src/code/index.ts @@ -0,0 +1,15 @@ +export { Code } from './base'; +export { Creator } from './creator'; +export { Field } from './field'; +export { FieldValue } from './field-value'; +export { IsEqual } from './is-equal'; +export { Load } from './load'; +export { Match } from './match'; +export { IMulAddOptions, MulAdd } from './mul-add'; +export { Or } from './or'; +export { And } from './and'; +export { Span } from './span'; +export { Store } from './store'; +export { Test } from './test'; +export { Update } from './update'; +export { Value } from './value'; diff --git a/llparse-builder/src/code/is-equal.ts b/llparse-builder/src/code/is-equal.ts new file mode 100644 index 0000000..91bb957 --- /dev/null +++ b/llparse-builder/src/code/is-equal.ts @@ -0,0 +1,7 @@ +import { FieldValue } from './field-value'; + +export class IsEqual extends FieldValue { + constructor(field: string, value: number) { + super('match', 'is_equal', field, value); + } +} diff --git a/llparse-builder/src/code/load.ts b/llparse-builder/src/code/load.ts new file mode 100644 index 0000000..9f3df2e --- /dev/null +++ b/llparse-builder/src/code/load.ts @@ -0,0 +1,7 @@ +import { Field } from './field'; + +export class Load extends Field { + constructor(field: string) { + super('match', 'load', field); + } +} diff --git a/llparse-builder/src/code/match.ts b/llparse-builder/src/code/match.ts new file mode 100644 index 0000000..631376a --- /dev/null +++ b/llparse-builder/src/code/match.ts @@ -0,0 +1,7 @@ +import { Code } from './base'; + +export class Match extends Code { + constructor(name: string) { + super('match', name); + } +} diff --git a/llparse-builder/src/code/mul-add.ts b/llparse-builder/src/code/mul-add.ts new file mode 100644 index 0000000..fd648ed --- /dev/null +++ b/llparse-builder/src/code/mul-add.ts @@ -0,0 +1,28 @@ +import { Field } from './field'; + +/** + * Options for `code.mulAdd()`. + */ +export interface IMulAddOptions { + /** Value to multiply the property with in the first step */ + readonly base: number; + + /** + * Maximum value of the property. If at any point of computation the + * intermediate result exceeds it - `mulAdd` returns 1 (overflow). + */ + readonly max?: number; + + /** + * If `true` - all arithmetics perfomed by `mulAdd` will be signed. + * + * Default value: `false` + */ + readonly signed?: boolean; +} + +export class MulAdd extends Field { + constructor(field: string, public readonly options: IMulAddOptions) { + super('value', 'mul_add', field); + } +} diff --git a/llparse-builder/src/code/or.ts b/llparse-builder/src/code/or.ts new file mode 100644 index 0000000..33bd402 --- /dev/null +++ b/llparse-builder/src/code/or.ts @@ -0,0 +1,7 @@ +import { FieldValue } from './field-value'; + +export class Or extends FieldValue { + constructor(field: string, value: number) { + super('match', 'or', field, value); + } +} diff --git a/llparse-builder/src/code/span.ts b/llparse-builder/src/code/span.ts new file mode 100644 index 0000000..b97e09e --- /dev/null +++ b/llparse-builder/src/code/span.ts @@ -0,0 +1,5 @@ +import { Match } from './match'; + +export class Span extends Match { + // no-op +} diff --git a/llparse-builder/src/code/store.ts b/llparse-builder/src/code/store.ts new file mode 100644 index 0000000..84abfef --- /dev/null +++ b/llparse-builder/src/code/store.ts @@ -0,0 +1,7 @@ +import { Field } from './field'; + +export class Store extends Field { + constructor(field: string) { + super('value', 'store', field); + } +} diff --git a/llparse-builder/src/code/test.ts b/llparse-builder/src/code/test.ts new file mode 100644 index 0000000..a9d0a22 --- /dev/null +++ b/llparse-builder/src/code/test.ts @@ -0,0 +1,7 @@ +import { FieldValue } from './field-value'; + +export class Test extends FieldValue { + constructor(field: string, value: number) { + super('match', 'test', field, value); + } +} diff --git a/llparse-builder/src/code/update.ts b/llparse-builder/src/code/update.ts new file mode 100644 index 0000000..de62476 --- /dev/null +++ b/llparse-builder/src/code/update.ts @@ -0,0 +1,7 @@ +import { FieldValue } from './field-value'; + +export class Update extends FieldValue { + constructor(field: string, value: number) { + super('match', 'update', field, value); + } +} diff --git a/llparse-builder/src/code/value.ts b/llparse-builder/src/code/value.ts new file mode 100644 index 0000000..06c6fd7 --- /dev/null +++ b/llparse-builder/src/code/value.ts @@ -0,0 +1,7 @@ +import { Code } from './base'; + +export class Value extends Code { + constructor(name: string) { + super('value', name); + } +} |