+246
| 'use strict'; | ||
| function toRadians(deg) { | ||
| return deg * Math.PI / 180; | ||
| } | ||
| function toDegrees(rad) { | ||
| return rad * 180 / Math.PI; | ||
| } | ||
| var Operator = /* @__PURE__ */ ((Operator2) => { | ||
| Operator2["ADD"] = "+"; | ||
| Operator2["SUB"] = "-"; | ||
| Operator2["MUL"] = "*"; | ||
| Operator2["DIV"] = "/"; | ||
| return Operator2; | ||
| })(Operator || {}); | ||
| const KEYWORDS = { | ||
| exp: (x) => Math.exp(x), | ||
| log: (x) => Math.log10(x), | ||
| ln: (x) => Math.log(x), | ||
| deg: (x) => toDegrees(x), | ||
| rad: (x) => toRadians(x), | ||
| sin: (x) => Math.sin(toRadians(x)), | ||
| cos: (x) => Math.cos(toRadians(x)), | ||
| tan: (x) => Math.tan(toRadians(x)), | ||
| asin: (x) => toDegrees(Math.asin(x)), | ||
| acos: (x) => toDegrees(Math.acos(x)), | ||
| atan: (x) => toDegrees(Math.atan(x)), | ||
| sqrt: (x) => Math.sqrt(x) | ||
| }; | ||
| const DEFAULT_VALUE = 0; | ||
| var TokenType = /* @__PURE__ */ ((TokenType2) => { | ||
| TokenType2[TokenType2["Number"] = 0] = "Number"; | ||
| TokenType2[TokenType2["BinaryOperator"] = 1] = "BinaryOperator"; | ||
| TokenType2[TokenType2["OpenParen"] = 2] = "OpenParen"; | ||
| TokenType2[TokenType2["ClosedParen"] = 3] = "ClosedParen"; | ||
| TokenType2[TokenType2["Identifier"] = 4] = "Identifier"; | ||
| TokenType2[TokenType2["Keyword"] = 5] = "Keyword"; | ||
| TokenType2[TokenType2["EOF"] = 6] = "EOF"; | ||
| return TokenType2; | ||
| })(TokenType || {}); | ||
| function createToken(value = "", type) { | ||
| return { value, type }; | ||
| } | ||
| function isBinaryOperator(char) { | ||
| return /^[*+/^-]$/.test(char); | ||
| } | ||
| function isAlpha(char) { | ||
| return /^[a-z]$/i.test(char); | ||
| } | ||
| function isInt(char) { | ||
| return /^\d$/.test(char); | ||
| } | ||
| function isSkippable(char) { | ||
| return /^\s$/.test(char); | ||
| } | ||
| function tokenize(expr) { | ||
| const tokens = new Array(); | ||
| let index = 0; | ||
| let openParen = false; | ||
| while (index < expr.length) { | ||
| if (expr[index] === "(") { | ||
| openParen = true; | ||
| tokens.push(createToken(expr[index++], 2 /* OpenParen */)); | ||
| } else if (expr[index] === ")") { | ||
| openParen = false; | ||
| tokens.push(createToken(expr[index++], 3 /* ClosedParen */)); | ||
| } else if (isBinaryOperator(expr[index])) { | ||
| tokens.push(createToken(expr[index++], 1 /* BinaryOperator */)); | ||
| } else if (isInt(expr[index])) { | ||
| let num = ""; | ||
| while (index < expr.length && (isInt(expr[index]) || expr[index] === "." && isInt(expr[index + 1]))) { | ||
| num += expr[index]; | ||
| index++; | ||
| } | ||
| tokens.push(createToken(num, 0 /* Number */)); | ||
| } else if (isAlpha(expr[index])) { | ||
| let identifier = ""; | ||
| let hasChar = false; | ||
| while (index < expr.length) { | ||
| if (isAlpha(expr[index]) || hasChar && isInt(expr[index])) { | ||
| hasChar = true; | ||
| identifier += expr[index]; | ||
| index++; | ||
| } else { | ||
| break; | ||
| } | ||
| } | ||
| if (KEYWORDS[identifier]) { | ||
| tokens.push(createToken(identifier, 5 /* Keyword */)); | ||
| } else { | ||
| tokens.push(createToken(identifier, 4 /* Identifier */)); | ||
| } | ||
| } else if (isSkippable(expr[index])) { | ||
| index++; | ||
| } else { | ||
| throw new Error( | ||
| "Unexpected character '" + expr[index] + "' near " + expr.slice(0, Math.max(0, index)) | ||
| ); | ||
| } | ||
| } | ||
| if (openParen) { | ||
| throw new Error("Unexpected end of expression: " + expr); | ||
| } | ||
| tokens.push(createToken("EOF", 6 /* EOF */)); | ||
| return tokens; | ||
| } | ||
| function interpret(node, scope) { | ||
| let result = DEFAULT_VALUE; | ||
| switch (node.type) { | ||
| case TokenType.Number: { | ||
| result = Number.parseFloat(node.value); | ||
| break; | ||
| } | ||
| case TokenType.BinaryOperator: { | ||
| switch (node.operator) { | ||
| case Operator.ADD: { | ||
| result = interpret(node.left, scope) + interpret(node.right, scope); | ||
| break; | ||
| } | ||
| case Operator.SUB: { | ||
| result = interpret(node.left, scope) - interpret(node.right, scope); | ||
| break; | ||
| } | ||
| case Operator.MUL: { | ||
| result = interpret(node.left, scope) * interpret(node.right, scope); | ||
| break; | ||
| } | ||
| case Operator.DIV: { | ||
| result = interpret(node.left, scope) / interpret(node.right, scope); | ||
| break; | ||
| } | ||
| } | ||
| break; | ||
| } | ||
| case TokenType.Keyword: { | ||
| result = KEYWORDS[node.name](interpret(node.argument, scope)); | ||
| break; | ||
| } | ||
| case TokenType.Identifier: { | ||
| result = scope.variables[node.name] || DEFAULT_VALUE; | ||
| break; | ||
| } | ||
| default: { | ||
| throw new Error(`Unknown node type: ${node.type}`); | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| function parse(tokens = []) { | ||
| let index = 0; | ||
| function isEOF() { | ||
| return tokens[index].type === TokenType.EOF; | ||
| } | ||
| function isType(...types) { | ||
| return types.includes(tokens[index].type); | ||
| } | ||
| function parseFactor() { | ||
| if (!isEOF() && isType(TokenType.OpenParen)) { | ||
| index++; | ||
| const result = parseNode(); | ||
| index++; | ||
| return result; | ||
| } else if (isType(TokenType.Number)) { | ||
| return tokens[index++]; | ||
| } else if (isType(TokenType.Identifier, TokenType.Keyword)) { | ||
| const { type, value: name } = tokens[index++]; | ||
| if (type === TokenType.Keyword) { | ||
| index++; | ||
| const argument = parseNode(); | ||
| index++; | ||
| return { type, name, argument }; | ||
| } | ||
| return { type, name }; | ||
| } else { | ||
| throw new Error(`Unexpected token: ${tokens[index].value}`); | ||
| } | ||
| } | ||
| function parseTerm() { | ||
| let result = parseFactor(); | ||
| while (!isEOF() && (tokens[index].value === Operator.MUL || tokens[index].value === Operator.DIV)) { | ||
| const operator = tokens[index].value; | ||
| index++; | ||
| const factor = parseFactor(); | ||
| result = { | ||
| type: TokenType.BinaryOperator, | ||
| operator, | ||
| left: result, | ||
| right: factor | ||
| }; | ||
| } | ||
| return result; | ||
| } | ||
| function parseNode() { | ||
| let result = parseTerm(); | ||
| while (!isEOF() && (tokens[index].value === Operator.ADD || tokens[index].value === Operator.SUB)) { | ||
| const operator = tokens[index].value; | ||
| index++; | ||
| const term = parseTerm(); | ||
| result = { | ||
| type: TokenType.BinaryOperator, | ||
| operator, | ||
| left: result, | ||
| right: term | ||
| }; | ||
| } | ||
| return result; | ||
| } | ||
| return parseNode(); | ||
| } | ||
| function execute(expr, scope) { | ||
| const tokens = tokenize(expr); | ||
| const ast = parse(tokens); | ||
| const result = interpret(ast, scope); | ||
| return result; | ||
| } | ||
| function evaluate(code) { | ||
| const scope = { | ||
| variables: {} | ||
| }; | ||
| const statements = code.trim().replace(/(\d)([a-z]|\()/gi, (_, num, char) => { | ||
| return num + "*" + char; | ||
| }).split("\n").filter((value) => { | ||
| value = value.trim(); | ||
| if (!value || value.startsWith("#")) { | ||
| return false; | ||
| } | ||
| const matches = value.replaceAll(" ", "").match(/^([A-Za-z]\d?)=(.+)$/); | ||
| if (matches) { | ||
| scope.variables[matches[1]] = execute(matches[2], scope); | ||
| return false; | ||
| } | ||
| return true; | ||
| }); | ||
| let result = DEFAULT_VALUE; | ||
| for (const stmt of statements) { | ||
| result = execute(stmt, scope); | ||
| } | ||
| return { value: result, scope }; | ||
| } | ||
| exports.evaluate = evaluate; |
| /** | ||
| * Object to store useful data used during interpretation | ||
| */ | ||
| type Scope = { | ||
| variables: Record<string, number>; | ||
| }; | ||
| type Result = { | ||
| value: number; | ||
| scope: Scope; | ||
| }; | ||
| /** | ||
| * Evaluate a set of statements in a script | ||
| */ | ||
| declare function evaluate(code: string): Result; | ||
| export { evaluate }; |
| /** | ||
| * Object to store useful data used during interpretation | ||
| */ | ||
| type Scope = { | ||
| variables: Record<string, number>; | ||
| }; | ||
| type Result = { | ||
| value: number; | ||
| scope: Scope; | ||
| }; | ||
| /** | ||
| * Evaluate a set of statements in a script | ||
| */ | ||
| declare function evaluate(code: string): Result; | ||
| export { evaluate }; |
| /** | ||
| * Object to store useful data used during interpretation | ||
| */ | ||
| type Scope = { | ||
| variables: Record<string, number>; | ||
| }; | ||
| type Result = { | ||
| value: number; | ||
| scope: Scope; | ||
| }; | ||
| /** | ||
| * Evaluate a set of statements in a script | ||
| */ | ||
| declare function evaluate(code: string): Result; | ||
| export { evaluate }; |
+244
| function toRadians(deg) { | ||
| return deg * Math.PI / 180; | ||
| } | ||
| function toDegrees(rad) { | ||
| return rad * 180 / Math.PI; | ||
| } | ||
| var Operator = /* @__PURE__ */ ((Operator2) => { | ||
| Operator2["ADD"] = "+"; | ||
| Operator2["SUB"] = "-"; | ||
| Operator2["MUL"] = "*"; | ||
| Operator2["DIV"] = "/"; | ||
| return Operator2; | ||
| })(Operator || {}); | ||
| const KEYWORDS = { | ||
| exp: (x) => Math.exp(x), | ||
| log: (x) => Math.log10(x), | ||
| ln: (x) => Math.log(x), | ||
| deg: (x) => toDegrees(x), | ||
| rad: (x) => toRadians(x), | ||
| sin: (x) => Math.sin(toRadians(x)), | ||
| cos: (x) => Math.cos(toRadians(x)), | ||
| tan: (x) => Math.tan(toRadians(x)), | ||
| asin: (x) => toDegrees(Math.asin(x)), | ||
| acos: (x) => toDegrees(Math.acos(x)), | ||
| atan: (x) => toDegrees(Math.atan(x)), | ||
| sqrt: (x) => Math.sqrt(x) | ||
| }; | ||
| const DEFAULT_VALUE = 0; | ||
| var TokenType = /* @__PURE__ */ ((TokenType2) => { | ||
| TokenType2[TokenType2["Number"] = 0] = "Number"; | ||
| TokenType2[TokenType2["BinaryOperator"] = 1] = "BinaryOperator"; | ||
| TokenType2[TokenType2["OpenParen"] = 2] = "OpenParen"; | ||
| TokenType2[TokenType2["ClosedParen"] = 3] = "ClosedParen"; | ||
| TokenType2[TokenType2["Identifier"] = 4] = "Identifier"; | ||
| TokenType2[TokenType2["Keyword"] = 5] = "Keyword"; | ||
| TokenType2[TokenType2["EOF"] = 6] = "EOF"; | ||
| return TokenType2; | ||
| })(TokenType || {}); | ||
| function createToken(value = "", type) { | ||
| return { value, type }; | ||
| } | ||
| function isBinaryOperator(char) { | ||
| return /^[*+/^-]$/.test(char); | ||
| } | ||
| function isAlpha(char) { | ||
| return /^[a-z]$/i.test(char); | ||
| } | ||
| function isInt(char) { | ||
| return /^\d$/.test(char); | ||
| } | ||
| function isSkippable(char) { | ||
| return /^\s$/.test(char); | ||
| } | ||
| function tokenize(expr) { | ||
| const tokens = new Array(); | ||
| let index = 0; | ||
| let openParen = false; | ||
| while (index < expr.length) { | ||
| if (expr[index] === "(") { | ||
| openParen = true; | ||
| tokens.push(createToken(expr[index++], 2 /* OpenParen */)); | ||
| } else if (expr[index] === ")") { | ||
| openParen = false; | ||
| tokens.push(createToken(expr[index++], 3 /* ClosedParen */)); | ||
| } else if (isBinaryOperator(expr[index])) { | ||
| tokens.push(createToken(expr[index++], 1 /* BinaryOperator */)); | ||
| } else if (isInt(expr[index])) { | ||
| let num = ""; | ||
| while (index < expr.length && (isInt(expr[index]) || expr[index] === "." && isInt(expr[index + 1]))) { | ||
| num += expr[index]; | ||
| index++; | ||
| } | ||
| tokens.push(createToken(num, 0 /* Number */)); | ||
| } else if (isAlpha(expr[index])) { | ||
| let identifier = ""; | ||
| let hasChar = false; | ||
| while (index < expr.length) { | ||
| if (isAlpha(expr[index]) || hasChar && isInt(expr[index])) { | ||
| hasChar = true; | ||
| identifier += expr[index]; | ||
| index++; | ||
| } else { | ||
| break; | ||
| } | ||
| } | ||
| if (KEYWORDS[identifier]) { | ||
| tokens.push(createToken(identifier, 5 /* Keyword */)); | ||
| } else { | ||
| tokens.push(createToken(identifier, 4 /* Identifier */)); | ||
| } | ||
| } else if (isSkippable(expr[index])) { | ||
| index++; | ||
| } else { | ||
| throw new Error( | ||
| "Unexpected character '" + expr[index] + "' near " + expr.slice(0, Math.max(0, index)) | ||
| ); | ||
| } | ||
| } | ||
| if (openParen) { | ||
| throw new Error("Unexpected end of expression: " + expr); | ||
| } | ||
| tokens.push(createToken("EOF", 6 /* EOF */)); | ||
| return tokens; | ||
| } | ||
| function interpret(node, scope) { | ||
| let result = DEFAULT_VALUE; | ||
| switch (node.type) { | ||
| case TokenType.Number: { | ||
| result = Number.parseFloat(node.value); | ||
| break; | ||
| } | ||
| case TokenType.BinaryOperator: { | ||
| switch (node.operator) { | ||
| case Operator.ADD: { | ||
| result = interpret(node.left, scope) + interpret(node.right, scope); | ||
| break; | ||
| } | ||
| case Operator.SUB: { | ||
| result = interpret(node.left, scope) - interpret(node.right, scope); | ||
| break; | ||
| } | ||
| case Operator.MUL: { | ||
| result = interpret(node.left, scope) * interpret(node.right, scope); | ||
| break; | ||
| } | ||
| case Operator.DIV: { | ||
| result = interpret(node.left, scope) / interpret(node.right, scope); | ||
| break; | ||
| } | ||
| } | ||
| break; | ||
| } | ||
| case TokenType.Keyword: { | ||
| result = KEYWORDS[node.name](interpret(node.argument, scope)); | ||
| break; | ||
| } | ||
| case TokenType.Identifier: { | ||
| result = scope.variables[node.name] || DEFAULT_VALUE; | ||
| break; | ||
| } | ||
| default: { | ||
| throw new Error(`Unknown node type: ${node.type}`); | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| function parse(tokens = []) { | ||
| let index = 0; | ||
| function isEOF() { | ||
| return tokens[index].type === TokenType.EOF; | ||
| } | ||
| function isType(...types) { | ||
| return types.includes(tokens[index].type); | ||
| } | ||
| function parseFactor() { | ||
| if (!isEOF() && isType(TokenType.OpenParen)) { | ||
| index++; | ||
| const result = parseNode(); | ||
| index++; | ||
| return result; | ||
| } else if (isType(TokenType.Number)) { | ||
| return tokens[index++]; | ||
| } else if (isType(TokenType.Identifier, TokenType.Keyword)) { | ||
| const { type, value: name } = tokens[index++]; | ||
| if (type === TokenType.Keyword) { | ||
| index++; | ||
| const argument = parseNode(); | ||
| index++; | ||
| return { type, name, argument }; | ||
| } | ||
| return { type, name }; | ||
| } else { | ||
| throw new Error(`Unexpected token: ${tokens[index].value}`); | ||
| } | ||
| } | ||
| function parseTerm() { | ||
| let result = parseFactor(); | ||
| while (!isEOF() && (tokens[index].value === Operator.MUL || tokens[index].value === Operator.DIV)) { | ||
| const operator = tokens[index].value; | ||
| index++; | ||
| const factor = parseFactor(); | ||
| result = { | ||
| type: TokenType.BinaryOperator, | ||
| operator, | ||
| left: result, | ||
| right: factor | ||
| }; | ||
| } | ||
| return result; | ||
| } | ||
| function parseNode() { | ||
| let result = parseTerm(); | ||
| while (!isEOF() && (tokens[index].value === Operator.ADD || tokens[index].value === Operator.SUB)) { | ||
| const operator = tokens[index].value; | ||
| index++; | ||
| const term = parseTerm(); | ||
| result = { | ||
| type: TokenType.BinaryOperator, | ||
| operator, | ||
| left: result, | ||
| right: term | ||
| }; | ||
| } | ||
| return result; | ||
| } | ||
| return parseNode(); | ||
| } | ||
| function execute(expr, scope) { | ||
| const tokens = tokenize(expr); | ||
| const ast = parse(tokens); | ||
| const result = interpret(ast, scope); | ||
| return result; | ||
| } | ||
| function evaluate(code) { | ||
| const scope = { | ||
| variables: {} | ||
| }; | ||
| const statements = code.trim().replace(/(\d)([a-z]|\()/gi, (_, num, char) => { | ||
| return num + "*" + char; | ||
| }).split("\n").filter((value) => { | ||
| value = value.trim(); | ||
| if (!value || value.startsWith("#")) { | ||
| return false; | ||
| } | ||
| const matches = value.replaceAll(" ", "").match(/^([A-Za-z]\d?)=(.+)$/); | ||
| if (matches) { | ||
| scope.variables[matches[1]] = execute(matches[2], scope); | ||
| return false; | ||
| } | ||
| return true; | ||
| }); | ||
| let result = DEFAULT_VALUE; | ||
| for (const stmt of statements) { | ||
| result = execute(stmt, scope); | ||
| } | ||
| return { value: result, scope }; | ||
| } | ||
| export { evaluate }; |
+3
-2
| { | ||
| "name": "mathflow", | ||
| "version": "0.0.2", | ||
| "version": "0.0.3", | ||
| "description": "A concise, expressive scripting language for mathematical calculations with standard functions.", | ||
@@ -29,3 +29,4 @@ "type": "module", | ||
| "prepare": "husky install", | ||
| "release": "release-it" | ||
| "release": "release-it", | ||
| "prepack": "pnpm build" | ||
| }, | ||
@@ -32,0 +33,0 @@ "keywords": [], |
Unpublished package
Supply chain riskPackage version was not found on the registry. It may exist on a different registry and need to be configured to pull from that registry.
Found 1 instance in 1 package
Empty package
Supply chain riskPackage does not contain any code. It may be removed, is name squatting, or the result of a faulty package publish.
Found 1 instance in 1 package
Unpublished package
Supply chain riskPackage version was not found on the registry. It may exist on a different registry and need to be configured to pull from that registry.
Found 1 instance in 1 package
18881
352.13%8
166.67%492
Infinity%1
-50%