mirror of
https://github.com/barsdeveloper/ueblueprint.git
synced 2026-02-15 17:54:52 +08:00
Grammar move to regex WIP
This commit is contained in:
@@ -40,6 +40,20 @@ let P = Parsimmon
|
||||
|
||||
export default class Grammar {
|
||||
|
||||
static Regex = {
|
||||
ByteInteger: /0*(?:25[0-5]|2[0-4]\d|1?\d?\d|)(?!\d)/, // A integer between 0 and 255
|
||||
HexDigit: /[0-9a-fA-F]/,
|
||||
InlineOptWhitespace: /[^\S\n]*/,
|
||||
InlineWhitespace: /[^\S\n]+/,
|
||||
InsideString: /(?:[^"\\]|\\.)*/,
|
||||
Integer: /[\-\+]?\d+/,
|
||||
MultilineWhitespace: /\s*\n\s*/,
|
||||
Number: /[-\+]?\d+(?:\.\d+)?/,
|
||||
RealUnit: /^\+?(?:0(?:\.\d+)?|1(?:\.0+)?)(?![\.\d])/, // A number between 0 and 1 included
|
||||
Symbol: /[a-zA-Z_]\w*/,
|
||||
Word: /[a-zA-Z_]+/,
|
||||
}
|
||||
|
||||
/* --- Factory --- */
|
||||
|
||||
/** @param {Grammar} r */
|
||||
@@ -92,6 +106,8 @@ export default class Grammar {
|
||||
return r.Integer
|
||||
case InvariantTextEntity:
|
||||
return r.InvariantText
|
||||
case KeyBindingEntity:
|
||||
return r.KeyBinding
|
||||
case LinearColorEntity:
|
||||
return r.LinearColor
|
||||
case LocalizedTextEntity:
|
||||
@@ -218,56 +234,37 @@ export default class Grammar {
|
||||
/* --- General --- */
|
||||
|
||||
/** @param {Grammar} r */
|
||||
InlineWhitespace = r => P.regex(/[^\S\n]+/).desc("single line whitespace")
|
||||
Null = r => P.regex(new RegExp(String.raw`\(${Grammar.Regex.InlineOptWhitespace.source}\)`)).map(() => null).desc("null: ()")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
InlineOptWhitespace = r => P.regex(/[^\S\n]*/).desc("single line 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("true"),
|
||||
P.string("False"),
|
||||
P.string("false"),
|
||||
).map(v => v.toLocaleLowerCase() === "true" ? true : false)
|
||||
Boolean = r => P.regex(/true|false/i).map(v => v.toLocaleLowerCase() === "true" ? true : false)
|
||||
.desc("either True or False")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
HexDigit = r => P.regex(/[0-9a-fA-f]/).desc("hexadecimal digit")
|
||||
Number = r => P.regex(Grammar.Regex.Number).map(Number).desc("a number")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Number = r => P.regex(/[-\+]?[0-9]+(?:\.[0-9]+)?/).map(Number).desc("a number")
|
||||
BigInt = r => P.regex(Grammar.Regex.Integer).map(v => BigInt(v)).desc("a big integer")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
BigInt = r => P.regex(/[\-\+]?[0-9]+/).map(v => BigInt(v)).desc("a big integer")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
RealNumber = r => P.regex(/[-\+]?[0-9]+\.[0-9]+/).map(Number).desc("a number written as real")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
RealUnit = r => P.regex(/\+?[0-9]+(?:\.[0-9]+)?/).map(Number).assert(v => v >= 0 && v <= 1).desc("a number between 0 and 1")
|
||||
RealUnit = r => P.regex(Grammar.Regex.RealUnit).map(Number).desc("a number between 0 and 1")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
NaturalNumber = r => P.regex(/0|[1-9]\d*/).map(Number).desc("a natural number")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
ColorNumber = r => r.NaturalNumber.assert(n => 0 <= n && n < 256, "the color must be between 0 and 256 excluded")
|
||||
ColorNumber = r => P.regexp(Grammar.Regex.ByteInteger).desc("a number between 0 and 255")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Word = r => P.regex(/[a-zA-Z_]+/).desc("a word")
|
||||
Word = r => P.regexp(Grammar.Regex.Word).desc("a word")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
String = r => P.regex(/(?:[^"\\]|\\.)*/).wrap(P.string('"'), P.string('"')).map(Utility.unescapeString)
|
||||
String = r => P.regexp(new RegExp(`"(${Grammar.Regex.InsideString.source})"`), 1).map(Utility.unescapeString)
|
||||
.desc('string (with possibility to escape the quote using \")')
|
||||
|
||||
/** @param {Grammar} r */
|
||||
AttributeName = r => r.Word.sepBy1(P.string(".")).tieWith(".").desc("dot-separated words")
|
||||
AttributeName = r => P.regexp(new RegExp(String.raw`(?:(?:^|(?<!^)\.)${Grammar.Regex.Word.source})+`))
|
||||
.desc("dot-separated words")
|
||||
|
||||
/* --- Entity --- */
|
||||
|
||||
@@ -278,32 +275,30 @@ export default class Grammar {
|
||||
Integer64 = r => r.BigInt.map(v => new Integer64Entity(v)).desc("an integer64")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Integer = r => P.regex(/[\-\+]?[0-9]+/).map(v => new IntegerEntity(v)).desc("an integer")
|
||||
Integer = r => P.regex(Grammar.Regex.Integer).map(v => new IntegerEntity(v)).desc("an integer")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Byte = r => P.regex(/\+?[0-9]+/)
|
||||
.map(v => parseInt(v))
|
||||
.assert(v => v >= 0 && v < 1 << 8)
|
||||
.map(v => new ByteEntity(v))
|
||||
.desc("a Byte")
|
||||
Byte = r => P.regex(Grammar.Regex.ByteInteger).map(v => new ByteEntity(parseInt(v))).desc("a Byte")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Guid = r => r.HexDigit.times(32).tie().map(v => new GuidEntity({ value: v })).desc("32 digit hexadecimal value")
|
||||
Guid = r => P.regexp(new RegExp(`${Grammar.Regex.HexDigit.source}{32}`))
|
||||
.map(v => new GuidEntity({ value: v }))
|
||||
.desc("32 digit hexadecimal value")
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Identifier = r => P.regex(/\w+/).map(v => new IdentifierEntity(v))
|
||||
|
||||
/** @param {Grammar} r */
|
||||
PathSymbol = r => P.regex(/[0-9\w]+/).map(v => new PathSymbolEntity({ value: v }))
|
||||
PathSymbol = r => P.regex(/\w+/).map(v => new PathSymbolEntity({ value: v }))
|
||||
|
||||
/** @param {Grammar} r */
|
||||
PathSymbolOptSpaces = r => P.regex(/[0-9\w]+(?: [0-9\w]+)+|[0-9\w]+/).map(v => new PathSymbolEntity({ value: v }))
|
||||
PathSymbolOptSpaces = r => P.regex(/(?:(?:^|(?<!^) )\w+)+/).map(v => new PathSymbolEntity({ value: v }))
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Symbol = r => P.regex(/[a-zA-Z_]\w*/).map(v => new SymbolEntity({ value: v }))
|
||||
Symbol = r => P.regex(Grammar.Regex.Symbol).map(v => new SymbolEntity({ value: v }))
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Enum = r => P.regex(/[a-zA-Z_]\w*/).map(v => new EnumEntity({ value: v }))
|
||||
Enum = r => P.regex(Grammar.Regex.Symbol).map(v => new EnumEntity({ value: v }))
|
||||
|
||||
/** @param {Grammar} r */
|
||||
ObjectReference = r => P.alt(
|
||||
@@ -458,8 +453,7 @@ export default class Grammar {
|
||||
|
||||
/** @param {Grammar} r */
|
||||
CustomProperties = r =>
|
||||
P.string("CustomProperties")
|
||||
.then(P.whitespace)
|
||||
P.regex(/CustomProperties\s+/)
|
||||
.then(r.Pin)
|
||||
.map(pin => entity => {
|
||||
/** @type {Array} */
|
||||
@@ -470,14 +464,14 @@ export default class Grammar {
|
||||
|
||||
/** @param {Grammar} r */
|
||||
Object = r => P.seqMap(
|
||||
P.seq(P.string("Begin"), P.whitespace, P.string("Object"), P.whitespace),
|
||||
P.regexp(/Begin\s+Object\s+/),
|
||||
P
|
||||
.alt(
|
||||
r.CustomProperties,
|
||||
Grammar.createAttributeGrammar(r, ObjectEntity)
|
||||
)
|
||||
.sepBy1(P.whitespace),
|
||||
P.seq(r.MultilineWhitespace, P.string("End"), P.whitespace, P.string("Object")),
|
||||
P.regexp(/\s+End\s+Object/),
|
||||
(_0, attributes, _2) => {
|
||||
let values = {}
|
||||
attributes.forEach(attributeSetter => attributeSetter(values))
|
||||
|
||||
Reference in New Issue
Block a user