@@ -233,46 +233,55 @@ class Parser(positions: Positions, tokens: Seq[Token], source: Source) {
233
233
/**
234
234
* Statements
235
235
*/
236
- def stmts (): Stmt =
236
+ def stmts (inBraces : Boolean = false ): Stmt =
237
237
nonterminal :
238
238
(peek.kind match {
239
- case `val` => valStmt()
240
- case _ if isDefinition => DefStmt (definition(), semi() ~> stmts(), span())
241
- case `with` => withStmt()
242
- case `var` => DefStmt (varDef(), semi() ~> stmts(), span())
239
+ case `{` => BlockStmt (braces { stmts(inBraces = true ) }, span())
240
+ case `val` => valStmt(inBraces)
241
+ case _ if isDefinition && inBraces => DefStmt (definition(), semi() ~> stmts(inBraces), span())
242
+ case _ if isDefinition => fail(" Definitions are only allowed, when enclosed in braces." )
243
+ case `with` => withStmt(inBraces)
244
+ case `var` => DefStmt (varDef(), semi() ~> stmts(inBraces), span())
243
245
case `return` =>
244
- val result = `return` ~> Return (expr() <~ maybeSemi(), span())
245
- result
246
- case `}` | `}$` => // Unexpected end of <STMTS> =>
246
+ // trailing semicolon only allowed when in braces
247
+ `return` ~> Return (expr() <~ ( if inBraces then maybeSemi()), span())
248
+ case `}` | `}$` if inBraces => // Unexpected end of <STMTS> =>
247
249
// insert a synthetic `return ()` into the block
248
250
Return (UnitLit (span().emptyAfter.synthesized), span().emptyAfter.synthesized)
251
+ // for now we do not allow multiple expressions in single-statement mode.
252
+ // That is, we rule out
253
+ // def foo() =
254
+ // expr;
255
+ // expr
256
+ case _ if ! inBraces =>
257
+ Return (expr(), span())
249
258
case _ =>
250
259
val e = expr()
251
260
semi()
252
261
if returnPosition then Return (e, span())
253
- else ExprStmt (e, stmts(), span())
262
+ else ExprStmt (e, stmts(inBraces ), span())
254
263
}) labelled " statements"
255
264
256
265
// ATTENTION: here the grammar changed (we added `with val` to disambiguate)
257
266
// with val <ID> (: <TYPE>)? = <EXPR>; <STMTS>
258
267
// with val (<ID> (: <TYPE>)?...) = <EXPR>
259
268
// with <EXPR>; <STMTS>
260
- def withStmt (): Stmt = `with` ~> peek.kind match {
269
+ def withStmt (inBraces : Boolean ): Stmt = `with` ~> peek.kind match {
261
270
case `val` =>
262
271
val params = (`val` ~> peek.kind match {
263
272
case `(` => valueParamsOpt()
264
273
case _ => List (valueParamOpt()) // TODO copy position
265
274
})
266
- desugarWith(params, Nil , `=` ~> expr(), semi() ~> stmts(), span())
275
+ desugarWith(params, Nil , `=` ~> expr(), semi() ~> stmts(inBraces ), span())
267
276
268
277
case `def` =>
269
278
val params = (`def` ~> peek.kind match {
270
279
case `{` => blockParamsOpt()
271
280
case _ => List (blockParamOpt()) // TODO copy position
272
281
})
273
- desugarWith(Nil , params, `=` ~> expr(), semi() ~> stmts(), span())
282
+ desugarWith(Nil , params, `=` ~> expr(), semi() ~> stmts(inBraces ), span())
274
283
275
- case _ => desugarWith(Nil , Nil , expr(), semi() ~> stmts(), span())
284
+ case _ => desugarWith(Nil , Nil , expr(), semi() ~> stmts(inBraces ), span())
276
285
}
277
286
278
287
def desugarWith (vparams : List [ValueParam ], bparams : List [BlockParam ], call : Term , body : Stmt , withSpan : Span ): Stmt = call match {
@@ -320,11 +329,10 @@ class Parser(positions: Positions, tokens: Seq[Token], source: Source) {
320
329
def stmt (): Stmt =
321
330
nonterminal :
322
331
{
323
- if peek(`{`) then BlockStmt (braces { stmts() }, span())
332
+ if peek(`{`) then BlockStmt (braces { stmts(inBraces = true ) }, span())
324
333
else when(`return`) { Return (expr(), span()) } { Return (expr(), span()) }
325
334
} labelled " statement"
326
335
327
-
328
336
/**
329
337
* Main entry point for the repl.
330
338
*/
@@ -467,7 +475,7 @@ class Parser(positions: Positions, tokens: Seq[Token], source: Source) {
467
475
nonterminal :
468
476
manyWhile(definition(), isDefinition)
469
477
470
- def functionBody : Stmt = stmt () // TODO error context: "the body of a function definition"
478
+ def functionBody : Stmt = stmts () // TODO error context: "the body of a function definition"
471
479
472
480
def valDef (): Def =
473
481
nonterminal :
@@ -479,7 +487,7 @@ class Parser(positions: Positions, tokens: Seq[Token], source: Source) {
479
487
* In statement position, val-definitions can also be destructing:
480
488
* i.e. val (l, r) = point(); ...
481
489
*/
482
- def valStmt (): Stmt =
490
+ def valStmt (inBraces : Boolean ): Stmt =
483
491
nonterminal :
484
492
val doc = maybeDocumentation()
485
493
val startPos = pos()
@@ -493,21 +501,21 @@ class Parser(positions: Positions, tokens: Seq[Token], source: Source) {
493
501
val binding = stmt()
494
502
val endPos = pos()
495
503
val valDef = ValDef (id, tpe, binding, doc, Span (source, startPos, endPos)).withRangeOf(startMarker, binding)
496
- DefStmt (valDef, { semi(); stmts() }, span())
504
+ DefStmt (valDef, { semi(); stmts(inBraces ) }, span())
497
505
}
498
506
def matchLhs () =
499
507
maybeDocumentation() ~ (`val` ~> matchPattern()) ~ manyWhile(`and` ~> matchGuard(), `and`) <~ `=` match {
500
508
case doc ~ AnyPattern (id, _) ~ Nil =>
501
509
val binding = stmt()
502
510
val endPos = pos()
503
511
val valDef = ValDef (id, None , binding, doc, Span (source, startPos, endPos)).withRangeOf(startMarker, binding)
504
- DefStmt (valDef, { semi(); stmts() }, span())
512
+ DefStmt (valDef, { semi(); stmts(inBraces ) }, span())
505
513
case doc ~ p ~ guards =>
506
514
// matches do not support doc comments, so we ignore `doc`
507
515
val sc = expr()
508
516
val endPos = pos()
509
517
val default = when(`else`) { Some (stmt()) } { None }
510
- val body = semi() ~> stmts()
518
+ val body = semi() ~> stmts(inBraces )
511
519
val clause = MatchClause (p, guards, body, Span (source, p.span.from, sc.span.to)).withRangeOf(p, sc)
512
520
val matching = Match (List (sc), List (clause), default, Span (source, startPos, endPos, Synthesized )).withRangeOf(startMarker, sc)
513
521
Return (matching, span().synthesized)
@@ -536,7 +544,7 @@ class Parser(positions: Positions, tokens: Seq[Token], source: Source) {
536
544
else
537
545
// [...](<PARAM>...) {...} `=` <STMT>>
538
546
val (tps, vps, bps) = params()
539
- FunDef (id, tps, vps, bps, maybeReturnAnnotation(), `=` ~> stmt (), doc, span())
547
+ FunDef (id, tps, vps, bps, maybeReturnAnnotation(), `=` ~> stmts (), doc, span())
540
548
541
549
542
550
// right now: data type definitions (should be renamed to `data`) and type aliases
@@ -691,7 +699,7 @@ class Parser(positions: Positions, tokens: Seq[Token], source: Source) {
691
699
nonterminal :
692
700
peek.kind match {
693
701
case _ : Ident => (peek(1 ).kind match {
694
- case `{` => ExternBody .EffektExternBody (featureFlag(), `{` ~> stmts() <~ `}`, span())
702
+ case `{` => ExternBody .EffektExternBody (featureFlag(), `{` ~> stmts(inBraces = true ) <~ `}`, span())
695
703
case _ => ExternBody .StringExternBody (maybeFeatureFlag(), template(), span())
696
704
}) labelled " extern body (string or block)"
697
705
case _ => ExternBody .StringExternBody (maybeFeatureFlag(), template(), span())
@@ -793,14 +801,14 @@ class Parser(positions: Positions, tokens: Seq[Token], source: Source) {
793
801
def ifExpr (): Term =
794
802
nonterminal :
795
803
If (`if` ~> parens { matchGuards().unspan },
796
- stmt (),
797
- when(`else`) { stmt () } { Return (UnitLit (span().emptyAfter), span().emptyAfter) }, span())
804
+ stmts (),
805
+ when(`else`) { stmts () } { Return (UnitLit (span().emptyAfter), span().emptyAfter) }, span())
798
806
799
807
def whileExpr (): Term =
800
808
nonterminal :
801
809
While (`while` ~> parens { matchGuards().unspan },
802
- stmt (),
803
- when(`else`) { Some (stmt ()) } { None },
810
+ stmts (),
811
+ when(`else`) { Some (stmts ()) } { None },
804
812
span())
805
813
806
814
def doExpr (): Term =
@@ -838,7 +846,7 @@ class Parser(positions: Positions, tokens: Seq[Token], source: Source) {
838
846
// TODO deprecate
839
847
def funExpr (): Term =
840
848
nonterminal :
841
- val blockLiteral = `fun` ~> BlockLiteral (Nil , valueParams().unspan, Nil , braces { stmts() }, span())
849
+ val blockLiteral = `fun` ~> BlockLiteral (Nil , valueParams().unspan, Nil , braces { stmts(inBraces = true ) }, span())
842
850
Box (Maybe .None (Span (source, pos(), pos(), Synthesized )), blockLiteral, blockLiteral.span.synthesized)
843
851
844
852
def unboxExpr (): Term =
@@ -920,9 +928,7 @@ class Parser(positions: Positions, tokens: Seq[Token], source: Source) {
920
928
MatchClause (
921
929
pattern,
922
930
manyWhile(`and` ~> matchGuard(), `and`),
923
- // allow a statement enclosed in braces or without braces
924
- // both is allowed since match clauses are already delimited by `case`
925
- `=>` ~> (if (peek(`{`)) { stmt() } else { stmts() }),
931
+ `=>` ~> stmts(inBraces = true ),
926
932
span()
927
933
)
928
934
@@ -1145,10 +1151,10 @@ class Parser(positions: Positions, tokens: Seq[Token], source: Source) {
1145
1151
case _ =>
1146
1152
// { (x: Int) => ... }
1147
1153
backtrack { lambdaParams() <~ `=>` } map {
1148
- case (tps, vps, bps) => BlockLiteral (tps, vps, bps, stmts(), Span .missing(source)) : BlockLiteral
1154
+ case (tps, vps, bps) => BlockLiteral (tps, vps, bps, stmts(inBraces = true ), Span .missing(source)) : BlockLiteral
1149
1155
} getOrElse {
1150
1156
// { <STMTS> }
1151
- BlockLiteral (Nil , Nil , Nil , stmts(), Span .missing(source)) : BlockLiteral
1157
+ BlockLiteral (Nil , Nil , Nil , stmts(inBraces = true ), Span .missing(source)) : BlockLiteral
1152
1158
}
1153
1159
}
1154
1160
}
@@ -1221,7 +1227,7 @@ class Parser(positions: Positions, tokens: Seq[Token], source: Source) {
1221
1227
peek.kind match {
1222
1228
case `<>` => `<>` ~> Hole (IdDef (" hole" , span().synthesized), Template (Nil , Nil ), span())
1223
1229
case `<{` => {
1224
- val s = `<{` ~> stmts() <~ `}>`
1230
+ val s = `<{` ~> stmts(inBraces = true ) <~ `}>`
1225
1231
Hole (IdDef (" hole" , span().synthesized), Template (Nil , List (s)), span())
1226
1232
}
1227
1233
case _ : HoleStr => {
@@ -1235,7 +1241,7 @@ class Parser(positions: Positions, tokens: Seq[Token], source: Source) {
1235
1241
def holeTemplate (): Template [Stmt ] =
1236
1242
nonterminal :
1237
1243
val first = holeString()
1238
- val (s, strs) = manyWhile((`${` ~> stmts() <~ `}$`, holeString()), `${`).unzip
1244
+ val (s, strs) = manyWhile((`${` ~> stmts(inBraces = true ) <~ `}$`, holeString()), `${`).unzip
1239
1245
Template (first :: strs, s)
1240
1246
1241
1247
def holeString (): String =
0 commit comments