binding compiler
This commit is contained in:
parent
bb9b300d6f
commit
4d5f81f7e5
8 changed files with 188 additions and 15 deletions
|
|
@ -17,7 +17,7 @@ export const Memory = {
|
||||||
return namespace
|
return namespace
|
||||||
},
|
},
|
||||||
|
|
||||||
gen_ui_file_content(namespace: string, elements: Map<string, UI<Type, Renderer | null>>) {
|
gen_ui_file_contents(namespace: string, elements: Map<string, UI<Type, Renderer | null>>) {
|
||||||
return JSON.stringify(
|
return JSON.stringify(
|
||||||
{
|
{
|
||||||
namespace,
|
namespace,
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,10 @@ declare global {
|
||||||
interface Map<K, V> {
|
interface Map<K, V> {
|
||||||
toJSON(): Record<string, V>
|
toJSON(): Record<string, V>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Array<T> {
|
||||||
|
lastItem(): T
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map.prototype.toJSON = function () {
|
Map.prototype.toJSON = function () {
|
||||||
|
|
@ -9,3 +13,7 @@ Map.prototype.toJSON = function () {
|
||||||
this.forEach((value, key) => (obj[key] = value))
|
this.forEach((value, key) => (obj[key] = value))
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Array.prototype.lastItem = function () {
|
||||||
|
return this[this.length - 1]
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,6 @@ import { Memory } from "./Memory.js"
|
||||||
|
|
||||||
process.on("beforeExit", () => {
|
process.on("beforeExit", () => {
|
||||||
Memory.cache.forEach(({ elements, namespace }) => {
|
Memory.cache.forEach(({ elements, namespace }) => {
|
||||||
console.log(Memory.gen_ui_file_content(namespace, elements))
|
const contents = Memory.gen_ui_file_contents(namespace, elements)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
149
src/compilers/bindings/Bindings.ts
Normal file
149
src/compilers/bindings/Bindings.ts
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
import { Token, TokenKind } from "./types.js"
|
||||||
|
|
||||||
|
export const BindingTranspiler = {
|
||||||
|
isBlankChar(char: string) {
|
||||||
|
return /\s/.test(char)
|
||||||
|
},
|
||||||
|
|
||||||
|
isWordChar(char: string) {
|
||||||
|
return char && /\w/.test(char)
|
||||||
|
},
|
||||||
|
|
||||||
|
isNumberChar(char: string) {
|
||||||
|
return /\d/.test(char)
|
||||||
|
},
|
||||||
|
|
||||||
|
token(input: string, kind: TokenKind, start: number, length: number = 1): Token {
|
||||||
|
return {
|
||||||
|
value: input.slice(start, start + length),
|
||||||
|
kind,
|
||||||
|
start,
|
||||||
|
length,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
lexer(input: string) {
|
||||||
|
const tokens: Token[] = []
|
||||||
|
|
||||||
|
let index = 0
|
||||||
|
do {
|
||||||
|
const token = input[index]
|
||||||
|
|
||||||
|
if (BindingTranspiler.isBlankChar(token)) continue
|
||||||
|
|
||||||
|
switch (token) {
|
||||||
|
// Literals
|
||||||
|
case "#":
|
||||||
|
case "$": {
|
||||||
|
const start = index++
|
||||||
|
|
||||||
|
do {
|
||||||
|
const token = input[index]
|
||||||
|
if (BindingTranspiler.isWordChar(token)) continue
|
||||||
|
else break
|
||||||
|
} while (++index < input.length)
|
||||||
|
|
||||||
|
tokens.push(BindingTranspiler.token(input, TokenKind.VARIABLE, start, index - start))
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
case "'": {
|
||||||
|
const start = index++
|
||||||
|
|
||||||
|
do {
|
||||||
|
const token = input[index]
|
||||||
|
if (token === "'") break
|
||||||
|
} while (++index < input.length)
|
||||||
|
|
||||||
|
tokens.push(BindingTranspiler.token(input, TokenKind.STRING, start, index - start + 1))
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
case "`": {
|
||||||
|
const start = index++,
|
||||||
|
struct: boolean[] = []
|
||||||
|
|
||||||
|
do {
|
||||||
|
const token = input[index]
|
||||||
|
let lastStruct = struct.lastItem()
|
||||||
|
|
||||||
|
if (token === "`") {
|
||||||
|
if (struct.length) {
|
||||||
|
if (lastStruct === false) struct.pop()
|
||||||
|
else struct.push(false)
|
||||||
|
} else break
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token === "$") {
|
||||||
|
if (input[index + 1] === "{" && !lastStruct) {
|
||||||
|
struct.push(true)
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token === "}" && lastStruct === true) struct.pop()
|
||||||
|
} while (++index < input.length)
|
||||||
|
|
||||||
|
tokens.push(BindingTranspiler.token(input, TokenKind.TEMPLATE_STRING, start, index - start + 1))
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
case ",":
|
||||||
|
tokens.push(BindingTranspiler.token(input, TokenKind.COMMA, index))
|
||||||
|
break
|
||||||
|
|
||||||
|
// Single operators
|
||||||
|
case "+":
|
||||||
|
case "-":
|
||||||
|
case "*":
|
||||||
|
case "/":
|
||||||
|
tokens.push(BindingTranspiler.token(input, TokenKind.OPERATOR, index))
|
||||||
|
break
|
||||||
|
|
||||||
|
case "(":
|
||||||
|
tokens.push(BindingTranspiler.token(input, TokenKind.OPEN_PARENTHESIS, index))
|
||||||
|
break
|
||||||
|
|
||||||
|
case ")":
|
||||||
|
tokens.push(BindingTranspiler.token(input, TokenKind.CLOSE_PARENTHESIS, index))
|
||||||
|
break
|
||||||
|
|
||||||
|
// Double operators
|
||||||
|
case "&":
|
||||||
|
case "|":
|
||||||
|
case "=":
|
||||||
|
if (input[index + 1] === input[index])
|
||||||
|
tokens.push(BindingTranspiler.token(input, TokenKind.OPERATOR, ++index, 2))
|
||||||
|
else tokens.push(BindingTranspiler.token(input, TokenKind.OPERATOR, index))
|
||||||
|
break
|
||||||
|
|
||||||
|
case "!":
|
||||||
|
case ">":
|
||||||
|
case "<":
|
||||||
|
if (input[index + 1] === "=")
|
||||||
|
tokens.push(BindingTranspiler.token(input, TokenKind.OPERATOR, ++index, 2))
|
||||||
|
else tokens.push(BindingTranspiler.token(input, TokenKind.OPERATOR, index))
|
||||||
|
break
|
||||||
|
|
||||||
|
default: {
|
||||||
|
let start = index
|
||||||
|
|
||||||
|
if (BindingTranspiler.isNumberChar(token)) {
|
||||||
|
while (BindingTranspiler.isNumberChar(input[index + 1])) index++
|
||||||
|
tokens.push(BindingTranspiler.token(input, TokenKind.NUMBER, start, index - start + 1))
|
||||||
|
} else if (BindingTranspiler.isWordChar(token)) {
|
||||||
|
while (BindingTranspiler.isWordChar(input[index + 1])) index++
|
||||||
|
tokens.push(BindingTranspiler.token(input, TokenKind.WORD, start, index - start + 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (++index < input.length)
|
||||||
|
|
||||||
|
return tokens
|
||||||
|
},
|
||||||
|
|
||||||
|
parser(input: string, tokens: Token[]) {},
|
||||||
|
}
|
||||||
1
src/compilers/bindings/index.ts
Normal file
1
src/compilers/bindings/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export * from "./Bindings.js"
|
||||||
20
src/compilers/bindings/types.ts
Normal file
20
src/compilers/bindings/types.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
export enum TokenKind {
|
||||||
|
VARIABLE,
|
||||||
|
NUMBER,
|
||||||
|
STRING,
|
||||||
|
TEMPLATE_STRING,
|
||||||
|
WORD,
|
||||||
|
|
||||||
|
OPEN_PARENTHESIS,
|
||||||
|
CLOSE_PARENTHESIS,
|
||||||
|
|
||||||
|
OPERATOR,
|
||||||
|
COMMA,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Token {
|
||||||
|
kind: TokenKind
|
||||||
|
value: string
|
||||||
|
start: number
|
||||||
|
length: number
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import "./compilers/PreCompile.js"
|
import "./compilers/PreCompile.js"
|
||||||
import "./compilers/RunEnd.js"
|
import "./compilers/RunEnd.js"
|
||||||
|
|
||||||
|
export * from "./components/Animation.js"
|
||||||
export * from "./components/UI.js"
|
export * from "./components/UI.js"
|
||||||
export { Animation } from "./components/Animation.js"
|
|
||||||
export * from "./components/Utils.js"
|
export * from "./components/Utils.js"
|
||||||
|
|
||||||
export * from "./types/enums/index.js"
|
export * from "./types/enums/index.js"
|
||||||
|
export * from "./compilers/bindings/index.js"
|
||||||
export * as Properties from "./types/properties/index.js"
|
export * as Properties from "./types/properties/index.js"
|
||||||
|
|
|
||||||
18
test/app.ts
18
test/app.ts
|
|
@ -1,13 +1,7 @@
|
||||||
import { Binding, Color, Label, Panel } from ".."
|
import { BindingTranspiler } from ".."
|
||||||
|
|
||||||
Panel({
|
const input = "abcdef + 123456"
|
||||||
"#test": 123,
|
|
||||||
[Binding.IS_CREATIVE_LAYOUT]: true,
|
const lexer = BindingTranspiler.lexer(input)
|
||||||
[Binding.INVENTORY_SELECTED_ITEM_COLOR]: Color(0x00ff00),
|
|
||||||
}).addChild(
|
console.log(lexer)
|
||||||
Label({
|
|
||||||
text: "Hello, World!",
|
|
||||||
shadow: true,
|
|
||||||
color: Color("#3b0202"),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
|
||||||
Reference in a new issue