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
3 changes: 1 addition & 2 deletions src/parser/plugins/validate-keyword.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,7 @@ function validateNode(node: Ast.Node): Ast.Node {
}
case 'ns':
case 'attr':
case 'identifier':
case 'prop': {
case 'identifier': {
validateName(node.name, node.loc.start);
break;
}
Expand Down
3 changes: 1 addition & 2 deletions src/parser/syntaxes/expressions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,7 @@ function parseInfix(s: ITokenStream, left: Ast.Expression, minBp: number): Ast.E
}

if (op === TokenKind.Dot) {
s.expect(TokenKind.Identifier);
const name = s.getTokenValue();
const name = parseObjectKey(s);
s.next();

return NODE('prop', {
Expand Down
67 changes: 61 additions & 6 deletions test/identifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,6 @@ const sampleCodes = Object.entries<[(definedName: string, referredName: string)
<: ${referredName}:f()
`, NUM(1)],

prop: [(definedName, referredName) =>
`
let x = { ${definedName}: 1 }
x.${referredName}
`, NUM(1)],

meta: [(definedName) =>
`
### ${definedName} 1
Expand Down Expand Up @@ -303,6 +297,67 @@ describe.each(
});
});

describe('identifier validation on obj key', () => {
const codes: [string, (definedName: string, referredName: string) => string][] = [
['literal', (definedName: string, referredName: string) => `
let x = { ${definedName}: 1 }
<: x["${referredName}"]
`],

['prop', (definedName: string, referredName: string) => `
let x = {}
x.${definedName} = 1
<: x.${referredName}
`],
]

describe.each(codes)('%s', (_, code) => {
test.concurrent.each(
reservedWords
)('reserved word %s must be allowed', async (word) => {
const res = await exe(code(word, word));
eq(res, NUM(1));
});

test.concurrent.each(
identifierCases
)('%s is allowed: %s', async (word, allowed) => {
expect.hasAssertions();
if (allowed) {
const res = await exe(code(word, word));
eq(res, NUM(1));
} else {
expect(() => parser.parse(code(word, word))).toThrow(AiScriptSyntaxError);
await Promise.resolve(); // https://github.com/vitest-dev/vitest/issues/4750
}
});
});
});

describe('reserved word validation on string obj key', () => {
const codes: [string, (definedName: string, referredName: string) => string][] = [
['literal', (definedName: string, referredName: string) => `
let x = { "${definedName}": 1 }
<: x["${referredName}"]
`],

['prop', (definedName: string, referredName: string) => `
let x = {}
x."${definedName}" = 1
<: x."${referredName}"
`],
]

describe.each(codes)('%s', (_, code) => {
test.concurrent.each(
reservedWords
)('reserved word %s must be allowed', async (word) => {
const res = await exe(code(word, word));
eq(res, NUM(1));
});
});
});

test.concurrent('Keyword cannot contain escape characters', async () => {
await expect(async () => await exe(`
\\u0069\\u0066 true {
Expand Down
12 changes: 6 additions & 6 deletions test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,7 @@ describe('Object', () => {
])));
});

/* 未実装
* see also: test/literals.ts > literal > obj (string key)
* issue: https://github.com/aiscript-dev/aiscript/issues/62
// see also: test/literals.ts > literal > obj (string key)
test.concurrent('string key', async () => {
const res = await exe(`
let obj = {
Expand All @@ -222,7 +220,10 @@ describe('Object', () => {
eq(res, NUM(42));
});

test.concurrent('expression key', async () => {
// 未実装
// issues: https://github.com/aiscript-dev/aiscript/issues/62
// https://github.com/aiscript-dev/aiscript/issues/225
test.concurrent.skip('expression key', async () => {
const res = await exe(`
let key = "藍"

Expand All @@ -234,7 +235,6 @@ describe('Object', () => {
`);
eq(res, NUM(42));
});
*/
});

describe('Array', () => {
Expand Down Expand Up @@ -1092,7 +1092,7 @@ describe('Security', () => {
`);
assert.fail();
} catch (e) {
assert.ok(e instanceof AiScriptSyntaxError);
assert.ok(e instanceof AiScriptRuntimeError);
}

try {
Expand Down
2 changes: 2 additions & 0 deletions unreleased/reserved-word-keys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- プロパティアクセスのドット記法に予約語を記述できるようになりました。
- プロパティアクセスのドット記法に文字列リテラルを記述できるようになりました。
Loading