From 8c21e6b9936299bce5b1a0b19a0c7ea09d3009b1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Jun 2026 14:21:59 +0000 Subject: [PATCH 1/4] Initial plan From 479f7928aaf50f630ef9d4a433b2ca48944aedc9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Jun 2026 14:32:52 +0000 Subject: [PATCH 2/4] docs(spec): document directive syntax in language grammar - Add LineTerminator and LineTerminatorSequence productions to lexical grammar, separate from WhiteSpace (matching how the scanner emits Token.NewLine vs Token.Whitespace) - Update Trivia to include LineTerminatorSequence alongside Comment and WhiteSpace - Fix the incorrect comment claiming newlines have no language-semantic impact; directives are terminated by newlines so they ARE significant - Add DirectiveList, DirectiveExpression, DirectiveArguments, and DirectiveArgument productions to the syntactic grammar with notes on newline-aware termination and currently supported directive names (#suppress, #deprecated) - Add DirectiveList? before DecoratorList? in all statement/declaration productions that accept annotations Closes #949 Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com> --- packages/spec/src/spec.emu.html | 105 +++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 37 deletions(-) diff --git a/packages/spec/src/spec.emu.html b/packages/spec/src/spec.emu.html index 1a74c894e72..22145713e43 100644 --- a/packages/spec/src/spec.emu.html +++ b/packages/spec/src/spec.emu.html @@ -30,6 +30,7 @@

Lexical Grammar

Trivia : Comment WhiteSpace + LineTerminatorSequence Keyword : BooleanLiteral @@ -207,21 +208,12 @@

Lexical Grammar

`|` `?` `=` `&` `:` `,` `;` `.` `<` `>` `(` `)` `{` `}` `[` `]` `@` `...` `#` /// -// Note that whitespace could also be specified equivalently as "Any Unicode -// code point with property value Pattern_White_Space=True" -// -// However, see http://www.unicode.org/reports/tr31/#Stability -// -// "The [...] Pattern_White_Space characters are immutable and will not -// change over successive versions of Unicode". This is therefore a fixed set -// of characters, which are simply listed below to serve as a more direct -// reference: +// WhiteSpace covers non-line-terminator whitespace characters. The +// Pattern_White_Space property from Unicode TR31 defines the full set: // // - U+0009 TAB HORIZONTAL TAB -// - U+000A LF LINE FEED // - U+000B VT VERTICAL TAB // - U+000C FF FORM FEED -// - U+000D CR CARRIAGE RETURN // - U+0020 SP SPACE // - U+0085 NEL NEXT LINE // - U+200E LRM LEFT-TO-RIGHT MARK @@ -229,19 +221,13 @@

Lexical Grammar

// - U+2028 LS LINE SEPARATOR // - U+2029 PS PARAGRAPH SEPARATOR // -// It is deliberately left unspecified which whitespace sequences are -// considered newlines as no language semantics are impacted by that choice. -// Only line and column numbers associated with diagnostics are impacted. In -// practice, only CR ("MAC"), LF ("UNIX"), and CRLF ("DOS") line endings are -// currently recognized by our implementation. Additional line endings may be -// recognized in the future. +// Note: U+000A (LF), U+000D (CR), and the CR+LF sequence are line terminators +// and are covered by LineTerminatorSequence instead of WhiteSpace. /// WhiteSpace : - - @@ -249,6 +235,21 @@

Lexical Grammar

+/// +// LineTerminatorSequence covers the sequences that are recognized as line +// endings. Only CR (U+000D), LF (U+000A), and the CRLF pair are currently +// recognized. Unlike WhiteSpace, line terminators are syntactically +// significant: they terminate directive expressions (see DirectiveExpression). +/// +LineTerminator : one of + + + +LineTerminatorSequence : + + [lookahead != ] + + Comment : MultiLineComment SingleLineComment @@ -298,7 +299,7 @@

Syntactic Grammar

Statement BlocklessNamespaceStatement : - DecoratorList? `namespace` IdentifierOrMemberExpression `;` + DirectiveList? DecoratorList? `namespace` IdentifierOrMemberExpression `;` ImportStatement : `import` StringLiteral `;` @@ -325,15 +326,15 @@

Syntactic Grammar

`using` IdentifierOrMemberExpression `;` ModelStatement : - DecoratorList? `model` Identifier TemplateParameters? IsModelHeritage `;` - DecoratorList? `model` Identifier TemplateParameters? ModelHeritage? `{` ModelBody? `}` + DirectiveList? DecoratorList? `model` Identifier TemplateParameters? IsModelHeritage `;` + DirectiveList? DecoratorList? `model` Identifier TemplateParameters? ModelHeritage? `{` ModelBody? `}` IsModelHeritage : `is` Expression ScalarStatement : - DecoratorList? `scalar` Identifier TemplateParameters? ScalarExtends? `;` - DecoratorList? `scalar` Identifier TemplateParameters? ScalarExtends? `{` ScalarBody? `}` + DirectiveList? DecoratorList? `scalar` Identifier TemplateParameters? ScalarExtends? `;` + DirectiveList? DecoratorList? `scalar` Identifier TemplateParameters? ScalarExtends? `{` ScalarBody? `}` ScalarExtends : `extends` Expression @@ -366,14 +367,14 @@

Syntactic Grammar

ModelProperty : ModelSpreadProperty - DecoratorList? Identifier `?`? `:` Expression - DecoratorList? StringLiteral `?`? `:` Expression + DirectiveList? DecoratorList? Identifier `?`? `:` Expression + DirectiveList? DecoratorList? StringLiteral `?`? `:` Expression ModelSpreadProperty : `...` ReferenceExpression InterfaceStatement : - DecoratorList? `interface` Identifier TemplateParameters? InterfaceHeritage? `{` InterfaceBody? `}` + DirectiveList? DecoratorList? `interface` Identifier TemplateParameters? InterfaceHeritage? `{` InterfaceBody? `}` InterfaceHeritage : `extends` ReferenceExpressionList; @@ -386,11 +387,11 @@

Syntactic Grammar

InterfaceMemberList `;` InterfaceMember InterfaceMember : - `op`? Identifier OperationSignature + DirectiveList? DecoratorList? `op`? Identifier OperationSignature UnionStatement : - DecoratorList? `union` Identifier TemplateParameters? `{` UnionBody? `}` + DirectiveList? DecoratorList? `union` Identifier TemplateParameters? `{` UnionBody? `}` UnionBody : UnionVariantList `;`? @@ -400,12 +401,12 @@

Syntactic Grammar

UnionVariantList `;` UnionVariant UnionVariant : - DecoratorList? Identifier `:` Expression - DecoratorList? StringLiteral `:` Expression - DecoratorList? Expression + DirectiveList? DecoratorList? Identifier `:` Expression + DirectiveList? DecoratorList? StringLiteral `:` Expression + DirectiveList? DecoratorList? Expression EnumStatement : - DecoratorList? `enum` Identifier `{` EnumBody? `}` + DirectiveList? DecoratorList? `enum` Identifier `{` EnumBody? `}` EnumBody : EnumMemberList `,`? @@ -418,8 +419,8 @@

Syntactic Grammar

EnumMember : EnumSpreadMember - DecoratorList? Identifier EnumMemberValue? - DecoratorList? StringLiteral EnumMemberValue? + DirectiveList? DecoratorList? Identifier EnumMemberValue? + DirectiveList? DecoratorList? StringLiteral EnumMemberValue? EnumSpreadMember : `...` ReferenceExpression @@ -457,7 +458,7 @@

Syntactic Grammar

IdentifierList `,` Identifier NamespaceStatement : - DecoratorList? `namespace` IdentifierOrMemberExpression `{` StatementList? `}` + DirectiveList? DecoratorList? `namespace` IdentifierOrMemberExpression `{` StatementList? `}` OperationSignatureDeclaration : `(` ModelPropertyList? `)` `:` Expression @@ -470,7 +471,7 @@

Syntactic Grammar

OperationSignatureReference OperationStatement : - DecoratorList? `op` Identifier TemplateParameters? OperationSignature `;` + DirectiveList? DecoratorList? `op` Identifier TemplateParameters? OperationSignature `;` Expression : UnionExpressionOrHigher @@ -588,6 +589,36 @@

Syntactic Grammar

DecoratorArguments : `(` ExpressionList? `)` +/// +// DirectiveExpression covers the #suppress and #deprecated directives. +// Unlike most constructs, a directive is terminated by a LineTerminatorSequence +// (or end of file) rather than a delimiter such as `;`. This means line +// terminators are syntactically significant inside directives: all arguments +// to the directive must appear on the same line as the `#` token. +// +// Currently recognized directive names are `suppress` and `deprecated`. +// #suppress -- suppresses a specific diagnostic (2 arguments) +// #deprecated -- marks a declaration as deprecated (1 argument) +// +// The number of required arguments is validated during semantic analysis, not +// by this grammar. The second alternative for DirectiveExpression handles the +// case where the directive appears at the very end of the file with no trailing +// line terminator. +/// +DirectiveList : + DirectiveList? DirectiveExpression + +DirectiveExpression : + `#` Identifier DirectiveArguments? LineTerminatorSequence + `#` Identifier DirectiveArguments? + +DirectiveArguments : + DirectiveArgument DirectiveArguments? + +DirectiveArgument : + StringLiteral + Identifier + CallExpression : IdentifierOrMemberExpression `(` ExpressionList? `)` From 303675db22ee51e8fc7addcc826462bf17b44cd6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Jun 2026 14:51:55 +0000 Subject: [PATCH 3/4] fix(spec): remove LineTerminator definition to fix ecmarkup OOM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Defining `LineTerminator` caused ecmarkup to try expanding the "SourceCharacter but not ... or LineTerminator" productions in BacktickedIdentifierChar, StringCharacter, and SingleLineCommentChar. This triggered a memory blowup that crashed the build at 4GB heap. Since LineTerminator was already referenced-but-undefined in those three productions before this PR, keep it undefined. Define only `LineTerminatorSequence` (using / character literals directly) since it is the production that needs to appear in Trivia. Also remove the two-alternative form of DirectiveExpression that used `LineTerminatorSequence` as a syntactic-grammar terminal — directive termination is explained in prose instead. Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com> --- packages/spec/src/spec.emu.html | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/packages/spec/src/spec.emu.html b/packages/spec/src/spec.emu.html index 22145713e43..7bbd278c9d3 100644 --- a/packages/spec/src/spec.emu.html +++ b/packages/spec/src/spec.emu.html @@ -236,15 +236,11 @@

Lexical Grammar

/// -// LineTerminatorSequence covers the sequences that are recognized as line -// endings. Only CR (U+000D), LF (U+000A), and the CRLF pair are currently -// recognized. Unlike WhiteSpace, line terminators are syntactically -// significant: they terminate directive expressions (see DirectiveExpression). +// LineTerminatorSequence covers the three sequences recognised as line endings: +// a lone LF (U+000A), a lone CR (U+000D) not followed by LF, or the CRLF pair. +// Unlike WhiteSpace, line terminators are syntactically significant: they +// terminate directive expressions (see DirectiveExpression). /// -LineTerminator : one of - - - LineTerminatorSequence : [lookahead != ] @@ -591,25 +587,23 @@

Syntactic Grammar

/// // DirectiveExpression covers the #suppress and #deprecated directives. -// Unlike most constructs, a directive is terminated by a LineTerminatorSequence -// (or end of file) rather than a delimiter such as `;`. This means line -// terminators are syntactically significant inside directives: all arguments -// to the directive must appear on the same line as the `#` token. +// A directive is terminated by a line terminator (CR, LF, or CRLF) or end of +// input. Because line terminators are classified as Trivia and are normally +// transparent to the syntactic grammar, the termination rule is enforced +// contextually by the parser rather than expressed as a formal production: all +// DirectiveArguments must appear on the same source line as the `#` token. // -// Currently recognized directive names are `suppress` and `deprecated`. +// Currently recognised directive names are `suppress` and `deprecated`. // #suppress -- suppresses a specific diagnostic (2 arguments) // #deprecated -- marks a declaration as deprecated (1 argument) // // The number of required arguments is validated during semantic analysis, not -// by this grammar. The second alternative for DirectiveExpression handles the -// case where the directive appears at the very end of the file with no trailing -// line terminator. +// by this grammar. /// DirectiveList : DirectiveList? DirectiveExpression DirectiveExpression : - `#` Identifier DirectiveArguments? LineTerminatorSequence `#` Identifier DirectiveArguments? DirectiveArguments : From 9914542736a6a1336b0f0c0ffdca94110ddb590b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Jun 2026 16:00:22 +0000 Subject: [PATCH 4/4] =?UTF-8?q?docs(spec):=20fix=20spelling=20recognised?= =?UTF-8?q?=20=E2=86=92=20recognized?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com> --- packages/spec/src/spec.emu.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/spec/src/spec.emu.html b/packages/spec/src/spec.emu.html index 7bbd278c9d3..5230dacc946 100644 --- a/packages/spec/src/spec.emu.html +++ b/packages/spec/src/spec.emu.html @@ -236,7 +236,7 @@

Lexical Grammar

/// -// LineTerminatorSequence covers the three sequences recognised as line endings: +// LineTerminatorSequence covers the three sequences recognized as line endings: // a lone LF (U+000A), a lone CR (U+000D) not followed by LF, or the CRLF pair. // Unlike WhiteSpace, line terminators are syntactically significant: they // terminate directive expressions (see DirectiveExpression). @@ -593,7 +593,7 @@

Syntactic Grammar

// contextually by the parser rather than expressed as a formal production: all // DirectiveArguments must appear on the same source line as the `#` token. // -// Currently recognised directive names are `suppress` and `deprecated`. +// Currently recognized directive names are `suppress` and `deprecated`. // #suppress -- suppresses a specific diagnostic (2 arguments) // #deprecated -- marks a declaration as deprecated (1 argument) //