mirror of
https://github.com/barsdeveloper/ueblueprint.git
synced 2026-02-27 10:44:43 +08:00
Refactoring, various fixes
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import FunctionReferenceEntity from "../entity/FunctionReferenceEntity"
|
||||
import GuidEntity from "../entity/GuidEntity"
|
||||
import Identifier from "../entity/Identifier"
|
||||
import IdentifierEntity from "../entity/IdentifierEntity"
|
||||
import IntegerEntity from "../entity/IntegerEntity"
|
||||
import KeyBindingEntity from "../entity/KeyBindingEntity"
|
||||
import LocalizedTextEntity from "../entity/LocalizedTextEntity"
|
||||
import ObjectEntity from "../entity/ObjectEntity"
|
||||
import ObjectReferenceEntity from "../entity/ObjectReferenceEntity"
|
||||
@@ -15,102 +16,7 @@ let P = Parsimmon
|
||||
|
||||
export default class Grammar {
|
||||
|
||||
/** @param {Grammar} r */
|
||||
InlineWhitespace = r => P.regex(/[^\S\n]+/).desc("inline whitespace")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
InlineOptWhitespace = r => P.regex(/[^\S\n]*/).desc("inline optional whitespace")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
WhitespaceNewline = r => P.regex(/[^\S\n]*\n\s*/).desc("whitespace with at least a newline")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Null = r => P.seq(P.string("("), r.InlineOptWhitespace, P.string(")")).map(_ => null).desc("null: ()")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
None = r => P.string("None").map(_ => new ObjectReferenceEntity({ type: "None", path: "" })).desc("none")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Boolean = r => P.alt(P.string("True"), P.string("False")).map(v => v === "True" ? true : false).desc("either True or False")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Number = r => P.regex(/[\-\+]?[0-9]+(?:\.[0-9]+)?/).map(Number).desc("a number")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Integer = r => P.regex(/[\-\+]?[0-9]+/).map(v => new IntegerEntity(v)).desc("an integer")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
String = r => P.regex(/(?:[^"\\]|\\.)*/).wrap(P.string('"'), P.string('"')).desc('string (with possibility to escape the quote using \")')
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Word = r => P.regex(/[a-zA-Z]+/).desc("a word")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Guid = r => P.regex(/[0-9a-zA-Z]{32}/).map(v => new GuidEntity({ value: v })).desc("32 digit hexadecimal (accepts all the letters for safety) value")
|
||||
|
||||
/** @param {Grammar} */
|
||||
Identifier = r => P.regex(/\w+/).map(v => new Identifier(v))
|
||||
|
||||
/** @param {Grammar} r */
|
||||
PathSymbolEntity = r => P.regex(/[0-9a-zA-Z_]+/).map(v => new PathSymbolEntity({ value: v }))
|
||||
|
||||
/** @param {Grammar} r */
|
||||
ReferencePath = r => P.seq(P.string("/"), r.PathSymbolEntity.map(v => v.toString()).sepBy1(P.string(".")).tieWith("."))
|
||||
.tie()
|
||||
.atLeast(2)
|
||||
.tie()
|
||||
.desc('a path (words with possibly underscore, separated by ".", separated by "/")')
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Reference = r => P.alt(
|
||||
r.None,
|
||||
...[r.ReferencePath.map(path => new ObjectReferenceEntity({ type: "", path: path }))].flatMap(
|
||||
v => [v, v.trim(P.string('"'))]
|
||||
),
|
||||
P.seqMap(
|
||||
r.Word,
|
||||
P.optWhitespace,
|
||||
P.alt(P.string('"'), P.string('\'"')).chain(
|
||||
result => r.ReferencePath.skip(
|
||||
P.string(result.split("").reverse().join(""))
|
||||
)
|
||||
),
|
||||
(referenceType, _, referencePath) => new ObjectReferenceEntity({ type: referenceType, path: referencePath })
|
||||
)
|
||||
)
|
||||
|
||||
/** @param {Grammar} r */
|
||||
AttributeName = r => r.Word.sepBy1(P.string(".")).tieWith(".").desc('words separated by ""')
|
||||
|
||||
/** @param {Grammar} r */
|
||||
AttributeAnyValue = r => P.alt(r.Null, r.None, r.Boolean, r.Number, r.Integer, r.String, r.Guid, r.Reference, r.LocalizedText)
|
||||
|
||||
/** @param {Grammar} r */
|
||||
LocalizedText = r => P.seqMap(
|
||||
P.string(LocalizedTextEntity.lookbehind).skip(P.optWhitespace).skip(P.string("(")),
|
||||
r.String.trim(P.optWhitespace), // namespace
|
||||
P.string(","),
|
||||
r.String.trim(P.optWhitespace), // key
|
||||
P.string(","),
|
||||
r.String.trim(P.optWhitespace), // value
|
||||
P.string(")"),
|
||||
(_, namespace, __, key, ___, value, ____) => new LocalizedTextEntity({
|
||||
namespace: namespace,
|
||||
key: key,
|
||||
value: value
|
||||
})
|
||||
)
|
||||
|
||||
/** @param {Grammar} r */
|
||||
PinReference = r => P.seqMap(
|
||||
r.PathSymbolEntity,
|
||||
P.whitespace,
|
||||
r.Guid,
|
||||
(objectName, _, pinGuid) => new PinReferenceEntity({
|
||||
objectName: objectName,
|
||||
pinGuid: pinGuid
|
||||
})
|
||||
)
|
||||
/* --- Factory --- */
|
||||
|
||||
/** @param {Grammar} r */
|
||||
static getGrammarForType(r, attributeType, defaultGrammar) {
|
||||
@@ -125,7 +31,7 @@ export default class Grammar {
|
||||
return r.String
|
||||
case GuidEntity:
|
||||
return r.Guid
|
||||
case Identifier:
|
||||
case IdentifierEntity:
|
||||
return r.Identifier
|
||||
case ObjectReferenceEntity:
|
||||
return r.Reference
|
||||
@@ -159,7 +65,7 @@ export default class Grammar {
|
||||
}
|
||||
|
||||
/** @param {Grammar} r */
|
||||
static CreateAttributeGrammar = (r, entityType, valueSeparator = P.string("=").trim(P.optWhitespace)) =>
|
||||
static createAttributeGrammar = (r, entityType, valueSeparator = P.string("=").trim(P.optWhitespace)) =>
|
||||
r.AttributeName.skip(valueSeparator)
|
||||
.chain(attributeName => {
|
||||
const attributeKey = attributeName.split(".")
|
||||
@@ -172,7 +78,7 @@ export default class Grammar {
|
||||
})
|
||||
|
||||
/** @param {Grammar} r */
|
||||
static CreateMultiAttributeGrammar = (r, entityType) =>
|
||||
static createMultiAttributeGrammar = (r, entityType) =>
|
||||
/**
|
||||
* Basically this creates a parser that looks for a string like 'Key (A=False,B="Something",)'
|
||||
* Then it populates an object of type EntityType with the attribute values found inside the parentheses.
|
||||
@@ -181,7 +87,7 @@ export default class Grammar {
|
||||
entityType.lookbehind
|
||||
? P.seq(P.string(entityType.lookbehind), P.optWhitespace, P.string("("))
|
||||
: P.string("("),
|
||||
Grammar.CreateAttributeGrammar(r, entityType)
|
||||
Grammar.createAttributeGrammar(r, entityType)
|
||||
.trim(P.optWhitespace)
|
||||
.sepBy(P.string(","))
|
||||
.skip(P.regex(/,?/).then(P.optWhitespace)), // Optional trailing comma
|
||||
@@ -192,11 +98,140 @@ export default class Grammar {
|
||||
return result
|
||||
})
|
||||
|
||||
/** @param {Grammar} r */
|
||||
FunctionReference = r => Grammar.CreateMultiAttributeGrammar(r, FunctionReferenceEntity)
|
||||
/* --- General --- */
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Pin = r => Grammar.CreateMultiAttributeGrammar(r, PinEntity)
|
||||
InlineWhitespace = r => P.regex(/[^\S\n]+/).desc("inline whitespace")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
InlineOptWhitespace = r => P.regex(/[^\S\n]*/).desc("inline optional whitespace")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
MultilineWhitespace = r => P.regex(/[^\S\n]*\n\s*/).desc("whitespace with at least a newline")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Null = r => P.seq(P.string("("), r.InlineOptWhitespace, P.string(")")).map(_ => null).desc("null: ()")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Boolean = r => P.alt(P.string("True"), P.string("False")).map(v => v === "True" ? true : false)
|
||||
.desc("either True or False")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Number = r => P.regex(/[\-\+]?[0-9]+(?:\.[0-9]+)?/).map(Number).desc("a number")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Word = r => P.regex(/[a-zA-Z]+/).desc("a word")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
String = r => P.regex(/(?:[^"\\]|\\.)*/).wrap(P.string('"'), P.string('"'))
|
||||
.desc('string (with possibility to escape the quote using \")')
|
||||
|
||||
/** @param {Grammar} r */
|
||||
ReferencePath = r => P.seq(
|
||||
P.string("/"),
|
||||
r.PathSymbol
|
||||
.map(v => v.toString())
|
||||
.sepBy1(P.string("."))
|
||||
.tieWith(".")
|
||||
)
|
||||
.tie()
|
||||
.atLeast(2)
|
||||
.tie()
|
||||
.desc('a path (words with possibly underscore, separated by ".", separated by "/")')
|
||||
|
||||
/** @param {Grammar} r */
|
||||
AttributeName = r => r.Word.sepBy1(P.string(".")).tieWith(".").desc('words separated by ""')
|
||||
|
||||
/* --- Entity --- */
|
||||
|
||||
/** @param {Grammar} r */
|
||||
None = r => P.string("None").map(_ => new ObjectReferenceEntity({ type: "None", path: "" })).desc("none")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Integer = r => P.regex(/[\-\+]?[0-9]+/).map(v => new IntegerEntity(v)).desc("an integer")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Guid = r => P.regex(/[0-9a-zA-Z]{32}/).map(v => new GuidEntity({ value: v }))
|
||||
.desc("32 digit hexadecimal (accepts all the letters for safety) value")
|
||||
|
||||
/** @param {Grammar} */
|
||||
Identifier = r => P.regex(/\w+/).map(v => new IdentifierEntity(v))
|
||||
|
||||
/** @param {Grammar} r */
|
||||
PathSymbol = r => P.regex(/[0-9a-zA-Z_]+/).map(v => new PathSymbolEntity({ value: v }))
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Reference = r => P.alt(
|
||||
r.None,
|
||||
...[r.ReferencePath.map(path => new ObjectReferenceEntity({ type: "", path: path }))]
|
||||
.flatMap(referencePath => [
|
||||
referencePath, // version having just path
|
||||
referencePath.trim(P.string('"')) // Version having path surround with double quotes
|
||||
]),
|
||||
P.seqMap(
|
||||
r.Word, // Goes into referenceType
|
||||
P.optWhitespace, // Goes into _ (ignored)
|
||||
P.alt(...[r.ReferencePath].flatMap(referencePath => [
|
||||
referencePath.wrap(P.string(`"`), P.string(`"`)),
|
||||
referencePath.wrap(P.string(`'"`), P.string(`"'`))
|
||||
])), // Goes into referencePath
|
||||
(referenceType, _, referencePath) => new ObjectReferenceEntity({ type: referenceType, path: referencePath })
|
||||
),
|
||||
r.Word.map(type => new ObjectReferenceEntity({ type: type, path: "" })),
|
||||
)
|
||||
|
||||
/** @param {Grammar} r */
|
||||
LocalizedText = r => P.seqMap(
|
||||
P.string(LocalizedTextEntity.lookbehind).skip(P.optWhitespace).skip(P.string("(")), // Goes into _ (ignored)
|
||||
r.String.trim(P.optWhitespace), // Goes into namespace
|
||||
P.string(","), // Goes into __ (ignored)
|
||||
r.String.trim(P.optWhitespace), // Goes into key
|
||||
P.string(","), // Goes into ___ (ignored)
|
||||
r.String.trim(P.optWhitespace), // Goes into value
|
||||
P.string(")"), // Goes into ____ (ignored)
|
||||
(_, namespace, __, key, ___, value, ____) => new LocalizedTextEntity({
|
||||
namespace: namespace,
|
||||
key: key,
|
||||
value: value
|
||||
})
|
||||
)
|
||||
|
||||
/** @param {Grammar} r */
|
||||
AttributeAnyValue = r => P.alt(
|
||||
r.Null,
|
||||
r.None,
|
||||
r.Boolean,
|
||||
r.Number,
|
||||
r.Integer,
|
||||
r.String,
|
||||
r.Guid,
|
||||
r.Reference,
|
||||
r.LocalizedText)
|
||||
|
||||
/** @param {Grammar} r */
|
||||
PinReference = r => P.seqMap(
|
||||
r.PathSymbol, // Goes into objectNAme
|
||||
P.whitespace, // Goes into _ (ignored)
|
||||
r.Guid, // Goes into pinGuid
|
||||
(objectName, _, pinGuid) => new PinReferenceEntity({
|
||||
objectName: objectName,
|
||||
pinGuid: pinGuid
|
||||
})
|
||||
)
|
||||
|
||||
/** @param {Grammar} r */
|
||||
FunctionReference = r => Grammar.createMultiAttributeGrammar(r, FunctionReferenceEntity)
|
||||
|
||||
/** @param {Grammar} r */
|
||||
KeyBinding = r => P.alt(
|
||||
r.Identifier.map(identifier => new KeyBindingEntity({
|
||||
Key: identifier
|
||||
})),
|
||||
Grammar.createMultiAttributeGrammar(r, KeyBindingEntity)
|
||||
)
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Pin = r => Grammar.createMultiAttributeGrammar(r, PinEntity)
|
||||
|
||||
/** @param {Grammar} r */
|
||||
CustomProperties = r =>
|
||||
@@ -216,10 +251,10 @@ export default class Grammar {
|
||||
P
|
||||
.alt(
|
||||
r.CustomProperties,
|
||||
Grammar.CreateAttributeGrammar(r, ObjectEntity)
|
||||
Grammar.createAttributeGrammar(r, ObjectEntity)
|
||||
)
|
||||
.sepBy1(P.whitespace),
|
||||
P.seq(r.WhitespaceNewline, P.string("End"), P.whitespace, P.string("Object")),
|
||||
P.seq(r.MultilineWhitespace, P.string("End"), P.whitespace, P.string("Object")),
|
||||
(_, attributes, __) => {
|
||||
let result = new ObjectEntity()
|
||||
attributes.forEach(attributeSetter => attributeSetter(result))
|
||||
|
||||
@@ -2,7 +2,9 @@ import CustomSerializer from "./CustomSerializer"
|
||||
import FunctionReferenceEntity from "../entity/FunctionReferenceEntity"
|
||||
import GeneralSerializer from "./GeneralSerializer"
|
||||
import GuidEntity from "../entity/GuidEntity"
|
||||
import IdentifierEntity from "../entity/IdentifierEntity"
|
||||
import IntegerEntity from "../entity/IntegerEntity"
|
||||
import KeyBindingEntity from "../entity/KeyBindingEntity"
|
||||
import LocalizedTextEntity from "../entity/LocalizedTextEntity"
|
||||
import ObjectEntity from "../entity/ObjectEntity"
|
||||
import ObjectReferenceEntity from "../entity/ObjectReferenceEntity"
|
||||
@@ -12,29 +14,39 @@ import PinEntity from "../entity/PinEntity"
|
||||
import PinReferenceEntity from "../entity/PinReferenceEntity"
|
||||
import SerializerFactory from "./SerializerFactory"
|
||||
import ToStringSerializer from "./ToStringSerializer"
|
||||
import Identifier from "../entity/Identifier"
|
||||
|
||||
export default function initializeSerializerFactory() {
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
ObjectEntity,
|
||||
new ObjectSerializer()
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
PinEntity,
|
||||
new GeneralSerializer(v => `${PinEntity.lookbehind} (${v})`, PinEntity, "", ",", true)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
FunctionReferenceEntity,
|
||||
new GeneralSerializer(v => `(${v})`, FunctionReferenceEntity, "", ",", false)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
KeyBindingEntity,
|
||||
new GeneralSerializer(v => `(${v})`, KeyBindingEntity, "", ",", false)
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
LocalizedTextEntity,
|
||||
new GeneralSerializer(v => `${LocalizedTextEntity.lookbehind}(${v})`, LocalizedTextEntity, "", ", ", false, "", _ => "")
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
PinReferenceEntity,
|
||||
new GeneralSerializer(v => v, PinReferenceEntity, "", " ", false, "", _ => "")
|
||||
)
|
||||
|
||||
SerializerFactory.registerSerializer(
|
||||
ObjectReferenceEntity,
|
||||
new CustomSerializer(
|
||||
@@ -45,8 +57,12 @@ export default function initializeSerializerFactory() {
|
||||
: ""
|
||||
))
|
||||
)
|
||||
SerializerFactory.registerSerializer(Identifier, new ToStringSerializer(Identifier))
|
||||
|
||||
SerializerFactory.registerSerializer(IdentifierEntity, new ToStringSerializer(IdentifierEntity))
|
||||
|
||||
SerializerFactory.registerSerializer(PathSymbolEntity, new ToStringSerializer(PathSymbolEntity))
|
||||
|
||||
SerializerFactory.registerSerializer(GuidEntity, new ToStringSerializer(GuidEntity))
|
||||
|
||||
SerializerFactory.registerSerializer(IntegerEntity, new ToStringSerializer(IntegerEntity))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user