Split grammar (#15)

* Move grammar parsers to entity classes

* Fix includes

* Fix Entity5 test

* Small detail

* Fix unknown keys entities

* Persistent grammar objects

* Fix grammar

* Grammar from variable
This commit is contained in:
barsdeveloper
2023-09-18 21:13:28 +02:00
committed by GitHub
parent 872bdb7128
commit 78c62ee59a
48 changed files with 1807 additions and 1845 deletions

View File

@@ -1,4 +1,5 @@
import IntegerEntity from "./IntegerEntity.js"
import Grammar from "../serialization/Grammar.js"
export default class ByteEntity extends IntegerEntity {
@@ -9,10 +10,14 @@ export default class ByteEntity extends IntegerEntity {
predicate: v => v % 1 == 0 && v >= 0 && v < 1 << 8,
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.byteNumber.map(v => new this(v))
}
constructor(values = 0) {
super(values)

View File

@@ -1,3 +1,4 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
export default class ColorChannelEntity extends IEntity {
@@ -8,10 +9,14 @@ export default class ColorChannelEntity extends IEntity {
default: 0,
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.number.map(value => new this(value))
}
constructor(values = 0) {
if (values.constructor !== Object) {

View File

@@ -1,5 +1,12 @@
import EnumEntity from "./EnumEntity.js"
import Grammar from "../serialization/Grammar.js"
import Parsimmon from "parsimmon"
export default class EnumDisplayValueEntity extends EnumEntity {
static grammar = this.createGrammar()
static createGrammar() {
return Parsimmon.regex(Grammar.Regex.InsideString).map(v => new this(v))
}
}

View File

@@ -1,5 +1,11 @@
import Grammar from "../serialization/Grammar.js"
import SymbolEntity from "./SymbolEntity.js"
export default class EnumEntity extends SymbolEntity {
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.symbol.map(v => new this(v))
}
}

View File

@@ -1,6 +1,8 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
import InvariantTextEntity from "./InvariantTextEntity.js"
import LocalizedTextEntity from "./LocalizedTextEntity.js"
import Parsimmon from "parsimmon"
import Union from "./Union.js"
export default class FormatTextEntity extends IEntity {
@@ -13,10 +15,30 @@ export default class FormatTextEntity extends IEntity {
default: [],
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Parsimmon.lazy(() =>
Parsimmon.seq(
Grammar.regexMap(
// Resulting regex: /(LOCGEN_FORMAT_NAMED|LOCGEN_FORMAT_ORDERED)\s*/
new RegExp(`(${this.lookbehind.values.reduce((acc, cur) => acc + "|" + cur)})\\s*`),
result => result[1]
),
Grammar.grammarFor(this.attributes.value)
)
.map(([lookbehind, values]) => {
const result = new this({
value: values,
})
result.lookbehind = lookbehind
return result
})
)
}
constructor(values) {
super(values)

View File

@@ -1,3 +1,4 @@
import Grammar from "../serialization/Grammar.js"
import GuidEntity from "./GuidEntity.js"
import IEntity from "./IEntity.js"
import ObjectReferenceEntity from "./ObjectReferenceEntity.js"
@@ -16,10 +17,14 @@ export default class FunctionReferenceEntity extends IEntity {
type: GuidEntity,
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.createEntityGrammar(this)
}
constructor(values) {
super(values)

View File

@@ -1,3 +1,4 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
export default class GuidEntity extends IEntity {
@@ -8,10 +9,14 @@ export default class GuidEntity extends IEntity {
default: "",
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.guid.map(v => new this(v))
}
static generateGuid(random = true) {
let values = new Uint32Array(4)

View File

@@ -1,5 +1,6 @@
import ComputedType from "./ComputedType.js"
import MirroredEntity from "./MirroredEntity.js"
import Serializable from "../serialization/Serializable.js"
import SerializerFactory from "../serialization/SerializerFactory.js"
import Union from "./Union.js"
import Utility from "../Utility.js"
@@ -42,7 +43,7 @@ import Utility from "../Utility.js"
* }} TypeGetter
*/
export default class IEntity {
export default class IEntity extends Serializable {
/** @type {String | Union<String[]>} */
static lookbehind = ""
@@ -62,6 +63,7 @@ export default class IEntity {
}
constructor(values = {}, suppressWarns = false) {
super()
/** @type {String} */ this.lookbehind
const Self = /** @type {EntityConstructor} */(this.constructor)
let attributes = Self.attributes
@@ -86,6 +88,9 @@ export default class IEntity {
const valuesNames = Object.keys(values)
const attributesNames = Object.keys(attributes)
const allAttributesNames = Utility.mergeArrays(valuesNames, attributesNames)
if (valuesNames.includes("lookbehind")) {
this.lookbehind = undefined // To keep it first
}
for (const attributeName of allAttributesNames) {
if (attributeName == "attributes") {
continue
@@ -219,6 +224,11 @@ export default class IEntity {
}
}
/**
* @template {new (...args: any) => any} C
* @param {C} type
* @returns {value is InstanceType<C>}
*/
static isValueOfType(value, type) {
return value != null && (value instanceof type || value.constructor === type)
}

View File

@@ -1,3 +1,4 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
export default class IdentifierEntity extends IEntity {
@@ -8,15 +9,18 @@ export default class IdentifierEntity extends IEntity {
default: "",
},
}
static {
this.cleanupAttributes(this.attributes)
}
static attributeConverter = {
fromAttribute: (value, type) => new IdentifierEntity(value),
toAttribute: (value, type) => value.toString()
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.symbol.map(v => new this(v))
}
constructor(values) {
if (values.constructor !== Object) {

View File

@@ -1,3 +1,4 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
export default class Integer64Entity extends IEntity {
@@ -9,10 +10,14 @@ export default class Integer64Entity extends IEntity {
predicate: v => v >= -(1n << 63n) && v < 1n << 63n,
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.bigInt.map(v => new this(v))
}
/** @param {BigInt | Number} value */
constructor(value = 0) {

View File

@@ -1,3 +1,4 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
export default class IntegerEntity extends IEntity {
@@ -9,10 +10,14 @@ export default class IntegerEntity extends IEntity {
predicate: v => v % 1 == 0 && v > 1 << 31 && v < -(1 << 31),
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.integer.map(v => new this(v))
}
constructor(value = 0) {
if (value.constructor !== Object) {

View File

@@ -1,4 +1,6 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
import Parsimmon from "parsimmon"
export default class InvariantTextEntity extends IEntity {
@@ -9,10 +11,23 @@ export default class InvariantTextEntity extends IEntity {
default: "",
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Parsimmon.alt(
Parsimmon.seq(
Parsimmon.regex(new RegExp(`${this.lookbehind}\\s*\\(`)),
Grammar.grammarFor(this.attributes.value),
Parsimmon.regex(/\s*\)/)
)
.map(([_0, value, _2]) => value),
Parsimmon.regex(new RegExp(this.lookbehind)) // InvariantTextEntity can not have arguments
.map(() => "")
).map(value => new this(value))
}
constructor(values) {
if (values.constructor !== Object) {

View File

@@ -1,5 +1,7 @@
import Grammar from "../serialization/Grammar.js"
import IdentifierEntity from "./IdentifierEntity.js"
import IEntity from "./IEntity.js"
import Parsimmon from "parsimmon"
export default class KeyBindingEntity extends IEntity {
@@ -24,10 +26,19 @@ export default class KeyBindingEntity extends IEntity {
type: IdentifierEntity,
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Parsimmon.alt(
IdentifierEntity.grammar.map(identifier => new this({
Key: identifier
})),
Grammar.createEntityGrammar(this)
)
}
constructor(values = {}) {
super(values, true)

View File

@@ -1,7 +1,9 @@
import ColorChannelEntity from "./ColorChannelEntity.js"
import IEntity from "./IEntity.js"
import Utility from "../Utility.js"
import { css } from "lit"
import ColorChannelEntity from "./ColorChannelEntity.js"
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
import Parsimmon from "parsimmon"
import Utility from "../Utility.js"
export default class LinearColorEntity extends IEntity {
@@ -42,10 +44,10 @@ export default class LinearColorEntity extends IEntity {
ignored: true,
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
/** @param {Number} x */
static linearToSRGB(x) {
@@ -81,6 +83,69 @@ export default class LinearColorEntity extends IEntity {
})
}
static createGrammar() {
return Grammar.createEntityGrammar(this, false)
}
static getLinearColorFromHexGrammar() {
return Grammar.regexMap(new RegExp(
`#(${Grammar.Regex.HexDigit.source
}{2})(${Grammar.Regex.HexDigit.source
}{2})(${Grammar.Regex.HexDigit.source
}{2})(${Grammar.Regex.HexDigit.source
}{2})?`
),
v => [v[1], v[2], v[3], v[4] ?? "FF"])
.map(([R, G, B, A]) => new this({
R: parseInt(R, 16) / 255,
G: parseInt(G, 16) / 255,
B: parseInt(B, 16) / 255,
A: parseInt(A, 16) / 255,
}))
}
static getLinearColorRGBListGrammar() {
return Parsimmon.seq(
Grammar.byteNumber,
Grammar.commaSeparation,
Grammar.byteNumber,
Grammar.commaSeparation,
Grammar.byteNumber,
).map(([R, _1, G, _3, B]) => new this({
R: R / 255,
G: G / 255,
B: B / 255,
A: 1,
}))
}
static getLinearColorRGBGrammar() {
return Parsimmon.seq(
Parsimmon.regex(/rgb\s*\(\s*/),
this.getLinearColorRGBListGrammar(),
Parsimmon.regex(/\s*\)/)
)
.map(([_0, linearColor, _2]) => linearColor)
}
static getLinearColorRGBAGrammar() {
return Parsimmon.seq(
Parsimmon.regex(/rgba\s*\(\s*/),
this.getLinearColorRGBListGrammar(),
Parsimmon.regex(/\s*\)/)
)
.map(([_0, linearColor, _2]) => linearColor)
}
static getLinearColorFromAnyFormat() {
return Parsimmon.alt(
this.getLinearColorFromHexGrammar(),
this.getLinearColorRGBAGrammar(),
this.getLinearColorRGBGrammar(),
this.getLinearColorRGBListGrammar(),
)
}
constructor(values) {
if (values instanceof Array) {
values = {

View File

@@ -1,3 +1,4 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
import Utility from "../Utility.js"
@@ -16,10 +17,29 @@ export default class LocalizedTextEntity extends IEntity {
default: "",
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.regexMap(
new RegExp(
String.raw`${this.lookbehind}\s*\(`
+ String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*,`
+ String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*,`
+ String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*`
+ String.raw`(?:,\s+)?`
+ String.raw`\)`,
"m"
),
matchResult => new this({
namespace: Utility.unescapeString(matchResult[1]),
key: Utility.unescapeString(matchResult[2]),
value: Utility.unescapeString(matchResult[3]),
})
)
}
constructor(values) {
super(values)

View File

@@ -1,3 +1,4 @@
import Grammar from "../serialization/Grammar.js"
import GuidEntity from "./GuidEntity.js"
import IEntity from "./IEntity.js"
import ObjectReferenceEntity from "./ObjectReferenceEntity.js"
@@ -19,10 +20,14 @@ export default class MacroGraphReferenceEntity extends IEntity {
default: () => new GuidEntity(),
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.createEntityGrammar(this)
}
constructor(values) {
super(values)

View File

@@ -1,8 +1,15 @@
import Grammar from "../serialization/Grammar.js"
import IntegerEntity from "./IntegerEntity.js"
import Utility from "../Utility.js"
export default class NaturalNumberEntity extends IntegerEntity {
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.naturalNumber.map(v => new this(v))
}
constructor(values = 0) {
super(values)
this.value = Math.round(Utility.clamp(this.value, 0))

View File

@@ -1,5 +1,6 @@
import Configuration from "../Configuration.js"
import FunctionReferenceEntity from "./FunctionReferenceEntity.js"
import Grammar from "../serialization/Grammar.js"
import GuidEntity from "./GuidEntity.js"
import IdentifierEntity from "./IdentifierEntity.js"
import IEntity from "./IEntity.js"
@@ -8,6 +9,7 @@ import LinearColorEntity from "./LinearColorEntity.js"
import MacroGraphReferenceEntity from "./MacroGraphReferenceEntity.js"
import MirroredEntity from "./MirroredEntity.js"
import ObjectReferenceEntity from "./ObjectReferenceEntity.js"
import Parsimmon from "parsimmon"
import PinEntity from "./PinEntity.js"
import SVGIcon from "../SVGIcon.js"
import SymbolEntity from "./SymbolEntity.js"
@@ -20,13 +22,41 @@ import VariableReferenceEntity from "./VariableReferenceEntity.js"
export default class ObjectEntity extends IEntity {
static #keyName = {
"A_AccentGrave": "à",
"Add": "Num +",
"C_Cedille": "ç",
"Decimal": "Num .",
"Divide": "Num /",
"E_AccentAigu": "é",
"E_AccentGrave": "è",
"F1": "F1", // Otherwise F and number will be separated
"F10": "F10",
"F11": "F11",
"F12": "F12",
"F2": "F2",
"F3": "F3",
"F4": "F4",
"F5": "F5",
"F6": "F6",
"F7": "F7",
"F8": "F8",
"F9": "F9",
"Gamepad_Special_Left_X": "Touchpad Button X Axis",
"Gamepad_Special_Left_Y": "Touchpad Button Y Axis",
"Mouse2D": "Mouse XY 2D-Axis",
"Multiply": "Num *",
"Section": "§",
"Subtract": "Num -",
"Tilde": "`",
}
static attributes = {
...super.attributes,
Class: {
type: ObjectReferenceEntity,
},
Name: {
default: "",
type: String,
},
Archetype: {
type: ObjectReferenceEntity,
@@ -277,41 +307,86 @@ export default class ObjectEntity extends IEntity {
type: [new Union(PinEntity, UnknownPinEntity)],
},
}
static nameRegex = /^(\w+?)(?:_(\d+))?$/
static sequencerScriptingNameRegex = /\/Script\/SequencerScripting\.MovieSceneScripting(.+)Channel/
static #keyName = {
"A_AccentGrave": "à",
"Add": "Num +",
"C_Cedille": "ç",
"Decimal": "Num .",
"Divide": "Num /",
"E_AccentAigu": "é",
"E_AccentGrave": "è",
"F1": "F1", // Otherwise F and number will be separated
"F10": "F10",
"F11": "F11",
"F12": "F12",
"F2": "F2",
"F3": "F3",
"F4": "F4",
"F5": "F5",
"F6": "F6",
"F7": "F7",
"F8": "F8",
"F9": "F9",
"Gamepad_Special_Left_X": "Touchpad Button X Axis",
"Gamepad_Special_Left_Y": "Touchpad Button Y Axis",
"Mouse2D": "Mouse XY 2D-Axis",
"Multiply": "Num *",
"Section": "§",
"Subtract": "Num -",
"Tilde": "`",
}
static {
this.cleanupAttributes(this.attributes)
}
static nameRegex = /^(\w+?)(?:_(\d+))?$/
static sequencerScriptingNameRegex = /\/Script\/SequencerScripting\.MovieSceneScripting(.+)Channel/
static customPropertyGrammar = Parsimmon.seq(
Parsimmon.regex(/CustomProperties\s+/),
Grammar.grammarFor(
undefined,
(this.attributes.CustomProperties ?? ObjectEntity.attributes.CustomProperties).type[0]
),
).map(([_0, pin]) => values => {
if (!values.CustomProperties) {
values.CustomProperties = []
}
values.CustomProperties.push(pin)
})
static inlinedArrayEntryGrammar = Parsimmon.seq(
Parsimmon.alt(
Grammar.symbolQuoted.map(v => [v, true]),
Grammar.symbol.map(v => [v, false]),
),
Grammar.regexMap(
new RegExp(`\\s*\\(\\s*(\\d+)\\s*\\)\\s*\\=\\s*`),
v => Number(v[1])
)
)
.chain(
/** @param {[[String, Boolean], Number]} param */
([[symbol, quoted], index]) =>
Grammar.grammarFor(this.attributes[symbol])
.map(currentValue =>
values => {
(values[symbol] ??= [])[index] = currentValue
Utility.objectSet(values, ["attributes", symbol, "quoted"], quoted, true)
if (!this.attributes[symbol]?.inlined) {
if (!values.attributes) {
IEntity.defineAttributes(values, {})
}
Utility.objectSet(values, ["attributes", symbol, "inlined"], true, true)
}
}
)
)
static grammar = this.createGrammar()
static createSubObjectGrammar() {
return Parsimmon.lazy(() =>
this.createGrammar()
.map(object =>
values => values[Configuration.subObjectAttributeNameFromEntity(object)] = object
)
)
}
static createGrammar() {
return Parsimmon.seq(
Parsimmon.regex(/Begin\s+Object/),
Parsimmon.seq(
Parsimmon.whitespace,
Parsimmon.alt(
this.customPropertyGrammar,
Grammar.createAttributeGrammar(this),
Grammar.createAttributeGrammar(this, Grammar.attributeNameQuoted, undefined, (obj, k, v) =>
Utility.objectSet(obj, ["attributes", ...k, "quoted"], true, true)
),
this.inlinedArrayEntryGrammar,
this.createSubObjectGrammar()
)
)
.map(([_0, entry]) => entry)
.many(),
Parsimmon.regex(/\s+End\s+Object/),
)
.map(([_0, attributes, _2]) => {
let values = {}
attributes.forEach(attributeSetter => attributeSetter(values))
return new this(values)
})
}
/** @param {String} value */
static keyName(value) {
@@ -332,6 +407,21 @@ export default class ObjectEntity extends IEntity {
}
}
static getMultipleObjectsGrammar() {
return Parsimmon.seq(
Parsimmon.optWhitespace,
this.grammar,
Parsimmon.seq(
Parsimmon.whitespace,
this.grammar,
)
.map(([_0, object]) => object)
.many(),
Parsimmon.optWhitespace
)
.map(([_0, first, remaining, _4]) => [first, ...remaining])
}
constructor(values = {}, suppressWarns = false) {
let keys = Object.keys(values)
if (keys.some(k => k.startsWith(Configuration.subObjectAttributeNamePrefix))) {
@@ -1043,8 +1133,9 @@ export default class ObjectEntity extends IEntity {
return undefined
}
switch (this.getType()) {
case Configuration.paths.asyncAction:
case Configuration.paths.addDelegate:
case Configuration.paths.asyncAction:
case Configuration.paths.callDelegate:
case Configuration.paths.createDelegate:
case Configuration.paths.functionEntry:
case Configuration.paths.functionResult:

View File

@@ -1,6 +1,8 @@
import Configuration from "../Configuration.js"
import Utility from "../Utility.js"
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
import Parsimmon from "parsimmon"
import Utility from "../Utility.js"
export default class ObjectReferenceEntity extends IEntity {
@@ -13,10 +15,34 @@ export default class ObjectReferenceEntity extends IEntity {
default: "",
},
}
static {
this.cleanupAttributes(this.attributes)
}
static noneReferenceGrammar = Parsimmon.string("None").map(() => this.createNoneInstance())
static fullReferenceGrammar = Parsimmon.seq(
Grammar.typeReference,
Parsimmon.regex(Grammar.Regex.InlineOptWhitespace),
Grammar.pathQuotes
)
.map(([type, _2, path]) =>
new this({ type: type, path: path })
)
static typeReferenceGrammar = Grammar.typeReference.map(v =>
new this({ type: v, path: "" })
)
static pathReferenceGrammar = Grammar.path.map(path =>
new this({ type: "", path: path })
)
static grammar = this.createGrammar()
static createGrammar() {
return Parsimmon.alt(
this.noneReferenceGrammar,
this.fullReferenceGrammar,
this.typeReferenceGrammar,
this.pathReferenceGrammar,
)
}
constructor(values = {}) {
if (values.constructor === String) {

View File

@@ -1,3 +1,4 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
export default class PathSymbolEntity extends IEntity {
@@ -8,10 +9,14 @@ export default class PathSymbolEntity extends IEntity {
default: "",
},
}
static {
this.cleanupAttributes(this.attributes)
}
static #grammar = Grammar.symbol.map(v => new PathSymbolEntity(v))
static createGrammar() {
return PathSymbolEntity.#grammar
}
constructor(values) {
if (values.constructor !== Object) {

View File

@@ -4,6 +4,7 @@ import Configuration from "../Configuration.js"
import EnumDisplayValueEntity from "./EnumDisplayValueEntity.js"
import EnumEntity from "./EnumEntity.js"
import FormatTextEntity from "./FormatTextEntity.js"
import Grammar from "../serialization/Grammar.js"
import GuidEntity from "./GuidEntity.js"
import IEntity from "./IEntity.js"
import Integer64Entity from "./Integer64Entity.js"
@@ -127,10 +128,14 @@ export default class PinEntity extends IEntity {
default: false,
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.createEntityGrammar(this)
}
constructor(values = {}, suppressWarns = false) {
super(values, suppressWarns)

View File

@@ -1,5 +1,6 @@
import GuidEntity from "./GuidEntity.js"
import IEntity from "./IEntity.js"
import Parsimmon from "parsimmon"
import PathSymbolEntity from "./PathSymbolEntity.js"
export default class PinReferenceEntity extends IEntity {
@@ -13,10 +14,23 @@ export default class PinReferenceEntity extends IEntity {
type: GuidEntity,
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Parsimmon.seq(
PathSymbolEntity.createGrammar(),
Parsimmon.whitespace,
GuidEntity.createGrammar()
).map(
([objectName, _1, pinGuid]) => new this({
objectName: objectName,
pinGuid: pinGuid,
})
)
}
constructor(values) {
super(values)

View File

@@ -1,4 +1,5 @@
import FunctionReferenceEntity from "./FunctionReferenceEntity.js"
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
import ObjectReferenceEntity from "./ObjectReferenceEntity.js"
import PathSymbolEntity from "./PathSymbolEntity.js"
@@ -44,10 +45,14 @@ export default class PinTypeEntity extends IEntity {
default: false,
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.createEntityGrammar(this)
}
constructor(values = {}, suppressWarns = false) {
super(values, suppressWarns)

View File

@@ -1,3 +1,4 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
export default class RotatorEntity extends IEntity {
@@ -17,10 +18,14 @@ export default class RotatorEntity extends IEntity {
expected: true,
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.createEntityGrammar(this, false)
}
constructor(values) {
super(values)

View File

@@ -1,4 +1,27 @@
import Parsimmon from "parsimmon"
import RotatorEntity from "./RotatorEntity.js"
import Grammar from "../serialization/Grammar.js"
export default class SimpleSerializationRotatorEntity extends RotatorEntity {
static grammar = this.createGrammar()
static createGrammar() {
return Parsimmon.alt(
Parsimmon.seq(
Grammar.number,
Grammar.commaSeparation,
Grammar.number,
Grammar.commaSeparation,
Grammar.number,
).map(([p, _1, y, _3, r]) =>
new this({
R: r,
P: p,
Y: y,
})
),
RotatorEntity.createGrammar()
)
}
}

View File

@@ -1,4 +1,22 @@
import Grammar from "../serialization/Grammar.js"
import Parsimmon from "parsimmon"
import Vector2DEntity from "./Vector2DEntity.js"
export default class SimpleSerializationVector2DEntity extends Vector2DEntity {
static grammar = this.createGrammar()
static createGrammar() {
return Parsimmon.alt(
Parsimmon.seq(
Grammar.number,
Grammar.commaSeparation,
Grammar.number,
).map(([x, _1, y]) => new this({
X: x,
Y: y,
})),
Vector2DEntity.createGrammar()
)
}
}

View File

@@ -1,4 +1,25 @@
import Grammar from "../serialization/Grammar.js"
import Parsimmon from "parsimmon"
import VectorEntity from "./VectorEntity.js"
export default class SimpleSerializationVectorEntity extends VectorEntity {
static grammar = this.createGrammar()
static createGrammar() {
return Parsimmon.alt(
Parsimmon.seq(
Grammar.number,
Grammar.commaSeparation,
Grammar.number,
Grammar.commaSeparation,
Grammar.number,
).map(([x, _1, y, _3, z]) => new this({
X: x,
Y: y,
Z: z,
})),
VectorEntity.createGrammar()
)
}
}

View File

@@ -1,3 +1,4 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
export default class SymbolEntity extends IEntity {
@@ -8,10 +9,14 @@ export default class SymbolEntity extends IEntity {
default: "",
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.symbol.map(v => new this(v))
}
/** @param {String | Object} values */
constructor(values) {

View File

@@ -1,4 +1,6 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
import Parsimmon from "parsimmon"
export default class UnknownKeysEntity extends IEntity {
@@ -9,10 +11,38 @@ export default class UnknownKeysEntity extends IEntity {
ignored: true,
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Parsimmon.seq(
// Lookbehind
Grammar.regexMap(
new RegExp(`(${Grammar.Regex.Path.source}|${Grammar.Regex.Symbol.source}\\s*)?\\(\\s*`),
result => result[1] ?? ""
),
Grammar.attributeName
.skip(Grammar.equalSeparation)
.chain(attributeName =>
Grammar.unknownValue
.map(attributeValue =>
values => values[attributeName] = attributeValue
)
)
.sepBy1(Grammar.commaSeparation),
Parsimmon.regex(/\s*(?:,\s*)?\)/),
)
.map(([lookbehind, attributes, _2]) => {
let values = {}
if (lookbehind.length) {
values.lookbehind = lookbehind
}
attributes.forEach(attributeSetter => attributeSetter(values))
return new this(values)
})
}
constructor(values) {
super(values, true)

View File

@@ -1,8 +1,31 @@
import Parsimmon from "parsimmon"
import PinEntity from "./PinEntity.js"
import Grammar from "../serialization/Grammar.js"
export default class UnknownPinEntity extends PinEntity {
static lookbehind = ""
static grammar = this.createGrammar()
static createGrammar() {
return Parsimmon.lazy(() => Parsimmon.seq(
Grammar.regexMap(
new RegExp(`${Grammar.Regex.Symbol.source}\\s*\\(\\s*`),
result => result[1] ?? ""
),
Grammar.createAttributeGrammar(this).sepBy1(Grammar.commaSeparation),
Parsimmon.regex(/\s*(?:,\s*)?\)/)
)
.map(([lookbehind, attributes, _2]) => {
let values = {}
if (lookbehind.length) {
values.lookbehind = lookbehind
}
attributes.forEach(attributeSetter => attributeSetter(values))
return new this(values)
})
)
}
constructor(values = {}) {
super(values, true)

View File

@@ -1,5 +1,6 @@
import IEntity from "./IEntity.js"
import Grammar from "../serialization/Grammar.js"
import GuidEntity from "./GuidEntity.js"
import IEntity from "./IEntity.js"
export default class VariableReferenceEntity extends IEntity {
@@ -18,10 +19,14 @@ export default class VariableReferenceEntity extends IEntity {
type: Boolean,
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.createEntityGrammar(this)
}
constructor(values) {
super(values)

View File

@@ -1,3 +1,4 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
export default class Vector2DEntity extends IEntity {
@@ -13,10 +14,14 @@ export default class Vector2DEntity extends IEntity {
expected: true,
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.createEntityGrammar(this, false)
}
constructor(values) {
super(values)

View File

@@ -1,3 +1,4 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
export default class VectorEntity extends IEntity {
@@ -17,10 +18,14 @@ export default class VectorEntity extends IEntity {
expected: true,
},
}
static {
this.cleanupAttributes(this.attributes)
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.createEntityGrammar(VectorEntity, false)
}
constructor(values) {
super(values)