Skip to content

Commit a077cdc

Browse files
committed
ASTGen: Translate precedence group declarations
1 parent 7bf8f7c commit a077cdc

File tree

6 files changed

+224
-0
lines changed

6 files changed

+224
-0
lines changed

include/swift/AST/CASTBridging.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,24 @@ void *OperatorDecl_create(BridgedASTContext cContext,
434434
BridgedIdentifier cPrecedenceGroupName,
435435
BridgedSourceLoc cPrecedenceGroupLoc);
436436

437+
typedef enum ENUM_EXTENSIBILITY_ATTR(open) {
438+
BridgedAssociativityNone,
439+
BridgedAssociativityLeft,
440+
BridgedAssociativityRight,
441+
} BridgedAssociativity;
442+
443+
void *PrecedenceGroupDecl_create(
444+
BridgedDeclContext cDeclContext,
445+
BridgedSourceLoc cPrecedencegroupKeywordLoc, BridgedIdentifier cName,
446+
BridgedSourceLoc cNameLoc, BridgedSourceLoc cLeftBraceLoc,
447+
BridgedSourceLoc cAssociativityKeywordLoc,
448+
BridgedSourceLoc cAssociativityValueLoc,
449+
BridgedAssociativity cAssociativity, BridgedSourceLoc cAssignmentKeywordLoc,
450+
BridgedSourceLoc cAssignmentValueLoc, _Bool isAssignment,
451+
BridgedSourceLoc cHigherThanKeywordLoc, BridgedArrayRef cHigherThanNames,
452+
BridgedSourceLoc cLowerThanKeywordLoc, BridgedArrayRef cLowerThanNames,
453+
BridgedSourceLoc cRightBraceLoc);
454+
437455
typedef enum ENUM_EXTENSIBILITY_ATTR(open) {
438456
BridgedImportKindModule,
439457
BridgedImportKindType,

lib/AST/CASTBridging.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,48 @@ void *OperatorDecl_create(BridgedASTContext cContext,
826826
return static_cast<Decl *>(decl);
827827
}
828828

829+
void *PrecedenceGroupDecl_create(
830+
BridgedDeclContext cDeclContext,
831+
BridgedSourceLoc cPrecedencegroupKeywordLoc, BridgedIdentifier cName,
832+
BridgedSourceLoc cNameLoc, BridgedSourceLoc cLeftBraceLoc,
833+
BridgedSourceLoc cAssociativityKeywordLoc,
834+
BridgedSourceLoc cAssociativityValueLoc,
835+
BridgedAssociativity cAssociativity, BridgedSourceLoc cAssignmentKeywordLoc,
836+
BridgedSourceLoc cAssignmentValueLoc, bool isAssignment,
837+
BridgedSourceLoc cHigherThanKeywordLoc, BridgedArrayRef cHigherThanNames,
838+
BridgedSourceLoc cLowerThanKeywordLoc, BridgedArrayRef cLowerThanNames,
839+
BridgedSourceLoc cRightBraceLoc) {
840+
841+
SmallVector<PrecedenceGroupDecl::Relation, 2> higherThanNames;
842+
for (auto &pair :
843+
convertArrayRef<BridgedIdentifierAndSourceLoc>(cHigherThanNames)) {
844+
higherThanNames.push_back({convertSourceLoc(pair.nameLoc),
845+
convertIdentifier(pair.name), nullptr});
846+
}
847+
848+
SmallVector<PrecedenceGroupDecl::Relation, 2> lowerThanNames;
849+
for (auto &pair :
850+
convertArrayRef<BridgedIdentifierAndSourceLoc>(cLowerThanNames)) {
851+
lowerThanNames.push_back({convertSourceLoc(pair.nameLoc),
852+
convertIdentifier(pair.name), nullptr});
853+
}
854+
855+
auto *decl = PrecedenceGroupDecl::create(
856+
convertDeclContext(cDeclContext),
857+
convertSourceLoc(cPrecedencegroupKeywordLoc), convertSourceLoc(cNameLoc),
858+
convertIdentifier(cName), convertSourceLoc(cLeftBraceLoc),
859+
convertSourceLoc(cAssociativityKeywordLoc),
860+
convertSourceLoc(cAssociativityValueLoc),
861+
static_cast<Associativity>(cAssociativity),
862+
convertSourceLoc(cAssignmentKeywordLoc),
863+
convertSourceLoc(cAssignmentValueLoc), isAssignment,
864+
convertSourceLoc(cHigherThanKeywordLoc), higherThanNames,
865+
convertSourceLoc(cLowerThanKeywordLoc), lowerThanNames,
866+
convertSourceLoc(cRightBraceLoc));
867+
868+
return static_cast<Decl *>(decl);
869+
}
870+
829871
void *ImportDecl_create(BridgedASTContext cContext,
830872
BridgedDeclContext cDeclContext,
831873
BridgedSourceLoc cImportKeywordLoc,

lib/ASTGen/Sources/ASTGen/ASTGen.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,15 @@ extension ASTGenVisitor {
220220

221221
return self.visit(node)
222222
}
223+
224+
@inline(__always)
225+
func visit(_ node: PrecedenceGroupNameListSyntax?) -> BridgedArrayRef {
226+
guard let node else {
227+
return .init()
228+
}
229+
230+
return self.visit(node)
231+
}
223232
}
224233

225234
extension SyntaxCollection {

lib/ASTGen/Sources/ASTGen/Decls.swift

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,119 @@ extension ASTGenVisitor {
351351
}
352352
}
353353

354+
// MARK: - PrecedenceGroupDecl
355+
356+
extension BridgedAssociativity {
357+
fileprivate init?(from tokenKind: TokenKind) {
358+
switch tokenKind {
359+
case .keyword(.none): self = .none
360+
case .keyword(.left): self = .left
361+
case .keyword(.right): self = .right
362+
default: return nil
363+
}
364+
}
365+
}
366+
367+
extension ASTGenVisitor {
368+
func visit(_ node: PrecedenceGroupDeclSyntax) -> ASTNode {
369+
let (name, nameLoc) = node.name.bridgedIdentifierAndSourceLoc(in: self)
370+
371+
struct PrecedenceGroupBody {
372+
var associativity: PrecedenceGroupAssociativitySyntax? = nil
373+
var assignment: PrecedenceGroupAssignmentSyntax? = nil
374+
var higherThanRelation: PrecedenceGroupRelationSyntax? = nil
375+
var lowerThanRelation: PrecedenceGroupRelationSyntax? = nil
376+
}
377+
378+
let body = node.groupAttributes.reduce(into: PrecedenceGroupBody()) { partialResult, element in
379+
let duplicate: Syntax
380+
let original: Syntax
381+
382+
switch element {
383+
case .precedenceGroupRelation(let node):
384+
let keyword = node.higherThanOrLowerThanLabel
385+
switch keyword.tokenKind {
386+
case .keyword(.higherThan):
387+
guard let current = partialResult.higherThanRelation else {
388+
partialResult.higherThanRelation = node
389+
return
390+
}
391+
(duplicate, original) = (Syntax(node), Syntax(current))
392+
case .keyword(.lowerThan):
393+
guard let current = partialResult.lowerThanRelation else {
394+
partialResult.lowerThanRelation = node
395+
return
396+
}
397+
(duplicate, original) = (Syntax(node), Syntax(current))
398+
default:
399+
return self.diagnose(Diagnostic(node: keyword, message: UnexpectedTokenKindError(token: keyword)))
400+
}
401+
case .precedenceGroupAssignment(let node):
402+
guard let current = partialResult.assignment else {
403+
partialResult.assignment = node
404+
return
405+
}
406+
(duplicate, original) = (Syntax(node), Syntax(current))
407+
case .precedenceGroupAssociativity(let node):
408+
guard let current = partialResult.associativity else {
409+
partialResult.associativity = node
410+
return
411+
}
412+
(duplicate, original) = (Syntax(node), Syntax(current))
413+
}
414+
415+
self.diagnose(Diagnostic(node: duplicate, message: DuplicateSyntaxError(duplicate: duplicate, original: original)))
416+
}
417+
418+
let associativityValue: BridgedAssociativity
419+
switch body.associativity?.value {
420+
case let token?:
421+
guard let value = BridgedAssociativity(from: token.tokenKind) else {
422+
self.diagnose(Diagnostic(node: token, message: UnexpectedTokenKindError(token: token)))
423+
fallthrough
424+
}
425+
426+
associativityValue = value
427+
case nil:
428+
associativityValue = .none
429+
}
430+
431+
let assignmentValue: Bool
432+
switch body.assignment?.value {
433+
case let token?:
434+
guard token.tokenKind == .keyword(.true) else {
435+
self.diagnose(Diagnostic(node: token, message: UnexpectedTokenKindError(token: token)))
436+
fallthrough
437+
}
438+
439+
assignmentValue = true
440+
case nil:
441+
assignmentValue = false
442+
}
443+
444+
return .decl(
445+
PrecedenceGroupDecl_create(
446+
self.declContext,
447+
self.bridgedSourceLoc(for: node.precedencegroupKeyword),
448+
name,
449+
nameLoc,
450+
self.bridgedSourceLoc(for: node.leftBrace),
451+
self.bridgedSourceLoc(for: body.associativity?.associativityLabel),
452+
self.bridgedSourceLoc(for: body.associativity?.value),
453+
associativityValue,
454+
self.bridgedSourceLoc(for: body.assignment?.assignmentLabel),
455+
self.bridgedSourceLoc(for: body.assignment?.value),
456+
assignmentValue,
457+
self.bridgedSourceLoc(for: body.higherThanRelation?.higherThanOrLowerThanLabel),
458+
self.visit(body.higherThanRelation?.precedenceGroups),
459+
self.bridgedSourceLoc(for: body.lowerThanRelation?.higherThanOrLowerThanLabel),
460+
self.visit(body.lowerThanRelation?.precedenceGroups),
461+
self.bridgedSourceLoc(for: node.rightBrace)
462+
)
463+
)
464+
}
465+
}
466+
354467
// MARK: - ImportDecl
355468

356469
extension BridgedImportKind {
@@ -406,4 +519,10 @@ extension ASTGenVisitor {
406519
func visit(_ node: InheritedTypeListSyntax) -> BridgedArrayRef {
407520
node.map(in: self) { self.visit($0.type).rawValue }
408521
}
522+
523+
func visit(_ node: PrecedenceGroupNameListSyntax) -> BridgedArrayRef {
524+
node.map(in: self) {
525+
$0.name.bridgedIdentifierAndSourceLoc(in: self) as BridgedIdentifierAndSourceLoc
526+
}
527+
}
409528
}

lib/ASTGen/Sources/ASTGen/Diagnostics.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,3 +539,28 @@ struct MissingChildTokenError: ASTGenError {
539539
"""
540540
}
541541
}
542+
543+
/// An error emitted when a syntax collection entry is encountered that is considered a duplicate of a previous entry
544+
/// per the language grammar.
545+
struct DuplicateSyntaxError: ASTGenError {
546+
let duplicate: Syntax
547+
let original: Syntax
548+
549+
init<S: SyntaxProtocol>(duplicate: S, original: S) {
550+
guard let duplicateParent = duplicate.parent, let originalParent = original.parent, duplicateParent == originalParent, duplicateParent.kind.isSyntaxCollection else {
551+
preconditionFailure("Expected a shared syntax collection parent")
552+
}
553+
554+
self.duplicate = Syntax(duplicate)
555+
self.original = Syntax(original)
556+
}
557+
558+
var message: String {
559+
"""
560+
unexpected duplicate syntax in list:
561+
\(duplicate.debugDescription(indentString: " "))
562+
previous syntax:
563+
\(original.debugDescription(indentString: " "))
564+
"""
565+
}
566+
}

test/ASTGen/verify-parse.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,14 @@ operator
191191

192192
postfix
193193
operator ⎩^-^⎩
194+
195+
196+
precedencegroup Precedence1 {
197+
}
198+
199+
precedencegroup Precedence2 {
200+
lowerThan: BitwiseShiftPrecedence, MultiplicationPrecedence
201+
higherThan: Precedence1, AdditionPrecedence
202+
associativity: left
203+
assignment: true
204+
}

0 commit comments

Comments
 (0)