Skip to content

Commit 545ec21

Browse files
committed
added negative numbers support
1 parent 02b1cf1 commit 545ec21

File tree

4 files changed

+41
-14
lines changed

4 files changed

+41
-14
lines changed

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
<body>
2929
<div class="container">
3030
<h4>JSPython development console</h4>
31-
<div id="editor">2 == 1/2+1/2 and 1/2+1/2 == 1</div>
31+
<div id="editor">x = -3.14 + 1</div>
3232
<!--
3333
def f(n):
3434
n * n

src/interpreter.spec.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ describe('Interpreter', () => {
5858

5959
it('1*2/4 + 2*3/6', () => {
6060
expect(e.eval("1*2/4 + 2*3/6")).toBe(1 * 2 / 4 + 2 * 3 / 6)
61-
expect(e.eval("1*2/4 + 2*3/6-2.3")).toBe(1 * 2 / 4 + 2 * 3 / 6 - 2.3)
62-
expect(e.eval("7+1*2/4 + 2*3/6-2.3")).toBe(7 + 1 * 2 / 4 + 2 * 3 / 6 - 2.3)
61+
expect(e.eval("1*2/4 + 2*3/6 - 2.3")).toBe(1 * 2 / 4 + 2 * 3 / 6 - 2.3)
62+
expect(e.eval("7+1*2/4 + 2*3/6 - 2.3")).toBe(7 + 1 * 2 / 4 + 2 * 3 / 6 - 2.3)
6363
});
6464

6565
it('5 – (5 * (32 + 4))', () => {
@@ -329,12 +329,39 @@ describe('Interpreter', () => {
329329
expect(await e.evaluate('x?.p1?.p != null and x.length >0')).toBe(false)
330330
});
331331

332-
it('arithmetic + comparison', async () => {
332+
it('arithmetic + comparison', async () => {
333+
expect(await e.evaluate('0.25 == 1/4')).toBe(true)
334+
expect(await e.evaluate('0.25 == 1/2')).toBe(false)
335+
333336
expect(await e.evaluate('1+2*3 == 5 or 1 > 3')).toBe(false)
334337
expect(await e.evaluate('1+2*3 == 5 or 1 < 3')).toBe(true)
335338

336339
expect(await e.evaluate('2 == 1/2 + 1/2 and 1/2 + 1/2 == 1')).toBe(false)
337340
expect(await e.evaluate('(2 == 1/2 + 1/2) and (1/2 + 1/2 == 1)')).toBe(false)
338341
expect(await e.evaluate('(2 == (1/2 + 1/2)) and ((1/2 + 1/2) == 1)')).toBe(false)
339-
});
342+
});
343+
344+
it('Negative numbers', async () => {
345+
expect(await e.evaluate('x=-1\nx')).toBe(-1)
346+
expect(await e.evaluate('x=-3.14 + 3\nx')).toBe(-3.14 + 3)
347+
expect(await e.evaluate('-3.14 - 3')).toBe(-3.14 - 3)
348+
expect(await e.evaluate('x=5\nx*-1')).toBe(-5)
349+
expect(await e.evaluate(`
350+
def f(x):
351+
return x
352+
353+
f(-5)
354+
`)).toBe(-5)
355+
356+
expect(await e.evaluate(`
357+
def f(x):
358+
return x
359+
360+
f(-0.14)
361+
`)).toBe(-0.14)
362+
363+
expect(await e.evaluate('1/2*-1 == -0.5')).toBe(true)
364+
365+
});
366+
340367
});

src/parser/parser.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe('Parser => ', () => {
1515
});
1616

1717
it('1+2-3', async () => {
18-
let ast = new Parser().parse(new Tokenizer().tokenize("1+2-3"))
18+
let ast = new Parser().parse(new Tokenizer().tokenize("1 + 2 - 3"))
1919
expect(ast.body.length).toBe(1);
2020
expect(ast.body[0].type).toBe("binOp");
2121
const binOp = ast.body[0] as BinOpNode

src/tokenizer/tokenizer.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Token, TokenTypes } from '../common';
1+
import { getTokenType, getTokenValue, Token, TokenTypes } from '../common';
22

33
const SeparatorsMap: Record<string, string[]> = {
44
'\n': ['\n'],
@@ -85,7 +85,7 @@ export class Tokenizer {
8585
if (symbol == ' ' && this.tokenText.length !== 0) {
8686
this.tokenText = this.processToken(this.tokenText, tokens);
8787
continue;
88-
} else if ((SeparatorsMap[symbol]) && !this.isPartOfNumber(symbol, this.tokenText, this._cursor)) {
88+
} else if ((SeparatorsMap[symbol] !== undefined) && !this.isPartOfNumber(symbol, tokens)) {
8989
// handle numbers with floating point e.g. 3.14
9090
this.tokenText = this.processToken(this.tokenText, tokens);
9191
this.tokenText = symbol;
@@ -242,12 +242,12 @@ export class Tokenizer {
242242
return !isNaN(res) ? res : null;
243243
}
244244

245-
private isPartOfNumber(symbol: string, token: string, cursor: number): boolean {
246-
// '-' needs to be handled e.g. -3; 2 + -2 etc
247-
// if(token.length == 0 && symbol === '-') {
248-
// return true;
249-
// }
250-
if (symbol === '.' && this.parseNumberOrNull(token)) {
245+
private isPartOfNumber(symbol: string, currentTokens: Token[]): boolean {
246+
if (symbol === '-' && !this.tokenText.length) {
247+
// '-' needs to be handled e.g. -3; 2 + -2 etc
248+
const prevToken = (currentTokens.length !== 0)? currentTokens[currentTokens.length - 1] : null;
249+
return prevToken === null || (getTokenType(prevToken) === TokenTypes.Operator && getTokenValue(prevToken) !== ')');
250+
} else if (symbol === '.' && this.parseNumberOrNull(this.tokenText) !== null) {
251251
return true;
252252
}
253253
return false;

0 commit comments

Comments
 (0)