Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

infix-postfix

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

infix-postfix - npm Package Compare versions

Comparing version 2.0.1 to 3.0.0

dist/Expression.d.ts

23

dist/InfixToPostfix.d.ts

@@ -1,11 +0,16 @@

import "./stringUtils";
import "./arrayUtils";
declare const _default: (expression: string, showSteps?: boolean) => string;
/**
* Converts infix expressions to postfix (rpn) expressions.
* @param expression the infix expression
* @param showSteps whether to print debug information to the console (default is false)
* @returns the postfix expression
*/
declare class InfixToPostfix {
private expression;
private queue;
private current;
private postfixExpression;
toString(): string;
private toObjectArray;
toArray(): (string | number)[];
constructor(expression: string);
private appendCurrent;
private parseToQueue;
private parseQueue;
}
declare const _default: (expression: string) => InfixToPostfix;
export default _default;
//# sourceMappingURL=InfixToPostfix.d.ts.map
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -6,204 +25,188 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

Object.defineProperty(exports, "__esModule", { value: true });
const Operand_1 = __importDefault(require("./Operand"));
require("./stringUtils");
require("./arrayUtils");
function getPresendence(op) {
switch (op) {
case "(":
case ")":
return 5;
case "plus_exp":
case "neg_exp":
return 4;
case "^":
return 3;
case "plus":
case "−":
return 2;
case "*":
case "/":
return 1;
case "-":
case "+":
return 0;
const Expression_1 = __importDefault(require("./Expression"));
const Operand_1 = __importStar(require("./Operand"));
const CloseMultiplication_1 = __importDefault(require("./operators/CloseMultiplication"));
const CloseNegation_1 = __importDefault(require("./operators/CloseNegation"));
const ClosePlus_1 = __importDefault(require("./operators/ClosePlus"));
const ClosingBracket_1 = __importDefault(require("./operators/ClosingBracket"));
const Exponentiation_1 = __importDefault(require("./operators/Exponentiation"));
const Multiplication_1 = __importDefault(require("./operators/Multiplication"));
const Negation_1 = __importDefault(require("./operators/Negation"));
const OpeningBracket_1 = __importDefault(require("./operators/OpeningBracket"));
const Operator_1 = __importDefault(require("./operators/Operator"));
const OperatorUtils_1 = __importDefault(require("./operators/OperatorUtils"));
const Plus_1 = __importDefault(require("./operators/Plus"));
const Stack_1 = __importDefault(require("./Stack"));
class InfixToPostfix {
constructor(expression) {
this.queue = new Stack_1.default();
this.current = null;
this.postfixExpression = new Stack_1.default();
this.expression = new Expression_1.default(expression);
this.parseToQueue();
this.parseQueue();
}
}
function isOperator(char) {
return char === "+" || char === "-" || char === "*" || char === "/" || char === "^" || char === "(" || char === ")";
}
function infixToPostfixOperator(op) {
switch (op) {
case "(":
case ")":
return op;
case "^":
return "^";
case "*":
return "*";
case "/":
return "/";
case "+":
return "+";
case "-":
return "-";
toString() {
return this.toObjectArray().join(" ");
}
}
function invert(op) {
switch (op) {
case "(":
return ")";
case ")":
return "(";
case "^":
return ")";
case "*":
return "/";
case "/":
return "*";
case "+":
return "-";
case "-":
return "+";
case "−":
return "plus";
case "plus":
return "−";
case "neg_exp":
return "plus_exp";
case "plus_exp":
return "neg_exp";
toObjectArray() {
return this.postfixExpression.toArray();
}
}
/**
* Converts infix expressions to postfix (rpn) expressions.
* @param expression the infix expression
* @param showSteps whether to print debug information to the console (default is false)
* @returns the postfix expression
*/
exports.default = (expression, showSteps = false) => {
const expressionRaw = expression;
let result = "";
const stack = [];
let charBefore = null;
let operand = null;
if (showSteps) {
console.log("#####################################");
console.log("Starting...");
toArray() {
const objectArray = this.toObjectArray();
const array = [];
for (const item of objectArray) {
if (item instanceof Operator_1.default) {
array.push(item.symbol);
}
else {
if (item.type === Operand_1.OperandType.Number)
array.push(Number(item.value));
else
array.push(item.value);
}
}
return array;
}
for (let i = 0; i < expression.length; i++) {
const char = expression[i];
if (showSteps) {
console.log(`Result: '${result}'`);
console.log("Stack: ", stack);
console.log("Operand: '" + (operand ? operand.getValue() : "") + "'");
console.log("#####################################");
console.log(`Input: '${char}'`);
appendCurrent() {
const last = this.queue.getLast();
// (a+b)(d-e) => (a+b)*(d-e), a(2) => a*(2)
if (this.current instanceof OpeningBracket_1.default &&
(last instanceof Operand_1.default || last instanceof ClosingBracket_1.default)) {
this.queue.push(new Multiplication_1.default());
}
if (i > 0)
charBefore = expression[i - 1];
if (isOperator(char)) {
const currentOp = char;
let postOp = infixToPostfixOperator(currentOp);
if (operand) {
result += operand.getValue() + " ";
operand = null;
}
let afterOperator = true;
if (charBefore)
afterOperator = isOperator(charBefore);
if (afterOperator) {
if (currentOp === "-" && charBefore !== ")") {
if (charBefore === "-") {
expression = expression.splice(i - 1, 2, "+");
stack[stack.length - 1] = invert(stack.top());
i -= 1;
continue;
// (3+4)2 = (3+4)*2
if (last instanceof ClosingBracket_1.default && this.current instanceof Operand_1.default) {
this.queue.push(new Multiplication_1.default());
}
// 2 a => 2*a
if (this.current instanceof Operand_1.default && last instanceof Operand_1.default) {
this.queue.push(new Multiplication_1.default());
}
// 2^-2/4 => 2^(-2)/4
if (last instanceof Exponentiation_1.default) {
if (this.current instanceof Negation_1.default)
this.current = new CloseNegation_1.default();
if (this.current instanceof Plus_1.default)
this.current = new ClosePlus_1.default();
}
this.queue.push(this.current);
this.current = null;
}
parseToQueue() {
while (this.expression.hasNext()) {
const currentCharacter = this.expression.next();
if (OperatorUtils_1.default.isOperatorSymbol(currentCharacter)) {
const operatorChar = currentCharacter;
if (this.current instanceof Operand_1.default) {
this.appendCurrent();
//this.current = null;
}
else if (this.current instanceof Operator_1.default) {
const merged = this.current.merge(operatorChar);
if (merged) {
this.current = merged;
}
else if (charBefore === "+") {
expression = expression.splice(i - 1, 1);
stack[stack.length - 1] = invert(stack.top());
i -= 1;
continue;
}
else if (charBefore === "^") {
postOp = "neg_exp";
}
else {
postOp = "−";
this.appendCurrent();
//this.current = null;
}
}
else if (currentOp === "+" && charBefore !== ")") {
expression = expression.splice(i, 1);
i -= 1;
continue;
if (this.current === null) {
const last = this.queue.getLast();
const preferUnary = !last || (last instanceof Operator_1.default && !(last instanceof ClosingBracket_1.default));
this.current = OperatorUtils_1.default.parse(operatorChar, preferUnary);
}
else if (currentOp !== "(" && charBefore !== ")") {
throw new Error(`Invalid infix expression '${expressionRaw}'`);
}
else if (currentCharacter.match(/[^\s]/)) {
if (this.current instanceof Operator_1.default) {
this.appendCurrent();
}
if (this.current === null) {
this.current = new Operand_1.default(currentCharacter);
}
else {
const merged = this.current.append(currentCharacter);
if (!merged) {
// 2a => 2&a
this.appendCurrent();
this.queue.push(new CloseMultiplication_1.default());
this.current = new Operand_1.default(currentCharacter);
}
}
}
const currentPres = getPresendence(postOp);
for (let j = stack.length - 1; j >= 0; j--) {
const op = stack[j];
if (op === "plus")
else if (currentCharacter.match(/\s/)) {
if (this.current === null || this.current instanceof Operator_1.default)
continue;
else if (postOp === ")") {
if (op === "(") {
stack.pop();
break;
}
else
result += stack.pop() + " ";
// b a !== ba
if (this.current instanceof Operand_1.default) {
this.appendCurrent();
}
else {
if (op === "(")
break;
else if (getPresendence(op) >= currentPres) {
result += stack.pop() + " ";
}
}
if (this.current)
this.appendCurrent();
}
parseQueue() {
const queueArray = this.queue.toArray();
const operatorStack = new Stack_1.default();
for (const item of queueArray) {
if (item instanceof Operator_1.default) {
while (operatorStack.hasItem()) {
const op = operatorStack.getLast();
if (item instanceof ClosingBracket_1.default) {
// If the current operator is ')' resolve all operators until a '(' operator is reached
if (!(op instanceof OpeningBracket_1.default)) {
// Skip plus operators (they can get ignored for mathematical reasons)
if (op instanceof Plus_1.default)
operatorStack.pop();
// Append other operators
else
this.postfixExpression.push(operatorStack.pop());
}
else {
// Pop '(' but don't append it
operatorStack.pop();
break;
}
}
else {
break;
// If the current operator is a common one resolve all operators
// until a '(' is reached or an operator has a smaller presendence
if (!(op instanceof OpeningBracket_1.default) && op.presendence >= item.presendence) {
// Skip plus operators (they can get ignored for mathematical reasons)
if (op instanceof Plus_1.default)
operatorStack.pop();
// Append other operators
else
this.postfixExpression.push(operatorStack.pop());
}
else {
// Stop resolving if the operator has a smaller presendence or if it is a '('
break;
}
}
}
if (!(item instanceof ClosingBracket_1.default))
operatorStack.push(item);
}
if (postOp !== ")")
stack.push(postOp);
else {
this.postfixExpression.push(item);
}
}
else if (char.match(/[^\s]/)) {
if (!operand) {
operand = new Operand_1.default(char);
// Resolve remained operators from their stack
while (operatorStack.hasItem()) {
const op = operatorStack.getLast();
if (op instanceof Plus_1.default || op instanceof OpeningBracket_1.default || op instanceof ClosingBracket_1.default) {
operatorStack.pop();
}
else {
const success = operand.append(char);
if (!success) {
result += operand.getValue() + " ";
operand = new Operand_1.default(char);
stack.push("*");
}
this.postfixExpression.push(operatorStack.pop());
}
}
else if (char.match(/\s/)) {
if (operand === null)
continue;
result += operand.getValue() + " ";
operand = null;
stack.push("*");
}
}
if (operand)
result += operand.getValue() + " ";
for (let j = stack.length - 1; j >= 0; j--) {
const op = stack[j];
if (op === "plus" || op === "(" || op === ")") {
stack.pop();
}
else {
result += stack.pop() + " ";
}
}
console.log(`Result: '${result}'`);
console.log("Stack:", stack);
console.log("Operand: '" + (operand ? operand.getValue() : "") + "'");
console.log("#####################################");
return result.replace(/neg_exp/g, "−").replace(/plus_exp/g, "").trim();
}
exports.default = (expression) => {
return new InfixToPostfix(expression);
};
//# sourceMappingURL=InfixToPostfix.js.map

@@ -0,1 +1,3 @@

/// <reference types="node" />
import { inspect } from "util";
export declare enum OperandType {

@@ -6,3 +8,3 @@ Number = 0,

export default class Operand {
private value;
value: string;
type: OperandType;

@@ -13,5 +15,6 @@ private dotCount;

isEmpty(): boolean;
getValue(): string;
static parseOperandType(value: string): OperandType;
[inspect.custom](depth?: any, options?: any): string;
toString(): string;
}
//# sourceMappingURL=Operand.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OperandType = void 0;
const util_1 = require("util");
var OperandType;

@@ -33,5 +34,2 @@ (function (OperandType) {

}
getValue() {
return this.value;
}
static parseOperandType(value) {

@@ -43,4 +41,12 @@ if (value.match(/[0-9.]/))

}
[util_1.inspect.custom](depth, options) {
// console.log(options.stylize.toString())
// console.log(inspect.styles)
return options.stylize(`${this.value}`, "special");
}
toString() {
return this.value.toString();
}
}
exports.default = Operand;
//# sourceMappingURL=Operand.js.map

@@ -6,4 +6,4 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = __importDefault(require("./index"));
console.log(index_1.default(" 12 N m"));
const InfixToPostfix_1 = __importDefault(require("./InfixToPostfix"));
console.log(InfixToPostfix_1.default("a(3)2").toString());
//# sourceMappingURL=test.js.map
{
"name": "infix-postfix",
"version": "2.0.1",
"version": "3.0.0",
"description": "infix to postfix converter",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -20,9 +20,26 @@ # infix-postfix

#### Converting
##### to a string
```javascript
console.log(infixToPostfix("(a+2b)^-2"));
console.log(infixToPostfix("(a+2b)^-2").toString());
/* Output:
a 2 b * + 2 − ^
*/
```
##### to an array
```javascript
console.log(infixToPostfix("(a+2b)^-2").toArray());
/* Output:
[
'a', 2, 'b', '*',
'+', 2, '−', '^'
]
*/
```
## Examples
`2+3*4` ▶ `2 3 4 * +`<br>
`a b(3+4)2` ▶ `a b * 3 4 + * 2 *`<br>
`-12-3` ▶ `12 − 3 -`<br>

@@ -43,10 +60,10 @@ `12^-2` ▶ `12 2 − ^`<br>

#### Number parsing support
Numbers get parsed. Obviously only works with the `toArray()` method.
#### Variable support
Any variable not containing operator characters (`+`, `-`, ...) is supported. For example `a-6` gets parsed to `a 6 -`.
#### Variable multiplication shortcut support
#### Multiplication shortcut support
A common parser would parse `b/10b` to `b 10b /` - which is unfortunately wrong. This parser recognizes that `10` and `b` are different operands. It parses the string to `b 10 b * /`.
Added to that `a b` gets parsed to `a b *`.
#### Behind the scenes
To understand how this converter works set the function's second argument to true: `infixToPostfix("2*2", true);`. This will print every step in detail to the console.
Added to that `a b` gets parsed to `a b *`. Furthermore `a(3)2` is translated to `a 3 * 2 *`.

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc