uh
This commit is contained in:
parent
4d5f81f7e5
commit
df7c642077
10 changed files with 440 additions and 157 deletions
|
|
@ -21,7 +21,7 @@
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "npx tsc",
|
"build": "npx tsc",
|
||||||
"watch": "npx tsc --watch",
|
"build-watch": "npx tsc --watch",
|
||||||
"test": "bun test/app.ts",
|
"test": "bun test/app.ts",
|
||||||
"test-watch": "bun --watch test/app.ts",
|
"test-watch": "bun --watch test/app.ts",
|
||||||
"prefetch": "bun scripts/prefetch"
|
"prefetch": "bun scripts/prefetch"
|
||||||
|
|
|
||||||
|
|
@ -1,149 +0,0 @@
|
||||||
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[]) {},
|
|
||||||
}
|
|
||||||
11
src/compilers/bindings/Checker.ts
Normal file
11
src/compilers/bindings/Checker.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
export function isBlankChar(char: string) {
|
||||||
|
return /\s/.test(char)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isWordChar(char: string) {
|
||||||
|
return char && /\w/.test(char)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isNumberChar(char: string) {
|
||||||
|
return /\d/.test(char)
|
||||||
|
}
|
||||||
33
src/compilers/bindings/Funtion.ts
Normal file
33
src/compilers/bindings/Funtion.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { RandomBindingString } from "../../components/Utils.js"
|
||||||
|
import { Expression, GenBinding } from "./types.js"
|
||||||
|
|
||||||
|
export const FuntionMap = new Map<
|
||||||
|
string,
|
||||||
|
(...args: Expression[]) => {
|
||||||
|
genBindings?: GenBinding[]
|
||||||
|
value: Expression
|
||||||
|
}
|
||||||
|
>()
|
||||||
|
|
||||||
|
// Default Functions
|
||||||
|
FuntionMap.set("abs", number => {
|
||||||
|
const randomBinding = RandomBindingString(16)
|
||||||
|
return {
|
||||||
|
genBindings: [{ source: `((-1 + (${number} > 0) * 2) * ${number})`, target: randomBinding }],
|
||||||
|
value: randomBinding,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
FuntionMap.set("new", expression => {
|
||||||
|
const randomBinding = RandomBindingString(16)
|
||||||
|
return {
|
||||||
|
genBindings: [{ source: expression, target: randomBinding }],
|
||||||
|
value: randomBinding,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
FuntionMap.set("max", (...args) => {
|
||||||
|
return {
|
||||||
|
value: "#a",
|
||||||
|
}
|
||||||
|
})
|
||||||
126
src/compilers/bindings/Lexer.ts
Normal file
126
src/compilers/bindings/Lexer.ts
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
import { makeToken, TokenKind, Token } from "./types.js"
|
||||||
|
import * as Checker from "./Checker.js"
|
||||||
|
|
||||||
|
export function Lexer(input: string) {
|
||||||
|
const tokens: Token[] = []
|
||||||
|
|
||||||
|
if (input.length === 0) return tokens
|
||||||
|
|
||||||
|
let index = 0
|
||||||
|
do {
|
||||||
|
const token = input[index]
|
||||||
|
|
||||||
|
if (Checker.isBlankChar(token)) continue
|
||||||
|
|
||||||
|
switch (token) {
|
||||||
|
// Literals
|
||||||
|
case "#":
|
||||||
|
case "$": {
|
||||||
|
const start = index++
|
||||||
|
|
||||||
|
while (index < input.length) {
|
||||||
|
const token = input[index]
|
||||||
|
if (Checker.isWordChar(token)) index++
|
||||||
|
else break
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens.push(makeToken(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(makeToken(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(makeToken(input, TokenKind.TEMPLATE_STRING, start, index - start + 1))
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
case ",":
|
||||||
|
tokens.push(makeToken(input, TokenKind.COMMA, index))
|
||||||
|
break
|
||||||
|
|
||||||
|
// Single operators
|
||||||
|
case "+":
|
||||||
|
case "-":
|
||||||
|
case "*":
|
||||||
|
case "/":
|
||||||
|
case "%":
|
||||||
|
tokens.push(makeToken(input, TokenKind.OPERATOR, index))
|
||||||
|
break
|
||||||
|
|
||||||
|
case "(":
|
||||||
|
tokens.push(makeToken(input, TokenKind.OPEN_PARENTHESIS, index))
|
||||||
|
break
|
||||||
|
|
||||||
|
case ")":
|
||||||
|
tokens.push(makeToken(input, TokenKind.CLOSE_PARENTHESIS, index))
|
||||||
|
break
|
||||||
|
|
||||||
|
// Double operators
|
||||||
|
case "&":
|
||||||
|
case "|":
|
||||||
|
case "=":
|
||||||
|
if (input[index + 1] === input[index]) tokens.push(makeToken(input, TokenKind.OPERATOR, index++, 2))
|
||||||
|
else tokens.push(makeToken(input, TokenKind.OPERATOR, index))
|
||||||
|
break
|
||||||
|
|
||||||
|
case "!":
|
||||||
|
case ">":
|
||||||
|
case "<":
|
||||||
|
if (input[index + 1] === "=") tokens.push(makeToken(input, TokenKind.OPERATOR, index++, 2))
|
||||||
|
else tokens.push(makeToken(input, TokenKind.OPERATOR, index))
|
||||||
|
break
|
||||||
|
|
||||||
|
default: {
|
||||||
|
let start = index
|
||||||
|
|
||||||
|
if (Checker.isNumberChar(token)) {
|
||||||
|
while (Checker.isNumberChar(input[index + 1])) index++
|
||||||
|
tokens.push(makeToken(input, TokenKind.NUMBER, start, index - start + 1))
|
||||||
|
} else if (Checker.isWordChar(token)) {
|
||||||
|
while (Checker.isWordChar(input[index + 1])) index++
|
||||||
|
tokens.push(makeToken(input, TokenKind.WORD, start, index - start + 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (++index < input.length)
|
||||||
|
|
||||||
|
return tokens
|
||||||
|
}
|
||||||
235
src/compilers/bindings/Parser.ts
Normal file
235
src/compilers/bindings/Parser.ts
Normal file
|
|
@ -0,0 +1,235 @@
|
||||||
|
import { BindingType } from "../../types/enums/BindingType.js"
|
||||||
|
import { BindingItem } from "../../types/properties/value.js"
|
||||||
|
import { FuntionMap } from "./Funtion.js"
|
||||||
|
import { Lexer } from "./Lexer.js"
|
||||||
|
import { Expression, GenBinding, Token, TokenKind } from "./types.js"
|
||||||
|
|
||||||
|
export class Parser {
|
||||||
|
position: number = 0
|
||||||
|
tokens: Token[]
|
||||||
|
|
||||||
|
genBindings: GenBinding[] = []
|
||||||
|
output: Expression
|
||||||
|
|
||||||
|
constructor(private input: string) {
|
||||||
|
this.tokens = Lexer(this.input)
|
||||||
|
this.output = this.parseExpression()
|
||||||
|
}
|
||||||
|
|
||||||
|
at() {
|
||||||
|
return this.tokens[this.position]
|
||||||
|
}
|
||||||
|
|
||||||
|
eat() {
|
||||||
|
return this.tokens[this.position++]
|
||||||
|
}
|
||||||
|
|
||||||
|
last() {
|
||||||
|
return this.tokens[this.tokens.length - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
private parseExpression(): Expression {
|
||||||
|
return this.parseAdditiveExpression()
|
||||||
|
}
|
||||||
|
|
||||||
|
private parseAdditiveExpression(): Expression {
|
||||||
|
let left = this.parseMultiplicativeExpression(),
|
||||||
|
current
|
||||||
|
|
||||||
|
while (
|
||||||
|
(current = this.at()) &&
|
||||||
|
this.at()?.kind === TokenKind.OPERATOR &&
|
||||||
|
["+", "-", "==", ">", "<", ">=", "<=", "!=", "&&", "||"].includes(current.value)
|
||||||
|
) {
|
||||||
|
const operator = this.eat()
|
||||||
|
const right = this.parseMultiplicativeExpression()
|
||||||
|
|
||||||
|
switch (operator.value) {
|
||||||
|
case "==":
|
||||||
|
left = `(${left} = ${right})`
|
||||||
|
break
|
||||||
|
|
||||||
|
case ">=":
|
||||||
|
case "<=":
|
||||||
|
left = `((${left} ${operator.value[0]} ${right}) or (${left} = ${right}))`
|
||||||
|
break
|
||||||
|
|
||||||
|
case "!=":
|
||||||
|
left = `(not (${left} = ${right}))`
|
||||||
|
break
|
||||||
|
|
||||||
|
case "&&":
|
||||||
|
left = `(${left} and ${right})`
|
||||||
|
break
|
||||||
|
|
||||||
|
case "||":
|
||||||
|
left = `(${left} or ${right})`
|
||||||
|
break
|
||||||
|
|
||||||
|
default:
|
||||||
|
left = `(${left} ${operator.value} ${right})`
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return left
|
||||||
|
}
|
||||||
|
|
||||||
|
private parseMultiplicativeExpression(): Expression {
|
||||||
|
let left = this.parsePrimaryExpression(),
|
||||||
|
current
|
||||||
|
|
||||||
|
while (
|
||||||
|
(current = this.at()) &&
|
||||||
|
this.at()?.kind === TokenKind.OPERATOR &&
|
||||||
|
["*", "/", "%"].includes(current.value)
|
||||||
|
) {
|
||||||
|
const operator = this.eat()
|
||||||
|
const right = this.parsePrimaryExpression()
|
||||||
|
|
||||||
|
if (current.value === "%") left = `(${left} - ${left} / ${right} * ${right})`
|
||||||
|
else left = `(${left} ${operator.value} ${right})`
|
||||||
|
}
|
||||||
|
|
||||||
|
return left
|
||||||
|
}
|
||||||
|
|
||||||
|
private parsePrimaryExpression(): Expression {
|
||||||
|
const left = this.at()
|
||||||
|
|
||||||
|
switch (left?.kind) {
|
||||||
|
case TokenKind.WORD:
|
||||||
|
return this.parseCallExpression(this.eat())
|
||||||
|
|
||||||
|
case TokenKind.OPEN_PARENTHESIS: {
|
||||||
|
this.eat()
|
||||||
|
const value = this.parseExpression()
|
||||||
|
this.expect(TokenKind.CLOSE_PARENTHESIS, "Unexpected token!")
|
||||||
|
this.eat()
|
||||||
|
return `(${value})`
|
||||||
|
}
|
||||||
|
|
||||||
|
case TokenKind.OPERATOR: {
|
||||||
|
if (left.value === "-" || left.value === "+") {
|
||||||
|
this.eat()
|
||||||
|
|
||||||
|
let negative = left.value === "-",
|
||||||
|
current
|
||||||
|
|
||||||
|
while ((current = this.at()) && current.kind === TokenKind.OPERATOR) {
|
||||||
|
if (current.value === "-") {
|
||||||
|
this.eat()
|
||||||
|
negative = !negative
|
||||||
|
} else if (current.value === "+") {
|
||||||
|
this.eat()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = this.parsePrimaryExpression()
|
||||||
|
|
||||||
|
return negative ? `(0 - ${value})` : value
|
||||||
|
} else if (left.value === "!") {
|
||||||
|
this.eat()
|
||||||
|
|
||||||
|
let not = true,
|
||||||
|
current
|
||||||
|
|
||||||
|
while ((current = this.at()) && current.kind === TokenKind.OPERATOR) {
|
||||||
|
if (current.value === "!") {
|
||||||
|
this.eat()
|
||||||
|
not = !not
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = this.parsePrimaryExpression()
|
||||||
|
return not ? `(not ${value})` : value
|
||||||
|
} else break
|
||||||
|
}
|
||||||
|
|
||||||
|
case TokenKind.VARIABLE:
|
||||||
|
case TokenKind.NUMBER:
|
||||||
|
case TokenKind.STRING:
|
||||||
|
return this.eat().value
|
||||||
|
|
||||||
|
case undefined:
|
||||||
|
this.expect(TokenKind.NUMBER, "Unexpected token!")
|
||||||
|
}
|
||||||
|
|
||||||
|
return left.value
|
||||||
|
}
|
||||||
|
|
||||||
|
private parseCallExpression(callerToken: Token): Expression {
|
||||||
|
const left = this.at()
|
||||||
|
|
||||||
|
if (left?.kind === TokenKind.OPEN_PARENTHESIS) {
|
||||||
|
this.eat()
|
||||||
|
const args: Expression[] = []
|
||||||
|
|
||||||
|
if (this.at().kind !== TokenKind.CLOSE_PARENTHESIS) {
|
||||||
|
args.push(this.parseExpression())
|
||||||
|
|
||||||
|
while (this.at().kind === TokenKind.COMMA) {
|
||||||
|
this.eat()
|
||||||
|
if (this.at().kind === TokenKind.CLOSE_PARENTHESIS) {
|
||||||
|
this.expect(TokenKind.CLOSE_PARENTHESIS, "Unexpected token!")
|
||||||
|
}
|
||||||
|
args.push(this.parseExpression())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.eat()
|
||||||
|
|
||||||
|
return this.funtionCall(callerToken.value, ...args)
|
||||||
|
} else {
|
||||||
|
this.warn("This token should be a string!", callerToken)
|
||||||
|
return callerToken.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private funtionCall(name: string, ...params: Expression[]): Expression {
|
||||||
|
const func = FuntionMap.get(name)
|
||||||
|
if (!func) {
|
||||||
|
return this.expect(TokenKind.WORD, "Function not found!")!
|
||||||
|
} else {
|
||||||
|
const { genBindings, value } = func(...params)
|
||||||
|
if (genBindings) this.genBindings.push(...genBindings)
|
||||||
|
return `(${value})`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private expect(kind: TokenKind, err: string) {
|
||||||
|
const prev = this.at() || this.last()
|
||||||
|
if (!prev || prev.kind !== kind) {
|
||||||
|
throw new Error(
|
||||||
|
`\x1b[31m${this.getPointer(prev)}\n` + `[ERROR]: ${err}\x1b[0m - Expected ${TokenKind[kind]}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private warn(err: string, token?: Token) {
|
||||||
|
const prev = token || this.at()
|
||||||
|
console.warn(`\x1b[33m${this.getPointer(prev)}\n` + `[WARNING]: ${err}\x1b[0m`)
|
||||||
|
}
|
||||||
|
|
||||||
|
private getPointer(token: Token) {
|
||||||
|
return `${this.input.slice(0, token.start)}>>>${this.input.slice(
|
||||||
|
token.start,
|
||||||
|
token.start + token.length
|
||||||
|
)}<<<${this.input.slice(token.start + token.length)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
out(): { gen?: BindingItem[]; out: Expression } {
|
||||||
|
return {
|
||||||
|
out: this.output,
|
||||||
|
gen: this.genBindings.map(
|
||||||
|
({ source, target }) =>
|
||||||
|
<BindingItem>{
|
||||||
|
binding_type: BindingType.VIEW,
|
||||||
|
source_property_name: `(${source})`,
|
||||||
|
target_property_name: `${target}`,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1 +1,4 @@
|
||||||
export * from "./Bindings.js"
|
export * from "./Checker.js"
|
||||||
|
export * from "./Lexer.js"
|
||||||
|
export * from "./Parser.js"
|
||||||
|
export * from "./types.js"
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,31 @@ export enum TokenKind {
|
||||||
COMMA,
|
COMMA,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum GroupType {
|
||||||
|
FUNCTION_CALL,
|
||||||
|
FUNCTION_PARAMS,
|
||||||
|
OPERATOR_SCOPE,
|
||||||
|
}
|
||||||
|
|
||||||
export interface Token {
|
export interface Token {
|
||||||
kind: TokenKind
|
kind: TokenKind
|
||||||
value: string
|
value: string
|
||||||
start: number
|
start: number
|
||||||
length: number
|
length: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Expression = string
|
||||||
|
|
||||||
|
export function makeToken(input: string, kind: TokenKind, start: number, length: number = 1): Token {
|
||||||
|
return {
|
||||||
|
value: input.slice(start, start + length),
|
||||||
|
kind,
|
||||||
|
start,
|
||||||
|
length,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GenBinding {
|
||||||
|
source: string
|
||||||
|
target: string
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Type } from "../types/enums/Type.js"
|
import { Type } from "../types/enums/Type.js"
|
||||||
import { Array3 } from "../types/properties/value.js"
|
import { Array3, Binding } from "../types/properties/value.js"
|
||||||
import { UI } from "./UI.js"
|
import { UI } from "./UI.js"
|
||||||
|
|
||||||
import { Renderer } from "../types/enums/Renderer.js"
|
import { Renderer } from "../types/enums/Renderer.js"
|
||||||
|
|
@ -75,6 +75,10 @@ export function RandomString(length: number, base: number = 32) {
|
||||||
return out.join("")
|
return out.join("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function RandomBindingString(length: number, base: number = 32): Binding {
|
||||||
|
return `#${RandomString(length, base)}`
|
||||||
|
}
|
||||||
|
|
||||||
// Quick Elements
|
// Quick Elements
|
||||||
export function Panel(properties?: Panel, name?: string, namespace?: string) {
|
export function Panel(properties?: Panel, name?: string, namespace?: string) {
|
||||||
return new UI(Type.PANEL, name, namespace).setProperties(properties || {})
|
return new UI(Type.PANEL, name, namespace).setProperties(properties || {})
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
import { BindingTranspiler } from ".."
|
import { Parser } from ".."
|
||||||
|
|
||||||
const input = "abcdef + 123456"
|
const { gen, out } = new Parser("new(#a + #b) >= #b").out()
|
||||||
|
|
||||||
const lexer = BindingTranspiler.lexer(input)
|
console.log(gen, out)
|
||||||
|
|
||||||
console.log(lexer)
|
|
||||||
|
|
|
||||||
Reference in a new issue