Skip to content

Commit 1c32c20

Browse files
Added JSDOC for challenge 7 - Write Your Own Calculator (#28)
1 parent b36e4af commit 1c32c20

File tree

4 files changed

+113
-3
lines changed

4 files changed

+113
-3
lines changed

src/7/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ const str = '1 + 1';
3131
const value = new Calculator(str).calculate(); // value = 2
3232
```
3333

34+
You can also use the command line tool as follows:
35+
36+
```bash
37+
# Using node
38+
node /path/to/calculator.index.js '1 + 1'
39+
40+
# Using ts-node
41+
npx ts-node calculator.index.ts '1 + 1'
42+
```
43+
3444
## Run tests
3545

3646
To run the tests for the Calculator tool, go to the root directory of this repository and run the following command:

src/7/calculator.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,28 @@ import { Postfix } from './postfix';
33
import { OperatorTokens } from './tokens';
44

55
export class Calculator {
6+
/**
7+
* The input provided by the user
8+
*
9+
* @type {string}
10+
*/
611
text: string;
12+
13+
/**
14+
* The Postfix class instance
15+
*
16+
* @private
17+
* @type {Postfix}
18+
*/
719
private postfix: Postfix;
20+
21+
/**
22+
* Stack used after infix to postfix conversion.
23+
* Used for calculating the value of the expression.
24+
*
25+
* @private
26+
* @type {Stack<number>}
27+
*/
828
private stack: Stack<number>;
929

1030
constructor(text: string) {
@@ -14,11 +34,14 @@ export class Calculator {
1434
}
1535

1636
public calculate(): number {
37+
// First convert the infix notation to postfix notation.
1738
const queue = this.postfix.parse();
1839

1940
while (queue.size() > 0) {
41+
// Get the next token from the queue.
2042
const str = queue.dequeue()!;
2143

44+
// If the token is an operator, pop two values from the stack,
2245
if (OperatorTokens.has(str)) {
2346
const operator = str;
2447

@@ -47,8 +70,10 @@ export class Calculator {
4770
throw new Error(`Invalid operator ${str}`);
4871
}
4972

73+
// Perform the operation and push the result to the stack.
5074
this.stack.push(value);
5175
} else {
76+
// If the token is an operand, push it to the stack.
5277
this.stack.push(parseFloat(str));
5378
}
5479
}

src/7/postfix.ts

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,55 @@ import { Stack } from '../utils/stack';
33
import { OperatorTokens } from './tokens';
44

55
export class Postfix {
6+
/**
7+
* Input infix string
8+
*
9+
* @private
10+
* @type {string}
11+
*/
612
private text: string;
13+
14+
/**
15+
* Position of the current token
16+
*
17+
* @private
18+
* @type {number}
19+
*/
720
private pos: number = 0;
21+
22+
/**
23+
* Final output queue
24+
*
25+
* @private
26+
* @type {Queue<string>}
27+
*/
828
private outputQueue: Queue<string>;
29+
30+
/**
31+
* Data structure to store the operators
32+
*
33+
* @private
34+
* @type {Stack<string>}
35+
*/
936
private operatorStack: Stack<string>;
1037
private textLength: number;
11-
private operatorCount = 0;
12-
private numberCount = 0;
38+
39+
/**
40+
* Number of operators encountered till `this.pos`
41+
*
42+
* @private
43+
* @type {number}
44+
*/
45+
private operatorCount: number = 0;
46+
47+
/**
48+
* Number of operands encountered till `this.pos`
49+
* @date 9/1/2023 - 1:44:00 PM
50+
*
51+
* @private
52+
* @type {number}
53+
*/
54+
private numberCount: number = 0;
1355

1456
constructor(text: string) {
1557
this.text = text;
@@ -81,6 +123,7 @@ export class Postfix {
81123
private parseRightParenthesis() {
82124
this.consumeToken();
83125

126+
// Pop all operators from the stack until we encounter a left parenthesis.
84127
while (this.operatorStack.peek() !== '(') {
85128
if (this.operatorStack.size() === 0) {
86129
throw new Error('Mismatched Parenthesis');
@@ -101,13 +144,15 @@ export class Postfix {
101144
this.consumeToken();
102145
const token1 = OperatorTokens.get(o1)!;
103146

147+
// While there is an operator token, o2, at the top of the stack
104148
while (this.operatorStack.size() > 0) {
105149
const o2 = this.operatorStack.peek()!;
106150

107151
if (o2 === '(') {
108152
break;
109153
}
110154

155+
// If o1 is left-associative and its precedence is less than or equal to that of o2,
111156
const token2 = OperatorTokens.get(o2)!;
112157
if (
113158
token2.precedence > token1.precedence ||
@@ -126,6 +171,7 @@ export class Postfix {
126171
private parseNumber(): string {
127172
this.numberCount++;
128173
let str = '';
174+
129175
while (this.pos < this.textLength) {
130176
const token = this.getCurrentToken();
131177
if (token === ' ' || token === ')') {
@@ -134,6 +180,7 @@ export class Postfix {
134180
str += token;
135181
this.consumeToken();
136182
}
183+
137184
return str;
138185
}
139186

src/7/tokens.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,29 @@
1+
/**
2+
* Interface used for comparing operators.
3+
* Used while converting infix to postfix notation.
4+
*
5+
* @interface IToken
6+
*/
17
interface IToken {
8+
/**
9+
* The operator character
10+
*
11+
* @type {string}
12+
*/
213
char: string;
14+
15+
/**
16+
* Precedence of the operator
17+
*
18+
* @type {number}
19+
*/
320
precedence: number;
21+
22+
/**
23+
* Whether the operator is left associative or not
24+
*
25+
* @type {boolean}
26+
*/
427
isLeftAssociative: boolean;
528
}
629

@@ -15,7 +38,12 @@ class Token implements IToken {
1538
}
1639
}
1740

18-
const OperatorTokens = new Map<string, Token>();
41+
/**
42+
* All the operators supported by the calculator.
43+
*
44+
* @type {Map<string, Token>}
45+
*/
46+
const OperatorTokens: Map<string, Token> = new Map<string, Token>();
1947

2048
OperatorTokens.set('^', new Token('^', 4, false));
2149
OperatorTokens.set('*', new Token('*', 3, true));

0 commit comments

Comments
 (0)