Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/parser/scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const spaceChars = [' ', '\t'];
const lineBreakChars = ['\r', '\n'];
const digit = /^[0-9]$/;
const wordChar = /^[A-Za-z0-9_]$/;
const exponentIndicatorPattern = /^[eE]$/;

/**
* 入力文字列からトークンを読み取るクラス
Expand Down Expand Up @@ -436,12 +437,38 @@ export class Scanner implements ITokenStream {
throw new AiScriptSyntaxError('digit expected', pos);
}
}

let exponentIndicator = '';
let exponentSign = '';
let exponentAbsolute = '';
if (!this.stream.eof && exponentIndicatorPattern.test(this.stream.char as string)) {
exponentIndicator = this.stream.char as string;
this.stream.next();
if (!this.stream.eof && (this.stream.char as string) === '-') {
exponentSign = '-';
this.stream.next();
} else if (!this.stream.eof && (this.stream.char as string) === '+') {
exponentSign = '+';
this.stream.next();
}
while (!this.stream.eof && digit.test(this.stream.char)) {
exponentAbsolute += this.stream.char;
this.stream.next();
}
if (exponentAbsolute.length === 0) {
throw new AiScriptSyntaxError('exponent expected', pos);
}
}

let value: string;
if (fractional.length > 0) {
value = wholeNumber + '.' + fractional;
} else {
value = wholeNumber;
}
if (exponentIndicator.length > 0) {
value += exponentIndicator + exponentSign + exponentAbsolute;
}
return TOKEN(TokenKind.NumberLiteral, pos, { hasLeftSpacing, value });
}

Expand Down
27 changes: 27 additions & 0 deletions test/literals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,33 @@ describe('literal', () => {
eq(res, NUM(0.5));
});

test.concurrent('number (positive exponent without plus sign)', async () => {
const res = await exe(`
<: 1.2e3
`);
eq(res, NUM(1200));
});

test.concurrent('number (positive exponent with plus sign)', async () => {
const res = await exe(`
<: 1.2e+3
`);
eq(res, NUM(1200));
});

test.concurrent('number (negative exponent)', async () => {
const res = await exe(`
<: 1.2e-3
`);
eq(res, NUM(0.0012));
});

test.concurrent('number (missing exponent)', async () => {
assert.rejects(() => exe(`
<: 1.2e+
`), 'exponent expected');
});

test.concurrent('arr (separated by comma)', async () => {
const res = await exe(`
<: [1, 2, 3]
Expand Down
1 change: 1 addition & 0 deletions unreleased/exponential-notation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- 数値リテラルを指数表記で記述できるようになりました。
Loading