Split grammar (#15)

* Move grammar parsers to entity classes

* Fix includes

* Fix Entity5 test

* Small detail

* Fix unknown keys entities

* Persistent grammar objects

* Fix grammar

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

View File

@@ -1,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: