Skip to content

Commit 77ea27e

Browse files
committed
Fixes instance_expression
Problem ------- Current grammar accepts expression immeidately after `new`, which is not correct, and doesn't work for Scala 3 syntax. Solution -------- This fixes it by actually using `$.template_body`. It does create a tricky conflict between `new A: <block>` construct and `new A: <type>`. To deal with that, we are using `prec.dynamic`.
1 parent 8677ff4 commit 77ea27e

File tree

5 files changed

+91
-35
lines changed

5 files changed

+91
-35
lines changed

corpus/definitions.txt

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,28 +1015,15 @@ Inline given (Scala 3)
10151015
=======================================
10161016

10171017
inline given Test =
1018-
new Test:
1019-
def apply(i: Int) = 2
1018+
new Test
10201019

10211020
---
10221021

10231022
(compilation_unit
10241023
(given_definition
10251024
(modifiers (inline_modifier))
10261025
(type_identifier)
1027-
(assignment_expression
1028-
(instance_expression
1029-
(ascription_expression
1030-
(identifier)
1031-
(infix_type
1032-
(type_identifier)
1033-
(identifier)
1034-
(tuple_type
1035-
(infix_type
1036-
(type_identifier)
1037-
(operator_identifier)
1038-
(type_identifier))))))
1039-
(integer_literal))))
1026+
(instance_expression (type_identifier))))
10401027

10411028

10421029
=======================================

corpus/expressions.txt

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ def main() {
250250
(case_class_pattern
251251
(type_identifier)
252252
(identifier))
253-
(throw_expression (instance_expression (call_expression (identifier) (arguments (identifier))))
253+
(throw_expression (instance_expression (type_identifier) (arguments (identifier)))
254254
)
255255
)
256256
)
@@ -314,7 +314,7 @@ def main(): Unit =
314314
(case_class_pattern
315315
(type_identifier)
316316
(identifier))
317-
(throw_expression (instance_expression (call_expression (identifier) (arguments (identifier))))
317+
(throw_expression (instance_expression (type_identifier) (arguments (identifier)))
318318
)
319319
)
320320
)
@@ -428,8 +428,15 @@ Instance expressions
428428

429429
class C {
430430
def main() {
431-
a = new B
432-
c = new D(e, f)
431+
val a = new B
432+
val c = new D(e, f)
433+
val e = new E:
434+
def app = 1
435+
val f = new F {}
436+
val g = new {
437+
"ok"
438+
}
439+
new Array: Array
433440
}
434441
}
435442

@@ -443,8 +450,25 @@ class C {
443450
(identifier)
444451
(parameters)
445452
(block
446-
(assignment_expression (identifier) (instance_expression (identifier)))
447-
(assignment_expression (identifier) (instance_expression (call_expression (identifier) (arguments (identifier) (identifier))))))))))
453+
(val_definition
454+
(identifier)
455+
(instance_expression (type_identifier)))
456+
(val_definition
457+
(identifier)
458+
(instance_expression (type_identifier) (arguments (identifier) (identifier))))
459+
(val_definition
460+
(identifier)
461+
(instance_expression (type_identifier) (template_body
462+
(function_definition (identifier) (integer_literal)))))
463+
(val_definition
464+
(identifier)
465+
(instance_expression (type_identifier) (template_body)))
466+
(val_definition
467+
(identifier)
468+
(instance_expression (template_body (string))))
469+
(ascription_expression
470+
(instance_expression (type_identifier))
471+
(type_identifier)))))))
448472

449473
===============================
450474
Infix expressions

grammar.js

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ const PREC = {
1111
ascription: 4,
1212
postfix: 5,
1313
infix: 6,
14-
new: 7,
14+
constructor_app: 7,
1515
prefix: 7,
1616
compound: 7,
1717
call: 8,
1818
field: 8,
1919
end_marker: 9,
2020
macro: 10,
21+
binding: 10,
2122
}
2223

2324
module.exports = grammar({
@@ -63,13 +64,15 @@ module.exports = grammar({
6364
conflicts: $ => [
6465
[$.tuple_type, $.parameter_types],
6566
[$.binding, $._simple_expression],
67+
[$.binding, $.ascription_expression],
6668
[$.if_expression, $.expression],
6769
[$.while_expression, $._simple_expression],
6870
[$.for_expression, $.infix_expression],
6971
[$._indentable_expression, $.do_while_expression],
7072
[$.if_expression],
7173
[$.match_expression],
7274
[$._type_identifier, $.identifier],
75+
[$.instance_expression],
7376
],
7477

7578
word: $ => $._alpha_identifier,
@@ -323,12 +326,12 @@ module.exports = grammar({
323326
$._block,
324327
$._outdent,
325328
)),
326-
seq(
329+
prec.left(PREC.control, seq(
327330
'{',
328331
optional($.self_type),
329332
optional($._block),
330333
'}',
331-
),
334+
)),
332335
),
333336

334337
/*
@@ -511,14 +514,35 @@ module.exports = grammar({
511514
* StructuralInstance ::= ConstrApp {'with' ConstrApp} ['with' WithTemplateBody]
512515
*/
513516
_structural_instance: $ => seq(
514-
choice(
515-
$._annotated_type,
516-
$.compound_type,
517-
),
517+
$._constructor_application,
518518
'with',
519519
field('body', $.with_template_body),
520520
),
521521

522+
/**
523+
* ConstrApp ::= SimpleType1 {Annotation} {ParArgumentExprs}
524+
*
525+
* Note: It would look more elegant if we could make seq(choice(), optional(arguments)),
526+
* but that doesn't seem to work.
527+
*/
528+
_constructor_application: $ => prec.left(PREC.constructor_app, choice(
529+
$._annotated_type,
530+
$.compound_type,
531+
// This adds _simple_type, but not the above intentionall/y.
532+
seq(
533+
$._simple_type,
534+
field('arguments', $.arguments),
535+
),
536+
seq(
537+
$._annotated_type,
538+
field('arguments', $.arguments),
539+
),
540+
seq(
541+
$.compound_type,
542+
field('arguments', $.arguments),
543+
),
544+
)),
545+
522546
modifiers: $ => repeat1(choice(
523547
'abstract',
524548
'final',
@@ -887,7 +911,7 @@ module.exports = grammar({
887911

888912
finally_clause: $ => prec.right(seq('finally', $._indentable_expression)),
889913

890-
binding: $ => prec.dynamic(PREC.binding_decl, seq(
914+
binding: $ => prec.dynamic(PREC.binding, seq(
891915
field('name', $._identifier),
892916
optional(seq(':', field('type', $._param_type))),
893917
)),
@@ -941,15 +965,32 @@ module.exports = grammar({
941965
field('field', $._identifier)
942966
)),
943967

944-
instance_expression: $ => prec(PREC.new, seq(
945-
'new',
946-
$.expression
947-
)),
968+
/**
969+
* SimpleExpr ::= SimpleRef
970+
* | 'new' ConstrApp {'with' ConstrApp} [TemplateBody]
971+
* | 'new' TemplateBody
972+
*/
973+
instance_expression: $ => choice(
974+
// This is weakened so ascription wins for new Array: Array
975+
prec.dynamic(0, seq(
976+
'new',
977+
$._constructor_application,
978+
$.template_body,
979+
)),
980+
seq(
981+
'new',
982+
$.template_body,
983+
),
984+
seq(
985+
'new',
986+
$._constructor_application,
987+
),
988+
),
948989

949990
/**
950991
* PostfixExpr [Ascription]
951992
*/
952-
ascription_expression: $ => prec.right(PREC.ascription, seq(
993+
ascription_expression: $ => prec.dynamic(PREC.ascription, seq(
953994
$._postfix_expression_choice,
954995
':',
955996
choice(

script/smoke_test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
SCALA_SCALA_LIBRARY_EXPECTED=100
66
SCALA_SCALA_COMPILER_EXPECTED=66
7-
DOTTY_COMPILER_EXPECTED=73
7+
DOTTY_COMPILER_EXPECTED=74
88

99
if [ ! -d "$SCALA_SCALA_DIR" ]; then
1010
echo "\$SCALA_SCALA_DIR must be set"

test/highlight/basics.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ object Hello {
1111
// ^string
1212
// ^conditional
1313

14+
val y = new lower_case_intentionally
15+
// ^keyword.operator
16+
// ^type
17+
1418
trait Test {
1519
// ^ keyword
1620
// ^ type.definition

0 commit comments

Comments
 (0)