Updated stale imports. Started experiment with parsing system. Got reduction scanner feature ready for use. Added several data utilities.
This commit is contained in:
31
source/data/iteration-utilities.mjs
Normal file
31
source/data/iteration-utilities.mjs
Normal file
@@ -0,0 +1,31 @@
|
||||
export class Switchable_Iterator {
|
||||
constructor(iterator=null, stack=[]) {
|
||||
Object.assign(this, { iterator, stack });
|
||||
}
|
||||
|
||||
push(iterator) {
|
||||
this.stack.push(this.iterator);
|
||||
this.switch_to(iterator);
|
||||
}
|
||||
|
||||
pop(iterator) {
|
||||
this.switch_to(this.stack.pop());
|
||||
}
|
||||
|
||||
switch_to(iterator) {
|
||||
this.iterator = iterator;
|
||||
}
|
||||
|
||||
next() {
|
||||
return this.iterator.next();
|
||||
}
|
||||
|
||||
peek() {
|
||||
return this.iterator.peek();
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
9
source/data/object-utilities.mjs
Normal file
9
source/data/object-utilities.mjs
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
export function assign_defined(target, source) {
|
||||
Object.assign(target, Object.fromEntries(Object.entries(source).filter(([k ,v]) => v !== undefined )));
|
||||
}
|
||||
|
||||
|
||||
export function assign_using_predicate(target, source, kv_predicate) {
|
||||
Object.assign(target, Object.fromEntries(Object.entries(source).filter(kv_predicate))); // Call predicate with ([k, v])
|
||||
}
|
||||
54
source/data/stack.mjs
Normal file
54
source/data/stack.mjs
Normal file
@@ -0,0 +1,54 @@
|
||||
export const DELETE_PROPERTY = Symbol('DELETE_PROPERTY');
|
||||
|
||||
|
||||
export class String_Keyed_Stack {
|
||||
constructor(target={}, stack=[]) {
|
||||
Object.assign(this, { target, stack });
|
||||
}
|
||||
|
||||
push(updates={}) {
|
||||
const frame = {}
|
||||
this.stack.push(frame);
|
||||
for (const [key, value] of Object.entries(updates)) {
|
||||
|
||||
if (key in this.target) {
|
||||
frame[key] = this.target[key];
|
||||
} else {
|
||||
frame[key] = DELETE_PROPERTY;
|
||||
}
|
||||
|
||||
if (value === DELETE_PROPERTY) {
|
||||
delete this.target[key];
|
||||
} else {
|
||||
this.target[key] = value;
|
||||
}
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
push_defined(updates={}) {
|
||||
this.push(Object.fromEntries(Object.entries(updates).filter(([k ,v]) => v !== undefined )));
|
||||
}
|
||||
|
||||
pop(copy_previous_state=false) {
|
||||
const frame = this.stack.pop();
|
||||
const { target } = this;
|
||||
|
||||
const return_value = copy_previous_state ? { ...target } : null;
|
||||
|
||||
for (const [key, value] of Object.entries(frame)) {
|
||||
if (value === DELETE_PROPERTY) {
|
||||
delete target[key];
|
||||
} else {
|
||||
target[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
get top_reverse_delta() {
|
||||
return this.stack.at(-1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -70,12 +70,15 @@ export class Abstract_RegExp_Token_Rule {
|
||||
}
|
||||
|
||||
export class RegExp_Token_Rule extends Abstract_RegExp_Token_Rule {
|
||||
constructor(pattern, identifier=this) {
|
||||
constructor(pattern, identifier=undefined) {
|
||||
super(pattern);
|
||||
Object.assign(this, { identifier });
|
||||
Object.assign(this, { identifier: identifier ?? this });
|
||||
}
|
||||
}
|
||||
|
||||
// Note: There is no clean built in way to set an end position of a RegExp pattern, the only generic way is to slice the string we match before.
|
||||
// We may at some point implement support for this (and it would only be done if end position was given)
|
||||
|
||||
export class RegExp_Tokenizer {
|
||||
constructor(rules=[], default_action=undefined) {
|
||||
Object.assign(this, { rules, default_action });
|
||||
|
||||
Reference in New Issue
Block a user