Skip to content

Commit 1ac12ce

Browse files
committed
Change doc pages for syntax and indentation
Change doc pages for syntax and indentation to reflect current implementation
1 parent 6d9e101 commit 1ac12ce

File tree

3 files changed

+163
-136
lines changed

3 files changed

+163
-136
lines changed

docs/docs/internals/syntax.md

Lines changed: 39 additions & 29 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
@@ -85,26 +85,36 @@ nl ::= “new line character”
8585
semi ::= ‘;’ | nl {nl}
8686
```
8787

88+
The lexical analyzer also inserts `indent` and `outdent` tokensthat represent regions of indented code [at certain points](../reference/other-new-features-indentation.html)
89+
90+
In the context-free productions below we use the notation `<<< ts >>>`
91+
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`.
92+
93+
8894
## Keywords
8995

9096
### Regular keywords
9197

9298
```
93-
abstract case catch class def do else enum
94-
export extends false final finally for given if
95-
implicit import lazy match new null object package
96-
private protected override return super sealed then throw
97-
trait true try type val var while with
98-
yield
99-
: = <- => <: :> # @
100-
=>> ?=>
99+
abstract case catch class def do else
100+
enum export extends false final finally for
101+
given if implicit import lazy match new
102+
null object override package private protected return
103+
sealed super then throw trait true try
104+
type val var while with yield
105+
: = <- => <: :> #
106+
@ =>> ?=>
101107
```
102108

103109
### Soft keywords
104110

105111
```
106-
derives end extension inline infix opaque open transparent using | * + -
112+
derives end extension infix inline opaque open transparent using | * + -
107113
```
114+
115+
See the [separate section on soft keywords](./soft-modifier.md) for additional
116+
details on where a soft keyword is recognized.
117+
108118
## Context-free Syntax
109119

110120
The context-free syntax of Scala is given by the following EBNF
@@ -146,7 +156,7 @@ FunArgTypes ::= InfixType
146156
| FunParamClause
147157
FunParamClause ::= ‘(’ TypedFunParam {‘,’ TypedFunParam } ‘)’
148158
TypedFunParam ::= id ‘:’ Type
149-
MatchType ::= InfixType `match` ‘{’ TypeCaseClauses ‘}’
159+
MatchType ::= InfixType `match` <<< TypeCaseClauses >>>
150160
InfixType ::= RefinedType {id [nl] RefinedType} InfixOp(t1, op, t2)
151161
RefinedType ::= WithType {[nl | ‘with’] Refinement} RefinedTypeTree(t, ds)
152162
WithType ::= AnnotType {‘with’ AnnotType} (deprecated)
@@ -172,7 +182,7 @@ FunArgType ::= Type
172182
ParamType ::= [‘=>’] ParamValueType
173183
ParamValueType ::= Type [‘*’] PostfixOp(t, "*")
174184
TypeArgs ::= ‘[’ Types ‘]’ ts
175-
Refinement ::= ‘{’ [RefineDcl] {semi [RefineDcl]} ‘}’ ds
185+
Refinement ::= <<< [RefineDcl] {semi [RefineDcl]} >>> ds
176186
TypeBounds ::= [‘>:’ Type] [‘<:’ Type] TypeBoundsTree(lo, hi)
177187
TypeParamBounds ::= TypeBounds {‘:’ Type} ContextBounds(typeBounds, tps)
178188
Types ::= Type {‘,’ Type}
@@ -208,7 +218,7 @@ PostfixExpr ::= InfixExpr [id]
208218
InfixExpr ::= PrefixExpr
209219
| InfixExpr id [nl] InfixExpr InfixOp(expr, op, expr)
210220
| InfixExpr MatchClause
211-
MatchClause ::= ‘match’ ‘{’ CaseClauses ‘}’ Match(expr, cases)
221+
MatchClause ::= ‘match’ <<< CaseClauses >>> Match(expr, cases)
212222
PrefixExpr ::= [‘-’ | ‘+’ | ‘~’ | ‘!’] SimpleExpr PrefixOp(expr, op)
213223
SimpleExpr ::= SimpleRef
214224
| Literal
@@ -235,7 +245,7 @@ ParArgumentExprs ::= ‘(’ [‘using’] ExprsInParens ‘)’
235245
| ‘(’ [ExprsInParens ‘,’] PostfixExpr ‘:’ ‘_’ ‘*’ ‘)’ exprs :+ Typed(expr, Ident(wildcardStar))
236246
ArgumentExprs ::= ParArgumentExprs
237247
| BlockExpr
238-
BlockExpr ::= ‘{’ (CaseClauses | Block) ‘}’
248+
BlockExpr ::= <<< (CaseClauses | Block) >>>
239249
Block ::= {BlockStat semi} [BlockResult] Block(stats, expr?)
240250
BlockStat ::= Import
241251
| {Annotation {nl}} [‘implicit’ | ‘lazy’] Def
@@ -354,7 +364,6 @@ EndMarkerTag ::= id | ‘if’ | ‘while’ | ‘for’ | ‘match’ |
354364
RefineDcl ::= ‘val’ ValDcl
355365
| ‘def’ DefDcl
356366
| ‘type’ {nl} TypeDcl
357-
| INT
358367
Dcl ::= RefineDcl
359368
| ‘var’ VarDcl
360369
ValDcl ::= ids ‘:’ Type PatDef(_, ids, tpe, EmptyTree)
@@ -370,7 +379,7 @@ Def ::= ‘val’ PatDef
370379
| ‘type’ {nl} TypeDcl
371380
| TmplDef
372381
PatDef ::= ids [‘:’ Type] ‘=’ Expr
373-
| Pattern2 [‘:’ Type] ‘=’ Expr PatDef(_, pats, tpe?, expr)
382+
| Pattern2 [‘:’ Type] ‘=’ Expr PatDef(_, pats, tpe?, expr)
374383
VarDef ::= PatDef
375384
| ids ‘:’ Type ‘=’ ‘_’
376385
DefDef ::= DefSig [‘:’ Type] ‘=’ Expr DefDef(_, name, tparams, vparamss, tpe, expr)
@@ -389,18 +398,19 @@ GivenDef ::= [GivenSig] (AnnotType [‘=’ Expr] | ConstrApps Templat
389398
GivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefParamClause`, `UsingParamClause` must be present
390399
Extension ::= ‘extension’ [DefTypeParamClause] ‘(’ DefParam ‘)’
391400
{UsingParamClause}] ExtMethods
392-
ExtMethods ::= ExtMethod | [nl] ‘{’ ExtMethod {semi ExtMethod ‘}’
401+
ExtMethods ::= ExtMethod | [nl] <<< ExtMethod {semi ExtMethod >>>
393402
ExtMethod ::= {Annotation [nl]} {Modifier} ‘def’ DefDef
394403
Template ::= InheritClauses [TemplateBody] Template(constr, parents, self, stats)
395404
InheritClauses ::= [‘extends’ ConstrApps] [‘derives’ QualId {‘,’ QualId}]
396405
ConstrApps ::= ConstrApp ({‘,’ ConstrApp} | {‘with’ ConstrApp})
397406
ConstrApp ::= SimpleType1 {Annotation} {ParArgumentExprs} Apply(tp, args)
398407
ConstrExpr ::= SelfInvocation
399-
| ‘{’ SelfInvocation {semi BlockStat} ‘}’
408+
| <<< SelfInvocation {semi BlockStat} >>>
400409
SelfInvocation ::= ‘this’ ArgumentExprs {ArgumentExprs}
401410
402-
TemplateBody ::= [nl | ‘with’] ‘{’ [SelfType] TemplateStat {semi TemplateStat} ‘}’
403-
| ‘with’ [SelfType] indent TemplateStats outdent
411+
TemplateBody ::= [nl | ‘with’] <<< [SelfType] TemplateStats >>>
412+
| ‘with’ SelfType indent TemplateStats outdent
413+
TemplateStats ::= TemplateStat {semi TemplateStat}
404414
TemplateStat ::= Import
405415
| Export
406416
| {Annotation [nl]} {Modifier} Def
@@ -412,14 +422,14 @@ TemplateStat ::= Import
412422
SelfType ::= id [‘:’ InfixType] ‘=>’ ValDef(_, name, tpt, _)
413423
| ‘this’ ‘:’ InfixType ‘=>’
414424
415-
EnumBody ::= [nl | ‘with’] ‘{’ [SelfType] EnumStats ‘}’
425+
EnumBody ::= [nl | ‘with’] <<< [SelfType] EnumStats >>>
416426
| ‘with’ [SelfType] indent EnumStats outdent
417427
EnumStats ::= EnumStat {semi EnumStat}
418428
EnumStat ::= TemplateStat
419429
| {Annotation [nl]} {Modifier} EnumCase
420430
EnumCase ::= ‘case’ (id ClassConstr [‘extends’ ConstrApps]] | ids)
421431
422-
TopStatSeq ::= TopStat {semi TopStat}
432+
TopStats ::= TopStat {semi TopStat}
423433
TopStat ::= Import
424434
| Export
425435
| {Annotation [nl]} {Modifier} Def
@@ -428,8 +438,8 @@ TopStat ::= Import
428438
| PackageObject
429439
| EndMarker
430440
|
431-
Packaging ::= ‘package’ QualId [nl| ‘with’] ‘{’ TopStatSeq ‘}’ Package(qid, stats)
441+
Packaging ::= ‘package’ QualId [nl| ‘with’] <<< TopStats >>> Package(qid, stats)
432442
PackageObject ::= ‘package’ ‘object’ ObjectDef object with package in mods.
433443
434-
CompilationUnit ::= {‘package’ QualId semi} TopStatSeq Package(qid, stats)
444+
CompilationUnit ::= {‘package’ QualId semi} TopStats Package(qid, stats)
435445
```

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

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,23 +58,20 @@ There are two rules:
5858

5959
An indentation region can start
6060

61-
- after the leading parameters of an `extension`, or
62-
- after a `with` in a given instance, or
63-
- after a ": at end of line" token (see below)
6461
- after one of the following tokens:
65-
6662
```
67-
= => ?=> <- catch do else finally for
68-
if match return then throw try while yield
63+
= => ?=> <- catch do else finally for if
64+
match return then throw try with while yield
6965
```
66+
- after the leading parameters of an `extension`.
7067

7168
If an `<indent>` is inserted, the indentation width of the token on the next line
7269
is pushed onto `IW`, which makes it the new current indentation width.
7370

7471
2. An `<outdent>` is inserted at a line break, if
7572

7673
- the first token on the next line has an indentation width strictly less
77-
than the current indentation width, and
74+
than the current indentation width, and
7875
- the last token on the previous line is not one of the following tokens
7976
which indicate that the previous statement continues:
8077
```
@@ -87,9 +84,11 @@ There are two rules:
8784
If the indentation width of the token on the next line is still less than the new current indentation width, step (2) repeats. Therefore, several `<outdent>` tokens
8885
may be inserted in a row.
8986

90-
An `<outdent>` is also inserted if the next token following a statement sequence starting with an `<indent>` closes an indentation region, i.e. is one of `then`, `else`, `do`, `catch`, `finally`, `yield`, `}`, `)`, `]` or `case`.
87+
The folllowing two additional rules support parsing of legacy code with ad-hoc layout. They might be withdrawn in future language versions:
88+
89+
- An `<outdent>` is also inserted if the next token following a statement sequence starting with an `<indent>` closes an indentation region, i.e. is one of `then`, `else`, `do`, `catch`, `finally`, `yield`, `}`, `)`, `]` or `case`.
9190

92-
An `<outdent>` is finally inserted in front of a comma that follows a statement sequence starting with an `<indent>` if the indented region is itself enclosed in parentheses
91+
- An `<outdent>` is finally inserted in front of a comma that follows a statement sequence starting with an `<indent>` if the indented region is itself enclosed in parentheses
9392

9493
It is an error if the indentation width of the token following an `<outdent>` does not match the indentation of some previous line in the enclosing indentation region. For instance, the following would be rejected.
9594

0 commit comments

Comments
 (0)