add binary expression

This commit is contained in:
Asaki Yuki 2026-02-19 14:16:17 +07:00
parent 1d00af88c0
commit 246cdbb8d2
3 changed files with 62 additions and 6 deletions

View file

@ -25,3 +25,7 @@ export function isOctalChar(char: string) {
export function isCompileBinding(input: string) { export function isCompileBinding(input: string) {
return input.startsWith("[") && input.endsWith("]") return input.startsWith("[") && input.endsWith("]")
} }
export function isHasBinding(input: string) {
return /#\w+/.test(input)
}

View file

@ -48,6 +48,8 @@ export function Lexer(input: string, start: number = 0, end?: number) {
case "/": case "/":
case "%": case "%":
case "^": case "^":
case "?":
case ":":
tokens.push(makeToken(input, TokenKind.OPERATOR, index)) tokens.push(makeToken(input, TokenKind.OPERATOR, index))
break break

View file

@ -4,6 +4,7 @@ import { BindingItem } from "../../types/properties/value.js"
import { FunctionMap } from "./Function.js" import { FunctionMap } from "./Function.js"
import { Lexer } from "./Lexer.js" import { Lexer } from "./Lexer.js"
import { RandomBindingString } from "../../components/Utils.js" import { RandomBindingString } from "../../components/Utils.js"
import { isHasBinding } from "./Checker.js"
export class Parser { export class Parser {
position: number = 0 position: number = 0
@ -72,14 +73,63 @@ export class Parser {
} }
private parseExpression(): Expression { private parseExpression(): Expression {
return this.parseOrExpression() return this.parseBinaryExpression()
}
private parseBinaryExpression(): Expression {
let left = this.parseOrExpression(),
current
while ((current = this.at()) && current.kind === TokenKind.OPERATOR && current.value === "?") {
this.eat()
let middle = this.parseExpression(),
right: string
if ((current = this.at()) && current.kind === TokenKind.OPERATOR && current.value === ":") {
this.eat()
right = this.parseExpression()
} else this.expect(TokenKind.OPERATOR, "Unexpected token!")
let leftBind, middleBind, rightBind
if (isHasBinding(left)) {
leftBind = RandomBindingString()
this.genBindings.push({
source: `((0 + ${left}) > 0)`,
target: leftBind,
})
} else this.expect(TokenKind.WORD, "Unexpected token!")
if (isHasBinding(middle)) {
middleBind = RandomBindingString()
this.genBindings.push({
source: middle,
target: middleBind,
})
} else this.expect(TokenKind.WORD, "Unexpected token!")
if (isHasBinding(right!)) {
rightBind = RandomBindingString()
this.genBindings.push({
source: right!,
target: rightBind,
})
} else this.expect(TokenKind.WORD, "Unexpected token!")
const ifTrueExpression = `(('prefix' + ${leftBind} + ${middleBind}) - ('prefixfalse' + ${middleBind})) - 'prefixtrue')`
const ifFalseExpression = `(('prefix' + ${leftBind} + ${rightBind}) - ('prefixtrue' + ${rightBind})) - 'prefixfalse')`
return `(${ifTrueExpression} + ${ifFalseExpression})`
}
return left
} }
private parseOrExpression(): Expression { private parseOrExpression(): Expression {
let left = this.parseAndExpression(), let left = this.parseAndExpression(),
current current
while ((current = this.at()) && this.at().kind === TokenKind.OPERATOR && current.value === "||") { while ((current = this.at()) && current.kind === TokenKind.OPERATOR && current.value === "||") {
this.eat() this.eat()
left = `(${left} or ${this.parseAndExpression()})` left = `(${left} or ${this.parseAndExpression()})`
} }
@ -91,7 +141,7 @@ export class Parser {
let left = this.parseComparisonExpression(), let left = this.parseComparisonExpression(),
current current
while ((current = this.at()) && this.at().kind === TokenKind.OPERATOR && current.value === "&&") { while ((current = this.at()) && current.kind === TokenKind.OPERATOR && current.value === "&&") {
this.eat() this.eat()
left = `(${left} and ${this.parseComparisonExpression()})` left = `(${left} and ${this.parseComparisonExpression()})`
} }
@ -105,7 +155,7 @@ export class Parser {
while ( while (
(current = this.at()) && (current = this.at()) &&
this.at().kind === TokenKind.OPERATOR && current.kind === TokenKind.OPERATOR &&
["==", ">", "<", ">=", "<=", "!="].includes(<string>current.value) ["==", ">", "<", ">=", "<=", "!="].includes(<string>current.value)
) { ) {
const operator = this.eat() const operator = this.eat()
@ -140,7 +190,7 @@ export class Parser {
while ( while (
(current = this.at()) && (current = this.at()) &&
this.at()?.kind === TokenKind.OPERATOR && current?.kind === TokenKind.OPERATOR &&
["+", "-"].includes(<string>current.value) ["+", "-"].includes(<string>current.value)
) { ) {
const operator = this.eat() const operator = this.eat()
@ -158,7 +208,7 @@ export class Parser {
while ( while (
(current = this.at()) && (current = this.at()) &&
this.at()?.kind === TokenKind.OPERATOR && current?.kind === TokenKind.OPERATOR &&
["*", "/", "%"].includes(<string>current.value) ["*", "/", "%"].includes(<string>current.value)
) { ) {
const operator = this.eat() const operator = this.eat()