mirror of
https://github.com/barsdeveloper/ueblueprint.git
synced 2026-03-06 15:47:30 +08:00
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:
@@ -97,6 +97,7 @@ export default class Configuration {
|
||||
blueprintMapLibrary: "/Script/Engine.BlueprintMapLibrary",
|
||||
blueprintSetLibrary: "/Script/Engine.BlueprintSetLibrary",
|
||||
callArrayFunction: "/Script/BlueprintGraph.K2Node_CallArrayFunction",
|
||||
callDelegate: "/Script/BlueprintGraph.K2Node_CallDelegate",
|
||||
callFunction: "/Script/BlueprintGraph.K2Node_CallFunction",
|
||||
comment: "/Script/UnrealEd.EdGraphNode_Comment",
|
||||
commutativeAssociativeBinaryOperator: "/Script/BlueprintGraph.K2Node_CommutativeAssociativeBinaryOperator",
|
||||
@@ -184,7 +185,6 @@ export default class Configuration {
|
||||
vector: "/Script/CoreUObject.Vector",
|
||||
vector2D: "/Script/CoreUObject.Vector2D",
|
||||
whileLoop: "/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:WhileLoop",
|
||||
|
||||
}
|
||||
static pinColor = {
|
||||
[this.paths.rotator]: css`157, 177, 251`,
|
||||
|
||||
@@ -246,9 +246,9 @@ export default class Utility {
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {AnyValue} T
|
||||
* @param {AnyValue} value
|
||||
* @param {AnyValueConstructor<T>} type
|
||||
* @template {new (...args: any) => any} C
|
||||
* @param {C} type
|
||||
* @returns {value is InstanceType<C>}
|
||||
*/
|
||||
static isValueOfType(value, type, acceptNull = false) {
|
||||
if (type instanceof MirroredEntity) {
|
||||
|
||||
@@ -3,7 +3,6 @@ import Configuration from "../Configuration.js"
|
||||
import ElementFactory from "./ElementFactory.js"
|
||||
import EnumPinTemplate from "../template/pin/EnumPinTemplate.js"
|
||||
import ExecPinTemplate from "../template/pin/ExecPinTemplate.js"
|
||||
import Grammar from "../serialization/Grammar.js"
|
||||
import GuidEntity from "../entity/GuidEntity.js"
|
||||
import IElement from "./IElement.js"
|
||||
import Int64PinTemplate from "../template/pin/Int64PinTemplate.js"
|
||||
@@ -61,7 +60,7 @@ export default class PinElement extends IElement {
|
||||
type: GuidEntity,
|
||||
converter: {
|
||||
fromAttribute: (value, type) => value
|
||||
? /** @type {Success<GuidEntity>} */(Grammar.guidEntity.parse(value)).value
|
||||
? /** @type {Success<GuidEntity>} */(GuidEntity.grammar.parse(value)).value
|
||||
: null,
|
||||
toAttribute: (value, type) => value?.toString(),
|
||||
},
|
||||
@@ -82,7 +81,7 @@ export default class PinElement extends IElement {
|
||||
type: LinearColorEntity,
|
||||
converter: {
|
||||
fromAttribute: (value, type) => value
|
||||
? /** @type {Success<LinearColorEntity>} */(Grammar.linearColorFromAnyFormat.parse(value)).value
|
||||
? /** @type {Success<LinearColorEntity>} */(LinearColorEntity.getLinearColorFromAnyFormat().parse(value)).value
|
||||
: null,
|
||||
toAttribute: (value, type) => value ? Utility.printLinearColor(value) : null,
|
||||
},
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import Configuration from "../../Configuration.js"
|
||||
import Grammar from "../../serialization/Grammar.js"
|
||||
import IInput from "../IInput.js"
|
||||
import KeyBindingEntity from "../../entity/KeyBindingEntity.js"
|
||||
|
||||
@@ -44,7 +43,7 @@ export default class KeyboardShortcut extends IInput {
|
||||
return v
|
||||
}
|
||||
if (typeof v === "string") {
|
||||
const parsed = Grammar.keyBindingEntity.parse(v)
|
||||
const parsed = KeyBindingEntity.createGrammar().parse(v)
|
||||
if (parsed.status) {
|
||||
return parsed.value
|
||||
}
|
||||
|
||||
@@ -1,41 +1,10 @@
|
||||
import ByteEntity from "../entity/ByteEntity.js"
|
||||
import ColorChannelEntity from "../entity/ColorChannelEntity.js"
|
||||
import Configuration from "../Configuration.js"
|
||||
import EnumDisplayValueEntity from "../entity/EnumDisplayValueEntity.js"
|
||||
import EnumEntity from "../entity/EnumEntity.js"
|
||||
import FormatTextEntity from "../entity/FormatTextEntity.js"
|
||||
import FunctionReferenceEntity from "../entity/FunctionReferenceEntity.js"
|
||||
import GuidEntity from "../entity/GuidEntity.js"
|
||||
import IdentifierEntity from "../entity/IdentifierEntity.js"
|
||||
import IEntity from "../entity/IEntity.js"
|
||||
import Integer64Entity from "../entity/Integer64Entity.js"
|
||||
import IntegerEntity from "../entity/IntegerEntity.js"
|
||||
import InvariantTextEntity from "../entity/InvariantTextEntity.js"
|
||||
import KeyBindingEntity from "../entity/KeyBindingEntity.js"
|
||||
import LinearColorEntity from "../entity/LinearColorEntity.js"
|
||||
import LocalizedTextEntity from "../entity/LocalizedTextEntity.js"
|
||||
import MacroGraphReferenceEntity from "../entity/MacroGraphReferenceEntity.js"
|
||||
import MirroredEntity from "../entity/MirroredEntity.js"
|
||||
import NaturalNumberEntity from "../entity/NaturalNumberEntity.js"
|
||||
import ObjectEntity from "../entity/ObjectEntity.js"
|
||||
import ObjectReferenceEntity from "../entity/ObjectReferenceEntity.js"
|
||||
import Parsimmon from "parsimmon"
|
||||
import PathSymbolEntity from "../entity/PathSymbolEntity.js"
|
||||
import PinEntity from "../entity/PinEntity.js"
|
||||
import PinReferenceEntity from "../entity/PinReferenceEntity.js"
|
||||
import RotatorEntity from "../entity/RotatorEntity.js"
|
||||
import SimpleSerializationRotatorEntity from "../entity/SimpleSerializationRotatorEntity.js"
|
||||
import SimpleSerializationVector2DEntity from "../entity/SimpleSerializationVector2DEntity.js"
|
||||
import SimpleSerializationVectorEntity from "../entity/SimpleSerializationVectorEntity.js"
|
||||
import SymbolEntity from "../entity/SymbolEntity.js"
|
||||
import TerminalTypeEntity from "../entity/TerminalTypeEntity.js"
|
||||
import Serializable from "./Serializable.js"
|
||||
import Union from "../entity/Union.js"
|
||||
import UnknownKeysEntity from "../entity/UnknownKeysEntity.js"
|
||||
import UnknownPinEntity from "../entity/UnknownPinEntity.js"
|
||||
import Utility from "../Utility.js"
|
||||
import VariableReferenceEntity from "../entity/VariableReferenceEntity.js"
|
||||
import Vector2DEntity from "../entity/Vector2DEntity.js"
|
||||
import VectorEntity from "../entity/VectorEntity.js"
|
||||
|
||||
/**
|
||||
* @typedef {import ("../entity/IEntity").AnyValue} AnyValue
|
||||
@@ -204,102 +173,17 @@ export default class Grammar {
|
||||
case Boolean:
|
||||
result = this.boolean
|
||||
break
|
||||
case ByteEntity:
|
||||
result = this.byteEntity
|
||||
break
|
||||
case ColorChannelEntity:
|
||||
result = this.colorChannelEntity
|
||||
break
|
||||
case EnumDisplayValueEntity:
|
||||
result = this.enumDisplayValueEntity
|
||||
break
|
||||
case EnumEntity:
|
||||
result = this.enumEntity
|
||||
break
|
||||
case FormatTextEntity:
|
||||
result = this.formatTextEntity
|
||||
break
|
||||
case FunctionReferenceEntity:
|
||||
result = this.functionReferenceEntity
|
||||
break
|
||||
case GuidEntity:
|
||||
result = this.guidEntity
|
||||
break
|
||||
case IdentifierEntity:
|
||||
result = this.identifierEntity
|
||||
break
|
||||
case Integer64Entity:
|
||||
result = this.integer64Entity
|
||||
break
|
||||
case IntegerEntity:
|
||||
result = this.integerEntity
|
||||
break
|
||||
case InvariantTextEntity:
|
||||
result = this.invariantTextEntity
|
||||
break
|
||||
case KeyBindingEntity:
|
||||
result = this.keyBindingEntity
|
||||
break
|
||||
case LinearColorEntity:
|
||||
result = this.linearColorEntity
|
||||
break
|
||||
case LocalizedTextEntity:
|
||||
result = this.localizedTextEntity
|
||||
break
|
||||
case MacroGraphReferenceEntity:
|
||||
result = this.macroGraphReferenceEntity
|
||||
break
|
||||
case Number:
|
||||
result = this.number
|
||||
break
|
||||
case ObjectReferenceEntity:
|
||||
result = this.objectReferenceEntity
|
||||
break
|
||||
case PathSymbolEntity:
|
||||
result = this.pathSymbolEntity
|
||||
break
|
||||
case PinEntity:
|
||||
result = this.pinEntity
|
||||
break
|
||||
case PinReferenceEntity:
|
||||
result = this.pinReferenceEntity
|
||||
break
|
||||
case TerminalTypeEntity:
|
||||
result = this.pinTypeEntity
|
||||
break
|
||||
case RotatorEntity:
|
||||
result = this.rotatorEntity
|
||||
break
|
||||
case SimpleSerializationRotatorEntity:
|
||||
result = this.simpleSerializationRotatorEntity
|
||||
break
|
||||
case SimpleSerializationVector2DEntity:
|
||||
result = this.simpleSerializationVector2DEntity
|
||||
break
|
||||
case SimpleSerializationVectorEntity:
|
||||
result = this.simpleSerializationVectorEntity
|
||||
break
|
||||
case String:
|
||||
result = this.string
|
||||
break
|
||||
case SymbolEntity:
|
||||
result = this.symbolEntity
|
||||
break
|
||||
case UnknownKeysEntity:
|
||||
result = this.unknownKeysEntity
|
||||
break
|
||||
case UnknownPinEntity:
|
||||
result = this.unknownPinEntity
|
||||
break
|
||||
case VariableReferenceEntity:
|
||||
result = this.variableReferenceEntity
|
||||
break
|
||||
case Vector2DEntity:
|
||||
result = this.vector2DEntity
|
||||
break
|
||||
case VectorEntity:
|
||||
result = this.vectorEntity
|
||||
break
|
||||
default:
|
||||
if (type?.prototype instanceof Serializable) {
|
||||
// @ts-expect-error
|
||||
return /** @type {typeof Serializable} */(type).grammar
|
||||
}
|
||||
}
|
||||
}
|
||||
if (attribute?.constructor === Object) {
|
||||
@@ -371,8 +255,10 @@ export default class Grammar {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {EntityConstructor} entityType
|
||||
* @template {IEntity} T
|
||||
* @param {new (...args: any) => T} entityType
|
||||
* @param {Boolean | Number} acceptUnknownKeys Number to specify the limit or true, to let it be a reasonable value
|
||||
* @returns {Parsimmon.Parser<T>}
|
||||
*/
|
||||
static createEntityGrammar = (entityType, acceptUnknownKeys = true) =>
|
||||
P.seq(
|
||||
@@ -416,438 +302,5 @@ export default class Grammar {
|
||||
|
||||
/* --- Entity --- */
|
||||
|
||||
static byteEntity = P.lazy(() => this.byteNumber.map(v => new ByteEntity(v)))
|
||||
|
||||
static colorChannelEntity = P.lazy(() => this.number.map(value => new ColorChannelEntity(value)))
|
||||
|
||||
static enumDisplayValueEntity = P.lazy(() =>
|
||||
P.regex(this.Regex.InsideString).map(v => new EnumDisplayValueEntity(v))
|
||||
)
|
||||
|
||||
static enumEntity = P.lazy(() => this.symbol.map(v => new EnumEntity(v)))
|
||||
|
||||
static formatTextEntity = P.lazy(() =>
|
||||
P.seq(
|
||||
this.regexMap(
|
||||
// Resulting regex: /(LOCGEN_FORMAT_NAMED|LOCGEN_FORMAT_ORDERED)\s*/
|
||||
new RegExp(`(${FormatTextEntity.lookbehind.values.reduce((acc, cur) => acc + "|" + cur)})\\s*`),
|
||||
result => result[1]
|
||||
),
|
||||
this.grammarFor(FormatTextEntity.attributes.value)
|
||||
)
|
||||
.map(([lookbehind, values]) => {
|
||||
const result = new FormatTextEntity({
|
||||
value: values,
|
||||
})
|
||||
result.lookbehind = lookbehind
|
||||
return result
|
||||
})
|
||||
)
|
||||
|
||||
static functionReferenceEntity = P.lazy(() => this.createEntityGrammar(FunctionReferenceEntity))
|
||||
|
||||
static guidEntity = P.lazy(() => this.guid.map(v => new GuidEntity(v)))
|
||||
|
||||
static identifierEntity = P.lazy(() => this.symbol.map(v => new IdentifierEntity(v)))
|
||||
|
||||
static integer64Entity = P.lazy(() => this.bigInt.map(v => new Integer64Entity(v)))
|
||||
|
||||
static integerEntity = P.lazy(() => this.integer.map(v => new IntegerEntity(v)))
|
||||
|
||||
static invariantTextEntity = P.lazy(() =>
|
||||
P.alt(
|
||||
P.seq(
|
||||
P.regex(new RegExp(`${InvariantTextEntity.lookbehind}\\s*\\(`)),
|
||||
this.grammarFor(InvariantTextEntity.attributes.value),
|
||||
P.regex(/\s*\)/)
|
||||
)
|
||||
.map(([_0, value, _2]) => value),
|
||||
P.regex(new RegExp(InvariantTextEntity.lookbehind)) // InvariantTextEntity can not have arguments
|
||||
.map(() => "")
|
||||
).map(value => new InvariantTextEntity(value))
|
||||
)
|
||||
|
||||
static keyBindingEntity = P.lazy(() =>
|
||||
P.alt(
|
||||
this.identifierEntity.map(identifier => new KeyBindingEntity({
|
||||
Key: identifier
|
||||
})),
|
||||
this.createEntityGrammar(KeyBindingEntity)
|
||||
)
|
||||
)
|
||||
|
||||
static linearColorEntity = P.lazy(() => this.createEntityGrammar(LinearColorEntity, false))
|
||||
|
||||
static localizedTextEntity = P.lazy(() =>
|
||||
Grammar.regexMap(
|
||||
new RegExp(
|
||||
String.raw`${LocalizedTextEntity.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 LocalizedTextEntity({
|
||||
namespace: Utility.unescapeString(matchResult[1]),
|
||||
key: Utility.unescapeString(matchResult[2]),
|
||||
value: Utility.unescapeString(matchResult[3]),
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
static macroGraphReferenceEntity = P.lazy(() => this.createEntityGrammar(MacroGraphReferenceEntity))
|
||||
|
||||
static naturalNumberEntity = P.lazy(() => this.naturalNumber.map(v => new NaturalNumberEntity(v)))
|
||||
|
||||
static noneReferenceEntity = P.lazy(() =>
|
||||
P.string("None").map(() => ObjectReferenceEntity.createNoneInstance())
|
||||
)
|
||||
|
||||
static typeReferenceEntity = P.lazy(() =>
|
||||
this.typeReference.map(v =>
|
||||
new ObjectReferenceEntity({ type: v, path: "" })
|
||||
)
|
||||
)
|
||||
|
||||
static pathReferenceEntity = P.lazy(() =>
|
||||
this.path.map(path =>
|
||||
new ObjectReferenceEntity({ type: "", path: path })
|
||||
)
|
||||
)
|
||||
|
||||
static fullReferenceEntity = P.lazy(() =>
|
||||
P.seq(this.typeReference, P.regex(Grammar.Regex.InlineOptWhitespace), this.pathQuotes)
|
||||
.map(([type, _2, path]) =>
|
||||
new ObjectReferenceEntity({ type: type, path: path })
|
||||
)
|
||||
)
|
||||
|
||||
static objectReferenceEntity = P.lazy(() =>
|
||||
P.alt(
|
||||
this.noneReferenceEntity,
|
||||
this.fullReferenceEntity,
|
||||
this.typeReferenceEntity,
|
||||
this.pathReferenceEntity,
|
||||
)
|
||||
)
|
||||
|
||||
static pathSymbolEntity = P.lazy(() => this.symbol.map(v => new PathSymbolEntity(v)))
|
||||
|
||||
static pinEntity = P.lazy(() => this.createEntityGrammar(PinEntity))
|
||||
|
||||
static pinReferenceEntity = P.lazy(() =>
|
||||
P.seq(
|
||||
this.pathSymbolEntity,
|
||||
P.whitespace,
|
||||
this.guidEntity
|
||||
).map(
|
||||
([objectName, _1, pinGuid]) => new PinReferenceEntity({
|
||||
objectName: objectName,
|
||||
pinGuid: pinGuid,
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
static pinTypeEntity = P.lazy(() => this.createEntityGrammar(TerminalTypeEntity))
|
||||
|
||||
static rotatorEntity = P.lazy(() => this.createEntityGrammar(RotatorEntity, false))
|
||||
|
||||
static simpleSerializationRotatorEntity = P.lazy(() =>
|
||||
P.alt(
|
||||
P.seq(
|
||||
this.number,
|
||||
this.commaSeparation,
|
||||
this.number,
|
||||
this.commaSeparation,
|
||||
this.number,
|
||||
).map(([p, _1, y, _3, r]) =>
|
||||
new SimpleSerializationRotatorEntity({
|
||||
R: r,
|
||||
P: p,
|
||||
Y: y,
|
||||
})
|
||||
),
|
||||
this.rotatorEntity
|
||||
)
|
||||
)
|
||||
|
||||
static vector2DEntity = P.lazy(() => this.createEntityGrammar(Vector2DEntity, false))
|
||||
|
||||
static simpleSerializationVector2DEntity = P.lazy(() =>
|
||||
P.alt(
|
||||
P.seq(
|
||||
this.number,
|
||||
this.commaSeparation,
|
||||
this.number,
|
||||
).map(([x, _1, y]) => new SimpleSerializationVector2DEntity({
|
||||
X: x,
|
||||
Y: y,
|
||||
})),
|
||||
this.vector2DEntity
|
||||
)
|
||||
)
|
||||
|
||||
static vectorEntity = P.lazy(() => this.createEntityGrammar(VectorEntity, false))
|
||||
|
||||
static simpleSerializationVectorEntity = P.lazy(() =>
|
||||
P.alt(
|
||||
P.seq(
|
||||
this.number,
|
||||
this.commaSeparation,
|
||||
this.number,
|
||||
this.commaSeparation,
|
||||
this.number,
|
||||
).map(([x, _1, y, _3, z]) => new SimpleSerializationVectorEntity({
|
||||
X: x,
|
||||
Y: y,
|
||||
Z: z,
|
||||
})),
|
||||
this.vectorEntity
|
||||
)
|
||||
)
|
||||
|
||||
static symbolEntity = P.lazy(() => this.symbol.map(v => new SymbolEntity(v)))
|
||||
|
||||
static variableReferenceEntity = P.lazy(() => this.createEntityGrammar(VariableReferenceEntity))
|
||||
|
||||
static unknownKeysEntity = P.lazy(() =>
|
||||
P.seq(
|
||||
// Lookbehind
|
||||
this.regexMap(
|
||||
new RegExp(`(${this.Regex.Path.source}\\s*)?\\(\\s*`),
|
||||
result => result[1] ?? ""
|
||||
),
|
||||
this.attributeName
|
||||
.skip(this.equalSeparation)
|
||||
.chain((attributeName) =>
|
||||
this.unknownValue
|
||||
.map(attributeValue =>
|
||||
values => values[attributeName] = attributeValue
|
||||
)
|
||||
)
|
||||
.sepBy1(this.commaSeparation),
|
||||
P.regex(/\s*(?:,\s*)?\)/),
|
||||
)
|
||||
.map(([lookbehind, attributes, _2]) => {
|
||||
let values = {}
|
||||
if (lookbehind.length) {
|
||||
values.lookbehind = lookbehind
|
||||
}
|
||||
attributes.forEach(attributeSetter => attributeSetter(values))
|
||||
return new UnknownKeysEntity(values)
|
||||
})
|
||||
)
|
||||
|
||||
static unknownPinEntity = P.lazy(() =>
|
||||
P.seq(
|
||||
this.regexMap(
|
||||
new RegExp(`${this.Regex.Symbol.source}\\s*\\(\\s*`),
|
||||
result => result[1] ?? ""
|
||||
),
|
||||
this.createAttributeGrammar(this.unknownPinEntity).sepBy1(this.commaSeparation),
|
||||
P.regex(/\s*(?:,\s*)?\)/)
|
||||
)
|
||||
.map(([lookbehind, attributes, _2]) => {
|
||||
let values = {}
|
||||
if (lookbehind.length) {
|
||||
values.lookbehind = lookbehind
|
||||
}
|
||||
attributes.forEach(attributeSetter => attributeSetter(values))
|
||||
return new UnknownPinEntity(values)
|
||||
})
|
||||
)
|
||||
|
||||
static unknownValue = P.lazy(() =>
|
||||
P.alt(
|
||||
// Remember to keep the order, otherwise parsing might fail
|
||||
this.boolean,
|
||||
this.guidEntity,
|
||||
this.noneReferenceEntity,
|
||||
this.null,
|
||||
this.number,
|
||||
this.string,
|
||||
this.fullReferenceEntity,
|
||||
this.localizedTextEntity,
|
||||
this.invariantTextEntity,
|
||||
this.formatTextEntity,
|
||||
this.pinReferenceEntity,
|
||||
this.vectorEntity,
|
||||
this.rotatorEntity,
|
||||
this.linearColorEntity,
|
||||
this.vector2DEntity,
|
||||
this.unknownKeysEntity,
|
||||
this.symbolEntity,
|
||||
this.grammarFor(undefined, [PinReferenceEntity]),
|
||||
this.grammarFor(undefined, [new Union(Number, String, SymbolEntity)]),
|
||||
)
|
||||
)
|
||||
|
||||
static customProperty = P.lazy(() =>
|
||||
P.seq(
|
||||
P.regex(/CustomProperties\s+/),
|
||||
this.grammarFor(undefined, ObjectEntity.attributes.CustomProperties.type[0]),
|
||||
).map(([_0, pin]) => values => {
|
||||
if (!values.CustomProperties) {
|
||||
values.CustomProperties = []
|
||||
}
|
||||
values.CustomProperties.push(pin)
|
||||
})
|
||||
)
|
||||
|
||||
static inlinedArrayEntry = P.lazy(() =>
|
||||
P.seq(
|
||||
P.alt(
|
||||
this.symbolQuoted.map(v => [v, true]),
|
||||
this.symbol.map(v => [v, false]),
|
||||
),
|
||||
this.regexMap(
|
||||
new RegExp(`\\s*\\(\\s*(\\d+)\\s*\\)\\s*\\=\\s*`),
|
||||
v => Number(v[1])
|
||||
)
|
||||
)
|
||||
.chain(
|
||||
/** @param {[[String, Boolean], Number]} param */
|
||||
([[symbol, quoted], index]) =>
|
||||
this.grammarFor(ObjectEntity.attributes[symbol])
|
||||
.map(currentValue =>
|
||||
values => {
|
||||
(values[symbol] ??= [])[index] = currentValue
|
||||
Utility.objectSet(values, ["attributes", symbol, "quoted"], quoted, true)
|
||||
if (!ObjectEntity.attributes[symbol]?.inlined) {
|
||||
if (!values.attributes) {
|
||||
IEntity.defineAttributes(values, {})
|
||||
}
|
||||
Utility.objectSet(values, ["attributes", symbol, "inlined"], true, true)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
static subObjectEntity = P.lazy(() =>
|
||||
this.objectEntity
|
||||
.map(object =>
|
||||
values => values[Configuration.subObjectAttributeNameFromEntity(object)] = object
|
||||
)
|
||||
)
|
||||
|
||||
/** @type {Parsimmon.Parser<ObjectEntity>} */
|
||||
static objectEntity = P.lazy(() =>
|
||||
P.seq(
|
||||
P.regex(/Begin\s+Object/),
|
||||
P.seq(
|
||||
P.whitespace,
|
||||
P.alt(
|
||||
this.customProperty,
|
||||
this.createAttributeGrammar(ObjectEntity),
|
||||
this.createAttributeGrammar(ObjectEntity, Grammar.attributeNameQuoted, undefined, (obj, k, v) =>
|
||||
Utility.objectSet(obj, ["attributes", ...k, "quoted"], true, true)
|
||||
),
|
||||
this.inlinedArrayEntry,
|
||||
this.subObjectEntity
|
||||
)
|
||||
)
|
||||
.map(([_0, entry]) => entry)
|
||||
.many(),
|
||||
P.regex(/\s+End\s+Object/),
|
||||
).map(
|
||||
([_0, attributes, _2]) => {
|
||||
let values = {}
|
||||
attributes.forEach(attributeSetter => attributeSetter(values))
|
||||
return new ObjectEntity(values)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
static multipleObject = P.lazy(() =>
|
||||
P.seq(
|
||||
P.optWhitespace,
|
||||
this.objectEntity,
|
||||
P.seq(
|
||||
P.whitespace,
|
||||
this.objectEntity,
|
||||
)
|
||||
.map(([_0, object]) => object)
|
||||
.many(),
|
||||
P.optWhitespace
|
||||
).map(([_0, first, remaining, _4]) => [first, ...remaining])
|
||||
)
|
||||
|
||||
/* --- Others --- */
|
||||
|
||||
static linearColorFromHex = P.lazy(() =>
|
||||
Grammar.regexMap(new RegExp(
|
||||
`#(${Grammar.Regex.HexDigit.source
|
||||
}{2})(${Grammar.Regex.HexDigit.source
|
||||
}{2})(${Grammar.Regex.HexDigit.source
|
||||
}{2})(${this.Regex.HexDigit.source
|
||||
}{2})?`
|
||||
),
|
||||
v => [v[1], v[2], v[3], v[4] ?? "FF"])
|
||||
.map(([R, G, B, A]) => new LinearColorEntity({
|
||||
R: parseInt(R, 16) / 255,
|
||||
G: parseInt(G, 16) / 255,
|
||||
B: parseInt(B, 16) / 255,
|
||||
A: parseInt(A, 16) / 255,
|
||||
}))
|
||||
)
|
||||
|
||||
static linearColorRGBList = P.lazy(() =>
|
||||
P.seq(
|
||||
this.byteNumber,
|
||||
this.commaSeparation,
|
||||
this.byteNumber,
|
||||
this.commaSeparation,
|
||||
this.byteNumber,
|
||||
).map(([R, _1, G, _3, B]) => new LinearColorEntity({
|
||||
R: R / 255,
|
||||
G: G / 255,
|
||||
B: B / 255,
|
||||
A: 1,
|
||||
}))
|
||||
)
|
||||
|
||||
static linearColorRGBAList = P.lazy(() =>
|
||||
P.seq(
|
||||
this.byteNumber,
|
||||
this.commaSeparation,
|
||||
this.byteNumber,
|
||||
this.commaSeparation,
|
||||
this.byteNumber,
|
||||
this.commaSeparation,
|
||||
this.byteNumber,
|
||||
).map(([R, _1, G, _3, B, _5, A]) => new LinearColorEntity({
|
||||
R: R / 255,
|
||||
G: G / 255,
|
||||
B: B / 255,
|
||||
A: A,
|
||||
}))
|
||||
)
|
||||
|
||||
static linearColorRGB = P.lazy(() =>
|
||||
P.seq(
|
||||
P.regex(/rgb\s*\(\s*/),
|
||||
this.linearColorRGBList,
|
||||
P.regex(/\s*\)/)
|
||||
).map(([_0, linearColor, _2]) => linearColor)
|
||||
)
|
||||
|
||||
static linearColorRGBA = P.lazy(() =>
|
||||
P.seq(
|
||||
P.regex(/rgba\s*\(\s*/),
|
||||
this.linearColorRGBAList,
|
||||
P.regex(/\s*\)/)
|
||||
).map(([_0, linearColor, _2]) => linearColor)
|
||||
)
|
||||
|
||||
static linearColorFromAnyFormat = P.lazy(() =>
|
||||
P.alt(
|
||||
this.linearColorFromHex,
|
||||
this.linearColorRGBA,
|
||||
this.linearColorRGB,
|
||||
this.linearColorRGBList,
|
||||
)
|
||||
)
|
||||
static unknownValue // Defined in initializeSerializerFactor to avoid circular include
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import SerializerFactory from "./SerializerFactory.js"
|
||||
|
||||
export default class ObjectSerializer extends Serializer {
|
||||
|
||||
constructor() {
|
||||
super(ObjectEntity, undefined, "\n", true, undefined, Serializer.same)
|
||||
constructor(entityType = ObjectEntity) {
|
||||
super(entityType, undefined, "\n", true, undefined, Serializer.same)
|
||||
}
|
||||
|
||||
showProperty(entity, key) {
|
||||
@@ -31,7 +31,7 @@ export default class ObjectSerializer extends Serializer {
|
||||
|
||||
/** @param {String} value */
|
||||
doRead(value) {
|
||||
const parseResult = Grammar.objectEntity.parse(value)
|
||||
const parseResult = Grammar.grammarFor(undefined, this.entityType).parse(value)
|
||||
if (!parseResult.status) {
|
||||
throw new Error("Error when trying to parse the object.")
|
||||
}
|
||||
@@ -43,7 +43,7 @@ export default class ObjectSerializer extends Serializer {
|
||||
* @returns {ObjectEntity[]}
|
||||
*/
|
||||
readMultiple(value) {
|
||||
const parseResult = Grammar.multipleObject.parse(value)
|
||||
const parseResult = ObjectEntity.getMultipleObjectsGrammar().parse(value)
|
||||
if (!parseResult.status) {
|
||||
throw new Error("Error when trying to parse the object.")
|
||||
}
|
||||
|
||||
15
js/serialization/Serializable.js
Normal file
15
js/serialization/Serializable.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import Parsimmon from "parsimmon"
|
||||
|
||||
const P = Parsimmon
|
||||
|
||||
export default class Serializable {
|
||||
|
||||
static grammar = this.createGrammar()
|
||||
|
||||
/** @protected */
|
||||
static createGrammar() {
|
||||
return /** @type {Parsimmon.Parser<Serializable>} */(P.fail(
|
||||
"Unimplemented createGrammar() method in " + this.name)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import EnumDisplayValueEntity from "../entity/EnumDisplayValueEntity.js"
|
||||
import EnumEntity from "../entity/EnumEntity.js"
|
||||
import FormatTextEntity from "../entity/FormatTextEntity.js"
|
||||
import FunctionReferenceEntity from "../entity/FunctionReferenceEntity.js"
|
||||
import Grammar from "./Grammar.js"
|
||||
import GuidEntity from "../entity/GuidEntity.js"
|
||||
import IdentifierEntity from "../entity/IdentifierEntity.js"
|
||||
import Integer64Entity from "../entity/Integer64Entity.js"
|
||||
@@ -18,6 +19,7 @@ import MirroredEntity from "../entity/MirroredEntity.js"
|
||||
import ObjectEntity from "../entity/ObjectEntity.js"
|
||||
import ObjectReferenceEntity from "../entity/ObjectReferenceEntity.js"
|
||||
import ObjectSerializer from "./ObjectSerializer.js"
|
||||
import Parsimmon from "parsimmon"
|
||||
import PathSymbolEntity from "../entity/PathSymbolEntity.js"
|
||||
import PinEntity from "../entity/PinEntity.js"
|
||||
import PinReferenceEntity from "../entity/PinReferenceEntity.js"
|
||||
@@ -30,6 +32,7 @@ import SimpleSerializationVectorEntity from "../entity/SimpleSerializationVector
|
||||
import SymbolEntity from "../entity/SymbolEntity.js"
|
||||
import TerminalTypeEntity from "../entity/TerminalTypeEntity.js"
|
||||
import ToStringSerializer from "./ToStringSerializer.js"
|
||||
import Union from "../entity/Union.js"
|
||||
import UnknownKeysEntity from "../entity/UnknownKeysEntity.js"
|
||||
import Utility from "../Utility.js"
|
||||
import VariableReferenceEntity from "../entity/VariableReferenceEntity.js"
|
||||
@@ -38,6 +41,30 @@ import VectorEntity from "../entity/VectorEntity.js"
|
||||
|
||||
/** @typedef {import("../entity/IEntity.js").AnySimpleValue} AnySimpleValue */
|
||||
|
||||
Grammar.unknownValue =
|
||||
Parsimmon.alt(
|
||||
// Remember to keep the order, otherwise parsing might fail
|
||||
Grammar.boolean,
|
||||
GuidEntity.createGrammar(),
|
||||
ObjectReferenceEntity.noneReferenceGrammar,
|
||||
Grammar.null,
|
||||
Grammar.number,
|
||||
Grammar.string,
|
||||
ObjectReferenceEntity.fullReferenceGrammar,
|
||||
LocalizedTextEntity.createGrammar(),
|
||||
InvariantTextEntity.createGrammar(),
|
||||
FormatTextEntity.createGrammar(),
|
||||
PinReferenceEntity.createGrammar(),
|
||||
VectorEntity.createGrammar(),
|
||||
RotatorEntity.createGrammar(),
|
||||
LinearColorEntity.createGrammar(),
|
||||
Vector2DEntity.createGrammar(),
|
||||
UnknownKeysEntity.createGrammar(),
|
||||
SymbolEntity.createGrammar(),
|
||||
Grammar.grammarFor(undefined, [PinReferenceEntity]),
|
||||
Grammar.grammarFor(undefined, [new Union(Number, String, SymbolEntity)]),
|
||||
)
|
||||
|
||||
export default function initializeSerializerFactory() {
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
|
||||
Reference in New Issue
Block a user