import { Tocken } from "@/types/type"; import { EmptyCharacter, EndingCharacter } from "@/utils/const"; import { Lexer } from ".."; import { AdditiveExpression, Arguments, Assign, BlockBody, E, Function, FunctionArgumentDefinition, MultiplicativeExpression, PrimaryExpression, Print, S, GlobalDefinition, UnaryExpression, VarDecl, Variable, Return, FunctionCall, IfStmt, CompareExpression, ForStmt, Break, Continue } from "./types"; let global = false; const terminals: Array<[string, RegExp]> = [ ["/", /^\//], ["++", /^\+\+/], ["+=", /^\+\=/], ["-=", /^\-\=/], ["*=", /^\*\=/], ["-", /^-/], ["+", /^\+/], ["*", /^\*/], ["%", /^\%/], ["(", /^\(/], [")", /^\)/], ["===", /^===/], ["==", /^==/], ["=", /^=/], [",", /^,/], [";", /^;/], ["{", /^{/], ["}", /^}/], [":", /^:/], [">=", /^\>\=/], ["<=", /^\<\=/], [">", /^\>/], ["<", /^\", ">=", "<", "<="].includes(opt)) { return new CompareExpression({ e1 }) } let e = new CompareExpression({ e1 }) while (["===", "==", "!=", ">", ">=", "<", "<="].includes(opt)) { this.lexer.popNotEmptyTerminal(); e.e2 = this.parse_AdditiveExpression(); e.opt = opt; e = new CompareExpression({ e1: e, }) opt = this.lexer.nextNotEmptyTerminal().tocken; } return e; } parse_AdditiveExpression(): AdditiveExpression { let e1 = this.parse_MultiplicativeExpression(); let tocken = this.lexer.nextNotEmptyTerminal(); let opt = tocken.tocken; if (!["+", "-"].includes(opt)) { return new AdditiveExpression({ e1 }) } let e = new AdditiveExpression({ e1 }) while (["+", "-"].includes(opt)) { this.lexer.popNotEmptyTerminal(); e.e2 = this.parse_MultiplicativeExpression(); e.opt = opt; e = new AdditiveExpression({ e1: e, }) opt = this.lexer.nextNotEmptyTerminal().tocken; } return e; } parse_MultiplicativeExpression(): MultiplicativeExpression { let e1 = this.parse_UnaryExpression(); let tocken = this.lexer.nextNotEmptyTerminal(); let opt = tocken.tocken; if (!["*", "/", "%"].includes(opt)) { return new MultiplicativeExpression({ e1 }) } let e = new MultiplicativeExpression({ e1 }) while (["*", "/", "%"].includes(opt)) { this.lexer.popNotEmptyTerminal(); e.e2 = this.parse_UnaryExpression(); e.opt = opt; e = new MultiplicativeExpression({ e1: e, }) opt = this.lexer.nextNotEmptyTerminal().tocken; } return e; } parse_UnaryExpression(): UnaryExpression { let tocken = this.lexer.nextNotEmptyTerminal(); switch (tocken.tocken) { case "-": this.lexer.popNotEmptyTerminal(); let e1 = this.parse_PrimaryExpression(); return new UnaryExpression({ e1, opt: "-" }) } return new UnaryExpression({ e1: this.parse_PrimaryExpression() }) } parse_PrimaryExpression(): PrimaryExpression { let tocken = this.lexer.popNotEmptyTerminal(); switch (tocken.tocken) { case "identifier": switch (this.lexer.nextNotEmpty(2).tocken) { case "(": const functionCall = this.parse_FunctionCall(); functionCall.needPushToStack = true; return new PrimaryExpression({ functionCall, }); default: return new PrimaryExpression({ identifier: tocken.origin }) } case "integer": return new PrimaryExpression({ val: tocken.origin }) case "(": let e1 = this.parse_E(); this.expect(")", "parse_PrimaryExpression") return new PrimaryExpression({ e1 }) } throw new Error("[parse_PrimaryExpression]") } expect(_tocken: string, error: string): Tocken { const tocken = this.lexer.popNotEmptyTerminal(); if (tocken.tocken !== _tocken) { throw new Error(`[${error}] expect: ${_tocken} get: ${tocken.tocken}`); } return tocken; } predict(_tocken: string): Tocken | null { const tocken = this.lexer.nextNotEmptyTerminal(); if (tocken.tocken === _tocken) { this.lexer.popNotEmptyTerminal(); return tocken; } return null; } }