This commit is contained in:
Asaki Yuki 2026-01-24 21:42:11 +07:00
parent 99c294a9ba
commit 3719a3f6b3
6 changed files with 57 additions and 111 deletions

View file

@ -1,13 +1,13 @@
import { Binding } from "../types/properties/value.js" import { Binding } from "../types/properties/value.js"
export function FormatProperties(properties: any) { export function FormatProperties(properties: any) {
const property_bags: Record<Binding, any> = {} const property_bag: Record<Binding, any> = {}
for (const key in properties) { for (const key in properties) {
const value = properties[key] const value = properties[key]
if (key.startsWith("#")) { if (key.startsWith("#")) {
property_bags[<Binding>key] = value property_bag[<Binding>key] = value
delete properties[key] delete properties[key]
} }
} }
@ -17,11 +17,11 @@ export function FormatProperties(properties: any) {
delete properties.anchor delete properties.anchor
} }
if (Object.keys(property_bags).length) { if (Object.keys(property_bag).length) {
if (properties.property_bags) { if (properties.property_bag) {
properties.property_bags = { ...property_bags, ...properties.property_bags } properties.property_bag = { ...property_bag, ...properties.property_bag }
} else { } else {
properties.property_bags = property_bags properties.property_bag = property_bag
} }
} }

View file

@ -1,10 +1,13 @@
import { makeToken, TokenKind, Token, TSToken, TSTokenKind } from "./types.js" import { makeToken, TokenKind, Token, TSToken, TSTokenKind } from "./types.js"
import * as Checker from "./Checker.js" import * as Checker from "./Checker.js"
export function Lexer(input: string, start: number = 0, end?: number) { export function Lexer(input: string, start: number = 0, length?: number) {
const tokens: Token[] = [] const tokens: Token[] = []
if (input.length === 0) return tokens if (input.length === 0) return tokens
length ||= input.length
console.log(input.slice(start, length))
let index = start let index = start
do { do {
@ -17,11 +20,18 @@ export function Lexer(input: string, start: number = 0, end?: number) {
case "#": case "#":
case "$": { case "$": {
const start = index++ const start = index++
while (index < length) {
while (index < input.length) {
const token = input[index] const token = input[index]
if (Checker.isWordChar(token)) index++ if (Checker.isWordChar(token)) index++
else break else {
if (start + 1 === index) {
console.error(
`\x1b[31merror: ${input + "\n" + " ".repeat(index + 6) + "^"}\nInvalid character.\x1b[0m`,
)
throw new Error()
}
break
}
} }
tokens.push(makeToken(input, TokenKind.VARIABLE, start, index-- - start)) tokens.push(makeToken(input, TokenKind.VARIABLE, start, index-- - start))
@ -29,19 +39,6 @@ export function Lexer(input: string, start: number = 0, end?: number) {
break 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 ",": case ",":
tokens.push(makeToken(input, TokenKind.COMMA, index)) tokens.push(makeToken(input, TokenKind.COMMA, index))
break break
@ -78,88 +75,39 @@ export function Lexer(input: string, start: number = 0, end?: number) {
else tokens.push(makeToken(input, TokenKind.OPERATOR, index)) else tokens.push(makeToken(input, TokenKind.OPERATOR, index))
break break
case "f": // string
case "F": { case "'": {
const start = index++
do {
const token = input[index]
if (token === "'") break
} while (++index < length)
tokens.push(makeToken(input, TokenKind.STRING, start, index - start + 1))
break
}
// template string
case "f": {
if (input[index + 1] === "'") { if (input[index + 1] === "'") {
const tsTokens: TSToken[] = [] const tsTokens: TSToken[] = []
const start = ++index const start = index
const tokenization = (start: number) => { const templateStringTokens = (start: number) => {
while (index < input.length) { while (index < length) {
const char = input[index] const char = input[index]
if (char === "'") { if (char === "'") {
index++
eatString()
} else if (char === "}") {
tsTokens.push({
kind: TSTokenKind.EXPRESSION,
tokens: Lexer(input, start + 1, index),
})
break
} }
index++ index++
} }
} }
const stringification = (start: number) => { templateStringTokens(index)
while (index < input.length) { tokens.push(makeToken(tsTokens, TokenKind.TEMPLATE_STRING, start, index - start))
const char = input[index]
if (char === "'") {
if (start + 1 !== index)
tsTokens.push({
kind: TSTokenKind.STRING,
tokens: {
kind: TokenKind.STRING,
start: start + 1,
length: index - start + 1,
value: `'${input.slice(start + 1, index)}'`,
},
})
break
} else if (char === "#" && input[index + 1] === "{") {
tsTokens.push({
kind: TSTokenKind.STRING,
tokens: {
value: `'${input.slice(start + 1, index)}'`,
kind: TokenKind.STRING,
length: index - start + 1,
start,
},
})
tokenization(++index)
start = index
}
index++
}
}
const eatString = () => {
while (index < input.length) {
const char = input[index]
if (char === "'") {
break
} else if (char === "#" && input[index + 1] === "{") {
index++
eatTemplate()
}
index++
}
}
const eatTemplate = () => {
while (index < input.length) {
const char = input[index]
if (char === "'") {
eatString()
} else if (char === "}") {
break
}
index++
}
}
stringification(index++)
tokens.push(makeToken(tsTokens, TokenKind.TEMPLATE_STRING, start - 1, index - start + 1))
break break
} }
} }
@ -181,7 +129,7 @@ export function Lexer(input: string, start: number = 0, end?: number) {
} }
} }
} }
} while (++index < (end || input.length)) } while (++index < length)
return tokens return tokens
} }

View file

@ -292,7 +292,7 @@ export class Parser {
out(): { gen?: BindingItem[]; out: Expression } { out(): { gen?: BindingItem[]; out: Expression } {
return { return {
out: this.output, out: `(${this.output})`,
gen: this.genBindings.map( gen: this.genBindings.map(
({ source, target }) => ({ source, target }) =>
<BindingItem>{ <BindingItem>{

View file

@ -11,7 +11,7 @@ export enum TokenKind {
OPERATOR, OPERATOR,
COMMA, COMMA,
EOF EOF,
} }
export enum TSTokenKind { export enum TSTokenKind {
@ -55,9 +55,9 @@ export function makeToken<T extends TokenKind>(
length: number = 1, length: number = 1,
): Token { ): Token {
if (kind === TokenKind.TEMPLATE_STRING) { if (kind === TokenKind.TEMPLATE_STRING) {
return { value: input as TSToken[], kind: kind, start, length } return { kind: kind, start, length, value: input as TSToken[] }
} else { } else {
return { value: input.slice(start, start + length) as string, kind, start, length } return { kind, start, length, value: input.slice(start, start + length) as string }
} }
} }

View file

@ -9,3 +9,5 @@ export * from "./types/enums/index.js"
export * as Properties from "./types/properties/index.js" export * as Properties from "./types/properties/index.js"
export { ItemAuxID } from "./types/enums/Items.js" export { ItemAuxID } from "./types/enums/Items.js"
export * from "./compilers/bindings/index.js"

View file

@ -1,14 +1,10 @@
import { BagBinding, f, ItemAuxID, Label } from ".." import { Panel } from ".."
const text = Label({ const panel = Panel()
text: "#text",
[BagBinding.ITEM_ID_AUX]: ItemAuxID.DIAMOND, panel.addBindings({
"#x": 2, source_property_name: `[ $abc ]`,
target_property_name: "#text",
}) })
text.addBindings({ console.log(panel)
source_property_name: f(`Test: #{ -(${BagBinding.ITEM_ID_AUX} % #x) == 0 }`),
target_property_name: BagBinding.TEXT,
})
console.log(text)