Add support for declaring constructors to the spec parser

Also fixes a bug whereby the file name message came after the first
syntax error diagnostic for each file.

Change-Id: Ice2da1e337fa54787696989b387d057ab5674819
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/453280
Commit-Queue: Erik Ernst <eernst@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Erik Ernst
2025-10-03 05:29:00 -07:00
committed by Commit Queue
parent e3fe4c3873
commit 37c3b5b443
3 changed files with 218 additions and 55 deletions
+103 -28
View File
@@ -4,6 +4,8 @@
// CHANGES:
//
// v0.53 Support declaring constructors.
//
// v0.52 Support static access shorthands.
//
// v0.51 Support a `switchExpression` with no cases.
@@ -176,18 +178,14 @@ import java.util.Stack;
@parser::members {
static String filePath = null;
static boolean errorHasOccurred = false;
/// Must be invoked before the first error is reported for a library.
/// Will print the name of the library and indicate that it has errors.
static void prepareForErrors() {
errorHasOccurred = true;
System.err.println("Syntax error in " + filePath + ":");
}
static boolean errorHeaderHasBeenPrinted = false;
/// Parse library, return true if success, false if errors occurred.
public boolean parseLibrary(String filePath) throws RecognitionException {
this.filePath = filePath;
errorHasOccurred = false;
errorHeaderHasBeenPrinted = false;
this.removeErrorListeners(); // Remove the default ConsoleErrorListener.
this.addErrorListener(new DartErrorListener()); // Add our custom one.
startSymbol();
return !errorHasOccurred;
}
@@ -397,13 +395,11 @@ functionFormalParameter
;
simpleFormalParameter
: declaredIdentifier
| COVARIANT? identifier
: COVARIANT? type? identifier
;
// NB: It is an anomaly that VAR can be a return type (`var this.x()`).
fieldFormalParameter
: finalConstVarOrType? THIS '.' identifier (formalParameterPart '?'?)?
: type? THIS '.' identifier (formalParameterPart '?'?)?
;
superFormalParameter
@@ -424,11 +420,25 @@ typeWithParameters
classDeclaration
: AUGMENT? (classModifiers | mixinClassModifiers)
CLASS typeWithParameters superclass? interfaces?
LBRACE (metadata classMemberDeclaration)* RBRACE
CLASS classNamePart superclass? interfaces? classBody
| classModifiers MIXIN? CLASS mixinApplicationClass
;
primaryConstructorNoConst
: typeIdentifier typeParameters?
('.' identifierOrNew)? declaringParameterList
;
classNamePart
: CONST? primaryConstructorNoConst
| typeWithParameters
;
classBody
: LBRACE (metadata classMemberDeclaration)* RBRACE
| ';'
;
classModifiers
: SEALED
| ABSTRACT? (BASE | INTERFACE | FINAL)?
@@ -466,25 +476,21 @@ mixinDeclaration
LBRACE (metadata mixinMemberDeclaration)* RBRACE
;
// TODO: We might want to make this more strict.
mixinMemberDeclaration
: classMemberDeclaration
;
extensionTypeDeclaration
: EXTENSION TYPE CONST? typeWithParameters
representationDeclaration interfaces?
LBRACE (metadata extensionTypeMemberDeclaration)* RBRACE
: EXTENSION TYPE classNamePart interfaces? extensionTypeBody
| AUGMENT EXTENSION TYPE typeWithParameters interfaces?
LBRACE (metadata extensionTypeMemberDeclaration)* RBRACE
extensionTypeBody
;
representationDeclaration
: ('.' identifierOrNew)? '(' metadata typedIdentifier ')'
extensionTypeBody
: LBRACE (metadata extensionTypeMemberDeclaration)* RBRACE
| ';'
;
// TODO: We might want to make this more strict.
extensionTypeMemberDeclaration
: classMemberDeclaration
;
@@ -498,7 +504,6 @@ extensionBody
: LBRACE (metadata extensionMemberDeclaration)* RBRACE
;
// TODO: We might want to make this more strict.
extensionMemberDeclaration
: classMemberDeclaration
;
@@ -564,13 +569,82 @@ setterSignature
constructorSignature
: constructorName formalParameterList
| declaringConstructorSignature
;
declaringConstructorSignature
: THIS ('.' identifierOrNew)? declaringParameterList?
;
declaringConstantConstructorSignature
: CONST THIS ('.' identifierOrNew)? declaringParameterList
;
declaringParameterList
: '(' ')'
| '(' declaringFormalParameters ','? ')'
| '(' declaringFormalParameters ','
optionalOrNamedDeclaringFormalParameters ')'
| '(' optionalOrNamedDeclaringFormalParameters ')'
;
declaringFormalParameters
: declaringFormalParameter (',' declaringFormalParameter)*
;
declaringFormalParameter
: metadata declaringFormalParameterNoMetadata
;
declaringFormalParameterNoMetadata
: declaringFunctionFormalParameter
| fieldFormalParameter
| declaringSimpleFormalParameter
| superFormalParameter
;
declaringFunctionFormalParameter
: COVARIANT? (VAR | FINAL)? type?
identifier formalParameterPart '?'?
;
declaringSimpleFormalParameter
: COVARIANT? (VAR | FINAL)? type? identifier
;
optionalOrNamedDeclaringFormalParameters
: optionalPositionalDeclaringFormalParameters
| namedDeclaringFormalParameters
;
optionalPositionalDeclaringFormalParameters
: '[' defaultDeclaringFormalParameter
(',' defaultDeclaringFormalParameter)* ','? ']'
;
defaultDeclaringFormalParameter
: declaringFormalParameter ('=' expression)?
;
namedDeclaringFormalParameters
: LBRACE defaultDeclaringNamedParameter
(',' defaultDeclaringNamedParameter)* ','? RBRACE
;
defaultDeclaringNamedParameter
: metadata REQUIRED? declaringFormalParameterNoMetadata
('=' expression)?
;
constructorName
: typeIdentifier ('.' identifierOrNew)?
: typeIdentifierOrNew ('.' identifierOrNew)?
;
typeIdentifierOrNew
: typeIdentifier
| NEW
;
// TODO: Add this in the language specification, use it in grammar rules.
identifierOrNew
: identifier
| NEW
@@ -613,6 +687,7 @@ redirectingFactoryConstructorSignature
constantConstructorSignature
: CONST constructorName formalParameterList
| declaringConstantConstructorSignature
;
mixinApplication
@@ -620,8 +695,8 @@ mixinApplication
;
enumType
: AUGMENT? ENUM typeWithParameters mixins? interfaces? LBRACE
enumEntry (',' enumEntry)* (',')?
: AUGMENT? ENUM classNamePart mixins? interfaces? LBRACE
enumEntry (',' enumEntry)* ','?
(';' (metadata classMemberDeclaration)*)?
RBRACE
;
+16 -8
View File
@@ -14,6 +14,7 @@ class ParsingResult {
}
class DartErrorListener implements ANTLRErrorListener {
@Override
public void reportAmbiguity(
Parser recognizer,
DFA dfa,
@@ -23,6 +24,7 @@ class DartErrorListener implements ANTLRErrorListener {
BitSet ambigAlts,
ATNConfigSet configs) {}
@Override
public void reportAttemptingFullContext(
Parser recognizer,
DFA dfa,
@@ -31,6 +33,7 @@ class DartErrorListener implements ANTLRErrorListener {
BitSet conflictingAlts,
ATNConfigSet configs) {}
@Override
public void reportContextSensitivity(
Parser recognizer,
DFA dfa,
@@ -39,14 +42,19 @@ class DartErrorListener implements ANTLRErrorListener {
int prediction,
ATNConfigSet configs) {}
public void syntaxError(
Recognizer<?,?> recognizer,
Object offendingSymbol,
int line,
int charPositionInLine,
String msg,
RecognitionException e) {
if (!DartParser.errorHasOccurred) DartParser.prepareForErrors();
@Override
public void syntaxError(Recognizer<?, ?> recognizer,
Object offendingSymbol,
int line,
int charPositionInLine,
String msg,
RecognitionException e) {
DartParser.errorHasOccurred = true;
if (!DartParser.errorHeaderHasBeenPrinted) {
System.err.println("Syntax error in " + DartParser.filePath + ":");
DartParser.errorHeaderHasBeenPrinted = true;
}
System.err.println("line " + line + ":" + charPositionInLine + " " + msg);
}
}
+99 -19
View File
@@ -4,6 +4,8 @@
// CHANGES:
//
// v0.54 Support declaring constructors.
//
// v0.53 Support static access shorthands.
//
// v0.52 Support a `switchExpression` with no cases.
@@ -403,13 +405,11 @@ functionFormalParameter
;
simpleFormalParameter
: declaredIdentifier
| COVARIANT? identifier
: COVARIANT? type? identifier
;
// NB: It is an anomaly that VAR can be a return type (`var this.x()`).
fieldFormalParameter
: finalConstVarOrType? THIS '.' identifier (formalParameterPart '?'?)?
: type? THIS '.' identifier (formalParameterPart '?'?)?
;
superFormalParameter
@@ -430,11 +430,25 @@ typeWithParameters
classDeclaration
: AUGMENT? (classModifiers | mixinClassModifiers)
CLASS typeWithParameters superclass? interfaces?
LBRACE (metadata classMemberDeclaration)* RBRACE
CLASS classNamePart superclass? interfaces? classBody
| classModifiers MIXIN? CLASS mixinApplicationClass
;
primaryConstructorNoConst
: typeIdentifier typeParameters?
('.' identifierOrNew)? declaringParameterList
;
classNamePart
: CONST? primaryConstructorNoConst
| typeWithParameters
;
classBody
: LBRACE (metadata classMemberDeclaration)* RBRACE
| ';'
;
classModifiers
: SEALED
| ABSTRACT? (BASE | INTERFACE | FINAL)?
@@ -472,25 +486,21 @@ mixinDeclaration
LBRACE (metadata mixinMemberDeclaration)* RBRACE
;
// TODO: We might want to make this more strict.
mixinMemberDeclaration
: classMemberDeclaration
;
extensionTypeDeclaration
: EXTENSION TYPE CONST? typeWithParameters
representationDeclaration interfaces?
LBRACE (metadata extensionTypeMemberDeclaration)* RBRACE
: EXTENSION TYPE classNamePart interfaces? extensionTypeBody
| AUGMENT EXTENSION TYPE typeWithParameters interfaces?
LBRACE (metadata extensionTypeMemberDeclaration)* RBRACE
extensionTypeBody
;
representationDeclaration
: ('.' identifierOrNew)? '(' metadata typedIdentifier ')'
extensionTypeBody
: LBRACE (metadata extensionTypeMemberDeclaration)* RBRACE
| ';'
;
// TODO: We might want to make this more strict.
extensionTypeMemberDeclaration
: classMemberDeclaration
;
@@ -570,13 +580,82 @@ setterSignature
constructorSignature
: constructorName formalParameterList
| declaringConstructorSignature
;
declaringConstructorSignature
: THIS ('.' identifierOrNew)? declaringParameterList?
;
declaringConstantConstructorSignature
: CONST THIS ('.' identifierOrNew)? declaringParameterList
;
declaringParameterList
: '(' ')'
| '(' declaringFormalParameters ','? ')'
| '(' declaringFormalParameters ','
optionalOrNamedDeclaringFormalParameters ')'
| '(' optionalOrNamedDeclaringFormalParameters ')'
;
declaringFormalParameters
: declaringFormalParameter (',' declaringFormalParameter)*
;
declaringFormalParameter
: metadata declaringFormalParameterNoMetadata
;
declaringFormalParameterNoMetadata
: declaringFunctionFormalParameter
| fieldFormalParameter
| declaringSimpleFormalParameter
| superFormalParameter
;
declaringFunctionFormalParameter
: COVARIANT? (VAR | FINAL)? type?
identifier formalParameterPart '?'?
;
declaringSimpleFormalParameter
: COVARIANT? (VAR | FINAL)? type? identifier
;
optionalOrNamedDeclaringFormalParameters
: optionalPositionalDeclaringFormalParameters
| namedDeclaringFormalParameters
;
optionalPositionalDeclaringFormalParameters
: '[' defaultDeclaringFormalParameter
(',' defaultDeclaringFormalParameter)* ','? ']'
;
defaultDeclaringFormalParameter
: declaringFormalParameter ('=' expression)?
;
namedDeclaringFormalParameters
: LBRACE defaultDeclaringNamedParameter
(',' defaultDeclaringNamedParameter)* ','? RBRACE
;
defaultDeclaringNamedParameter
: metadata REQUIRED? declaringFormalParameterNoMetadata
('=' expression)?
;
constructorName
: typeIdentifier ('.' identifierOrNew)?
: typeIdentifierOrNew ('.' identifierOrNew)?
;
typeIdentifierOrNew
: typeIdentifier
| NEW
;
// TODO: Add this in the language specification, use it in grammar rules.
identifierOrNew
: identifier
| NEW
@@ -619,6 +698,7 @@ redirectingFactoryConstructorSignature
constantConstructorSignature
: CONST constructorName formalParameterList
| declaringConstantConstructorSignature
;
mixinApplication
@@ -626,8 +706,8 @@ mixinApplication
;
enumType
: AUGMENT? ENUM typeWithParameters mixins? interfaces? LBRACE
enumEntry (',' enumEntry)* (',')?
: AUGMENT? ENUM classNamePart mixins? interfaces? LBRACE
enumEntry (',' enumEntry)* ','?
(';' (metadata classMemberDeclaration)*)?
RBRACE
;