Skip to content

Commit c840d21

Browse files
authored
Merge pull request #11219 from dotty-staging/fix-syntax-pages
Make indentation explicit in context-free syntax
2 parents a3b7ed6 + fcfb579 commit c840d21

File tree

3 files changed

+77
-52
lines changed

3 files changed

+77
-52
lines changed

docs/docs/internals/syntax.md

Lines changed: 54 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ layout: doc-page
33
title: "Scala 3 Syntax Summary"
44
---
55

6-
The following descriptions of Scala tokens uses literal characters `‘c’` when
6+
The following description of Scala tokens uses literal characters `‘c’` when
77
referring to the ASCII fragment `\u0000``\u007F`.
88

9-
_Unicode escapes_ are used to represent the Unicode character with the given
9+
_Unicode escapes_ are used to represent the [Unicode character](https://www.w3.org/International/articles/definitions-characters/) with the given
1010
hexadecimal code:
1111

1212
```ebnf
@@ -17,6 +17,7 @@ hexDigit ::= ‘0’ | … | ‘9’ | ‘A’ | … | ‘F’ | ‘a’ |
1717
Informal descriptions are typeset as `“some comment”`.
1818

1919
### Lexical Syntax
20+
2021
The lexical syntax of Scala is given by the following grammar in EBNF
2122
form.
2223

@@ -28,9 +29,9 @@ letter ::= upper | lower “… and Unicode categories Lo, Lt, Nl”
2829
digit ::= ‘0’ | … | ‘9’
2930
paren ::= ‘(’ | ‘)’ | ‘[’ | ‘]’ | ‘{’ | ‘}’ | ‘'(’ | ‘'[’ | ‘'{’
3031
delim ::= ‘`’ | ‘'’ | ‘"’ | ‘.’ | ‘;’ | ‘,’
31-
opchar ::= “printableChar not matched by (whiteSpace | upper | lower |
32-
letter | digit | paren | delim | opchar | Unicode_Sm |
33-
Unicode_So)”
32+
opchar ::= “printableChar not matched by (whiteSpace | upper |
33+
lower | letter | digit | paren | delim | opchar |
34+
Unicode_Sm | Unicode_So)”
3435
printableChar ::= “all characters in [\u0020, \u007F] inclusive”
3536
charEscapeSeq ::= ‘\’ (‘b’ | ‘t’ | ‘n’ | ‘f’ | ‘r’ | ‘"’ | ‘'’ | ‘\’)
3637
@@ -42,7 +43,6 @@ plainid ::= alphaid
4243
| op
4344
id ::= plainid
4445
| ‘`’ { charNoBackQuoteOrNewline | UnicodeEscape | charEscapeSeq } ‘`’
45-
| INT // interpolation id, only for quasi-quotes
4646
idrest ::= {letter | digit} [‘_’ op]
4747
quoteId ::= ‘'’ alphaid
4848
@@ -83,29 +83,49 @@ comment ::= ‘/*’ “any sequence of characters; nested comments ar
8383
8484
nl ::= “new line character”
8585
semi ::= ‘;’ | nl {nl}
86-
colonEol ::= ": at end of line that can start a template body"
8786
```
8887

88+
89+
## Optional Braces
90+
91+
The lexical analyzer also inserts `indent` and `outdent` tokens that represent regions of indented code [at certain points](../reference/other-new-features-indentation.html)
92+
93+
In the context-free productions below we use the notation `<<< ts >>>`
94+
to indicate a token sequence `ts` that is either enclosed in a pair of braces `{ ts }` or that constitutes an indented region `indent ts outdent`. Analogously, the
95+
notation `:<<< ts >>>` indicates a token sequence `ts` that is either enclosed in a pair of braces `{ ts }` or that constitutes an indented region `indent ts outdent` that follows
96+
a `:` at the end of a line.
97+
98+
99+
```
100+
<<< ts >>> ::= ‘{’ ts ‘}’
101+
| indent ts outdent
102+
:<<< ts >>> ::= [nl] ‘{’ ts ‘}’
103+
| `:` indent ts outdent
104+
89105
## Keywords
90106
91107
### Regular keywords
92108
93109
```
94-
abstract case catch class def do else enum
95-
export extends false final finally for given if
96-
implicit import lazy match new null object package
97-
private protected override return super sealed then throw
98-
trait true try type val var while with
99-
yield
100-
: = <- => <: :> # @
101-
=>> ?=>
110+
abstract case catch class def do else
111+
enum export extends false final finally for
112+
given if implicit import lazy match new
113+
null object override package private protected return
114+
sealed super then throw trait true try
115+
type val var while with yield
116+
: = <- => <: :> #
117+
@ =>> ?=>
102118
```
103119
104120
### Soft keywords
105121
106122
```
107-
derives end extension inline infix opaque open transparent using | * + -
123+
derives end extension infix inline opaque open transparent using | * + -
108124
```
125+
126+
See the [separate section on soft keywords](./soft-modifier.md) for additional
127+
details on where a soft keyword is recognized.
128+
109129
## Context-free Syntax
110130
111131
The context-free syntax of Scala is given by the following EBNF
@@ -147,10 +167,9 @@ FunArgTypes ::= InfixType
147167
| FunParamClause
148168
FunParamClause ::= ‘(’ TypedFunParam {‘,’ TypedFunParam } ‘)’
149169
TypedFunParam ::= id ‘:’ Type
150-
MatchType ::= InfixType `match` ‘{’ TypeCaseClauses ‘}’
170+
MatchType ::= InfixType `match` <<< TypeCaseClauses >>>
151171
InfixType ::= RefinedType {id [nl] RefinedType} InfixOp(t1, op, t2)
152-
RefinedType ::= WithType {[nl] Refinement} RefinedTypeTree(t, ds)
153-
WithType ::= AnnotType {‘with’ AnnotType} (deprecated)
172+
RefinedType ::= AnnotType {[nl] Refinement} RefinedTypeTree(t, ds)
154173
AnnotType ::= SimpleType {Annotation} Annotated(t, annot)
155174
156175
SimpleType ::= SimpleLiteral SingletonTypeTree(l)
@@ -209,7 +228,7 @@ PostfixExpr ::= InfixExpr [id]
209228
InfixExpr ::= PrefixExpr
210229
| InfixExpr id [nl] InfixExpr InfixOp(expr, op, expr)
211230
| InfixExpr MatchClause
212-
MatchClause ::= ‘match’ ‘{’ CaseClauses ‘}’ Match(expr, cases)
231+
MatchClause ::= ‘match’ <<< CaseClauses >>> Match(expr, cases)
213232
PrefixExpr ::= [‘-’ | ‘+’ | ‘~’ | ‘!’] SimpleExpr PrefixOp(expr, op)
214233
SimpleExpr ::= SimpleRef
215234
| Literal
@@ -218,9 +237,8 @@ SimpleExpr ::= SimpleRef
218237
| ‘$’ ‘{’ Block ‘}’
219238
| Quoted
220239
| quoteId -- only inside splices
221-
| ‘new’ ConstrApp {‘with’ ConstrApp} New(constr | templ)
222-
[[colonEol] TemplateBody
223-
| ‘new’ [colonEol] TemplateBody
240+
| ‘new’ ConstrApp {‘with’ ConstrApp} [TemplateBody] New(constr | templ)
241+
| ‘new’ TemplateBody
224242
| ‘(’ ExprsInParens ‘)’ Parens(exprs)
225243
| SimpleExpr ‘.’ id Select(expr, id)
226244
| SimpleExpr ‘.’ MatchClause
@@ -237,7 +255,7 @@ ParArgumentExprs ::= ‘(’ [‘using’] ExprsInParens ‘)’
237255
| ‘(’ [ExprsInParens ‘,’] PostfixExpr ‘:’ ‘_’ ‘*’ ‘)’ exprs :+ Typed(expr, Ident(wildcardStar))
238256
ArgumentExprs ::= ParArgumentExprs
239257
| BlockExpr
240-
BlockExpr ::= ‘{’ (CaseClauses | Block) ‘}’
258+
BlockExpr ::= <<< (CaseClauses | Block) >>>
241259
Block ::= {BlockStat semi} [BlockResult] Block(stats, expr?)
242260
BlockStat ::= Import
243261
| {Annotation {nl}} [‘implicit’ | ‘lazy’] Def
@@ -356,7 +374,6 @@ EndMarkerTag ::= id | ‘if’ | ‘while’ | ‘for’ | ‘match’ |
356374
RefineDcl ::= ‘val’ ValDcl
357375
| ‘def’ DefDcl
358376
| ‘type’ {nl} TypeDcl
359-
| INT
360377
Dcl ::= RefineDcl
361378
| ‘var’ VarDcl
362379
ValDcl ::= ids ‘:’ Type PatDef(_, ids, tpe, EmptyTree)
@@ -372,7 +389,7 @@ Def ::= ‘val’ PatDef
372389
| ‘type’ {nl} TypeDcl
373390
| TmplDef
374391
PatDef ::= ids [‘:’ Type] ‘=’ Expr
375-
| Pattern2 [‘:’ Type] ‘=’ Expr PatDef(_, pats, tpe?, expr)
392+
| Pattern2 [‘:’ Type] ‘=’ Expr PatDef(_, pats, tpe?, expr)
376393
VarDef ::= PatDef
377394
| ids ‘:’ Type ‘=’ ‘_’
378395
DefDef ::= DefSig [‘:’ Type] ‘=’ Expr DefDef(_, name, tparams, vparamss, tpe, expr)
@@ -386,23 +403,23 @@ ClassDef ::= id ClassConstr [Template]
386403
ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses with DefDef(_, <init>, Nil, vparamss, EmptyTree, EmptyTree) as first stat
387404
ConstrMods ::= {Annotation} [AccessModifier]
388405
ObjectDef ::= id [Template] ModuleDef(mods, name, template) // no constructor
389-
EnumDef ::= id ClassConstr InheritClauses [colonEol] EnumBody
406+
EnumDef ::= id ClassConstr InheritClauses EnumBody
390407
GivenDef ::= [GivenSig] (AnnotType [‘=’ Expr] | StructuralInstance)
391408
GivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefParamClause`, `UsingParamClause` must be present
392409
StructuralInstance ::= ConstrApp {‘with’ ConstrApp} ‘with’ TemplateBody
393410
Extension ::= ‘extension’ [DefTypeParamClause] ‘(’ DefParam ‘)’
394411
{UsingParamClause}] ExtMethods
395-
ExtMethods ::= ExtMethod | [nl] ‘{’ ExtMethod {semi ExtMethod ‘}’
412+
ExtMethods ::= ExtMethod | [nl] <<< ExtMethod {semi ExtMethod} >>>
396413
ExtMethod ::= {Annotation [nl]} {Modifier} ‘def’ DefDef
397-
Template ::= InheritClauses [colonEol] [TemplateBody] Template(constr, parents, self, stats)
414+
Template ::= InheritClauses [TemplateBody]
398415
InheritClauses ::= [‘extends’ ConstrApps] [‘derives’ QualId {‘,’ QualId}]
399416
ConstrApps ::= ConstrApp ({‘,’ ConstrApp} | {‘with’ ConstrApp})
400-
ConstrApp ::= SimpleType1 {Annotation} {ParArgumentExprs} Apply(tp, args)
417+
ConstrApp ::= SimpleType1 {Annotation} {ParArgumentExprs}
401418
ConstrExpr ::= SelfInvocation
402-
| ‘{’ SelfInvocation {semi BlockStat} ‘}’
419+
| <<< SelfInvocation {semi BlockStat} >>>
403420
SelfInvocation ::= ‘this’ ArgumentExprs {ArgumentExprs}
404421
405-
TemplateBody ::= [nl] ‘{’ [SelfType] TemplateStat {semi TemplateStat} ‘}’
422+
TemplateBody ::= :<<< [SelfType] TemplateStat {semi TemplateStat} >>>
406423
TemplateStat ::= Import
407424
| Export
408425
| {Annotation [nl]} {Modifier} Def
@@ -414,12 +431,12 @@ TemplateStat ::= Import
414431
SelfType ::= id [‘:’ InfixType] ‘=>’ ValDef(_, name, tpt, _)
415432
| ‘this’ ‘:’ InfixType ‘=>’
416433
417-
EnumBody ::= [nl] ‘{’ [SelfType] EnumStat {semi EnumStat} ‘}’
434+
EnumBody ::= :<<< [SelfType] EnumStat {semi EnumStat} >>>
418435
EnumStat ::= TemplateStat
419436
| {Annotation [nl]} {Modifier} EnumCase
420437
EnumCase ::= ‘case’ (id ClassConstr [‘extends’ ConstrApps]] | ids)
421438
422-
TopStatSeq ::= TopStat {semi TopStat}
439+
TopStats ::= TopStat {semi TopStat}
423440
TopStat ::= Import
424441
| Export
425442
| {Annotation [nl]} {Modifier} Def
@@ -428,8 +445,8 @@ TopStat ::= Import
428445
| PackageObject
429446
| EndMarker
430447
|
431-
Packaging ::= ‘package’ QualId [nl | colonEol] ‘{’ TopStatSeq ‘}’ Package(qid, stats)
432-
PackageObject ::= ‘package’ ‘object’ ObjectDef object with package in mods.
448+
Packaging ::= ‘package’ QualId :<<< TopStats >>>
449+
PackageObject ::= ‘package’ ‘object’ ObjectDef
433450
434-
CompilationUnit ::= {‘package’ QualId semi} TopStatSeq Package(qid, stats)
451+
CompilationUnit ::= {‘package’ QualId semi} TopStats
435452
```

docs/docs/reference/other-new-features/indentation.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@ layout: doc-page
33
title: Optional Braces
44
---
55

6-
As an experimental feature, Scala 3 enforces some rules on indentation and allows
7-
some occurrences of braces `{...}` to be optional.
8-
It can be turned off with the compiler flag `-noindent`.
6+
Scala 3 enforces some rules on indentation and allows some occurrences of braces `{...}` to be optional:
97

108
- First, some badly indented programs are flagged with warnings.
119
- Second, some occurrences of braces `{...}` are made optional. Generally, the rule
1210
is that adding a pair of optional braces will not change the meaning of a well-indented program.
1311

12+
These changescan can be turned off with the compiler flag `-noindent`.
1413
### Indentation Rules
1514

1615
The compiler enforces two rules for well-indented programs, flagging violations as warnings.

docs/docs/reference/syntax.md

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,23 @@ comment ::= ‘/*’ “any sequence of characters; nested comments ar
8383
8484
nl ::= “new line character”
8585
semi ::= ‘;’ | nl {nl}
86-
colonEol ::= ": at end of line that can start a template body"
8786
```
8887

88+
## Optional Braces
89+
8990
The lexical analyzer also inserts `indent` and `outdent` tokens that represent regions of indented code [at certain points](../reference/other-new-features-indentation.html)
9091

9192
In the context-free productions below we use the notation `<<< ts >>>`
92-
to indicate a token sequence `ts` that is either enclosed in a pair of braces `{ ts }` or that constitutes an indented region `indent ts outdent`.
93+
to indicate a token sequence `ts` that is either enclosed in a pair of braces `{ ts }` or that constitutes an indented region `indent ts outdent`. Analogously, the
94+
notation `:<<< ts >>>` indicates a token sequence `ts` that is either enclosed in a pair of braces `{ ts }` or that constitutes an indented region `indent ts outdent` that follows
95+
a `:` at the end of a line.
96+
9397

98+
```
99+
<<< ts >>> ::= ‘{’ ts ‘}’
100+
| indent ts outdent
101+
:<<< ts >>> ::= [nl] ‘{’ ts ‘}’
102+
| `:` indent ts outdent
94103
95104
## Keywords
96105
@@ -226,8 +235,8 @@ SimpleExpr ::= SimpleRef
226235
| ‘$’ ‘{’ Block ‘}’
227236
| Quoted
228237
| quoteId -- only inside splices
229-
| ‘new’ ConstrApp {‘with’ ConstrApp} [[colonEol] TemplateBody
230-
| ‘new’ [colonEol] TemplateBody
238+
| ‘new’ ConstrApp {‘with’ ConstrApp} [TemplateBody]
239+
| ‘new’ TemplateBody
231240
| ‘(’ ExprsInParens ‘)’
232241
| SimpleExpr ‘.’ id
233242
| SimpleExpr ‘.’ MatchClause
@@ -242,7 +251,7 @@ ParArgumentExprs ::= ‘(’ [‘using’] ExprsInParens ‘)’
242251
| ‘(’ [ExprsInParens ‘,’] PostfixExpr ‘:’ ‘_’ ‘*’ ‘)’
243252
ArgumentExprs ::= ParArgumentExprs
244253
| BlockExpr
245-
BlockExpr ::= ‘{’ (CaseClauses | Block) ‘}’
254+
BlockExpr ::= <<< (CaseClauses | Block) >>>
246255
Block ::= {BlockStat semi} [BlockResult]
247256
BlockStat ::= Import
248257
| {Annotation {nl}} [‘implicit’ | ‘lazy’] Def
@@ -384,23 +393,23 @@ ClassDef ::= id ClassConstr [Template]
384393
ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses
385394
ConstrMods ::= {Annotation} [AccessModifier]
386395
ObjectDef ::= id [Template]
387-
EnumDef ::= id ClassConstr InheritClauses [colonEol] EnumBody
388-
GivenDef ::= [GivenSig] (Type [‘=’ Expr] | StructuralInstance)
396+
EnumDef ::= id ClassConstr InheritClauses EnumBody
397+
GivenDef ::= [GivenSig] (AnnotType [‘=’ Expr] | StructuralInstance)
389398
GivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefParamClause`, `UsingParamClause` must be present
390399
StructuralInstance ::= ConstrApp {‘with’ ConstrApp} ‘with’ TemplateBody
391400
Extension ::= ‘extension’ [DefTypeParamClause] ‘(’ DefParam ‘)’
392401
{UsingParamClause}] ExtMethods
393-
ExtMethods ::= ExtMethod | [nl] ‘{’ ExtMethod {semi ExtMethod ‘}’
402+
ExtMethods ::= ExtMethod | [nl] <<< ExtMethod {semi ExtMethod} >>>
394403
ExtMethod ::= {Annotation [nl]} {Modifier} ‘def’ DefDef
395-
Template ::= InheritClauses [colonEol] [TemplateBody]
404+
Template ::= InheritClauses [TemplateBody]
396405
InheritClauses ::= [‘extends’ ConstrApps] [‘derives’ QualId {‘,’ QualId}]
397406
ConstrApps ::= ConstrApp ({‘,’ ConstrApp} | {‘with’ ConstrApp})
398407
ConstrApp ::= SimpleType1 {Annotation} {ParArgumentExprs}
399408
ConstrExpr ::= SelfInvocation
400409
| <<< SelfInvocation {semi BlockStat} >>>
401410
SelfInvocation ::= ‘this’ ArgumentExprs {ArgumentExprs}
402411
403-
TemplateBody ::= [nl] ‘{’ [SelfType] TemplateStat {semi TemplateStat} ‘}’
412+
TemplateBody ::= :<<< [SelfType] TemplateStat {semi TemplateStat} >>>
404413
TemplateStat ::= Import
405414
| Export
406415
| {Annotation [nl]} {Modifier} Def
@@ -412,7 +421,7 @@ TemplateStat ::= Import
412421
SelfType ::= id [‘:’ InfixType] ‘=>’
413422
| ‘this’ ‘:’ InfixType ‘=>’
414423
415-
EnumBody ::= [nl] ‘{’ [SelfType] EnumStat {semi EnumStat} ‘}’
424+
EnumBody ::= :<<< [SelfType] EnumStat {semi EnumStat} >>>
416425
EnumStat ::= TemplateStat
417426
| {Annotation [nl]} {Modifier} EnumCase
418427
EnumCase ::= ‘case’ (id ClassConstr [‘extends’ ConstrApps]] | ids)
@@ -426,7 +435,7 @@ TopStat ::= Import
426435
| PackageObject
427436
| EndMarker
428437
|
429-
Packaging ::= ‘package’ QualId [nl | colonEol] ‘{’ TopStats‘}’
438+
Packaging ::= ‘package’ QualId :<<< TopStats >>>
430439
PackageObject ::= ‘package’ ‘object’ ObjectDef
431440
432441
CompilationUnit ::= {‘package’ QualId semi} TopStats

0 commit comments

Comments
 (0)