diff --git a/src/parser/syntaxes/statements.ts b/src/parser/syntaxes/statements.ts index d8918adf..fef67df7 100644 --- a/src/parser/syntaxes/statements.ts +++ b/src/parser/syntaxes/statements.ts @@ -379,7 +379,7 @@ function parseReturn(s: ITokenStream): Ast.Return { * StatementWithAttr = *Attr Statement * ``` */ -function parseStatementWithAttr(s: ITokenStream): Ast.Definition { +export function parseStatementWithAttr(s: ITokenStream): Ast.Definition { const attrs: Ast.Attribute[] = []; while (s.is(TokenKind.OpenSharpBracket)) { attrs.push(parseAttr(s) as Ast.Attribute); diff --git a/src/parser/syntaxes/toplevel.ts b/src/parser/syntaxes/toplevel.ts index 91a07787..7a1bed2e 100644 --- a/src/parser/syntaxes/toplevel.ts +++ b/src/parser/syntaxes/toplevel.ts @@ -1,7 +1,7 @@ import { NODE } from '../utils.js'; import { TokenKind } from '../token.js'; import { AiScriptSyntaxError, AiScriptUnexpectedEOFError } from '../../error.js'; -import { parseDefStatement, parseStatement } from './statements.js'; +import { parseDefStatement, parseStatement, parseStatementWithAttr } from './statements.js'; import { parseExpr } from './expressions.js'; import type * as Ast from '../../node.js'; @@ -91,6 +91,10 @@ export function parseNamespace(s: ITokenStream): Ast.Namespace { members.push(parseNamespace(s)); break; } + case TokenKind.OpenSharpBracket: { + members.push(parseStatementWithAttr(s)); + break; + } } // terminator diff --git a/test/index.ts b/test/index.ts index e66b855b..fa158707 100644 --- a/test/index.ts +++ b/test/index.ts @@ -929,6 +929,25 @@ describe('Attribute', () => { if (attr.value.type !== 'bool') assert.fail(); assert.equal(attr.value.value, true); }); + + test.concurrent('attribute with statement under namespace', async () => { + const parser = new Parser(); + const nodes = parser.parse(` + :: Tests { + #[test] + @assert_success() { + <: "Hello, world!" + } + } + `); + assert.equal(nodes.length, 1); + const ns = nodes[0]; + assert.ok(ns.type === 'ns'); + const member = ns.members[0]; + assert.ok(member.type === 'def'); + const attr = member.attr[0]; + assert.equal(attr.name, 'test'); + }); }); describe('Location', () => { diff --git a/unreleased/attr-under-ns.md b/unreleased/attr-under-ns.md new file mode 100644 index 00000000..2cdf909b --- /dev/null +++ b/unreleased/attr-under-ns.md @@ -0,0 +1 @@ +- 名前空間下の変数定義に属性を付与できるようになりました。