Replace parsing and test libraries

* WIP

* WIP

* wip

* WIP

* Several fixes

* Tests wip port to playwright

* WIP

* Fix more tests

* Serialization tests fixed

* Several fixes for tests

* Input options types

* Type adjustments

* Fix object reference parser

* Tests fixes

* More tests fixes
This commit is contained in:
barsdeveloper
2024-02-14 00:40:42 +01:00
committed by GitHub
parent 90584e16c0
commit 7469d55518
126 changed files with 7443 additions and 6253 deletions

View File

@@ -1,5 +1,5 @@
import IntegerEntity from "./IntegerEntity.js"
import Grammar from "../serialization/Grammar.js"
import Parsernostrum from "parsernostrum"
export default class ByteEntity extends IntegerEntity {
@@ -16,7 +16,7 @@ export default class ByteEntity extends IntegerEntity {
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.byteNumber.map(v => new this(v))
return Parsernostrum.numberByte.map(v => new this(v))
}
constructor(values = 0) {

View File

@@ -1,5 +1,5 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
import Parsernostrum from "parsernostrum"
export default class ColorChannelEntity extends IEntity {
@@ -15,7 +15,7 @@ export default class ColorChannelEntity extends IEntity {
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.number.map(value => new this(value))
return Parsernostrum.number.map(value => new this(value))
}
constructor(values = 0) {

View File

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

View File

@@ -2,7 +2,7 @@ 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 Parsernostrum from "parsernostrum"
import Union from "./Union.js"
export default class FormatTextEntity extends IEntity {
@@ -21,23 +21,21 @@ export default class FormatTextEntity extends IEntity {
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
})
return Parsernostrum.seq(
Parsernostrum.reg(
// Resulting regex: /(LOCGEN_FORMAT_NAMED|LOCGEN_FORMAT_ORDERED)\s*/
new RegExp(`(${this.lookbehind.values.reduce((acc, cur) => acc + "|" + cur)})\\s*`),
1
),
Grammar.grammarFor(this.attributes.value)
)
.map(([lookbehind, values]) => {
const result = new this({
value: values,
})
result.lookbehind = lookbehind
return result
})
}
constructor(values) {

View File

@@ -1,10 +1,12 @@
import ComputedType from "./ComputedType.js"
import Configuration from "../Configuration.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"
/** @abstract */
export default class IEntity extends Serializable {
/** @type {String | Union<String[]>} */
@@ -31,7 +33,7 @@ export default class IEntity extends Serializable {
let attributes = Self.attributes
if (values.attributes) {
attributes = { ...Self.attributes }
Utility.mergeArrays(Object.keys(attributes), Object.keys(values.attributes))
Utility.mergeArrays(Object.keys(values.attributes), Object.keys(attributes))
.forEach(k => {
attributes[k] = {
...IEntity.defaultAttribute,
@@ -55,13 +57,17 @@ export default class IEntity extends Serializable {
}
for (const attributeName of allAttributesNames) {
if (attributeName == "attributes") {
// Ignore this special attribute describing all the attributes
continue
}
let value = values[attributeName]
let attribute = attributes[attributeName]
if (!suppressWarns && value !== undefined) {
if (!(attributeName in attributes) && !attributeName.startsWith("#SubObject")) {
if (
!(attributeName in attributes)
&& !attributeName.startsWith(Configuration.subObjectAttributeNamePrefix)
) {
const typeName = value instanceof Array ? `[${value[0]?.constructor.name}]` : value.constructor.name
console.warn(
`UEBlueprint: Attribute ${attributeName} (of type ${typeName}) in the serialized data is not `
@@ -128,7 +134,7 @@ export default class IEntity extends Serializable {
.getSerializer(defaultType)
.read(/** @type {String} */(value))
}
assignAttribute(Utility.sanitize(value, /** @type {SimpleValueType<SimpleValue>} */(defaultType)))
assignAttribute(Utility.sanitize(value, /** @type {AttributeConstructor<Attribute>} */(defaultType)))
continue // We have a value, need nothing more
}
if (Object.hasOwn(attribute, "default")) { // Accept also explicit undefined
@@ -137,7 +143,7 @@ export default class IEntity extends Serializable {
}
}
/** @param {AttributeType} attributeType */
/** @param {AttributeTypeDescription} attributeType */
static defaultValueProviderFromType(attributeType) {
if (attributeType === Boolean) {
return false
@@ -152,12 +158,11 @@ export default class IEntity extends Serializable {
} else if (attributeType instanceof Union) {
return this.defaultValueProviderFromType(attributeType.values[0])
} else if (attributeType instanceof MirroredEntity) {
return () => new MirroredEntity(attributeType.type, attributeType.key, attributeType.getter)
return () => new MirroredEntity(attributeType.type, attributeType.getter)
} else if (attributeType instanceof ComputedType) {
return undefined
} else {
// @ts-expect-error
return () => new attributeType()
return () => new /** @type {AnyConstructor<Attribute>} */(attributeType)()
}
}
@@ -205,6 +210,7 @@ export default class IEntity extends Serializable {
return this.getAttributes(object)[attribute]
}
/** @returns {AttributeDeclarations} */
static getAttributes(object) {
return object.attributes ?? object.constructor?.attributes ?? {}
}

View File

@@ -1,5 +1,5 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
import Parsernostrum from "parsernostrum"
export default class Integer64Entity extends IEntity {
@@ -16,7 +16,7 @@ export default class Integer64Entity extends IEntity {
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.bigInt.map(v => new this(v))
return Parsernostrum.numberBigInteger.map(v => new this(v))
}
/** @param {BigInt | Number} value */

View File

@@ -1,5 +1,5 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
import Parsernostrum from "parsernostrum"
export default class IntegerEntity extends IEntity {
@@ -16,11 +16,14 @@ export default class IntegerEntity extends IEntity {
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.integer.map(v => new this(v))
return Parsernostrum.numberInteger.map(v => new this(v))
}
/** @param {Number | AttributeInformation} value */
constructor(value = 0) {
if (value === -0) {
value = 0
}
super(value.constructor === Object
? value
: {

View File

@@ -1,6 +1,6 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
import Parsimmon from "parsimmon"
import Parsernostrum from "parsernostrum"
export default class InvariantTextEntity extends IEntity {
@@ -17,14 +17,14 @@ export default class InvariantTextEntity extends IEntity {
static grammar = this.createGrammar()
static createGrammar() {
return Parsimmon.alt(
Parsimmon.seq(
Parsimmon.regex(new RegExp(`${this.lookbehind}\\s*\\(`)),
return Parsernostrum.alt(
Parsernostrum.seq(
Parsernostrum.reg(new RegExp(`${this.lookbehind}\\s*\\(`)),
Grammar.grammarFor(this.attributes.value),
Parsimmon.regex(/\s*\)/)
Parsernostrum.reg(/\s*\)/)
)
.map(([_0, value, _2]) => value),
Parsimmon.regex(new RegExp(this.lookbehind)) // InvariantTextEntity can not have arguments
Parsernostrum.reg(new RegExp(this.lookbehind)) // InvariantTextEntity can not have arguments
.map(() => "")
).map(value => new this(value))
}

View File

@@ -1,7 +1,7 @@
import Grammar from "../serialization/Grammar.js"
import IdentifierEntity from "./IdentifierEntity.js"
import IEntity from "./IEntity.js"
import Parsimmon from "parsimmon"
import Parsernostrum from "parsernostrum"
export default class KeyBindingEntity extends IEntity {
@@ -32,7 +32,7 @@ export default class KeyBindingEntity extends IEntity {
static grammar = this.createGrammar()
static createGrammar() {
return Parsimmon.alt(
return Parsernostrum.alt(
IdentifierEntity.grammar.map(identifier => new this({
Key: identifier
})),

View File

@@ -2,7 +2,7 @@ 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 Parsernostrum from "parsernostrum"
import Utility from "../Utility.js"
export default class LinearColorEntity extends IEntity {
@@ -88,29 +88,26 @@ export default class LinearColorEntity extends IEntity {
}
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,
}))
return Parsernostrum.regArray(new RegExp(
"#(" + Grammar.Regex.HexDigit.source + "{2})"
+ "(" + Grammar.Regex.HexDigit.source + "{2})"
+ "(" + Grammar.Regex.HexDigit.source + "{2})"
+ "(" + Grammar.Regex.HexDigit.source + "{2})?"
)).map(([m, R, G, B, A]) => new this({
R: parseInt(R, 16) / 255,
G: parseInt(G, 16) / 255,
B: parseInt(B, 16) / 255,
A: parseInt(A ?? "FF", 16) / 255,
}))
}
static getLinearColorRGBListGrammar() {
return Parsimmon.seq(
Grammar.byteNumber,
return Parsernostrum.seq(
Parsernostrum.numberByte,
Grammar.commaSeparation,
Grammar.byteNumber,
Parsernostrum.numberByte,
Grammar.commaSeparation,
Grammar.byteNumber,
Parsernostrum.numberByte,
).map(([R, _1, G, _3, B]) => new this({
R: R / 255,
G: G / 255,
@@ -120,25 +117,23 @@ export default class LinearColorEntity extends IEntity {
}
static getLinearColorRGBGrammar() {
return Parsimmon.seq(
Parsimmon.regex(/rgb\s*\(\s*/),
return Parsernostrum.seq(
Parsernostrum.reg(/rgb\s*\(\s*/),
this.getLinearColorRGBListGrammar(),
Parsimmon.regex(/\s*\)/)
)
.map(([_0, linearColor, _2]) => linearColor)
Parsernostrum.reg(/\s*\)/)
).map(([_0, linearColor, _2]) => linearColor)
}
static getLinearColorRGBAGrammar() {
return Parsimmon.seq(
Parsimmon.regex(/rgba\s*\(\s*/),
return Parsernostrum.seq(
Parsernostrum.reg(/rgba\s*\(\s*/),
this.getLinearColorRGBListGrammar(),
Parsimmon.regex(/\s*\)/)
)
.map(([_0, linearColor, _2]) => linearColor)
Parsernostrum.reg(/\s*\)/)
).map(([_0, linearColor, _2]) => linearColor)
}
static getLinearColorFromAnyFormat() {
return Parsimmon.alt(
return Parsernostrum.alt(
this.getLinearColorFromHexGrammar(),
this.getLinearColorRGBAGrammar(),
this.getLinearColorRGBGrammar(),
@@ -327,6 +322,11 @@ export default class LinearColorEntity extends IEntity {
this.#updateHSV()
}
/** @returns {[Number, Number, Number, Number]} */
toArray() {
return [this.R.value, this.G.value, this.B.value, this.A.value]
}
toString() {
return Utility.printLinearColor(this)
}

View File

@@ -1,5 +1,6 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
import Parsernostrum from "parsernostrum"
import Utility from "../Utility.js"
export default class LocalizedTextEntity extends IEntity {
@@ -23,22 +24,19 @@ export default class LocalizedTextEntity extends IEntity {
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]),
})
)
return Parsernostrum.regArray(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"
)).map(matchResult => new this({
namespace: Utility.unescapeString(matchResult[1]),
key: Utility.unescapeString(matchResult[2]),
value: Utility.unescapeString(matchResult[3]),
}))
}
constructor(values) {

View File

@@ -1,24 +1,21 @@
/** @template {Attribute} T */
export default class MirroredEntity {
static attributes = {
type: {
ignored: true,
},
key: {
ignored: true,
},
getter: {
ignored: true,
},
}
/**
* @param {EntityConstructor} type
* @param {String} key
* @param {ConstructorType<T>} type
* @param {() => T} getter
*/
constructor(type, key, getter = () => null) {
constructor(type, getter = null) {
this.type = type
this.key = key
this.getter = getter
}
@@ -26,8 +23,9 @@ export default class MirroredEntity {
return this.getter()
}
/** @returns {AttributeConstructor<Attribute>} */
getTargetType() {
const result = this.type.attributes[this.key].type
const result = this.type
if (result instanceof MirroredEntity) {
return result.getTargetType()
}

View File

@@ -1,5 +1,5 @@
import Grammar from "../serialization/Grammar.js"
import IntegerEntity from "./IntegerEntity.js"
import Parsernostrum from "parsernostrum"
import Utility from "../Utility.js"
export default class NaturalNumberEntity extends IntegerEntity {
@@ -7,7 +7,7 @@ export default class NaturalNumberEntity extends IntegerEntity {
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.naturalNumber.map(v => new this(v))
return Parsernostrum.numberNatural.map(v => new this(v))
}
constructor(values = 0) {

View File

@@ -9,7 +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 Parsernostrum from "parsernostrum"
import PinEntity from "./PinEntity.js"
import SVGIcon from "../SVGIcon.js"
import SymbolEntity from "./SymbolEntity.js"
@@ -50,271 +50,115 @@ export default class ObjectEntity extends IEntity {
}
static attributes = {
...super.attributes,
Class: {
type: ObjectReferenceEntity,
AdvancedPinDisplay: { type: IdentifierEntity },
Archetype: { type: ObjectReferenceEntity },
AxisKey: { type: SymbolEntity },
bAlt: { type: Boolean },
bCanRenameNode: { type: Boolean },
bColorCommentBubble: { type: Boolean },
bCommand: { type: Boolean },
bCommentBubblePinned: { type: Boolean },
bCommentBubbleVisible_InDetailsPanel: { type: Boolean },
bCommentBubbleVisible: { type: Boolean },
bConsumeInput: { type: Boolean },
bControl: { type: Boolean },
bExecuteWhenPaused: { type: Boolean },
bExposeToLibrary: { type: Boolean },
bInternalEvent: { type: Boolean },
bIsCaseSensitive: { type: Boolean },
bIsConstFunc: { type: Boolean },
bIsPureFunc: { type: Boolean },
BlueprintElementInstance: { type: ObjectReferenceEntity },
BlueprintElementType: { type: ObjectReferenceEntity },
bOverrideFunction: { type: Boolean },
bOverrideParentBinding: { type: Boolean },
bShift: { type: Boolean },
Class: { type: ObjectReferenceEntity },
CommentColor: { type: LinearColorEntity },
ComponentPropertyName: { type: String },
CustomFunctionName: { type: String },
CustomProperties: { type: [new Union(PinEntity, UnknownPinEntity)] },
DelegateOwnerClass: { type: ObjectReferenceEntity },
DelegatePropertyName: { type: String },
DelegateReference: { type: VariableReferenceEntity },
EnabledState: { type: IdentifierEntity },
Enum: { type: ObjectReferenceEntity },
EnumEntries: {
type: [String],
inlined: true,
},
Name: {
type: String,
ErrorMsg: { type: String },
ErrorType: { type: IntegerEntity },
EventReference: { type: FunctionReferenceEntity },
ExportPath: { type: ObjectReferenceEntity },
FunctionReference: { type: FunctionReferenceEntity },
G: { type: Number },
Graph: { type: ObjectReferenceEntity },
HiGenGridSize: { type: SymbolEntity },
InputAxisKey: { type: SymbolEntity },
InputKey: { type: SymbolEntity },
InputPins: {
type: [ObjectReferenceEntity],
inlined: true,
},
Archetype: {
type: ObjectReferenceEntity,
MacroGraphReference: { type: MacroGraphReferenceEntity },
MaterialExpression: { type: ObjectReferenceEntity },
MaterialExpressionComment: { type: ObjectReferenceEntity },
MaterialExpressionEditorX: { type: new MirroredEntity(IntegerEntity) },
MaterialExpressionEditorY: { type: new MirroredEntity(IntegerEntity) },
MaterialFunction: { type: ObjectReferenceEntity },
MoveMode: { type: SymbolEntity },
Name: { type: String },
Node: { type: new MirroredEntity(ObjectReferenceEntity) },
NodeComment: { type: String },
NodeGuid: { type: GuidEntity },
NodeHeight: { type: IntegerEntity },
NodePosX: { type: IntegerEntity },
NodePosY: { type: IntegerEntity },
NodeTitle: { type: String },
NodeTitleColor: { type: LinearColorEntity },
NodeWidth: { type: IntegerEntity },
NumAdditionalInputs: { type: Number },
ObjectRef: { type: ObjectReferenceEntity },
Operation: { type: SymbolEntity },
OutputPins: {
type: [ObjectReferenceEntity],
inlined: true,
},
ExportPath: {
type: ObjectReferenceEntity,
},
ObjectRef: {
type: ObjectReferenceEntity,
},
BlueprintElementType: {
type: ObjectReferenceEntity
},
BlueprintElementInstance: {
type: ObjectReferenceEntity
PCGNode: { type: ObjectReferenceEntity },
PinNames: {
type: [String],
inlined: true,
},
PinTags: {
type: [null],
inlined: true,
},
PinNames: {
type: [String],
inlined: true,
},
AxisKey: {
type: SymbolEntity,
},
InputAxisKey: {
type: SymbolEntity,
},
NumAdditionalInputs: {
type: Number,
},
bIsPureFunc: {
type: Boolean,
},
bIsConstFunc: {
type: Boolean,
},
bIsCaseSensitive: {
type: Boolean,
},
VariableReference: {
type: VariableReferenceEntity,
},
SelfContextInfo: {
type: SymbolEntity,
},
DelegatePropertyName: {
type: String,
},
DelegateOwnerClass: {
type: ObjectReferenceEntity,
},
ComponentPropertyName: {
type: String,
},
EventReference: {
type: FunctionReferenceEntity,
},
FunctionReference: {
type: FunctionReferenceEntity,
},
CustomFunctionName: {
type: String,
},
TargetType: {
type: ObjectReferenceEntity,
},
MacroGraphReference: {
type: MacroGraphReferenceEntity,
},
Enum: {
type: ObjectReferenceEntity,
},
EnumEntries: {
type: [String],
inlined: true,
},
InputKey: {
type: SymbolEntity,
},
MaterialFunction: {
type: ObjectReferenceEntity,
},
bOverrideFunction: {
type: Boolean,
},
bInternalEvent: {
type: Boolean,
},
bConsumeInput: {
type: Boolean,
},
bExecuteWhenPaused: {
type: Boolean,
},
bOverrideParentBinding: {
type: Boolean,
},
bControl: {
type: Boolean,
},
bAlt: {
type: Boolean,
},
bShift: {
type: Boolean,
},
bCommand: {
type: Boolean,
},
CommentColor: {
type: LinearColorEntity,
},
bCommentBubbleVisible_InDetailsPanel: {
type: Boolean,
},
bColorCommentBubble: {
type: Boolean,
},
ProxyFactoryFunctionName: {
type: String,
},
ProxyFactoryClass: {
type: ObjectReferenceEntity,
},
ProxyClass: {
type: ObjectReferenceEntity,
},
R: {
type: Number,
},
G: {
type: Number,
},
StructType: {
type: ObjectReferenceEntity,
},
MaterialExpression: {
type: ObjectReferenceEntity,
},
MaterialExpressionComment: {
type: ObjectReferenceEntity,
},
MoveMode: {
type: SymbolEntity,
},
TimelineName: {
type: String,
},
TimelineGuid: {
type: GuidEntity,
},
SizeX: {
type: new MirroredEntity(ObjectEntity, "NodeWidth"),
},
SizeY: {
type: new MirroredEntity(ObjectEntity, "NodeHeight"),
},
Text: {
type: new MirroredEntity(ObjectEntity, "NodeComment"),
},
MaterialExpressionEditorX: {
type: new MirroredEntity(ObjectEntity, "NodePosX"),
},
MaterialExpressionEditorY: {
type: new MirroredEntity(ObjectEntity, "NodePosY"),
},
NodeTitle: {
type: String,
},
NodeTitleColor: {
type: LinearColorEntity,
},
PositionX: {
type: new MirroredEntity(ObjectEntity, "NodePosX"),
},
PositionY: {
type: new MirroredEntity(ObjectEntity, "NodePosY"),
},
PCGNode: {
type: ObjectReferenceEntity,
},
HiGenGridSize: {
type: SymbolEntity,
},
Operation: {
type: SymbolEntity,
},
NodePosX: {
type: IntegerEntity,
},
NodePosY: {
type: IntegerEntity,
},
NodeWidth: {
type: IntegerEntity,
},
NodeHeight: {
type: IntegerEntity,
},
Graph: {
type: ObjectReferenceEntity,
},
SubgraphInstance: {
type: String,
},
SettingsInterface: {
type: ObjectReferenceEntity,
},
InputPins: {
type: [ObjectReferenceEntity],
inlined: true,
},
OutputPins: {
type: [ObjectReferenceEntity],
inlined: true,
},
bExposeToLibrary: {
type: Boolean,
},
bCanRenameNode: {
type: Boolean,
},
bCommentBubblePinned: {
type: Boolean,
},
bCommentBubbleVisible: {
type: Boolean,
},
NodeComment: {
type: String,
},
AdvancedPinDisplay: {
type: IdentifierEntity,
},
EnabledState: {
type: IdentifierEntity,
},
NodeGuid: {
type: GuidEntity,
},
ErrorType: {
type: IntegerEntity,
},
ErrorMsg: {
type: String,
},
CustomProperties: {
type: [new Union(PinEntity, UnknownPinEntity)],
}
PositionX: { type: new MirroredEntity(IntegerEntity) },
PositionY: { type: new MirroredEntity(IntegerEntity) },
ProxyClass: { type: ObjectReferenceEntity },
ProxyFactoryClass: { type: ObjectReferenceEntity },
ProxyFactoryFunctionName: { type: String },
R: { type: Number },
SelfContextInfo: { type: SymbolEntity },
SettingsInterface: { type: ObjectReferenceEntity },
SizeX: { type: new MirroredEntity(IntegerEntity) },
SizeY: { type: new MirroredEntity(IntegerEntity) },
StructType: { type: ObjectReferenceEntity },
SubgraphInstance: { type: String },
TargetType: { type: ObjectReferenceEntity },
Text: { type: new MirroredEntity(String) },
TimelineGuid: { type: GuidEntity },
TimelineName: { type: String },
VariableReference: { type: VariableReferenceEntity },
}
static {
this.cleanupAttributes(this.attributes)
}
static nameRegex = /^(\w+?)(?:_(\d+))?$/
static sequencerScriptingNameRegex = /\/Script\/SequencerScripting\.MovieSceneScripting(.+)Channel/
static customPropertyGrammar = Parsimmon.seq(
Parsimmon.regex(/CustomProperties\s+/),
static customPropertyGrammar = Parsernostrum.seq(
Parsernostrum.reg(/CustomProperties\s+/),
Grammar.grammarFor(
undefined,
this.attributes.CustomProperties.type[0]
@@ -325,15 +169,15 @@ export default class ObjectEntity extends IEntity {
}
values.CustomProperties.push(pin)
})
static inlinedArrayEntryGrammar = Parsimmon.seq(
Parsimmon.alt(
static inlinedArrayEntryGrammar = Parsernostrum.seq(
Parsernostrum.alt(
Grammar.symbolQuoted.map(v => [v, true]),
Grammar.symbol.map(v => [v, false]),
),
Grammar.regexMap(
Parsernostrum.reg(
new RegExp(`\\s*\\(\\s*(\\d+)\\s*\\)\\s*\\=\\s*`),
v => Number(v[1])
)
1
).map(Number)
)
.chain(
/** @param {[[String, Boolean], Number]} param */
@@ -355,20 +199,19 @@ export default class ObjectEntity extends IEntity {
static grammar = this.createGrammar()
static createSubObjectGrammar() {
return Parsimmon.lazy(() =>
this.createGrammar()
.map(object =>
values => values[Configuration.subObjectAttributeNameFromEntity(object)] = object
)
)
return Parsernostrum.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(
return Parsernostrum.seq(
Parsernostrum.reg(/Begin\s+Object/),
Parsernostrum.seq(
Parsernostrum.whitespace,
Parsernostrum.alt(
this.customPropertyGrammar,
Grammar.createAttributeGrammar(this),
Grammar.createAttributeGrammar(this, Grammar.attributeNameQuoted, undefined, (obj, k, v) =>
@@ -380,7 +223,7 @@ export default class ObjectEntity extends IEntity {
)
.map(([_0, entry]) => entry)
.many(),
Parsimmon.regex(/\s+End\s+Object/),
Parsernostrum.reg(/\s+End\s+Object/),
)
.map(([_0, attributes, _2]) => {
const values = {}
@@ -410,16 +253,16 @@ export default class ObjectEntity extends IEntity {
}
static getMultipleObjectsGrammar() {
return Parsimmon.seq(
Parsimmon.optWhitespace,
return Parsernostrum.seq(
Parsernostrum.whitespaceOpt,
this.createGrammar(),
Parsimmon.seq(
Parsimmon.whitespace,
Parsernostrum.seq(
Parsernostrum.whitespace,
this.createGrammar(),
)
.map(([_0, object]) => object)
.many(),
Parsimmon.optWhitespace
Parsernostrum.whitespaceOpt
)
.map(([_0, first, remaining, _4]) => [first, ...remaining])
}
@@ -443,91 +286,93 @@ export default class ObjectEntity extends IEntity {
}
}
super(values, suppressWarns)
/** @type {ObjectReferenceEntity} */ this.Class
/** @type {String} */ this.Name
/** @type {ObjectReferenceEntity} */ this.Archetype
/** @type {ObjectReferenceEntity} */ this.ExportPath
/** @type {ObjectReferenceEntity} */ this.ObjectRef
/** @type {ObjectReferenceEntity} */ this.BlueprintElementType
/** @type {ObjectReferenceEntity} */ this.BlueprintElementInstance
/** @type {null[]} */ this.PinTags
/** @type {String[]} */ this.PinNames
/** @type {SymbolEntity} */ this.AxisKey
/** @type {SymbolEntity} */ this.InputAxisKey
/** @type {Number} */ this.NumAdditionalInputs
/** @type {Boolean} */ this.bIsPureFunc
/** @type {Boolean} */ this.bIsConstFunc
/** @type {(PinEntity | UnknownPinEntity)[]} */ this.CustomProperties
/** @type {Boolean} */ this.bAlt
/** @type {Boolean} */ this.bCanRenameNode
/** @type {Boolean} */ this.bColorCommentBubble
/** @type {Boolean} */ this.bCommand
/** @type {Boolean} */ this.bCommentBubblePinned
/** @type {Boolean} */ this.bCommentBubbleVisible
/** @type {Boolean} */ this.bCommentBubbleVisible_InDetailsPanel
/** @type {Boolean} */ this.bConsumeInput
/** @type {Boolean} */ this.bControl
/** @type {Boolean} */ this.bExecuteWhenPaused
/** @type {Boolean} */ this.bExposeToLibrary
/** @type {Boolean} */ this.bInternalEvent
/** @type {Boolean} */ this.bIsCaseSensitive
/** @type {VariableReferenceEntity} */ this.VariableReference
/** @type {SymbolEntity} */ this.SelfContextInfo
/** @type {String} */ this.DelegatePropertyName
/** @type {ObjectReferenceEntity} */ this.DelegateOwnerClass
/** @type {Boolean} */ this.bIsConstFunc
/** @type {Boolean} */ this.bIsPureFunc
/** @type {Boolean} */ this.bOverrideFunction
/** @type {Boolean} */ this.bOverrideParentBinding
/** @type {Boolean} */ this.bShift
/** @type {FunctionReferenceEntity} */ this.ComponentPropertyName
/** @type {FunctionReferenceEntity} */ this.EventReference
/** @type {FunctionReferenceEntity} */ this.FunctionReference
/** @type {String} */ this.CustomFunctionName
/** @type {ObjectReferenceEntity} */ this.TargetType
/** @type {MacroGraphReferenceEntity} */ this.MacroGraphReference
/** @type {ObjectReferenceEntity} */ this.Enum
/** @type {String[]} */ this.EnumEntries
/** @type {SymbolEntity} */ this.InputKey
/** @type {ObjectReferenceEntity} */ this.MaterialFunction
/** @type {Boolean} */ this.bOverrideFunction
/** @type {Boolean} */ this.bInternalEvent
/** @type {Boolean} */ this.bConsumeInput
/** @type {Boolean} */ this.bExecuteWhenPaused
/** @type {Boolean} */ this.bOverrideParentBinding
/** @type {Boolean} */ this.bControl
/** @type {Boolean} */ this.bAlt
/** @type {Boolean} */ this.bShift
/** @type {Boolean} */ this.bCommand
/** @type {LinearColorEntity} */ this.CommentColor
/** @type {Boolean} */ this.bCommentBubbleVisible_InDetailsPanel
/** @type {Boolean} */ this.bColorCommentBubble
/** @type {String} */ this.ProxyFactoryFunctionName
/** @type {ObjectReferenceEntity} */ this.ProxyFactoryClass
/** @type {ObjectReferenceEntity} */ this.ProxyClass
/** @type {Number} */ this.R
/** @type {Number} */ this.G
/** @type {ObjectReferenceEntity} */ this.StructType
/** @type {ObjectReferenceEntity} */ this.MaterialExpression
/** @type {ObjectReferenceEntity} */ this.MaterialExpressionComment
/** @type {SymbolEntity} */ this.MoveMode
/** @type {String} */ this.TimelineName
/** @type {GuidEntity} */ this.NodeGuid
/** @type {GuidEntity} */ this.TimelineGuid
/** @type {MirroredEntity} */ this.SizeX
/** @type {MirroredEntity} */ this.SizeY
/** @type {MirroredEntity} */ this.Text
/** @type {MirroredEntity} */ this.MaterialExpressionEditorX
/** @type {MirroredEntity} */ this.MaterialExpressionEditorY
/** @type {String} */ this.NodeTitle
/** @type {LinearColorEntity} */ this.NodeTitleColor
/** @type {MirroredEntity} */ this.PositionX
/** @type {MirroredEntity} */ this.PositionY
/** @type {ObjectReferenceEntity} */ this.PCGNode
/** @type {SymbolEntity} */ this.HiGenGridSize
/** @type {String} */ this.Operation
/** @type {IdentifierEntity} */ this.AdvancedPinDisplay
/** @type {IdentifierEntity} */ this.EnabledState
/** @type {IntegerEntity} */ this.ErrorType
/** @type {IntegerEntity} */ this.NodeHeight
/** @type {IntegerEntity} */ this.NodePosX
/** @type {IntegerEntity} */ this.NodePosY
/** @type {IntegerEntity} */ this.NodeWidth
/** @type {IntegerEntity} */ this.NodeHeight
/** @type {ObjectReferenceEntity} */ this.Graph
/** @type {String} */ this.SubgraphInstance
/** @type {ObjectReferenceEntity} */ this.SettingsInterface
/** @type {LinearColorEntity} */ this.CommentColor
/** @type {LinearColorEntity} */ this.NodeTitleColor
/** @type {MacroGraphReferenceEntity} */ this.MacroGraphReference
/** @type {MirroredEntity} */ this.MaterialExpressionEditorX
/** @type {MirroredEntity} */ this.MaterialExpressionEditorY
/** @type {MirroredEntity} */ this.SizeX
/** @type {MirroredEntity} */ this.SizeY
/** @type {MirroredEntity} */ this.Text
/** @type {MirroredEntity<IntegerEntity>} */ this.PositionX
/** @type {MirroredEntity<IntegerEntity>} */ this.PositionY
/** @type {MirroredEntity<ObjectReferenceEntity>} */ this.Node
/** @type {null[]} */ this.PinTags
/** @type {Number} */ this.G
/** @type {Number} */ this.NumAdditionalInputs
/** @type {Number} */ this.R
/** @type {ObjectReferenceEntity[]} */ this.InputPins
/** @type {ObjectReferenceEntity[]} */ this.OutputPins
/** @type {Boolean} */ this.bExposeToLibrary
/** @type {Boolean} */ this.bCanRenameNode
/** @type {Boolean} */ this.bCommentBubblePinned
/** @type {Boolean} */ this.bCommentBubbleVisible
/** @type {String} */ this.Text
/** @type {String} */ this.NodeComment
/** @type {IdentifierEntity} */ this.AdvancedPinDisplay
/** @type {IdentifierEntity} */ this.EnabledState
/** @type {GuidEntity} */ this.NodeGuid
/** @type {IntegerEntity} */ this.ErrorType
/** @type {ObjectReferenceEntity} */ this.Archetype
/** @type {ObjectReferenceEntity} */ this.BlueprintElementInstance
/** @type {ObjectReferenceEntity} */ this.BlueprintElementType
/** @type {ObjectReferenceEntity} */ this.Class
/** @type {ObjectReferenceEntity} */ this.DelegateOwnerClass
/** @type {ObjectReferenceEntity} */ this.Enum
/** @type {ObjectReferenceEntity} */ this.ExportPath
/** @type {ObjectReferenceEntity} */ this.Graph
/** @type {ObjectReferenceEntity} */ this.MaterialExpression
/** @type {ObjectReferenceEntity} */ this.MaterialExpressionComment
/** @type {ObjectReferenceEntity} */ this.MaterialFunction
/** @type {ObjectReferenceEntity} */ this.ObjectRef
/** @type {ObjectReferenceEntity} */ this.PCGNode
/** @type {ObjectReferenceEntity} */ this.ProxyClass
/** @type {ObjectReferenceEntity} */ this.ProxyFactoryClass
/** @type {ObjectReferenceEntity} */ this.SettingsInterface
/** @type {ObjectReferenceEntity} */ this.StructType
/** @type {ObjectReferenceEntity} */ this.TargetType
/** @type {String[]} */ this.EnumEntries
/** @type {String[]} */ this.PinNames
/** @type {String} */ this.CustomFunctionName
/** @type {String} */ this.DelegatePropertyName
/** @type {String} */ this.ErrorMsg
/** @type {(PinEntity | UnknownPinEntity)[]} */ this.CustomProperties
/** @type {String} */ this.Name
/** @type {String} */ this.NodeComment
/** @type {String} */ this.NodeTitle
/** @type {String} */ this.Operation
/** @type {String} */ this.ProxyFactoryFunctionName
/** @type {String} */ this.SubgraphInstance
/** @type {String} */ this.Text
/** @type {String} */ this.TimelineName
/** @type {SymbolEntity} */ this.AxisKey
/** @type {SymbolEntity} */ this.HiGenGridSize
/** @type {SymbolEntity} */ this.InputAxisKey
/** @type {SymbolEntity} */ this.InputKey
/** @type {SymbolEntity} */ this.MoveMode
/** @type {SymbolEntity} */ this.SelfContextInfo
/** @type {VariableReferenceEntity} */ this.DelegateReference
/** @type {VariableReferenceEntity} */ this.VariableReference
// Legacy nodes cleanup
if (this["Pins"] instanceof Array) {
@@ -564,6 +409,25 @@ export default class ObjectEntity extends IEntity {
if (pcgObject) {
pcgObject.PositionX && (pcgObject.PositionX.getter = () => this.NodePosX)
pcgObject.PositionY && (pcgObject.PositionY.getter = () => this.NodePosY)
pcgObject.getSubobjects()
.forEach(
/** @param {ObjectEntity} obj */
obj => {
if (obj.Node !== undefined) {
const nodeRef = obj.Node.get()
if (
nodeRef.type === this.PCGNode.type
&& nodeRef.path === `${this.Name}.${this.PCGNode.path}`
) {
obj.Node.getter = () => new ObjectReferenceEntity({
type: this.PCGNode.type,
path: `${this.Name}.${this.PCGNode.path}`,
})
}
}
}
)
}
let inputIndex = 0
let outputIndex = 0
@@ -684,6 +548,13 @@ export default class ObjectEntity extends IEntity {
return this.getCustomproperties().filter(v => v.constructor === PinEntity)
}
/** @returns {ObjectEntity[]} */
getSubobjects() {
return Object.keys(this)
.filter(k => k.startsWith(Configuration.subObjectAttributeNamePrefix))
.flatMap(k => [this[k], .../** @type {ObjectEntity} */(this[k]).getSubobjects()])
}
switchTarget() {
const switchMatch = this.getClass().match(Configuration.switchTargetPattern)
if (switchMatch) {
@@ -779,6 +650,8 @@ export default class ObjectEntity extends IEntity {
case Configuration.paths.actorBoundEvent:
case Configuration.paths.componentBoundEvent:
return `${Utility.formatStringName(this.DelegatePropertyName)} (${this.ComponentPropertyName ?? "Unknown"})`
case Configuration.paths.callDelegate:
return `Call ${this.DelegateReference?.MemberName ?? "None"}`
case Configuration.paths.createDelegate:
return "Create Event"
case Configuration.paths.customEvent:
@@ -1142,7 +1015,7 @@ export default class ObjectEntity extends IEntity {
nodeIcon() {
if (this.isMaterial() || this.isPcg()) {
return undefined
return null
}
switch (this.getType()) {
case Configuration.paths.addDelegate:

View File

@@ -1,7 +1,7 @@
import Configuration from "../Configuration.js"
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
import Parsimmon from "parsimmon"
import Parsernostrum from "parsernostrum"
import Utility from "../Utility.js"
export default class ObjectReferenceEntity extends IEntity {
@@ -18,25 +18,18 @@ export default class ObjectReferenceEntity extends IEntity {
static {
this.cleanupAttributes(this.attributes)
}
static noneReferenceGrammar = Parsimmon.string("None").map(() => this.createNoneInstance())
static fullReferenceGrammar = Parsimmon.seq(
static noneReferenceGrammar = Parsernostrum.str("None").map(() => this.createNoneInstance())
static fullReferenceGrammar = Parsernostrum.seq(
Grammar.typeReference,
Parsimmon.regex(Grammar.Regex.InlineOptWhitespace),
Parsernostrum.whitespaceInlineOpt,
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 })
)
).map(([type, _2, path]) => new this({ type, 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(
return Parsernostrum.alt(
this.noneReferenceGrammar,
this.fullReferenceGrammar,
this.typeReferenceGrammar,

View File

@@ -24,7 +24,7 @@ import Utility from "../Utility.js"
import Vector2DEntity from "./Vector2DEntity.js"
import VectorEntity from "./VectorEntity.js"
/** @template {AnyValue} T */
/** @template {TerminalAttribute} T */
export default class PinEntity extends IEntity {
static #typeEntityMap = {

View File

@@ -1,6 +1,6 @@
import GuidEntity from "./GuidEntity.js"
import IEntity from "./IEntity.js"
import Parsimmon from "parsimmon"
import Parsernostrum from "parsernostrum"
import PathSymbolEntity from "./PathSymbolEntity.js"
export default class PinReferenceEntity extends IEntity {
@@ -20,9 +20,9 @@ export default class PinReferenceEntity extends IEntity {
static grammar = this.createGrammar()
static createGrammar() {
return Parsimmon.seq(
return Parsernostrum.seq(
PathSymbolEntity.createGrammar(),
Parsimmon.whitespace,
Parsernostrum.whitespace,
GuidEntity.createGrammar()
).map(
([objectName, _1, pinGuid]) => new this({

View File

@@ -1,5 +1,4 @@
import Grammar from "../serialization/Grammar.js"
import Parsimmon from "parsimmon"
import Parsernostrum from "parsernostrum"
import Vector2DEntity from "./Vector2DEntity.js"
export default class RBSerializationVector2DEntity extends Vector2DEntity {
@@ -7,14 +6,14 @@ export default class RBSerializationVector2DEntity extends Vector2DEntity {
static grammar = this.createGrammar()
static createGrammar() {
return Parsimmon.alt(
Parsimmon.seq(
Parsimmon.string("X").then(Grammar.equalSeparation).then(Grammar.number),
Parsimmon.regex(Grammar.Regex.InlineWhitespace),
Parsimmon.string("Y").then(Grammar.equalSeparation).then(Grammar.number),
).map(([x, _1, y]) => new this({
X: x,
Y: y,
return Parsernostrum.alt(
Parsernostrum.regArray(new RegExp(
/X\s*=\s*/.source + "(?<x>" + Parsernostrum.number.getParser().parser.regexp.source + ")"
+ "\\s+"
+ /Y\s*=\s*/.source + "(?<y>" + Parsernostrum.number.getParser().parser.regexp.source + ")"
)).map(({ groups: { x, y } }) => new this({
X: Number(x),
Y: Number(y),
})),
Vector2DEntity.createGrammar()
)

View File

@@ -1,26 +1,24 @@
import Parsimmon from "parsimmon"
import Parsernostrum from "parsernostrum"
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,
})
),
const number = Parsernostrum.number.getParser().parser.regexp.source
return Parsernostrum.alt(
Parsernostrum.reg(new RegExp(
"(" + number + ")"
+ "\\s*,\\s"
+ "(" + number + ")"
+ "\\s*,\\s"
+ "(" + number + ")"
)).map(([p, y, r]) => new this({
R: Number(r),
P: Number(p),
Y: Number(y),
})),
RotatorEntity.createGrammar()
)
}

View File

@@ -1,5 +1,4 @@
import Grammar from "../serialization/Grammar.js"
import Parsimmon from "parsimmon"
import Parsernostrum from "parsernostrum"
import Vector2DEntity from "./Vector2DEntity.js"
export default class SimpleSerializationVector2DEntity extends Vector2DEntity {
@@ -7,14 +6,15 @@ 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,
const number = Parsernostrum.number.getParser().parser.regexp.source
return Parsernostrum.alt(
Parsernostrum.reg(new RegExp(
"(" + number + ")"
+ "\\s*,\\s"
+ "(" + number + ")"
)).map(([x, y]) => new this({
X: Number(x),
Y: Number(y),
})),
Vector2DEntity.createGrammar()
)

View File

@@ -1,5 +1,4 @@
import Grammar from "../serialization/Grammar.js"
import Parsimmon from "parsimmon"
import Parsernostrum from "parsernostrum"
import VectorEntity from "./VectorEntity.js"
export default class SimpleSerializationVectorEntity extends VectorEntity {
@@ -7,18 +6,20 @@ 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,
})),
const number = Parsernostrum.number.getParser().parser.regexp.source
return Parsernostrum.alt(
Parsernostrum.regArray(new RegExp(
"(" + number + ")"
+ "\\s*,\\s*"
+ "(" + number + ")"
+ "\\s*,\\s*"
+ "(" + number + ")"
))
.map(([_0, x, y, z]) => new this({
X: Number(x),
Y: Number(y),
Z: Number(z),
})),
VectorEntity.createGrammar()
)
}

View File

@@ -1,6 +1,6 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
import Parsimmon from "parsimmon"
import Parsernostrum from "parsernostrum"
export default class UnknownKeysEntity extends IEntity {
@@ -17,31 +17,29 @@ export default class UnknownKeysEntity extends IEntity {
static grammar = this.createGrammar()
static createGrammar() {
return Parsimmon.seq(
return Parsernostrum.seq(
// Lookbehind
Grammar.regexMap(
Parsernostrum.reg(
new RegExp(`(${Grammar.Regex.Path.source}|${Grammar.Regex.Symbol.source}\\s*)?\\(\\s*`),
result => result[1] ?? ""
1
),
Grammar.attributeName
.skip(Grammar.equalSeparation)
Parsernostrum.seq(Grammar.attributeName, Grammar.equalSeparation).map(([attribute, equal]) => attribute)
.chain(attributeName =>
Grammar.unknownValue
.map(attributeValue =>
values => values[attributeName] = attributeValue
)
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)
})
.sepBy(Grammar.commaSeparation),
Parsernostrum.reg(/\s*(?:,\s*)?\)/),
).map(([lookbehind, attributes, _2]) => {
lookbehind ??= ""
let values = {}
if (lookbehind.length) {
values.lookbehind = lookbehind
}
attributes.forEach(attributeSetter => attributeSetter(values))
return new this(values)
})
}
constructor(values) {

View File

@@ -1,6 +1,6 @@
import Parsimmon from "parsimmon"
import PinEntity from "./PinEntity.js"
import Grammar from "../serialization/Grammar.js"
import Parsernostrum from "parsernostrum"
import PinEntity from "./PinEntity.js"
export default class UnknownPinEntity extends PinEntity {
@@ -8,23 +8,22 @@ export default class UnknownPinEntity extends PinEntity {
static grammar = this.createGrammar()
static createGrammar() {
return Parsimmon.lazy(() => Parsimmon.seq(
Grammar.regexMap(
return Parsernostrum.seq(
Parsernostrum.reg(
new RegExp(`${Grammar.Regex.Symbol.source}\\s*\\(\\s*`),
result => result[1] ?? ""
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)
})
)
Grammar.createAttributeGrammar(this).sepBy(Grammar.commaSeparation),
Parsernostrum.reg(/\s*(?:,\s*)?\)/)
).map(([lookbehind, attributes, _2]) => {
lookbehind ??= ""
let values = {}
if (lookbehind.length) {
values.lookbehind = lookbehind
}
attributes.forEach(attributeSetter => attributeSetter(values))
return new this(values)
})
}
constructor(values = {}) {

View File

@@ -28,4 +28,9 @@ export default class Vector2DEntity extends IEntity {
/** @type {Number} */ this.X
/** @type {Number} */ this.Y
}
/** @returns {[Number, Number]} */
toArray() {
return [this.X, this.Y]
}
}

View File

@@ -33,4 +33,9 @@ export default class VectorEntity extends IEntity {
/** @type {Number} */ this.Y
/** @type {Number} */ this.Z
}
/** @returns {[Number, Number, Number]} */
toArray() {
return [this.X, this.Y, this.Z]
}
}