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
|
||||
},
|
||||
|
||||
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(
|
||||
{
|
||||
namespace,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@ declare global {
|
|||
interface Map<K, V> {
|
||||
toJSON(): Record<string, V>
|
||||
}
|
||||
|
||||
interface Array<T> {
|
||||
lastItem(): T
|
||||
}
|
||||
}
|
||||
|
||||
Map.prototype.toJSON = function () {
|
||||
|
|
@ -9,3 +13,7 @@ Map.prototype.toJSON = function () {
|
|||
this.forEach((value, key) => (obj[key] = value))
|
||||
return obj
|
||||
}
|
||||
|
||||
Array.prototype.lastItem = function () {
|
||||
return this[this.length - 1]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@ import { Memory } from "./Memory.js"
|
|||
|
||||
process.on("beforeExit", () => {
|
||||
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/RunEnd.js"
|
||||
|
||||
export * from "./components/Animation.js"
|
||||
export * from "./components/UI.js"
|
||||
export { Animation } from "./components/Animation.js"
|
||||
export * from "./components/Utils.js"
|
||||
|
||||
export * from "./types/enums/index.js"
|
||||
export * from "./compilers/bindings/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({
|
||||
"#test": 123,
|
||||
[Binding.IS_CREATIVE_LAYOUT]: true,
|
||||
[Binding.INVENTORY_SELECTED_ITEM_COLOR]: Color(0x00ff00),
|
||||
}).addChild(
|
||||
Label({
|
||||
text: "Hello, World!",
|
||||
shadow: true,
|
||||
color: Color("#3b0202"),
|
||||
})
|
||||
)
|
||||
const input = "abcdef + 123456"
|
||||
|
||||
const lexer = BindingTranspiler.lexer(input)
|
||||
|
||||
console.log(lexer)
|
||||
|
|
|
|||
Reference in a new issue